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.

[FAQ] PROCESSOR-SDK-J721E: How to capture embedded metadata with the data type 0x12 using CSIRX?

Part Number: PROCESSOR-SDK-TDAX

There are two ways to send embedded metadata in MIPI protocol.

1, Metadata with same data type as image/video data. 

2, Metadata with the data type as 0x12, different from image/video data. 

The current PSDKRA already supports capturing embedded metadata, when it is sent using #1. This article provides the method to capture embedded metadata when it is sent using #2. 

  • Please follow below steps in order to capture embedded metadata with datatype as 0x12.

    1. Please apply attached patch on top of ti-processor-sdk-rtos-j721e-evm-08_01_00_13\tiovx folder. Although patch is for PSDKRA8.1 release, it can also be cleanly applied on PSDKRA8.2.
    2. This patch adds additional parameter, meta_on_separate_channel, in the tivx_raw_image_create_params_t. When flag is set to true, metadata is assumed to be available with the data type 0x12. 
    3. Then application can select the position and size, in terms of lines, of the metadata in fields meta_height_before and meta_height_after fields of the tivx_raw_image_create_params_t.
    4. This essentially means metadata would be stored in the same raw_image buffer, even though it is captured with the separate data type.
    5. The next node/component can extract captured metadata from the same raw_image buffer. The advantage of keeping metadata in the same raw_image buffer is that they are always in sync. 

    /cfs-file/__key/communityserver-discussions-components-files/791/Added_5F00_Support_5F00_For_5F00_Capturing_5F00_Metadata.zip

    Regards,

    Brijesh

  • After applying attached patch, please replace function tivxCaptureDequeueFrameFromDriver with below code.

    static vx_status tivxCaptureDequeueFrameFromDriver(tivxCaptureParams *prms)
    {
        vx_status status = VX_SUCCESS;
        uint32_t instIdx, tmp_obj_desc_id = 0U;
        uint64_t tmp_timestamp = 0U;
        uintptr_t timestamp_buf = 0U;
        tivxCaptureInstParams *instParams;
        Fvid2_Frame *fvid2Frame;
        vx_uint32 frmIdx = 0U, chId = 0U;
        int32_t fvid2_status = FVID2_SOK;
        static Fvid2_FrameList frmList;
    
        for (instIdx = 0U ; instIdx < prms->numOfInstUsed ; instIdx++)
        {
            instParams = &prms->instParams[instIdx];
            fvid2_status = Fvid2_dequeue(instParams->drvHandle,
                                         &frmList,
                                         0,
                                         FVID2_TIMEOUT_NONE);
    
            if(FVID2_SOK == fvid2_status)
            {
                for(frmIdx=0; frmIdx < frmList.numFrames; frmIdx++)
                {
                    fvid2Frame = frmList.frames[frmIdx];
    
                    chId = tivxCaptureGetNodeChannelNum(
                                        prms,
                                        instIdx,
                                        fvid2Frame->chNum);
    
                    tmp_obj_desc_id = (uint32_t)fvid2Frame->appData;
                    tmp_timestamp = fvid2Frame->timeStamp64;
                    
                    if (fvid2Frame->chNum >= prms->instParams[instIdx].numCh)
                    {
                        tivxQueuePut(&prms->freeFvid2FrameQ[chId], (uintptr_t)fvid2Frame, TIVX_EVENT_TIMEOUT_NO_WAIT);
                    }
                    else
                    {
                        tivxQueuePut(&prms->freeFvid2FrameQ[chId], (uintptr_t)fvid2Frame, TIVX_EVENT_TIMEOUT_NO_WAIT);
                        tivxQueuePut(&prms->pendingFrameQ[chId], (uintptr_t)tmp_obj_desc_id, TIVX_EVENT_TIMEOUT_NO_WAIT);
                        tivxQueueGet(&prms->pendingFrameTimestampFreeQ[chId], (uintptr_t*)&timestamp_buf, TIVX_EVENT_TIMEOUT_NO_WAIT);
    
                        if(timestamp_buf != 0U)
                        {
                            uint64_t *p_tmp_timestamp = (uint64_t *)timestamp_buf;
                            *p_tmp_timestamp          = tmp_timestamp;
                            tivxQueuePut(&prms->pendingFrameTimestampQ[chId], timestamp_buf, TIVX_EVENT_TIMEOUT_NO_WAIT);
                        }
                        else
                        {
                            VX_PRINT(VX_ZONE_ERROR, " Invalid address, timestamp_buf is NULL !!! \n");
                        }                    
                    }
                }
            }
            else if (fvid2_status == FVID2_ENO_MORE_BUFFERS)
            {
                /* continue: move onto next driver instance
                  within node as current driver instance did
                  not generate this CB */
            }
            else
            {
                /* TIOVX-687: Note: disabling for now until investigated further */
                if (FVID2_EAGAIN != fvid2_status)
                {
                    status = (vx_status)VX_FAILURE;
                    VX_PRINT(VX_ZONE_ERROR,
                        " CAPTURE: ERROR: FVID2 Dequeue failed !!!\n");
                }
            }
        }
    
        return status;
    }

    Essentially, the below if condition is moved inside else portion of valid channel check.

    if(timestamp_buf != 0U)
    {
    uint64_t *p_tmp_timestamp = (uint64_t *)timestamp_buf;
    *p_tmp_timestamp = tmp_timestamp;
    tivxQueuePut(&prms->pendingFrameTimestampQ[chId], timestamp_buf, TIVX_EVENT_TIMEOUT_NO_WAIT);
    }
    else
    {
    VX_PRINT(VX_ZONE_ERROR, " Invalid address, timestamp_buf is NULL !!! \n");
    }

  • Additionally, when using this patch in multiple channel capture with embedded data, there might be error "CAPTURE: Could not retrieve buffer from buffer queue". In order to fix this error, please replace tivxCaptureGetNodeChannelNum as shown below.

    static uint32_t tivxCaptureGetNodeChannelNum(const tivxCaptureParams *prms,
    uint32_t instId,
    uint32_t chId)
    {
        return prms->instParams[instId].chInfo[chId].nodeChId;
    }