MPEG2 Audio and Video Splitter

Apr 02, 2007 2 Replies

I am using an Altera FPGA to split video and audio data from an *.mpg file. I receive mpg data and send to a IP MPEG2 Decoder Core purchased from Amphion Semiconductors. I have attempted to code a data splitter but have plenty of questions with the demultiplexing of the data.



The below describes the code at higher level:



if (prefix_code_recognized) // received 24'h000001 start_code


What is the format of your *.mpg file? It is almost certainly either a mpeg2 transport stream or a packetized elementary stream. Either way, you will find start codes inside, but you will be looking "inside" the TS or PES packets and your output will be a hash.

A TS will start with 0x47 (and repeat every 188 bytes). I forget if there's anything special about a PES, but knowing it exists is half the battle. Either one will have enough information to allow you to split the file at a higher level than the individual start codes.

BTW, are you the Amit Patel I know?

Ben Jackson AD7GD http://www.ben.com/

Hello Ben,

Thank you for your response. I believe the data is PES, because the stream starts with a start_code of 32'h000001BA. I am using an IP MPEG2 Video Decoder in my design, and I need to split the mpeg2 video and audio data. I am doing so as shown above, but am still uncertain if this is the proper way to transmit the data. Do I have to go by the packet information and count my data? Below is a C++ description I am following. Let me know what you think. Thanks:

#include #include #include "MpegStream.h"

void MpegWrite(char* fname, HANDLE hFile, LPBYTE base, DWORD len, LPDWORD count, BYTE c) { base[*count] = c; if (++*count >= len) { DWORD dwBytesWritten; if (!WriteFile(hFile, base, len, &dwBytesWritten, NULL)) { LPVOID errmsg; FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM, 0, GetLastError(), 0, (LPSTR)&errmsg, 0, NULL); fprintf(stderr, "WriteFile %s failure (%d) %s\n", fname, GetLastError(), errmsg); LocalFree(errmsg); ExitProcess(1); } *count = 0; } }

int main(int argc, char* argv[]) { LPVOID errmsg; BYTE cMpegBuf[1024]; BYTE cVideoBuf[1024]; BYTE cAudioBuf[1024]; LPBYTE lpMpeg; DWORD dwMpeg; DWORD dwVideo; DWORD dwAudio; DWORD dwVES; DWORD dwAES;

// check command line arguments if (argc != 4) { fputs("Usage: MpegSplitter \n", stderr); ExitProcess(1); }

// open input MPG file HANDLE hMpeg = CreateFile(argv[1], GENERIC_READ, 0, NULL, OPEN_EXISTING, 0, NULL); if (hMpeg == (HANDLE)INVALID_HANDLE_VALUE) { FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM, 0, GetLastError(), 0, (LPSTR)&errmsg, 0, NULL); fprintf(stderr, "CreateFile %s failure (%d) %s\n", argv[1], GetLastError(), errmsg); LocalFree(errmsg); ExitProcess(1); }

// create output video file HANDLE hVideo = CreateFile(argv[2], GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, 0, NULL); if (hVideo == (HANDLE)INVALID_HANDLE_VALUE) { FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM, 0, GetLastError(), 0, (LPSTR)&errmsg, 0, NULL); fprintf(stderr, "CreateFile %s failure (%d) %s\n", argv[2], GetLastError(), errmsg); LocalFree(errmsg); ExitProcess(1); }

// open input MPG file HANDLE hAudio = CreateFile(argv[3], GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, 0, NULL); if (hAudio == (HANDLE)INVALID_HANDLE_VALUE) { FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM, 0, GetLastError(), 0, (LPSTR)&errmsg, 0, NULL); fprintf(stderr, "CreateFile %s failure (%d) %s\n", argv[3], GetLastError(), errmsg); LocalFree(errmsg); ExitProcess(1); }

// split mpeg into video and audio lpMpeg = cMpegBuf; dwMpeg = 0; dwVideo = 0; dwAudio = 0; dwVES = 0; dwAES = 0;

int state = 1; while (1) { // if need mpeg data if (dwMpeg == 0) { if (!ReadFile(hMpeg, cMpegBuf, sizeof(cMpegBuf), &dwMpeg, NULL)) { FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM, 0, GetLastError(), 0, (LPSTR)&errmsg, 0, NULL); fprintf(stderr, "ReadFile %s failure (%d) %s\n", argv[1], GetLastError(), errmsg); LocalFree(errmsg); ExitProcess(1); } if (dwMpeg == 0) break; lpMpeg = cMpegBuf; }

// process mpeg data switch (state) { case 1 : // look for first byte of start code if (*lpMpeg == 0) state = 2; else { MpegWrite(argv[2], hVideo, cVideoBuf, sizeof(cVideoBuf), &dwVideo,

*lpMpeg); MpegWrite(argv[3], hAudio, cAudioBuf, sizeof(cAudioBuf), &dwAudio, *lpMpeg); } break;

case 2 : // look for second byte of start code if (*lpMpeg == 0) state = 3; else { state = 1;

MpegWrite(argv[2], hVideo, cVideoBuf, sizeof(cVideoBuf), &dwVideo,

0); MpegWrite(argv[2], hVideo, cVideoBuf, sizeof(cVideoBuf), &dwVideo, *lpMpeg);

MpegWrite(argv[3], hAudio, cAudioBuf, sizeof(cAudioBuf), &dwAudio,

0); MpegWrite(argv[3], hAudio, cAudioBuf, sizeof(cAudioBuf), &dwAudio, *lpMpeg); } break;

case 3 : // look for third byte of start code if (*lpMpeg == 1) state = 4; else if (*lpMpeg != 0) { state = 1;

MpegWrite(argv[2], hVideo, cVideoBuf, sizeof(cVideoBuf), &dwVideo,

0); MpegWrite(argv[2], hVideo, cVideoBuf, sizeof(cVideoBuf), &dwVideo, 0); MpegWrite(argv[2], hVideo, cVideoBuf, sizeof(cVideoBuf), &dwVideo, *lpMpeg);

MpegWrite(argv[3], hAudio, cAudioBuf, sizeof(cAudioBuf), &dwAudio,

0); MpegWrite(argv[3], hAudio, cAudioBuf, sizeof(cAudioBuf), &dwAudio, 0); MpegWrite(argv[3], hAudio, cAudioBuf, sizeof(cAudioBuf), &dwAudio, *lpMpeg); } break;

case 4 : // have start code. process start code // if start of video elementary stream if (*lpMpeg >= VIDEO_ELEMENTARY_STREAM && *lpMpeg < VIDEO_ELEMENTARY_STREAM + 0x10) // VIDEO_ELEMENTARY_STREAM == 0xE0 { state = 5;

MpegWrite(argv[2], hVideo, cVideoBuf, sizeof(cVideoBuf), &dwVideo,

0); MpegWrite(argv[2], hVideo, cVideoBuf, sizeof(cVideoBuf), &dwVideo, 0); MpegWrite(argv[2], hVideo, cVideoBuf, sizeof(cVideoBuf), &dwVideo, 1); MpegWrite(argv[2], hVideo, cVideoBuf, sizeof(cVideoBuf), &dwVideo, *lpMpeg); } // if start of audio elementary stream else if (*lpMpeg >= AUDIO_ELEMENTARY_STREAM && *lpMpeg < AUDIO_ELEMENTARY_STREAM + 0x20) // AUDIO_ELEMENTARY_STREAM == 0xC0 { state = 8;

MpegWrite(argv[3], hAudio, cAudioBuf, sizeof(cAudioBuf), &dwAudio,

0); MpegWrite(argv[3], hAudio, cAudioBuf, sizeof(cAudioBuf), &dwAudio, 0); MpegWrite(argv[3], hAudio, cAudioBuf, sizeof(cAudioBuf), &dwAudio, 1); MpegWrite(argv[3], hAudio, cAudioBuf, sizeof(cAudioBuf), &dwAudio, *lpMpeg); } // if none of the above else { state = 1;

MpegWrite(argv[2], hVideo, cVideoBuf, sizeof(cVideoBuf), &dwVideo,

0); MpegWrite(argv[2], hVideo, cVideoBuf, sizeof(cVideoBuf), &dwVideo, 0); MpegWrite(argv[2], hVideo, cVideoBuf, sizeof(cVideoBuf), &dwVideo, 1); MpegWrite(argv[2], hVideo, cVideoBuf, sizeof(cVideoBuf), &dwVideo, *lpMpeg);

MpegWrite(argv[3], hAudio, cAudioBuf, sizeof(cAudioBuf), &dwAudio,

0); MpegWrite(argv[3], hAudio, cAudioBuf, sizeof(cAudioBuf), &dwAudio, 0); MpegWrite(argv[3], hAudio, cAudioBuf, sizeof(cAudioBuf), &dwAudio, 1); MpegWrite(argv[3], hAudio, cAudioBuf, sizeof(cAudioBuf), &dwAudio, *lpMpeg); } break;

case 5 : // here for MSB of VES byte count dwVES = *lpMpeg

Join the Discussion

Have something to add? Share your thoughts — no account required.

Didn't find your answer?

Ask the community — no account required