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.

At DM365, use h264 encoder, After force IDR frame, no I frame output.

Hi,

For corrent display encoded H264 frame, I alway output a IDR frame, after i change intra frame interval.  But if interval change is far,  after IDR frame output, it will have't I frame ouput. for example I change interval value from 30 to 2.

my program is:

...

H264VENC_DynamicParams     h264DynParams;

...

h264DynParams.videncDynamicParams.forceFrame = IVIDEO_IDR_FRAME;

h264DynParams.videncDynamicParams.targetBitRate     = gm_stEncParams[iChannel][i].uiTargetBitRate*1000;
h264DynParams.videncDynamicParams.inputWidth        = gm_stEncParams[iChannel][i].uiWidth; 
h264DynParams.videncDynamicParams.inputHeight       = gm_stEncParams[iChannel][i].uiHeight;
h264DynParams.videncDynamicParams.refFrameRate      = gm_stEncParams[iChannel][i].uiFps*1000;
h264DynParams.videncDynamicParams.targetFrameRate   = gm_stEncParams[iChannel][i].uiFps*1000;
h264DynParams.videncDynamicParams.interFrameInterval  = 1;
h264DynParams.videncDynamicParams.intraFrameInterval  = gm_stEncParams[iChannel][i].uiGop;

Venc1_control(hVe1[i], (VIDENC1_DynamicParams *)&h264DynParams );

expect your reply,

  • This works for me....  I use zero for interFrameIntrframe and intraFrameInterval as I don't have B frames.


            if ((frame % 30) == 0)
            {
              /* Set video encoder dynamic parameters */
              encStatus.size = sizeof(VIDENC1_Status);
              encStatus.data.buf = NULL;
              dynParams->videncDynamicParams.forceFrame = IVIDEO_IDR_FRAME;
              Xstatus = VIDENC1_control(hEncode, XDM_SETPARAMS, (VIDENC1_DynamicParams*)dynParams, &encStatus);

              if (Xstatus != VIDENC1_EOK) {
                  //Dmai_err1("XDM_SETPARAMS failed, status=%d\n", status);
                  ERR("XDM_SETPARAMS failed\n");
                  cleanup(THREAD_FAILURE);
              }
            }

            /* Decode the video buffer */
            if (Venc1_process(hVe1, hCapBuf, hDstBuf) < 0) {
                ERR("Failed to encode video buffer\n");
                cleanup(THREAD_FAILURE);
            }

            if ((frame % 30) == 0)
            {
              /* Set video encoder dynamic parameters */
              encStatus.size = sizeof(VIDENC1_Status);
              encStatus.data.buf = NULL;
              dynParams->videncDynamicParams.forceFrame = IVIDEO_NA_FRAME; // IVIDEO_P_FRAME
              Xstatus = VIDENC1_control(hEncode, XDM_SETPARAMS, (VIDENC1_DynamicParams*)dynParams, &encStatus);

              if (Xstatus != VIDENC1_EOK) {
                  //Dmai_err1("XDM_SETPARAMS failed, status=%d\n", status);
                  ERR("XDM_SETPARAMS failed\n");
                  cleanup(THREAD_FAILURE);
              }
            }
            frame++;

    John A

  • Hi, John

        Thank you! I has upate h264 codec lib to v2.0 to solve my problem. So far, it work well.

        I read your code, it out a IDR frame ervey 30 frame. I want Dynamic Intra/IDR frame interval change. I has prove previously h264 codec version is some issues for this situation.

    Best Reagards

    tanyu

  • There was some problem with dynamic IDR update. It did not work in some cases. It got fixed in ver 2.0.

    regards

    Yashwant

  • John/(anyone),

       Background:  Similar to Tanyu in the post to which to replied above, I need to force the H.264 encoder to encode every 30th video frame as an IDR frame.  I have written a streaming server that is based on the TI's encode demo code but am having a problem updating the codec's dynamic parameters once the codec is created and processing captured frame since, as you know, there is no "Venc1_control()" function from which the dynamic parameter "forceFrame = IVIDEO_IDR_FRAME" can be passed.  FYI: my system is an EVM365 running the latest release of DVSDK 4.00 (i.e., version 2.x codecs, etc.) with everything standard per the TI software developer's guide and everything else works just fine (so far).

       Questions: 1. Can you tell me which version DVSDK of you were using for the above code?  When I compile my code, the compiler complains that 'VIDENC_DynamicParams' has no member named 'videncDynamicParams' (see code snippet below).  2. Could the VIDENC1_control() function have been deprecated in the newer version DVSDK?  3. I'm confused about how to call VIDENC1_control(): how do you get the handle "hEncode" i.e., do I have to call VIDENC1_create() to get the handle or just cast "hVe1" obtained from calling the Venc1_create() function earlier in the code (since it should be referencing the same codec object)?

    ......

    // Force an IDR frame here

            if ((frameCnt % 30) == 0) {

               dynParams->videncDynamicParams.forceFrame = IVIDEO_IDR_FRAME;

            VIDENC1_control(hEncode, XDM_SETPARAMS, (VIDENC1_DynamicParams*) dynParams, &encStatus);

            }

    ......

     

    Thanks,

    --Chuck

  • Chuck@Cimarron Systems said:

    John/(anyone),

       Questions: 1. Can you tell me which version DVSDK of you were using for the above code?

    4_00_00_22

     

    Chuck@Cimarron Systems said:
    When I compile my code, the compiler complains that 'VIDENC_DynamicParams' has no member named 'videncDynamicParams' (see code snippet below).
    You need to use the codec specific IH264VENC_DynamicParams instead.

    Chuck@Cimarron Systems said:
    2. Could the VIDENC1_control() function have been deprecated in the newer version DVSDK?  3. I'm confused about how to call VIDENC1_control(): how do you get the handle "hEncode" i.e., do I have to call VIDENC1_create() to get the handle or just cast "hVe1" obtained from calling the Venc1_create() function earlier in the code (since it should be referencing the same codec object)?

    It's there, you need to make the following call to get the handle..

        hEncode = Venc1_getVisaHandle(hVe1);

    John A

     

     

  • John,

    Your answers make perfect sense and clarify the issues for me.

    Thank you very much,

    --Chuck

  • In case periodic IDR frame is needed, it is better to use IH264VENC_DynamicParams->idrFrameInterval.

    regards

    yashwant

  • Yashwant,

       Thank you very much for you clarifying reply.

    --Chuck

  • Chuck,

    Glad to help. The suggestion to use idrFrameInterval may be better.  But I implemented this long ago and it's been working.  Here's a link to the thread where this was originally discussed.  It has some important info regarding SPS/PPS.  I don't know if the current SDK supports automatically inserting the SPS/PPS for each IDR frame.

    http://e2e.ti.com/support/dsp/davinci_digital_media_processors/f/100/p/7826/31428.aspx?PageIndex=1

    John A

  • John,

    Thank you for the additional information at the link you included: I believe that I will try Yashwant's suggested method for forcing an IDR frame first.  And yes, as described on this page http://processors.wiki.ti.com/index.php/DM365_Codecs_FAQ SPS and PPS headers are generated using this method described in the text below (although I don't know if this is still the best method):

    How to generate SPS and PPS headers in H.264 encoder?

    It can be done using generateHeader parameter of dynamicParams.

    Set the following:

    1. SET dynamicParams.generateHeader = XDM_GENERATE_HEADER;

    2. Call VIDENC1_control() for XDM_SETPARAMS. This will set header generation mode

    3. Call VIDENC1_process(). This will generate SPS and PPS. No frame data will be encoded

    4. SET dynamicParams.forceFrame = XDM_ENCODE_AU;

    5. Call VIDENC1_control() for XDM_SETPARAMS. This will set the original parameters for encoding.

    6. Call VIDENC1_process(). This will resume normal encoding

    Thanks again,

    --Chuck

     

  • Chuck,

    Thanks for the additional info on the SPS/PPS.  At the time I first implemented my code I think the encoder was "broke" in the sense that it couldn't generate periodic SPS/PPS info, and only sent it out at the beginning.  Since I have so many fish to fry, once I got my implementation working (manual insertion every IDR) I never revisited it again.

    John A

  • John,

    Perfectly understandable - if it's not broken, just leave it alone...

    --Chuck

  •  Questions: 1. Can you tell me which version DVSDK of you were using for the above code?

    dvsdk_2_10_01_18

    I fixed my problem just throught instead of codec lib from 1.0 to 2.0, not change dvsdk version. Here is codec lib 2.0 address:

    http://processors.wiki.ti.com/index.php/H.264_DM36x_Ver_2.0_Codec#Will_the_ver_2.0_codecs_run_on_DM365_or_it_can_run_only_on_DM368.3F

    2. Could the VIDENC1_control() function have been deprecated in the newer version DVSDK?  3. I'm confused about how to call VIDENC1_control(): how do you get the handle "hEncode" i.e., do I have to call VIDENC1_create() to get the handle or just cast "hVe1" obtained from calling the Venc1_create() function earlier in the code (since it should be referencing the same codec object)?

    At my program, i create struct

    typedef struct Venc1_Object {
        VIDENC1_Handle          hEncode;
        IVIDEO1_BufDesc         reconBufs;
        Int32                   minNumInBufs;
        Int32                   minInBufSize[XDM_MAX_IO_BUFFERS];
        Int32                   minNumOutBufs;
        Int32                   minOutBufSize[XDM_MAX_IO_BUFFERS];
        BufTab_Handle           hInBufTab;
        Buffer_Handle           hFreeBuf;
        VIDENC1_DynamicParams   dynParams;
    } Venc1_Object;

    This same with dmai_1_21_00_10's definition( Venc1.c ).

    Usage is:

    VIDENC1_control( ((Venc1_Object*)hVe1[i])->hEncode, ..., ..., ..);

    Best Regards

    Tanyu

  • Tanyu,

    Thank you this is also very helpful...

    Thanks again,

    --Chuck

  • hi :

    thanks for your code.

    I using your code to force generate IDR frame, but i got -1, that means the "Xstatus" value is -1. and very interesting, i did got the IDR frame.

    so, why i got IDR frame but "XDM_SETPARAMS" failed ??? and what is the side effect??

    thanks a lots!!!

    Sincerely

    Antony

  • Antony,

    If I understand your question, you are saying that when you call VIDENC1_control()  like this:

         Xstatus = VIDENC1_control(hEncode, XDM_SETPARAMS, (VIDENC1_DynamicParams*)dynParams, &encStatus);

    Xstatus= -1 but you do see that the IDR frame rate is set to the correct new value?

    Without seeing your code, I suspect that either one or more of your other dynParams are set to improper values are perhaps you do not have encStatus initialized properly.

    Can you show us your code?

    -Chuck

  • Hi,

    Yes, you are right! This code should is:

    ...

     VIDENC1_Status          encStatus;

    /* Set video encoder dynamic parameters */
    encStatus.size = sizeof(VIDENC1_Status);
    encStatus.data.buf = NULL;

    Xstatus = VIDENC1_control(hEncode, XDM_SETPARAMS, (VIDENC1_DynamicParams*)dynParams, &encStatus);

    ...

    Hope this code segment is useful for you!

    Best Regards

    TanYu

  • Hi : Chuck:

    thanks for your reply!!!

    here is my code :

    {
     Venc1_Handle hVenc1 = (Venc1_Handle)hVenc;
     VIDENC1_Status  encStatus;
      XDAS_Int32      xStatus;
      VIDENC1_Handle  hEncode = Venc1_getVisaHandle(hVenc1);

     VIDENC1_DynamicParams dynParams = Venc1_DynamicParams_DEFAULT;

     //Set video encoder dynamic parameters
      encStatus.size = sizeof(VIDENC1_Status);
      encStatus.data.buf = NULL;

     dynParams.interFrameInterval = 0;
      dynParams.forceFrame = IVIDEO_IDR_FRAME;

      xStatus = VIDENC1_control(hEncode, XDM_SETPARAMS, &dynParams, &encStatus);

      if(xStatus != VIDENC1_EOK)
     {
       printf("force IDR frame failed, xStatus:%d!\n", (int)xStatus);
     }
    }

    I got  xStatus = -1, that's means xStatus != VIDENC1_EOK, but after Venc1_process(),  i did got the frame type is 3 , that's mean IDR frame.

    so, i got confuse!!!

    I need the IDR frame, because I want to split my video file,  like very 1 minutes saving a file, and each file, just as you known,  the first frame should be IDR frame.

    actually, i have done it, and it did work, but I always got "xStatus != VIDENC1_EOK", and I am worry that maybe goes something wrong after a long time recording!!!

    do you have any idea, or suggestions???

    thanks a lot!!!

    Sincerely

    Antony

     

  • Hi, Antony

    Have you setting parameter as below?

    ...

    h264DynParams = H264VENC_TI_IH264VENC_DYNAMICPARAMS;
    h264DynParams.videncDynamicParams = Venc1_DynamicParams_DEFAULT;

    ...

    h264DynParams.videncDynamicParams.size = sizeof(H264VENC_DynamicParams);

    ...

    H264VENC_DynamicParams is defined at ih264venc.h, this file can be find in codec. Sure you need put it at your project.

    Regards

    TanYu

     

     

     

  • Antony,

    Your code looks correct to me: the only other thing I can think of is that you may have a dynamic parameter with a wrong value or, perhaps, that is missing.  Also, as Tanyu says, you should make sure that you have the size of the dynamic parameters are set correctly.  This is how I set the size:

            dynParams.size = sizeof(IH264VENC_DynamicParams);

    As Tanyu says, you can find the definition of the extended dynamic parameters in ../ti/sdo/dmai/ce/ih264venc.h 

    I hope this helps,

    -Chuck

  • Hi TanYu:

    thanks for your reply!!!

    no, i am using DMAI API for my program, and i don't know how to set it in DMAI API. could you give me some codes to teach me???

    And i believe that setting idrFrameInterval's value in IVIDENC1_DynamicParams structure is the better way, but i still dont know how to set it using DMAI API?

    i am so appreciate if you can give me some hints!!!

    Sincerely

    Antony

  • Hi Antony

    H264VENC_DynamicParams h264DynParams];

    h264DynParams = H264VENC_TI_IH264VENC_DYNAMICPARAMS;
    h264DynParams.videncDynamicParams = Venc1_DynamicParams_DEFAULT;

     h264DynParams.videncDynamicParams.size = sizeof(H264VENC_DynamicParams);

    ...//previously posted code

         h264DynParams.idrFrameInterval = //you need idr-frame gap
         
         Venc1_control(hVe1[i], (VIDENC1_DynamicParams *)&h264DynParams);
         

    other is previously posted code, As chunk say, you need I264venc.h file.

    Hope that helps!

    regadrs

    TanYu

  • Chuck : i add the code into my program, but i still got the same result, xStatus = -1!!! >_
  • TanYu : thanks for your code, but where i can find Venc1_control() this function??? and "H264VENC_DynamicParams" this should be "IH264VENC_DynamicParams" right??? Sincerely Antony
  • TanYu : i tried your code already, and it did works!!! thanks very much!!! i have another problem, could you help me : i got the "CMEM error : failed to find a pool which fits 518400", what's wrong??? and what should i do??? thanks a lot!!! Sincerely Antony
  • Hi, Antony

    You need to modify cmem's memory layout, when insmod cmem.ko.  For example, change your loadmodules.sh file:

    insmod /opt/driver/cmemk.ko phys_start=0x85000000 phys_end=0x88000000 pools=1x518400, ... allowOverlap=1 phys_start_1=0x00001000 phys_end_1=0x00008000 pools_1=1x28672

    Regards

    TanYu

  • Antony,

    It's good to know that, with TanYu's help, you were able to get your code working.  

    As a side note, I no longer use: extDynamicParams.videncDynamicParams.forceFrame = IVIDEO_IDR_FRAME; to force an IDR frame because I don't require the IDR frame interval to change in a dynamic fashion.  As Yashwant Dutt recommends earlier in this thread, I just set the IDR frame interval before I create the H.264 Encode as follows:

             extDynamicParams.idrFrameInterval = 30;            /* idrFrameInterval: IDR frame interval */ 

    In any case, here's the code for setting the IDR frame interval dynamically that I used previously (I hope my cut/paste is readable):

    #include <ti/sdo/dmai/ce/ih264venc.h>

    /* Codec Engine, video buffer, and video processing parameters are defined here */

        Engine_Handle           hEngine             = NULL;

        Venc1_Handle            hVe1                = NULL;

        ... (other code here omitted for clarity)

        /* VIDENC1 arguments and parameters are defined here */

        IH264VENC_Params extParams;

        IH264VENC_DynamicParams extDynamicParams;

        VIDENC1_Params params = Venc1_Params_DEFAULT;

        VIDENC1_DynamicParams dynParams = Venc1_DynamicParams_DEFAULT;

        VIDENC1_Handle hEncoder = NULL;       /* Handle for control call */

        VIDENC1_Status encStatus;                        /* Stores the status of control call */

        XDAS_Int32 errorCode;                                /* Error Code */

        ... (other code here omitted for clarity)

       /* Update dynParams for IDR Frame */

       if ((frameCount != 0) && ((frameCount % 60) == 0)) {

       hEncoder = Venc1_getVisaHandle(hVe1);

       encStatus.size = sizeof(VIDENC1_Status);

       encStatus.data.buf = NULL;

       extDynamicParams.videncDynamicParams.forceFrame = IVIDEO_IDR_FRAME;

       errorCode = VIDENC1_control(hEncoder, XDM_SETPARAMS, (VIDENC1_DynamicParams *)&extDynamicParams, &encStatus);

       if (errorCode < 0) {

           ERR("Failed to update frame type to IVIDEO_IDR_FRAME\n");

           cleanup(THREAD_FAILURE);

        }

        /* Encode the video buffer using modified Venc1_process() function */

        if (Venc1_process(hVe1, hCapBuf, hDstBuf, frameCount) < 0) {

            ERR("Failed to encode video buffer\n");

            cleanup(THREAD_FAILURE);

        }  

        /* Update dynParams back to Standard Frame */

        if ((frameCount != 0) && ((frameCount % 60) == 0)) {

        hEncoder= Venc1_getVisaHandle(hVe1);

        encStatus.size = sizeof(VIDENC1_Status);

        encStatus.data.buf = NULL;

        extDynamicParams.videncDynamicParams.forceFrame = IVIDEO_NA_FRAME;

        errorCode = VIDENC1_control(hEncoder, XDM_SETPARAMS, (VIDENC1_DynamicParams *)&extDynamicParams, &encStatus); 

        if (errorCode < 0) {

            ERR("Failed to update frame type to IVIDEO_NA_FRAME\n");

            cleanup(THREAD_FAILURE);

        }

    }

    Note that I have modified the DMAI Venc1_process() function to accept a frameCount for purposes of inserting the timeStamp via extended inArgs but other than that everything else is standard.

    So that others can benefit from your experience, could you please post the part of your code that changes the IDR frame interval dynamically?  Also, it's always interesting to see how others solve the same problem.

    Thanks,

    -Chuck

  • Chuck :

    thanks!!!

    i give up forcing an IDR frame, in my intuition, this way is risky!!!

    so, with TanYu's great jelp, now i setting the idrFrameInterval, here is my code:

    //encode : "mpeg4enc" "h264enc"
    void *dapi_video_encode_open(void *engine, char *encName, int width, int height, int frate, int brate)
    {
     Engine_Handle hEngine = (Engine_Handle)engine;
      Venc1_Handle hVenc1 = NULL;

     VIDENC1_Params params = Venc1_Params_DEFAULT;
     VIDENC1_DynamicParams dynParams = Venc1_DynamicParams_DEFAULT;
     
      //Set up encode parameters
      params.maxWidth  = width;
      params.maxHeight = height;
      params.encodingPreset = XDM_HIGH_SPEED;

     //Set up encode parameters depending on device
     //Determine which device the application is running on
     Cpu_Device  device;

      if(Cpu_getDevice(NULL, &device) < 0)
     {
         printf("Failed to determine target board!\n");
         return NULL;
      }

      switch(device)
     {
         case Cpu_Device_DM6467:
           printf("This is a DM6467 device!\n");
              break;

         case Cpu_Device_DM355:
              params.inputChromaFormat = XDM_YUV_422ILE;
              params.reconChromaFormat = XDM_YUV_420P;
          printf("This is a DM355 device!\n");
              break;           

         case Cpu_Device_DM365:
              params.inputChromaFormat = XDM_YUV_420SP;
              params.reconChromaFormat = XDM_YUV_420SP;
          printf("This is a DM365 device!\n");
              break;

         default:
              params.inputChromaFormat = XDM_YUV_422ILE;
          printf("This is a DMxxx device!\n");
              break;
      }

      params.maxFrameRate = frate * 1000;//NTSC:30000, PAL:25000

      //Set up encode parameters depending on bit rate
      if(brate < 0)
     {
         //Variable bit rate
         params.rateControlPreset = IVIDEO_NONE;

         //If variable bit rate use a bogus bit rate value (> 0)
         //since it will be ignored.
         params.maxBitRate = 0;
      }
      else
     {
         //Constant bit rate
         params.rateControlPreset = IVIDEO_STORAGE;
         params.maxBitRate = brate;
      }

      dynParams.targetBitRate = params.maxBitRate;
      dynParams.inputWidth    = params.maxWidth;
      dynParams.inputHeight   = params.maxHeight;   
      dynParams.refFrameRate  = params.maxFrameRate;
      dynParams.targetFrameRate = params.maxFrameRate;
      dynParams.interFrameInterval = 0;
     dynParams.forceFrame = IVIDEO_NA_FRAME;
     
      hVenc1 = Venc1_create(hEngine, encName, &params, &dynParams);

      if(hVenc1 == NULL)
     {
         fprintf(stderr, "Error: can't open %s encoder!\n", encName);
         return NULL;
      }

     //set IDR frame every 1 second----------------------------------------
     IH264VENC_DynamicParams h264DynParams;
      h264DynParams = H264VENC_TI_IH264VENC_DYNAMICPARAMS;

      h264DynParams.videncDynamicParams = dynParams;
      h264DynParams.videncDynamicParams.size = sizeof(IH264VENC_DynamicParams);
      h264DynParams.idrFrameInterval = 30;

     VIDENC1_Handle hEncode = Venc1_getVisaHandle(hVenc1);
     VIDENC1_Status encStatus;
      XDAS_Int32 xStatus;

      encStatus.size = sizeof(VIDENC1_Status);
      encStatus.data.buf = NULL;

      xStatus = VIDENC1_control(hEncode, XDM_SETPARAMS, (VIDENC1_DynamicParams *)&h264DynParams, &encStatus);

      if(xStatus != VIDENC1_EOK)
       printf("set IDR frame interval failed, xStatus:%d!\n", (int)xStatus);
     //---------------------------------------------------------------------

     return hVenc1;
    }

    thanks TanYu again!!!

    Sincerely

    Antony

  • Antony,

    Excellent!  I'm happy that everything is working for you...

    Take care,

    -Chuck

  • TanYu :

    thanks for your help again!!

    may i ask you, what is the "pools" mean ???

    in loadmodules.sh :

    pools=6x4096,2x8192,1x11908,2x13184,1x2697152,6x4096,1x30720,3x81920,1x3185664,64x56,1x320,1x640,1x81920,1x6650880,2x608,1x296,1x28,2x24,23x1548288,1x154288

    and the digitals are stand for what???

    thanks a lot!!!

    Sincerely

    Antony

     

  • Him Antony,

    May be is useful for you, below link .

    http://processors.wiki.ti.com/index.php/CMEM_Overview

    cmem is reserved continued memory space, that used by framework component, codec etc.., pools is for bulk continue memory, digitals is for small continue memory in bulk.

    Regards

    TanYu

  • TanYu :

    i change the pools blocks:

    23x1548288 ==> 4x1548288

    and add 56x518400

    then the "CMEM Error : cannot get a pool which fits 518400" is solved!!!

    thanks again!!!

    Sincerely

    Antony

  • Antony,

    Congratulations to you and TanYu!!!

    Regards,

    -Chuck