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?
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 <windows.h>
#include <stdio.h>
#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 <input MPG> <output video> <output audio>
\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 << 8;
state = 6;
MpegWrite(argv[2], hVideo, cVideoBuf, sizeof(cVideoBuf), &dwVideo,
*lpMpeg);
break;
case 6 : // here for LSB of VES byte count
dwVES |= *lpMpeg;
state = 7;
MpegWrite(argv[2], hVideo, cVideoBuf, sizeof(cVideoBuf), &dwVideo,
*lpMpeg);
break;
case 7 : // here to copy VES data
if (--dwVES == 0)
state = 1;
MpegWrite(argv[2], hVideo, cVideoBuf, sizeof(cVideoBuf), &dwVideo,
*lpMpeg);
break;
case 8 : // here for MSB of AES byte count
dwAES = *lpMpeg << 8;
state = 9;
MpegWrite(argv[3], hAudio, cAudioBuf, sizeof(cAudioBuf), &dwAudio,
*lpMpeg);
break;
case 9 : // here for LSB of AES byte count
dwAES |= *lpMpeg;
state = 10;
MpegWrite(argv[3], hAudio, cAudioBuf, sizeof(cAudioBuf), &dwAudio,
*lpMpeg);
break;
case 10 : // here to copy AES data
if (--dwAES == 0)
state = 1;
MpegWrite(argv[3], hAudio, cAudioBuf, sizeof(cAudioBuf), &dwAudio,
*lpMpeg);
break;
}
// decrement mpeg buffer count
lpMpeg++;
dwMpeg--;
}
// close files
CloseHandle(hMpeg);
CloseHandle(hVideo);
CloseHandle(hAudio);
return(0);
}