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.

DVR RDK Multichannel Encoder Use case Link API

Hi,

   Thanks a lots to this forum, I could successfully realize many RDK use cases. I want to realize one more, Multichannel Encoder using Link APIs. (File Read -> ENC -> File write). 16 channel @ 720x576

I feel I connected the Links correctly with correct parameters...


/*******************************************************************************
 *                                                                             *
 * Copyright (c) 2009 Texas Instruments Incorporated - http://www.ti.com/      *
 *                        ALL RIGHTS RESERVED                                  *
 *                                                                             *
 ******************************************************************************/

#include <demos/link_api_demos/common/chains.h>
#include <demos/link_api_demos/video_chains/system_chain.h>
#include <demos/link_api_demos/video_chains/system_frame_chain.h>


/**
                        FILE (YUV)
                          |
                          |
                   IPC_FRAMES_OUT_A8 (Frames)
                          |
                   IPC_FRAMES_IN_M3 (Frames)
                          |
                         ENC
                          |
                    IPC_BITS_OUT_M3 (Bits Stream)
                          |
                    IPC_BITS_IN_A8 (Bits Stream)
                          |
                          |
                        FILE (H264)
*/
#define SRC_NUM_CH 16
#define NUM_BUF_PER_CH 6
#define CH_WIDTH    720
#define CH_HEIGHT    576
static SystemVideo_Ivahd2ChMap_Tbl systemVid_encDecIvaChMapTbl =
{
    .isPopulated = 1,
    .ivaMap[0] =
    {
        .EncNumCh  = 16,
        .EncChList = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13 , 14, 15},
        .DecNumCh  = 0,
        .DecChList = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
    },
    .ivaMap[1] =
    {
        .EncNumCh  = 0,
        .EncChList = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
        .DecNumCh  = 0,
        .DecChList = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 , 0, 0},
    },
    .ivaMap[2] =
    {
        .EncNumCh  = 0,
        .EncChList = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
        .DecNumCh  = 0,
        .DecChList = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
    },
};


Void Chains_multiChH264Enc(Chains_Ctrl *chainsCfg)
{
    IpcFramesOutLinkHLOS_CreateParams  ipcFramesOutHostPrm;
    IpcFramesInLinkRTOS_CreateParams   ipcFramesInVideoPrm;

    EncLink_CreateParams     encPrm;

    IpcBitsOutLinkRTOS_CreateParams    ipcBitsOutVideoPrm;
    IpcBitsInLinkHLOS_CreateParams   ipcBitsInHostPrm;

    Int i, SndRcvConfig;
    Bool isProgressive;
    System_LinkInfo bitsProducerLinkInfo;

    UInt32 encId;
    UInt32 ipcFramesInVideoId, ipcFramesOutHostId;
    UInt32 ipcBitsOutVideoId, ipcBitsInHostId;
    char ch;

    iChains_ipcBitsInit();
    SndRcvConfig = ICHAINS_IPC_FRAMES_SND_ONLY;
    iChains_ipcFramesInit(SndRcvConfig);


    CHAINS_INIT_STRUCT(IpcFramesOutLinkHLOS_CreateParams,ipcFramesOutHostPrm);
    CHAINS_INIT_STRUCT(IpcFramesInLinkRTOS_CreateParams,ipcFramesInVideoPrm);

    CHAINS_INIT_STRUCT(EncLink_CreateParams, encPrm);

    CHAINS_INIT_STRUCT(IpcBitsOutLinkRTOS_CreateParams,ipcBitsOutVideoPrm);
    CHAINS_INIT_STRUCT(IpcBitsInLinkHLOS_CreateParams,ipcBitsInHostPrm);

    ipcFramesOutHostId = SYSTEM_HOST_LINK_ID_IPC_FRAMES_OUT_0;
    ipcFramesInVideoId = SYSTEM_VIDEO_LINK_ID_IPC_FRAMES_IN_0;

    encId  = SYSTEM_LINK_ID_VENC_0;

    ipcBitsOutVideoId  = SYSTEM_VIDEO_LINK_ID_IPC_BITS_OUT_0;
    ipcBitsInHostId  = SYSTEM_HOST_LINK_ID_IPC_BITS_IN_0;

    isProgressive = TRUE;

    System_linkControl(
        SYSTEM_LINK_ID_M3VIDEO,
        SYSTEM_COMMON_CMD_SET_CH2IVAHD_MAP_TBL,
        &systemVid_encDecIvaChMapTbl,
        sizeof(SystemVideo_Ivahd2ChMap_Tbl),
        TRUE
    );
/**
 * IPC Frames OUT (A8)
 * */
    ipcFramesOutHostPrm.baseCreateParams.outQueParams[0].nextLink = ipcFramesInVideoId;
    ipcFramesOutHostPrm.baseCreateParams.notifyNextLink = FALSE;
    ipcFramesOutHostPrm.baseCreateParams.notifyPrevLink = FALSE;
    ipcFramesOutHostPrm.baseCreateParams.noNotifyMode = TRUE;
    ipcFramesOutHostPrm.baseCreateParams.numOutQue = 1;
    ipcFramesOutHostPrm.baseCreateParams.inQueParams.prevLinkId = SYSTEM_LINK_ID_INVALID;
    ipcFramesOutHostPrm.inQueInfo.numCh = SRC_NUM_CH;


    for (i=0; i<SRC_NUM_CH; i++)
    {
        ipcFramesOutHostPrm.inQueInfo.chInfo[i].width = CH_WIDTH;
        ipcFramesOutHostPrm.inQueInfo.chInfo[i].height = CH_HEIGHT;
        ipcFramesOutHostPrm.inQueInfo.chInfo[i].scanFormat = SYSTEM_SF_PROGRESSIVE;
        ipcFramesOutHostPrm.inQueInfo.chInfo[i].bufType        = 0; // NOT USED
        ipcFramesOutHostPrm.inQueInfo.chInfo[i].codingformat   = 0; // NOT USED
        ipcFramesOutHostPrm.inQueInfo.chInfo[i].dataFormat     = 0x07; //FVID2_DF_YUV420SP_UV
        ipcFramesOutHostPrm.inQueInfo.chInfo[i].memType        = 0; // NON-TILED MEM
        ipcFramesOutHostPrm.inQueInfo.chInfo[i].startX         = 0; // NOT USED
        ipcFramesOutHostPrm.inQueInfo.chInfo[i].startY         = 0; // NOT USED
        ipcFramesOutHostPrm.inQueInfo.chInfo[i].pitch[0]       = CH_WIDTH;
        ipcFramesOutHostPrm.inQueInfo.chInfo[i].pitch[1]       = CH_WIDTH;
        ipcFramesOutHostPrm.inQueInfo.chInfo[i].pitch[2]       = 0; // NOT USED
    }

/**
 * IPC Frames OUT (A8) to IPC Frames IN (Video)
 * */
    ipcFramesInVideoPrm.baseCreateParams.noNotifyMode = TRUE;
    ipcFramesInVideoPrm.baseCreateParams.notifyNextLink = TRUE;
    ipcFramesInVideoPrm.baseCreateParams.notifyPrevLink = FALSE;
    ipcFramesInVideoPrm.baseCreateParams.inQueParams.prevLinkId = ipcFramesOutHostId;
    ipcFramesInVideoPrm.baseCreateParams.inQueParams.prevLinkQueId = 0;
    ipcFramesInVideoPrm.baseCreateParams.outQueParams[0].nextLink = encId;
/**
 * IPC Frames IN (Video) to Encoder
 * */
    for (i=0; i<SRC_NUM_CH; i++) {
        encPrm.chCreateParams[i].format     = IVIDEO_H264HP;
        encPrm.chCreateParams[i].profile    = IH264_HIGH_PROFILE;
        encPrm.chCreateParams[i].dataLayout = IVIDEO_FIELD_SEPARATED;
        encPrm.chCreateParams[i].fieldMergeEncodeEnable  = FALSE;
        encPrm.chCreateParams[i].defaultDynamicParams.intraFrameInterval = 20;
        encPrm.chCreateParams[i].encodingPreset = XDM_DEFAULT;
        encPrm.chCreateParams[i].enableAnalyticinfo = 0;
        encPrm.chCreateParams[i].enableWaterMarking = 0;
        encPrm.chCreateParams[i].rateControlPreset =
                                 IVIDEO_STORAGE;
        encPrm.chCreateParams[i].defaultDynamicParams.inputFrameRate = 30;
        encPrm.chCreateParams[i].defaultDynamicParams.targetBitRate =
                                 (3 * 1000 * 1000);
        encPrm.chCreateParams[i].defaultDynamicParams.interFrameInterval = 1;
        encPrm.chCreateParams[i].defaultDynamicParams.mvAccuracy =
                                 IVIDENC2_MOTIONVECTOR_QUARTERPEL;
    }
    encPrm.inQueParams.prevLinkId   = ipcFramesInVideoId;
    encPrm.inQueParams.prevLinkQueId= 0;
    encPrm.outQueParams.nextLink = ipcBitsOutVideoId;
    encPrm.numBufPerCh[0] = NUM_BUF_PER_CH;
/**
* Encoder to ipcBitsOutVideo
**/
    ipcBitsOutVideoPrm.baseCreateParams.inQueParams.prevLinkId         = encId;
    ipcBitsOutVideoPrm.baseCreateParams.inQueParams.prevLinkQueId     = 0;
    ipcBitsOutVideoPrm.baseCreateParams.numOutQue                     = 1;
    ipcBitsOutVideoPrm.baseCreateParams.notifyPrevLink                = TRUE;
    ipcBitsOutVideoPrm.baseCreateParams.notifyNextLink                = FALSE;
    ipcBitsOutVideoPrm.baseCreateParams.outQueParams[0].nextLink = ipcBitsInHostId;
/**
* ipcBitsOutVideo to
**/
    ipcBitsInHostPrm.baseCreateParams.inQueParams.prevLinkId = ipcBitsOutVideoId;
    ipcBitsInHostPrm.baseCreateParams.inQueParams.prevLinkQueId = 0;
    ipcBitsInHostPrm.baseCreateParams.notifyNextLink            = FALSE;
    ipcBitsInHostPrm.baseCreateParams.notifyPrevLink            = FALSE;
    ipcBitsInHostPrm.baseCreateParams.noNotifyMode                 = TRUE;
    ipcBitsInHostPrm.baseCreateParams.outQueParams[0].nextLink   = SYSTEM_LINK_ID_INVALID;


     System_linkCreate(ipcFramesOutHostId,&ipcFramesOutHostPrm,sizeof(ipcFramesOutHostPrm));
     System_linkCreate(ipcFramesInVideoId,&ipcFramesInVideoPrm,sizeof(ipcFramesInVideoPrm));
     System_linkCreate(encId, &encPrm, sizeof(encPrm));
     sleep(2);
     System_linkCreate(ipcBitsOutVideoId, &ipcBitsOutVideoPrm, sizeof(ipcBitsOutVideoPrm));
     System_linkCreate(ipcBitsInHostId, &ipcBitsInHostPrm, sizeof(ipcBitsInHostPrm));
    printf("SYSTEM INFO >>> FILE - ENC - FILE Links Created\n");

    Chains_memPrintHeapStatus();

    {

        System_linkStart(ipcBitsInHostId);
        System_linkStart(ipcBitsOutVideoId);
        System_linkStart(encId);
        System_linkStart(ipcFramesInVideoId);
        System_linkStart(ipcFramesOutHostId);

        /* Start taking CPU load just before starting of links */
        Chains_prfLoadCalcEnable(TRUE, FALSE, FALSE);

        while(1)
        {
            ch = Chains_menuRunTime();
            if(ch=='0')
                break;
            if(ch=='i')
                System_linkControl(encId, ENC_LINK_CMD_PRINT_IVAHD_STATISTICS, NULL, 0, TRUE);
            if(ch=='e')
                System_linkControl(encId, ENC_LINK_CMD_PRINT_STATISTICS, NULL, 0, TRUE);
            if(ch=='E')
                   System_linkControl(encId, ENC_LINK_CMD_PRINT_BUFFER_STATISTICS, NULL, 0, TRUE);
        }
        iChains_ipcBitsStop();
        System_linkStop(ipcFramesOutHostId);
        System_linkStop(ipcFramesInVideoId);
        System_linkStop(encId);
        System_linkStop(ipcBitsOutVideoId);
        System_linkStop(ipcBitsInHostId);
    }

    System_linkDelete(ipcBitsInHostId);
    System_linkDelete(ipcBitsOutVideoId);
    System_linkDelete(encId);
    System_linkDelete(ipcFramesInVideoId);
    System_linkDelete(ipcFramesOutHostId);
    Chains_prfLoadCalcEnable(FALSE, TRUE, FALSE);
    iChains_ipcBitsExit();
}


All the links are getting created.. But when I periodically poll for empty video frames ,

status =  IpcFramesOutLink_getEmptyVideoFrames(SYSTEM_HOST_LINK_ID_IPC_FRAMES_OUT_0,
                                                     &bufList);

I get numFrames as '0'.


Thanks



  • ipcFramesOutLInk on HLOS does not allocate buffers.So doing IpcFramesOutLink_getEmptyVideoFrames will not return any buffers. It is expected that the application allocates physically contiguous buffers (Vsys_allocBuf can be used) , populates the physical address and invokes IpcFramesOutLink_putFullVideoFrames. It will then invoke IpcFramesOutLink_getEmptyVideoFrames to get back the passed frames after processing is completed on the remote core. So your sequence should be :

    Vsys_allocBuf(buf)

    while(1) {

      IpcFramesOutLink_putFullVideoFrames /* QUeue frames to remote core for processing */

      ..

      IpcFramesOutLink_getEmptyVideoFrames /* Get back the processed frames */

    }

    Refer demo_ipc_frames_exch.c for reference code

  • Thanks Badri for your prompt response,

    Let me make it more clear before I start coding this logic. I am running 16 channel encoder, with 6 buffer per encoder channel .

    Vsys_allocBuf() /*allocate 16 buffers, 1 frame per channel & get virtual address*/

    Memory_translate() /*pass virtual addr, and get Phy Addr*/

    while(1) {

      /* Populate the VIDFrame_BufList and memcpy the frames*/

    IpcFramesOutLink_putFullVideoFrames /* QUeue frames to remote core for processing */

     sleep(x);

      IpcFramesOutLink_getEmptyVideoFrames /* Get back the processed frames */

    }

    Is the above logic correct?


    Thanks



  • Yes this is correct. Vsys_allocBuf itself populates the physical address so you dont need memory_translate.

  • Thanks Badri,

        I got it working. No we have 16 channel FILE READ - > ENC -> FILE WRITE Demo. H264.

    Thanks a lot.

  • Hi

       Can you tell me the what the srRegId  is about Vsys_allocBuf()

  • srRegId   is Shared Region ID. indicates which region to allocate memory.

    Thanks

    Subash

  • There are two sharedRegions available on A8. SharedRegion 0 and SharedRegion 1. If you want cached buffers use srId 1 and if you want non-cached buffers use srId 0. It is better to use SrIdx 0 else application has to be careful and handle cache coherency correctly.

  • Thanks Badri In the beginning ,I used the Sridx 0 and I used memcpy to copy data to m3vpss display.but the performance is very low. It would spent 60 ms when coping 2MB data to the buffer . So I used teh Sridx 1,which the speed is 4 ms. I used IpcFramesOutLink_getEmptyVideoFrames , IpcFramesOutLink_putFullVideoFrames to get and put buffer. So I wonder whether the function IpcFramesOutLink_putFullVideoFrames would handle cache coherency correctly

  • IpcFramesOut link do not handle cache coherency operation. Application will have to do cache coherency operation and provide a coherent buffer to ipcFramesOut. It is expected that you use DMA to copy video frames and not CPU copy hence supporting cache coherency operation in ipcFrames link was not considered.

  • Hi Quote Today I haven't used DMA to copy video frames, only use CPU to copy video frames and I have't handled the cache coherency operation. but I can get a smooth video disp[ay. just sometimes the video have some shake. wether it is related to the cache coherency operation.

  • Copying a video frame via CPU will cause the A8 cache to automatically get flushed. There would be issues with the last pixels copied to the frame as Cache wont get flushed which could cause artifacts at the end of the frame or top of the frame.It is better to do cache coherency as that is the correct way.Refer dvr_rdk/mcfw/src_linux/links/ipcBitsOutLink for reference code for how cache coherency operation should be done.WHat do you mean by shake. Is the video nor smooth or is the image corrupted.

  • The shake I mean is that the lower half of the picture will be lifting up one centimete about every 4 sesconds.

    and even if the video is still.the video also will shake, So I think it is not the cache problem

  • The image will not corrupt

  • Hi, Have you solved your problem? I got the same problem.