This thread has been locked.

If you have a related question, please click the "Ask a related question" button in the top right corner. The newly created question will be automatically linked to this question.

How to generate MPEG4 VOL header?

Hi all,

 

I'm developing my own encode program. I have successfuly captured and encoded the image.

My own encode program uses VIDENC1_create, VIDENC1_control and VIDENC1_process API which

are the same as encode demo program.

 

Encoded image will be streamed over the network and will be decoded by Xvid.

As far as I know, Xvid requires MPEG4 VOL header. I don't know how to generate MPEG4 VOL header.

There are no example codes which generate MPEG4 VOL header.

 

My development enviroments are the followings.

1. HW board : DM355 DVEVM

2. OS : Montavista Linux 2.6.10

3. Compiler : Montavista 4.0.1 demonstration version

 

  • Our codecs primarily work with elementary streams; therefore, any additional information such as VOL headers will have to be added in software.  I believe tools such as GStreamer will do this in software.

  • Thanks for your answer.

    As far as I know, MPEG4 VOL header is 18 bytes. I don't know the format of MPEG4 VOL header. I have googling using "MPEG4 VOL header". I can not find the useful information. I have invetigated Xvid source code, but I could not the useful information about MPEG4 VOL header.

    Do you know the bitstream format of MPEG4 VOL header?

  • I think I am facing a similar problem, according to this link, http://wiki.davincidsp.com/index.php/DM355_Codecs  , the mpeg4 encoder does create VOL information in the stream, but only at the beginning.  I am trying to figure out how to send the VOL information more often so my decoder program can start in the middle of a stream.

     

    Did you have any luck creating the VOL header?

  • The MPEG-4 standard tells you the VOL/VOSS header sequence, which you can then use to populate the at the front of the bitstream - i don't have it on the top of my head, but i did use the standard to help me get MPEG-4 streaming working on the Davinci.

     

  • It's the part of my code. Please refer to the below code.

    My code has some redundant code. Be careful.

    static int generateMPEG4VolHeader( VIDENC1_Handle hEncode, char *inBuf, int inSize, char *outBuf, int *outBufSize, int *frametype, int width, int height, int framerate , int bitrate)
    {
        VIDENC1_DynamicParams   dynamicParams;
        VIDENC1_Status          encStatus;
        VIDENC1_Params          params;
        char                    *algName;
           
        IVIDEO1_BufDescIn       inBufDesc;
        XDM_BufDesc             outBufDesc;
        XDAS_Int32              outBufSizeArray[1];
        XDAS_Int32              status;
        VIDENC1_InArgs          inArgs;
        VIDENC1_OutArgs         outArgs;
       
        dynamicParams.size                = sizeof(VIDENC1_DynamicParams);
        dynamicParams.inputHeight         = height;
        dynamicParams.inputWidth          = width;
        dynamicParams.targetBitRate       = bitrate < 0 ? 0 : bitrate;
        dynamicParams.intraFrameInterval  = 10;
        dynamicParams.generateHeader      = XDM_GENERATE_HEADER;
        dynamicParams.captureWidth        = 0;
        dynamicParams.targetFrameRate = framerate * 1000;
        dynamicParams.refFrameRate    = framerate * 1000;
       

      DBG("MPEG frame rate : %d\n",framerate);
        /* Set video encoder dynamic parameters */
        encStatus.size = sizeof(VIDENC1_Status);
        encStatus.data.buf = NULL;
        status = VIDENC1_control(hEncode, XDM_SETPARAMS, &dynamicParams,
                                &encStatus);

        if (status != VIDENC1_EOK) {
            ERR("XDM_SETPARAMS failed, status=%ld\n", status);
            return FAILURE;
        }

        outBufSizeArray[0]      = D1_FRAME_SIZE;

        inBufDesc.numBufs       = 1;
        inBufDesc.frameWidth    = width;
        inBufDesc.frameHeight   = height;
        inBufDesc.bufDesc[0].bufSize = inSize;
        inBufDesc.bufDesc[0].buf = (XDAS_Int8 *)inBuf;

        outBufDesc.numBufs      = 1;
        outBufDesc.bufSizes     = outBufSizeArray;
        outBufDesc.bufs         = (XDAS_Int8 **) &outBuf;

        inArgs.size             = sizeof(VIDENC1_InArgs);
        outArgs.size            = sizeof(VIDENC1_OutArgs);

        /* Encode video buffer */
        status = VIDENC1_process(hEncode, &inBufDesc, &outBufDesc, &inArgs,
                                &outArgs);

        if (status != VIDENC1_EOK) {
            ERR("VIDENC1_process() failed with a fatal error (%ld ext: %#lx\n",
                status, outArgs.extendedError);
            return FAILURE;
        }

        *outBufSize = outArgs.bytesGenerated;

      switch(outArgs.encodedFrameType){
                    case IVIDEO_I_FRAME:
                            *frametype = 1;
                            break;
                    case IVIDEO_P_FRAME:
                            *frametype = 2;
                            break;
                    default:
                            *frametype = -1;
                            printf("Unkown frame type\n");
                            break;
            }

      dynamicParams.size                = sizeof(VIDENC1_DynamicParams);
        dynamicParams.inputHeight         = height;
        dynamicParams.inputWidth          = width;
        dynamicParams.targetBitRate       = bitrate < 0 ? 0 : bitrate;
        dynamicParams.intraFrameInterval  = 10;
        dynamicParams.generateHeader      = XDM_ENCODE_AU;
        dynamicParams.captureWidth        = 0;

        dynamicParams.targetFrameRate = framerate * 1000;
        dynamicParams.refFrameRate    = framerate * 1000;
       

      DBG("MPEG frame rate : %d\n",framerate);
        /* Set video encoder dynamic parameters */
        encStatus.size = sizeof(VIDENC1_Status);
        encStatus.data.buf = NULL;
        status = VIDENC1_control(hEncode, XDM_SETPARAMS, &dynamicParams,
                                &encStatus);

        if (status != VIDENC1_EOK) {
            ERR("XDM_SETPARAMS failed, status=%ld\n", status);
            return FAILURE;
        }
       
        return SUCCESS;
    }

  • Don't think your code's doing anything right now besides just encoding a frame - you don't have to request an XDM_GENERATE_HEADER to specifically prepare the header - as for the standards document that is relevant, please read the ISO-IEC-14496-2 spec.

    You need to add the VOSS and VO headers - just append 0xb0010000 followed by 0x00000001 and you should be fine.

    Jerry

  • I had a similar problem. Encoding to MPEG4  on DM355 EVM and UDP streaming to Win PC , and decoding with Xvid.
    Decoding worked only if i first start  program on PC and after that on DVEVM.
    DVEVM generates all necessary headers at he beggining of the first encoded frame.

    I found the following solution.

    - On the PC make a program that  waits for UDP data from DM355. After recvfrom(...) set a breakpoint
    - Then on DM355 start the encoding/streaming program
    - Then you shoud get on the PC first encoded frame from EVM, with included VOL ... headers at first 28 bytes. Copy first 28 bytes in a BYTE array variable , and also store that first frame size in a variable.
    - Then each time you start decoding program, you should first decode a dummy frame, with previously recorded VOL header at the beginning. Also specify previously recorded frame length.
       (what is the rest of the first dummy frame date doesn't matter).

    Now Xvid decoder has enough information, to decode,
    even if you strart decoding in the middle of the  DVEVM GOP sequence, it won't crash,
    yet you will still have to wait for the key frame to come.
    This header/length works only for the  resolution / bitrate it was captured for.
    If you use several resolutions / bitrates, repeate this for each of them.

  • Thanks for all the replies.  I still have to go through the spec and try to figure out what I'm looking at, but I was able to get the decoder working correctly.  My setup is basically video in -> first dm365 -> send data across network to antohter dm365 -> video out.  I was able to figure out that the decoder was looking for the header at the beginning of the file that started with 0x00000101.  For me though this header was only 18 bytes long ( i figured that out by looking for the next 0x000001 PES header?).  Anyway, so I just copied that header in the encoder and send it out every 10 frames.  That seems to make the decoder happy.  This only works for mpeg4 in my testing (not h264).  It would be really nice if they had some of the header information in with the mpeg4 encoder documentation.  Because from what I've seen so far in the ISO specs, Its going to take me a while to decode all the bytes of the header.  It doesn't even have to be in the documentation, if they could just put it up on the TI wiki pages.  But if I get it all parsed out I will try to at least post it here.

  • We are having a similar problem with the TI MPEG-4 encoder. It is very difficult to correctly mux video using this codec because you cannot (or I cannot figure out how to) output the Video Object Layer (VOL) header anywhere other than automatically just before the first frame. The VOL header should usually placed into the STSD box of an MP4 / MOV / F4V file, or the CodecPrivate field of a Matroska video track. AVI files typically just repeat the VOL header before each I-Frame as I don't think they have specified a field for them.

    A VOL header will typically start 00 00 01 20 (though 20 -> 2F are valid, last 4 bits specify layer number)

    A VOL header contains information like Aspect Ratio, Chroma Format, Bitrate, Shape, Time increment, VOP rate, Interlacing, Quantisation, etc and isn't particularly easy to rebuild outside of the codec doing the encoding.

    Here is a VOL header produced by the TI codec :

    00 00 01 20 00 84 7A 98 28 50 21 20 A3 1F

  • Hi,

    MPEG4 Encoder does have an option to generate only VOL header.

     's posting on 16-Jul-2009 has more information about that.

    In summary, if you set "dynamicParams.generateHeader      = XDM_GENERATE_HEADER"; and make process call, output buffer (after process call) will have only VOL header.

    Since this is a dynamic parameter, this can be done at run time before any frame.

    Application then need to set this parameter back to "XDM_ENCODE_AU" for complete frame encoding.

     

    Regards,

    Tej