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 add new data available callback function to DecLink?

Hi,

In mcfw the CapLink and EncLink have new data available callback function. Now I want to get the Decode output data on ARM side. So I need this callback function to tell the main process periodically gets the output data. I read the EncLink codes but could not find how it  releases the callback. Could someone help me to add this callback function to DecLink?

Thanks in advance!

  • If you want decoder output on ARM connect DecLink -> ipcFramesOutRTOS (Video M3) -> ipcFramesInHLOS (VPSS M3). ipcFramesInHLOS supports application registered callback invocation when new frame is available. THis has nothing to do with DecLink code.

  • Hi Badri,

    Thanks for your reply! I refer to multich_vcap_venc_vdis.c and do as you said above. Connect DecLink->ipcFramesOutRTOS(video)->ipcFramesInHLOS(arm). In multich_vcap_venc_vdis.c it registered callback function as below:

    ipcFramesInHostPrm.cbCtx = &gVcapModuleContext;
    ipcFramesInHostPrm.cbFxn = Vcap_ipcFramesInCbFxn;

    The Vcap_ipcFramesInCbFxn function defined in ti_vcap.c. It finally refers to VCAP_CALLBACK_S struct. As there is no VDEC_CALLBACK_S struct, I don't know how to register callback functions.

  • Hi Badri,

    I go through the ti_venc.h and ti_venc.c again and add newdata available callback function to DecLink. I could  assign callback function which will be called when the DecLink has new output data. Now the problem is I write the decode output yuv data to a yuv file, the picture is not right. As the decode output format is 420SP(NV12), the output frame size should be calculate as 

    pBuf->frameWidth * pBuf->frameHeight * 1.5

    I use the same codes in demo_vcap_venc_vdis_ipc_frames_exch.c to convert the pBuf->phyAddr[0][0] to pMemVirtAddr and just call fwrite to write the data to yuv file. I don't know what's wrong with it.

  • You should not just multiply use width x height x 1.5. You are supposed to use the separate pointers for luma and chroma.Try decoding a solid color pattern like black frame so that it is easy to debug the YUV file to know whether youa re getting luma and chroma data correctly

  • Hi Badri,

    I try to write the luma and chroma seperately as below, but the result is just the same.

    pMemVirtAddr = 0;
    frameSize = pBuf->frameWidth * pBuf->frameHeight;
    VdecVenc_mMap((UInt32)(pBuf->phyAddr[0][0]), frameSize, &pMemVirtAddr);
    writeDataSize = fwrite((Ptr) pMemVirtAddr, 1, frameSize, gVdecVenc_ctrl.fp);

    pMemVirtAddr = 0;
    frameSize = pBuf->frameWidth * pBuf->frameHeight * 0.5;
    VdecVenc_mMap((UInt32)(pBuf->phyAddr[0][1]), frameSize, &pMemVirtAddr);
    writeDataSize = fwrite((Ptr) pMemVirtAddr, 1, frameSize, gVdecVenc_ctrl.fp);

    I also try to set the ipcFramesInHostPrm.exportOnlyPhyAddr = FALSE and use the pBuf->Addr[0][0]. But I get the following error:

    ASSERT (ipcFramesInLink_tsk.c|IpcFramesInLink_setVirtBufAddr|691)

    I check it and find the pitch used in IpcFramesInLink_memFrameGetSize function is 512 for pitch[0] and pitch[1]. I wonder if this is not right because I could not set the pitch value in program. If I change the width and height of the video the pitch should not be the same for all resolution.

    I will use the black video to do further test.

  • Hi Badri,

    I use black video to test. I open the yuv file and the following is the picture. 

    It seems the buffer addr used to write is not right. Do you know what's the problem?

  • What API are you using to get the video Frames on A8 ? The image looks like you are trying to open YUV420 file in some other format.

    Can you mention width,height pitch of the frame received on A8 and attach the YUV file.

  • Hi Badri,

    I use the following codes to get video frames on A8:

    Vcap_getFullVideoFrames(&bufList,0);

    yuv file write function;

    Vcap_putEmptyVideoFrames(&bufList);

    Set gVcapModuleContext.ipcFramesInHostId = SYSTEM_HOST_LINK_ID_IPC_FRAMES_IN_0.

    The pBuf->frameWidth and pBuf->frameHeight are 320 and 240. The pBuf->framePitch[0] and pBuf->framePitch[1] are 512 and 512. The yuv file is attached in the end.

    0310.VDEC_CH0.zip

  • You should use framePitch[0]/framePitch[1] x height to mmp and copy both luma and chroma and then set display width, height to 320 x 240.

  • Ok, I will have a try and let you know the result.

  • Does your YUV viewer support YUV 420 SP format viewing ?

  • Hi Badri,

    I do as you said but the yuv file seems to be the same. The following are the codes:

    UInt32 pMemVirtAddr;

    pMemVirtAddr = 0;
    frameSize = 320*240;
    VdecVenc_mMap((UInt32)(pBuf->phyAddr[0][0]), pBuf->framePitch[0] * pBuf->frameHeight, &pMemVirtAddr);
    writeDataSize = fwrite((Ptr) pMemVirtAddr, 1, frameSize, gVdecVenc_ctrl.fp);

    pMemVirtAddr = 0;
    frameSize = 320*240*0.5;
    VdecVenc_mMap((UInt32)(pBuf->phyAddr[0][1]), pBuf->framePitch[1] * pBuf->frameHeight * 0.5, &pMemVirtAddr);
    writeDataSize = fwrite((Ptr) pMemVirtAddr, 1, frameSize, gVdecVenc_ctrl.fp);

    I aslo set the frameSize to pBuf->framePitch[0] * pBuf->frameHeight and pBuf->framePitch[1] * pBuf->frameHeight * 0.5. The yuv file looks like the same as before.

  • Yes,  I use 7yuv and it supports 420SP format. I check the pMemVirtAddr converted from pBuf->phyAddr[0][0] and find the buffer size of pBuf is 294912 = 512*576. Why is 576?

  • You should only use pitch x height. Use of any other value for frameSize is wrong.

    Code should be

     pMemVirtAddr = 0;
     frameSize = pBuf->framePitch[0] * pBuf->frameHeight; 
     OSA_mmap((UInt32)(pBuf->phyAddr[0][0]),frameSize , &pMemVirtAddr); 
     writeDataSize = fwrite((Ptr) pMemVirtAddr, 1, frameSize, gVdecVenc_ctrl.fp);
    

     pMemVirtAddr = 0;
     frameSize = pBuf->framePitch[1] * pBuf->frameHeight; ; 
     OSA_mmap((UInt32)(pBuf->phyAddr[0][1]), frameSize, &pMemVirtAddr); 
     writeDataSize = fwrite((Ptr) pMemVirtAddr, 1, frameSize, gVdecVenc_ctrl.fp);

    I opened the YUV file you shard in a YUV viewer that _does_not_ support 420SP and it looks the same as the image you shared so confirm you are really configuring your YUV viewer for 420SP display.

    The pitch for the YUV frame looks to 512 which is correct.

    The height in the image looks wrong. Print the pitch and confirm it is 512.

    The decoder output will  have startX startY and displayed image should crop the startX, startY.


     

     

  • Hi Badri,

    For 420SP format, the size of chroma should be half of luma. So the frameSize for pBuf->phyAddr[0][1] should be frameSize = pBuf->framePitch[1] * pBuf->frameHeight *0.5. Is that right?

    The YUV viewer I used does support 420SP format. You could download it from here.

    http://www.softpedia.com/get/Multimedia/Graphic/Graphic-Others/7yuv.shtml

  • Hi Badri,

    The pBuf->framewidth =320 pBuf->frameheight =240 pBuf->pitch[0]=pBuf->pitch[1]=512

    The OSA_mapMem print out mmapMemSize is 126976=512x248

    The output yuv file is just as before. I don't know if there is something wrong with the decode param. The following is the params of decode link.

    decPrm.chCreateParams[i].format = IVIDEO_H264HP;
    decPrm.chCreateParams[i].profile = IH264VDEC_PROFILE_ANY;
    decPrm.chCreateParams[i].processCallLevel = VDEC_FRAMELEVELPROCESSCALL;
    decPrm.chCreateParams[i].dpbBufSizeInFrames = IH264VDEC_DPB_NUMFRAMES_AUTO;
    decPrm.chCreateParams[i].targetMaxWidth = ipcBitsOutHostPrm.inQueInfo.chInfo[i].width;
    decPrm.chCreateParams[i].targetMaxHeight = ipcBitsOutHostPrm.inQueInfo.chInfo[i].height;
    decPrm.chCreateParams[i].numBufPerCh = 6;
    decPrm.chCreateParams[i].defaultDynamicParams.targetFrameRate =
    gVdecModuleContext.vdecConfig.decChannelParams[i].dynamicParam.frameRate;
    decPrm.chCreateParams[i].defaultDynamicParams.targetBitRate =
    gVdecModuleContext.vdecConfig.decChannelParams[i].dynamicParam.targetBitRate;
    decPrm.chCreateParams[i].tilerEnable = FALSE;

    8080.VDEC_CH0 (2).zip

  •  

    I see valid black frame for the first frame. Can you compare the same settings and check at your end

  • It is the same as on my end. But I don't think it is right. The chroma is not right. I encode the output yuv file using x264. The encoded h264 file is not right.

     

     

  • The file attached is a correct 420SP yuv file. You could open it in 7yuv and check.

    4276.320x240_420SP.zip

  • Is this the decoder output or your input file ? I don't see any issues with the file.

  • This is the input file to test  fileread->encode->filewrite

  • Hi Badri,

    For the fileread->decode->filewrite usecase, I still could not get the correct 420SP yuv file. I think the decoder output should be right. There must be something wrong with the address to read data. 

    For the fileread->encode->filewrite usecase, I also meet some issues. I use the following steps to feed yuv data to encode input.

    0. VdecVdis_ipcFramesFillBufInfo()

    1. read yuv data from input file 

    2. Vdis_putFullVideoFrames()

    3. Vdis_getEmptyVideoFrames()

    4. VdecVdis_ipcFramesFreeFrameBuf()

    I use the following steps to get h264 data from encode output.

    0. Venc_getBitstreamBuffer()

    1. write h264 data to file

    2. Venc_releaseBitstreamBuffer()

    Now the program could run successfully. But once I feed one frame per channel to encode input I will get newdata available callback twice and if the encode channel number are more than 2, the channel index larger than 1 will have each frames twice. The following figure will show the situation.

    I don't know why this happens, could you give me some advise?

  • Hi Badri,

    I do some test and find some result. When I use the following codes to save the yuv data I could open it in 7yuv setting width and height to 512x240. The picture shows correctly and I could encode the yuv file to h264 file successfully using x264. The actual video res is 368x240 as you can see there is 8 pix on the left side and 136 pix on the right side.

    Then how could I get the right res? Why the frame width is changed? 

    Ptr pMemVirtAddr;
    pMemVirtAddr = 0;
    frameSize = pBuf->framePitch[0] * pBuf->frameHeight;
    OSA_mapMem((UInt32)(pBuf->phyAddr[0][0]),frameSize , &pMemVirtAddr); 
    writeDataSize = fwrite(pMemVirtAddr, 1, frameSize, gVdecVenc_ctrl.fp);
    OSA_unmapMem(pMemVirtAddr, frameSize);
                    
    pMemVirtAddr = 0;
    frameSize = pBuf->framePitch[1] * pBuf->frameHeight * 0.5;
    OSA_mapMem((UInt32)(pBuf->phyAddr[0][1]), frameSize, &pMemVirtAddr); 
    writeDataSize = fwrite(pMemVirtAddr, 1, frameSize, gVdecVenc_ctrl.fp);
    OSA_unmapMem(pMemVirtAddr, frameSize);

  • As I mentioned previously you should use startX, startY of 32,24  . The output buffer pitch is 512 and is not related to the actual image width. If you want to copy only the image write a loop like below to copy luma.:

    frameSize = pBuf->framePitch[0] * pBuf->frameHeight;
    OSA_mapMem((UInt32)(pBuf->phyAddr[0][0]),frameSize , &pMemVirtAddr); 
    
    startX = 32,
    
    startY = 24;
    
    pictureBaseAddress = pMemVirtAddr;
    
    
     for (IineIdx = 0 ; IineIdx < frameHeight; IineIdx++)
    
    {
    
       lineStartAddress = (UInt8 *)pictureBaseAddress + ((startY + IineIdx) * framePitch) + startX;
    
       fwrite(lineStartAddress, 1, frameWidth - startX, gVdecVenc_ctrl.fp);
    
    }
    

  • Hi Badri,

    Thanks for your reply! Is the framePitch you mentioned pBuf->framePitch[0] ? the frameWidth is pBuf->frameWidth? 

  • bing liu said:
    Is the framePitch you mentioned pBuf->framePitch[0] ?

    For luma it is pBuf->framePitch[0], For chroma it is pBuf->framePitch[1]

    bing liu said:
    the frameWidth is pBuf->frameWidth? 

    Yes

     

  • The pBuf->frameWidth is 320 already, why the fwrite size is pBuf->frameWidth - StartX.

    Why the StartX and StartY are 32 and 24?

  • Hi Badri,

    When I use startX and startY to save the image, whatever value I use I always get the following errors after the for loop run a few times. When I set startX=8 and startY=0, the following codes run 62 times before get error.

                    pictureBaseAddress = pMemVirtAddr;     
                    for (LineIdx = 0 ; LineIdx < pBuf->frameHeight; LineIdx++)
                    {     
                        lineStartAddress = (UInt32 *)pictureBaseAddress + ((startY + LineIdx) * pBuf->framePitch[0]) + startX;
                        fwrite(lineStartAddress, 1, pBuf->frameWidth, gVdecVenc_ctrl.fp);
                        printf("index is %d\n", LineIdx);
                    }

     There is something wrong with the address.

    mmap of [0xae586000:126976]
    mmap virt addresss:0x40018480

    index is 0
    index is 1

    ...
    index is 60
    index is 61

    ****** Segmentation fault caught ....
    Faulty address is 0x400374a0, called from 0x4027e920
    Totally Obtained 2 stack frames. signal number =11
     Signal number = 11, Signal errno = 0
     SI code = 1 (Address not mapped to object)
     Fault addr = 0x400374a0
    [bt] Execution path:
    [bt] ./dvr_rdk_demo_mcfw_api.out() [0xae90]
    [bt] /lib/libc.so.6(__default_rt_sa_restorer_v2+0) [0x40236810]

    I open the output yuv file in 7yuv and set the res to 320x240. The luma width is 320 and height is just 62. So I think if the loop could run successfully the output luma should be correct.

  • Can you try

    pictureBaseAddress = pMemVirtAddr;
     
    pictureBaseAddress = (UInt8 *)pictureBaseAddress + ((startY * framePitch[0]) + startX);
     
     
     for (IineIdx = 0 ; IineIdx < frameHeight; IineIdx++)
     
    {
     
       lineStartAddress = (UInt8 *)pictureBaseAddress + (lineIdx * framePitch);
     
       fwrite(lineStartAddress, 1, frameWidth, gVdecVenc_ctrl.fp);
     
    }
  • Hi Badri,

    As you said now I use startX=32 startY=24. Because the pBuf->frameHeight = 240, I add 24 to pBuf->frameHeight. The program could run successfully without any addr error. I open the output yuv file in 7yuv, the Y component is correct. But the U V components seem to be in wrong place. Could you pls check the following codes for saving chroma?

                   Ptr pMemVirtAddr, pictureBaseAddress, lineStartAddress;                 
                    pMemVirtAddr = 0;
                    frameSize = pBuf->framePitch[1] * (pBuf->frameHeight + 48) * 0.5;
                    OSA_mapMem((UInt32)(pBuf->phyAddr[0][1]), frameSize, &pMemVirtAddr);
                   
                    pictureBaseAddress = pMemVirtAddr;
                    pictureBaseAddress = (UInt8 *)pictureBaseAddress + ((startY * pBuf->framePitch[1]) + startX);
                    for (LineIdx = 0 ; LineIdx < pBuf->frameHeight/2; LineIdx++)
                    {

                        lineStartAddress = (UInt8 *)pictureBaseAddress + (LineIdx * pBuf->framePitch[1]);

                        fwrite(lineStartAddress, 1, pBuf->frameWidth, gVdecVenc_ctrl.fp);
                    }
                    OSA_unmapMem(pMemVirtAddr, frameSize);

  • Hi Badri,

    I find the issue. For chroma, the startY should be 12. Now the saved yuv file is correct.

    As you mentioned before, you said that the pBuf->frameHeight should not be 320. I don't know why. And if I change the input res, should I change startX and startY accordingly?

    Thanks so much!

  • startX,startY doesn't depend on the resolution. startX,startY is exported in the pBuf so you can use that to know correct startX,startY values.

  • Thanks so much! I find startX and startY in VIDEO_FRAMEBUF_S in 4.0.

    Now the decode usecase is correct. But the encode usecase still has issue. Could you pls see the post I posted above?