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.

H264 decoder clips 24 lines in 1080p

Hi,

We have a problem with the h264 decoder in 1080p with the DM8148 EVM + Video conference daughter board. The last 24 lines of the video image are clipped.

We use "capture_encode" example (OMX, EZSDK 5.03.01.15) to create the h264 video file (Modified version to capture from the hdmi receiver Sii9135):

    root@dm814x-evm:/usr/share/ti/ti-omx# ./capture_encode_a8host_debug.xv5T -o test.h264 -m 1080p -f 60 -b 15000000 -n 600 -d 0

and then "decode_display" example to play back the video:

    root@dm814x-evm:/usr/share/ti/ti-omx# ./decode_display_a8host_debug.xv5T -i test.h264 -w 1920 -h 1080 -f 60 -c h264 -g 0 -d 0

The video image is 1920x1056 instead of 1920x1080. No problems with a software h264 decoder (ex: VLC on Ubuntu) to decode the same video file (test.h264). No problems in 720p.

Thanks

Stephane Rousseau

  • Hi,

    Can you see if this is display or decoder issue by displaying known images on display alone?

    Thanks,

    brijesh jadav

  • The display is ok when I run "capture_encode". So, I assume it is ok when we run "decode_display". Also, the monitor info indicates 1920x1080. So, I presume the 1920x1056 frame is stretched to 1920x1080 before to be displayed.

    Thanks

    Edit: I think the problem could also be in the scaler (OMX.TI.VPSSM3.VFPC.INDTXSCWB).

  • I found a patch to fix the bug. It is in the file "${EZSDK}/component-sources/omx-ti81xx-src_05_02_00_30/src/ti/omx/comp/vfpc/src/omx_vfpc_IndTxSC_if.c" (overlay sdk). In the beginning of the function "_OMX_VFPCIndTxSCWb_SetFVIDFrameInfo", the frame width and the frame height of the buffer are respectively clipped to 1920 and 1080. But, the buffer size is 1952x1104 and the video frame size is 1920x1080 with the origin at x = 32 and y = 24 (1920+32=1952 and 1080+24=1104). This result with a video frame of 1948x1056 with the origin at x = 32 and y = 24. Note that not only 24 bottom lines was clipped but also 32 rightmost columns of pixel.

    By removing the code that does the clipping to 1920x1080, the displayed frame is effectively 1920x1080 but...

    But now I'm facing a new problem: The 24 bottom lines are ok but the 32 rightmost columns of pixel are corrupted.

  • Stephane,

    Decoder produce o/p for 1920x1080 video in  a buffer of size 2048x1176 due to alignement and padding requirement. effective video in this o/p buffer is at x =32 and y=24 pixel offset. So in SC video is cropped to get the proper o/p. Now since VPSS handles max line width of 1920, it ends up cropping rightmost 32 pixel and cropped video is 1888 x 1080, which is scaled to 1920x1080. 

    We have not tried, but you can modify the pointers given to SC5 and get the correct o/p. Note OMX  buffer pointer and buffer headers are tied, you will have to do bookkeeping of pointers given to SC and returned pointer will need to be modifed to original pointer

    Regards

    Vimal

  • Hi Vimal,

    Thank you for answering. In the function "_OMX_VFPCIndTxSCWb_SetFVIDFrameInfo" (see my previous post), I offset the buffer pointer to startX + startY * pitch then reset startX and startY to zero and then set width and height to 1920 and 1080 respectively. This result in full garbage to the screen. But, if I offset only to startY * pitch, this is ok (but the 32 rightmost columns of pixel are still corrupted).  I think that adding 32 to the address of the buffer no longer respects the alignment constraint.

    Thanks

  • Stephane,

    You are using EZSDK 5.03 ? I assume you are using non tunneled mode of OMX. Do you have CCS connected on your board. If yes, you could check the image for one frame itself. Chroma pointer is calculated properly ? Alignment of 32 should have been sufficient. (You can also experiment with 128). Is the pitch set properly, if not you should see garbage as checkerd pattern and almost same throughout the screen.

    Regards

    Vimal

  • Vimal,

    I found the problem with the full corrupted frame: some parameters of the scaler are not set correctly (probably the pitch) when the application set the config with "OMX_TI_IndexConfigVidChResolution" in "_OMX_VFPCIndTxSCWbConfig" function even if the dynamic config parameters are set correctly ("drvState->ScWbDynamicCfg[...]"). So, when the function "_OMX_VFPCIndTxSCWb_SetFVIDFrameInfo" is called, all the dynamic config parameters are identical to the new ones computed from the buffer header. The parameter update is then skipped and the frame is totally corrupted. If we force an update of the parameters, everything works fine. Also, in the application (decode_display), If we set any parameter of the structure "OMX_CONFIG_VIDCHANNEL_RESOLUTION" with any value except the good one (ex: Frm0Pitch = 0) , everything works fine because this will force an update of the parameters (in the function "_OMX_VFPCIndTxSCWb_SetFVIDFrameInfo").

    To sum up, there is a bug with "OMX_TI_IndexConfigVidChResolution". When we workaround this bug, we can solve the other bugs (24x32 trimming and 32 columns of corruption) by offsetting the buffer address.

    Now, the question is: Are all these bugs will be fixed in the next release of OMX?

    Thanks

  • Stephane,

    Thanks for root causing the issue..Pitch should be fine, as this does not change based on offset. May be offsets are not set correctly. For summary and in order to take the changes, could you please list all the changes you did. Also are you using 5.3.15 non tunneled mode OMX version ? I will try to take the changes and try out in our set-up.

    Regards

    Vimal

  • Stephane,

    I have rectified this, and will be available in next release.

    Thanks..

    Vimal

    FYI  modified code:

    _OMX_VFPCIndTxSCWb_SetFVIDFrameInfo 
    
    
    ...
    .....

    if ( OMX_DirInput == eDir ) {

    chParams = &drvState->scConfig.chParams[chNum];
    pitch = pOmxBufHdr->nFramePitch;

    if ( pOmxBufHdr->nFrameWidth >= 1920 ) {
    width = 1920; //pOmxBufHdr->nFrameWidth;
    }
    else {
    width = pOmxBufHdr->nFrameWidth;
    }
    if ( pOmxBufHdr->nFrameHeight >= 1080 ) {
    height = 1080;
    }
    else {
    height = pOmxBufHdr->nFrameHeight;
    }

    startX = 0;
    startY = 0;

    if ( pOmxBufHdr->nFrameWidth >= 1920 ) {
    cropWidth = width - startX;
    }
    else {
    cropWidth = pOmxBufHdr->nCropWidth;
    }
    if ( pOmxBufHdr->nFrameHeight >= 1080 ) {
    cropHeight = height - startY;
    }
    else {
    cropHeight = pOmxBufHdr->nCropHeight;
    }

    OMX_BASE_ASSERT (cropWidth + startX <= width, OMX_ErrorUndefined);
    OMX_BASE_ASSERT (cropHeight + startY <= height, OMX_ErrorUndefined);



    /** Check for any dynamic video frame parameter change and enable the
    * rtparam upadte in that case */
    if ( ( pitch != drvState->ScWbDynamicCfg[chNum].nInPitch ) || (chParams->inFmt.pitch[FVID2_YUV_INT_ADDR_IDX] != pitch) ){
    drvState->ScWbDynamicCfg[chNum].nInPitch = pitch;
    if (VPS_VPDMA_MT_TILEDMEM == drvState->scConfig.chParams[chNum].inMemType)
    {
    drvState->ScWbDynamicCfg[chNum].nInPitch = VPSUTILS_TILER_CNT_8BIT_PITCH;
    }
    chParams->inFmt.pitch[FVID2_YUV_INT_ADDR_IDX] = drvState->ScWbDynamicCfg[chNum].nInPitch;
    rtParamUpdate = TRUE;
    }
    if ( width != drvState->ScWbDynamicCfg[chNum].nInWidth ) {
    drvState->ScWbDynamicCfg[chNum].nInWidth = width;
    chParams->inFmt.width = drvState->ScWbDynamicCfg[chNum].nInWidth;
    rtParamUpdate = TRUE;
    }
    if ( height != drvState->ScWbDynamicCfg[chNum].nInHeight ) {
    drvState->ScWbDynamicCfg[chNum].nInHeight = height;
    chParams->inFmt.height = drvState->ScWbDynamicCfg[chNum].nInHeight;
    rtParamUpdate = TRUE;
    }
    if ( startX != drvState->ScWbDynamicCfg[chNum].nFrmStartX ) {
    drvState->ScWbDynamicCfg[chNum].nFrmStartX = startX;
    chParams->srcCropCfg->cropStartX = drvState->ScWbDynamicCfg[chNum].nFrmStartX;
    rtParamUpdate = TRUE;
    }
    if ( startY != drvState->ScWbDynamicCfg[chNum].nFrmStartY ) {
    drvState->ScWbDynamicCfg[chNum].nFrmStartY = startY;
    chParams->srcCropCfg->cropStartY = drvState->ScWbDynamicCfg[chNum].nFrmStartY;
    rtParamUpdate = TRUE;
    }
    if ( cropWidth != drvState->ScWbDynamicCfg[chNum].nFrmCropWidth ) {
    drvState->ScWbDynamicCfg[chNum].nFrmCropWidth = cropWidth;
    chParams->srcCropCfg->cropWidth = drvState->ScWbDynamicCfg[chNum].nFrmCropWidth;
    rtParamUpdate = TRUE;
    }
    if ( cropHeight != drvState->ScWbDynamicCfg[chNum].nFrmCropHeight ) {
    drvState->ScWbDynamicCfg[chNum].nFrmCropHeight = cropHeight;
    chParams->srcCropCfg->cropHeight = drvState->ScWbDynamicCfg[chNum].nFrmCropHeight;
    rtParamUpdate = TRUE;
    }

    pFrame->addr[FVID2_FRAME_ADDR_IDX]
    [FVID2_YUV_SP_Y_ADDR_IDX] = pOmxBufHdr->pBuffer + pOmxBufHdr->nVerOffset* pitch + pOmxBufHdr->nHorOffset;

    if (pOmxBufHdr->pBuffer) {
    pFrame->addr[FVID2_FRAME_ADDR_IDX]
    [FVID2_YUV_SP_CBCR_ADDR_IDX] = pOmxBufHdr->nCBufPtr + (pOmxBufHdr->nVerOffset / 2) * pitch + pOmxBufHdr->nHorOffset;
    }
    else {
    pFrame->addr[FVID2_FRAME_ADDR_IDX]
    [FVID2_YUV_SP_CBCR_ADDR_IDX] = NULL;
    }
  • Thanks Vimal,

    your fix works fine in 1920x1080 but could be problematic in smaller resolutions (ex: 1280x720) where cropWidth/cropHeight will be smaller than width/height. This will crash when the scaler is bypassed (bAlgBypass = 1) because the source region will be larger than the destination region. Here is the fix I suggest:

    ...

     if ( OMX_DirInput == eDir ) {
    chParams = &drvState->scConfig.chParams[chNum]
     pitch = pOmxBufHdr->nFramePitch;
     width = pOmxBufHdr->nFrameWidth - pOmxBufHdr->nHorOffset;
    height = pOmxBufHdr->nFrameHeight - pOmxBufHdr->nVerOffset;
    cropWidth = pOmxBufHdr->nCropWidth;
    cropHeight = pOmxBufHdr->nCropHeight;
    startX = 0;
    startY = 0;

    #if 0
    if ( pOmxBufHdr->nFrameWidth >= 1920 ) {
    width = 1920; //pOmxBufHdr->nFrameWidth;
    }

    else {
    width = pOmxBufHdr->nFrameWidth;
    }
    if ( pOmxBufHdr->nFrameHeight >= 1080 ) {
    height = 1080;
    }
    else {
    height = pOmxBufHdr->nFrameHeight;
    }

    startX = drvState->ScWbDynamicCfg[chNum].nFrmStartX;
    startY = drvState->ScWbDynamicCfg[chNum].nFrmStartY;
    if ( pOmxBufHdr->nHorOffset != startX ) {
    /* If application programmed startX is not equal to what buffer supplier is
    specifying, reset it to what the buffer supplier says*/

    startX = pOmxBufHdr->nHorOffset;
    }
    if ( pOmxBufHdr->nVerOffset != startY ) {
    /* If application programmed startY is not equal to what buffer supplier is
    specifying, reset it to what the buffer supplier says*/
    startY = pOmxBufHdr->nVerOffset;
    }

    if ( pOmxBufHdr->nFrameWidth >= 1920 ) {
    cropWidth = width - startX;
    }
    else {
    cropWidth = pOmxBufHdr->nCropWidth;
    }
    if ( pOmxBufHdr->nFrameHeight >= 1080 ) {
    cropHeight = height - startY;
    }
    else {
    cropHeight = pOmxBufHdr->nCropHeight;
    }
    #endif
    // Same modifications for the remaining code
    ....
  • Stephane,

    Modified code was tested for 5 different resolution streams inclding 720p. Also crop height / width is always smaller than width /height. Could you please clarify issue you observe ?

    (On a sidenote though, we know cropping will not work if horizontal/vertical offsets are zero; Which we are looking into for taking from SC config)

    Regards

    Vimal

  • Vimal,

    I observe a crash in 1280x720 when the scaler is programmed in bypass mode. Here is how the bypass mode is enabled into the OMX example "decode_display" in the file "ilclient_utils.c":

    OMX_ERRORTYPE IL_ClientSetScalarParams (IL_Client *pAppData)

    {

       OMX_CONFIG_ALG_ENABLE algEnable;

    ...

       /* disable algo bypass mode */

     OMX_INIT_PARAM (&algEnable);
    algEnable.nPortIndex = 0;
    algEnable.nChId = 0;
    // algEnable.bAlgBypass = 0;
    algEnable.bAlgBypass = 1;

    eError =
    OMX_SetConfig (pAppData->pScHandle,
    (OMX_INDEXTYPE) OMX_TI_IndexConfigAlgEnable, &algEnable);
    ...

    }

    Thanks

  • Stephane,

     For algBypass input width/height should be same as output width/height, which is not true for the decoder o/p buffer format ( as in the code it was done as cropping). Most likely you see assertion from driver for width/height not matching. Please see OMX_DIO_NonTunnel_FillCustomHeader in the omxbase code, where width , height was set as added with offsets. You can  remove the offsets in width, height calculation. Since NOW offsets are added in address. width, height can be same as crop height /width in buffer header. So in effect no cropping is done for decoder o/p.  for 1920 because of clipping in the code, it works without this change. I have tested both bypass / no bypass mode with the change and it works for different resolutions. 

    btw, your intention for bypass is disabling 1:1 scaling ?

    Regards

    Vimal

  • Vimal,

    my intention is to disable the filtering when the scaling is 1:1 because it is very important for us to have a sharp image.

    thanks

  • Stephane,

    I and my colleagues are working DM8148 video interfaces. We experiencing some problems similar to the ones you described in your posts.

    I'd like to ask you some questions:

    1) you mentioned a "Video conference daughter board". I googled around to find more information about it but I could not find anything. Could you tell me where you purchased it?

    2) In the "overlay sdk" we did not find sources of the firmware of the Cortex-M3 managing HDVICP2 codec. Did you? We'd like to put the hands on this firmware in order to verify how the codec parameters - set at IL client level - are passed to the HDVICP2 hardware module. We suspect that several parameters are ignored. For more details please see http://e2e.ti.com/support/dsp/davinci_digital_media_processors/f/716/t/181568.aspx

    Thanks in advance and regards.

  • Hi llandre,

    1) As the video conference daughter board has an HDMI input, it can be purchased only if you have some HDCP certification (High Definition Copy Protection). Ask your TI representative for more details.

    2) I do not have the driver source code of the codec and I think TI will never make it available.

  • Hi Stephane,

    thanks a lot for your feedback.

    What do you think about encoder settings? Did you experience the same problem?

  • llandre said:

    What do you think about encoder settings? Did you experience the same problem?

    Yes, I had many problems to make this work. So far, i use only those following OMX parameters that seems to work correctly with the DM814x (I suspect that this is different with the DM816x):

    OMX_TI_IndexParamVideoEncoderPreset 

    OMX_IndexParamVideoAvc

    OMX_TI_IndexConfigVideoDynamicParams

    And no, OMX_TI_IndexParamVideoStaticParams parameter has no effect (at least with the DM814x).

  • Thanks a lot for sharing your experience that confirms what we see.

    We need to encode a 1080p60 video stream in real-time keeping frame drop rate as low as possible. For this reason we are trying to play with encoder settings in order to reduce frame drop rate at the expense of other things (for example latency). However we don't clearly understand which parameters are actually supported and which not. It seems OMX_IndexParamVideoBitrate is passed to encoder while the others are completely ignored. By the chance, have you ever performed specific tests about frame drop rate in encoding?