Connect with us

MPEG2 Audio and Video Splitter

Discussion in 'Electronic Design' started by [email protected], Apr 2, 2007.

Scroll to continue with content
  1. Guest

    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 <= next_data_byte;

    if ((8'h00 <= start_code <= 8'BF) ||
    (8'hE0 <= start_code <= 8'hFF))
    video_start_code <= 1'b1;

    if (8'hC0 <= start_code <= 8'hDF)
    audio_start_code <= 1'b1;

    Once I have decoded a video start code, I send all data to the Video
    Decoder, until I recognize a prefix followed by an audio start code,
    when I then send data to the audio decoder core until Video start_code
    is recognized.

    To test my splitter I input an mpg file into the stimulus and split
    the data out, writing the video contents to a file. I then convert
    the dump file to an mpg file and play in media player. If the
    splitter is working, then the file would play w/out sound. However, I
    only get a black screen which tells me the code is not functioning
    correctly.

    Can someone please point me in the right direction? Thanks.

    Amit
     
  2. Ben Jackson

    Ben Jackson Guest

    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?
     
  3. Guest

    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);
    }
     
Ask a Question
Want to reply to this thread or ask your own question?
You'll need to choose a username for the site, which only take a couple of moments (here). After that, you can post your question and our members will help you out.
Electronics Point Logo
Continue to site
Quote of the day

-