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.

question about the dup link? (DVRRDK-3.5 on dm8168)

Other Parts Discussed in Thread: TVP7002


hi,
i'm do a test of 1 channel display&encode.

the 1channel data from tvp7002, and use dup2 for the 2 branch,
one for display, another for encode.

but after add the osd alg, osd content also show on diplay and encode stream.
i itented it only show on encode stram.

in the src_bios6 source code, the dup link only add one reference of the frame?

thanks.

  • Yes the dupLink does not create copies of the frames.Only the frameinfo is copied and sent to two links. This means the buffer should be treated as readonly because if one link changes the buffer it will get modified for both the links.

    RDK 4.0 supports a feature in the dupLink whereby if one of the next link of dupLink modifies the content, the dupLink can be configured such that  modifying the buffer does not affect the other link which would resolve the issue you are seeing.

  • hi, badri, thanks for your reply. 

    RDK 4.0 will release date is?

    and RDK 3.5 have any way to solve the problem?

  • RDK 4.0 will be available next week.It is not possible to resolve the issue on RDK 3.5.Attached is a patch which you can try and check if it resolves the issue.if it doesnt solve the issue you will have to migrate to RDK 4.0.

    You will have to invoke the code after creating the dupLink:

    static
    Void duplink_configure_delay(UInt32 dupId,UInt32 delayOutQueId)
    {
        DupLink_DelayParams delayPrms;
        Int32 status;

        delayPrms.outQueId = delayOutQueId; //IN YOUR CASE THIS WILL BE THE ipcFramesOut output queue out of dupLink

        status =
        System_linkControl(dupId,                             DUP_LINK_CMD_SET_DELAY_OUTPUT_QUE_PARAMS,
                           &delayPrms,
                           sizeof(delayPrms),
                           TRUE);
        OSA_assert(status == 0);
    }

    diff --git a/mcfw/interfaces/link_api/dupLink.h b/mcfw/interfaces/link_api/dupLink.h
    index 9eb93fe..048979c 100755
    --- a/mcfw/interfaces/link_api/dupLink.h
    +++ b/mcfw/interfaces/link_api/dupLink.h
    @@ -31,6 +31,19 @@
     /** \brief Max output queues to which a given DUP link can connect to */
     #define DUP_LINK_MAX_OUT_QUE	(5)
     
    +/**
    +    \brief configure one of the output queue of the dupLink to be delayed and output.
    +
    +    When one the outputs of the dupLink is modified by the nextLink (for example OSD)
    +    the frames to that output queue should be output only after the frame has been
    +    freed by the other output queues. This ensures the other output queues
    +    receive the unmodified original frame
    +
    +    \param DupLink_DelayParams * delayPrms [IN] audio parameter to set
    +*/
    +#define DUP_LINK_CMD_SET_DELAY_OUTPUT_QUE_PARAMS  (0x1001)
    +
    +
     /* @} */
     
     /* Data structure's */
    @@ -55,6 +68,19 @@ typedef struct
     
     } DupLink_CreateParams;
     
    +
    +/**
    +    \brief DUP link create parameters
    +*/
    +typedef struct
    +{
    +    UInt32  outQueId;
    +    /**< QueueId for which frame should be dleayed and output.
    +     *   Should be less than DupLink_CreateParams.numOutQue
    +     */
    +} DupLink_DelayParams;
    +
    +
     /* @} */
     
     /* function's */
    diff --git a/mcfw/src_bios6/links_common/dup/dupLink_priv.h b/mcfw/src_bios6/links_common/dup/dupLink_priv.h
    index dc94f28..d50930d 100755
    --- a/mcfw/src_bios6/links_common/dup/dupLink_priv.h
    +++ b/mcfw/src_bios6/links_common/dup/dupLink_priv.h
    @@ -15,6 +15,8 @@
     
     #define DUP_LINK_MAX_FRAMES_PER_OUT_QUE		(SYSTEM_LINK_FRAMES_PER_CH*SYSTEM_MAX_CH_PER_OUT_QUE)
     
    +#define DUP_LINK_DELAYED_OUTPUT_QUE_INVALID_ID (~0u)
    +
     typedef struct DupLink_statsObj {
         UInt32 recvCount;
         UInt32 forwardCount[DUP_LINK_MAX_OUT_QUE];
    @@ -47,6 +49,7 @@ typedef struct {
     
         FVID2_FrameList inFrameList;
         FVID2_FrameList outFrameList[DUP_LINK_MAX_OUT_QUE];
    +    UInt32          delayedOutputQueId;
         DupLink_statsObj stats;
     
     } DupLink_Obj;
    diff --git a/mcfw/src_bios6/links_common/dup/dupLink_tsk.c b/mcfw/src_bios6/links_common/dup/dupLink_tsk.c
    index ef821f7..1811ec9 100755
    --- a/mcfw/src_bios6/links_common/dup/dupLink_tsk.c
    +++ b/mcfw/src_bios6/links_common/dup/dupLink_tsk.c
    @@ -82,6 +82,7 @@ Int32 DupLink_drvCreate(DupLink_Obj * pObj, DupLink_CreateParams * pPrm)
             }
         }
         DupLink_drvInitStats(pObj);
    +    pObj->delayedOutputQueId = DUP_LINK_DELAYED_OUTPUT_QUE_INVALID_ID;
     #ifdef SYSTEM_DEBUG_DUP
         Vps_printf(" %d: DUP   : Create Done !!!\n", Utils_getCurTimeInMsec());
     #endif
    @@ -101,6 +102,7 @@ Int32 DupLink_drvDelete(DupLink_Obj * pObj)
         }
     
         Semaphore_delete(&pObj->lock);
    +    pObj->delayedOutputQueId = DUP_LINK_DELAYED_OUTPUT_QUE_INVALID_ID;
     
     #ifdef SYSTEM_DEBUG_DUP
         Vps_printf(" %d: DUP   : Delete Done !!!\n", Utils_getCurTimeInMsec());
    @@ -136,6 +138,94 @@ Int32 DupLink_getFullFrames(Utils_TskHndl * pTsk, UInt16 queId,
         return status;
     }
     
    +static
    +Void  DupLink_drvPutFramesInDelayOutQue(DupLink_Obj * pObj,FVID2_Frame *pOrgFrame)
    +{
    +    FVID2_Frame *pFrame;
    +    System_FrameInfo *pFrameInfo, *pOrgFrameInfo;
    +    UInt32 outId;
    +    Int32 status;
    +
    +    UTILS_assert(pObj->delayedOutputQueId != DUP_LINK_DELAYED_OUTPUT_QUE_INVALID_ID);
    +
    +    if (pObj->delayedOutputQueId < pObj->createArgs.numOutQue)
    +    {
    +        outId = pObj->delayedOutputQueId;
    +
    +        pObj->outFrameList[outId].numFrames = 0;
    +        pOrgFrameInfo = (System_FrameInfo *) pOrgFrame->appData;
    +        UTILS_assert(pOrgFrameInfo != NULL);
    +        UTILS_assert(pOrgFrameInfo->dupCount == 1);
    +        status = Utils_bufGetEmptyFrame(&pObj->outFrameQue[outId],
    +                                        &pFrame, BIOS_NO_WAIT);
    +        UTILS_assert(status == FVID2_SOK);
    +        UTILS_assert(pFrame != NULL);
    +
    +        pFrameInfo = (System_FrameInfo *) pFrame->appData;
    +        UTILS_assert(pFrameInfo != NULL);
    +
    +        memcpy(pFrame, pOrgFrame, sizeof(*pOrgFrame));
    +        memcpy(pFrameInfo, pOrgFrameInfo, sizeof(*pOrgFrameInfo));
    +
    +        pFrame->appData = pFrameInfo;
    +
    +        pFrameInfo->pDupOrgFrame = pOrgFrame;
    +
    +        pObj->outFrameList[outId].frames[pObj->outFrameList[outId].
    +                                         numFrames] = pFrame;
    +
    +        pObj->outFrameList[outId].numFrames++;
    +        status =
    +            Utils_bufPutFull(&pObj->outFrameQue[outId],
    +                             &pObj->outFrameList[outId]);
    +        UTILS_assert(status == FVID2_SOK);
    +
    +        if (pObj->createArgs.notifyNextLink)
    +        {
    +            System_sendLinkCmd(pObj->createArgs.outQueParams[outId].nextLink,
    +                               SYSTEM_CMD_NEW_DATA);
    +        }
    +
    +    }
    +}
    +
    +static
    +Int32 DupLink_validateDelayOutQuePrms(DupLink_Obj * pObj,DupLink_DelayParams *delayPrms)
    +{
    +    Int32 status = 0;
    +
    +    UTILS_assertError(
    +                     ((delayPrms->outQueId < pObj->createArgs.numOutQue)
    +                      &&
    +                      (pObj->stats.recvCount == 0)
    +                      &&
    +                      (pObj->delayedOutputQueId == DUP_LINK_DELAYED_OUTPUT_QUE_INVALID_ID)
    +                      &&
    +                      (pObj->createArgs.numOutQue > 1)),
    +                      status,
    +                      -1,
    +                      pObj->tskId,
    +                      -1);
    +    return status;
    +}
    +
    +
    +static
    +Int32 DupLink_setDelayOutQuePrms(DupLink_Obj * pObj,DupLink_DelayParams *delayPrms)
    +{
    +    Int32 status;
    +
    +    Semaphore_pend(pObj->lock, BIOS_WAIT_FOREVER);
    +    status = DupLink_validateDelayOutQuePrms(pObj,delayPrms);
    +    if (status == 0)
    +    {
    +        pObj->delayedOutputQueId = delayPrms->outQueId;
    +    }
    +    Semaphore_post(pObj->lock);
    +    return status;
    +}
    +
    +
     Int32 DupLink_drvProcessFrames(DupLink_Obj * pObj)
     {
         UInt32 frameId, outId;
    @@ -173,39 +263,47 @@ Int32 DupLink_drvProcessFrames(DupLink_Obj * pObj)
     
                 for (outId = 0; outId < pCreateArgs->numOutQue; outId++)
                 {
    -                status = Utils_bufGetEmptyFrame(&pObj->outFrameQue[outId],
    -                                                &pFrame, BIOS_NO_WAIT);
    -                UTILS_assert(status == FVID2_SOK);
    -                UTILS_assert(pFrame != NULL);
    +                if ((pCreateArgs->numOutQue == 1) ||
    +                    (pObj->delayedOutputQueId != outId))
    +                {
    +                    status = Utils_bufGetEmptyFrame(&pObj->outFrameQue[outId],
    +                                                    &pFrame, BIOS_NO_WAIT);
    +                    UTILS_assert(status == FVID2_SOK);
    +                    UTILS_assert(pFrame != NULL);
     
    -                pFrameInfo = (System_FrameInfo *) pFrame->appData;
    -                UTILS_assert(pFrameInfo != NULL);
    +                    pFrameInfo = (System_FrameInfo *) pFrame->appData;
    +                    UTILS_assert(pFrameInfo != NULL);
     
    -                memcpy(pFrame, pOrgFrame, sizeof(*pOrgFrame));
    -                memcpy(pFrameInfo, pOrgFrameInfo, sizeof(*pOrgFrameInfo));
    +                    memcpy(pFrame, pOrgFrame, sizeof(*pOrgFrame));
    +                    memcpy(pFrameInfo, pOrgFrameInfo, sizeof(*pOrgFrameInfo));
     
    -                pFrame->appData = pFrameInfo;
    +                    pFrame->appData = pFrameInfo;
     
    -                pFrameInfo->pDupOrgFrame = pOrgFrame;
    +                    pFrameInfo->pDupOrgFrame = pOrgFrame;
     
    -                pObj->outFrameList[outId].frames[pObj->outFrameList[outId].
    -                                                 numFrames] = pFrame;
    +                    pObj->outFrameList[outId].frames[pObj->outFrameList[outId].
    +                                                     numFrames] = pFrame;
     
    -                pObj->outFrameList[outId].numFrames++;
    +                    pObj->outFrameList[outId].numFrames++;
    +                }
                 }
             }
     
             for (outId = 0; outId < pCreateArgs->numOutQue; outId++)
             {
    -            status =
    -                Utils_bufPutFull(&pObj->outFrameQue[outId],
    -                                 &pObj->outFrameList[outId]);
    -            UTILS_assert(status == FVID2_SOK);
    -
    -            if (pCreateArgs->notifyNextLink)
    +            if ((pCreateArgs->numOutQue == 1) ||
    +                (pObj->delayedOutputQueId != outId))
                 {
    -                System_sendLinkCmd(pCreateArgs->outQueParams[outId].nextLink,
    -                                   SYSTEM_CMD_NEW_DATA);
    +                status =
    +                    Utils_bufPutFull(&pObj->outFrameQue[outId],
    +                                     &pObj->outFrameList[outId]);
    +                UTILS_assert(status == FVID2_SOK);
    +
    +                if (pCreateArgs->notifyNextLink)
    +                {
    +                    System_sendLinkCmd(pCreateArgs->outQueParams[outId].nextLink,
    +                                       SYSTEM_CMD_NEW_DATA);
    +                }
                 }
             }
         }
    @@ -253,6 +351,12 @@ Int32 DupLink_putEmptyFrames(Utils_TskHndl * pTsk, UInt16 queId,
                 freeFrameList.frames[freeFrameList.numFrames] = pOrgFrame;
                 freeFrameList.numFrames++;
             }
    +
    +        if ((pOrgFrameInfo->dupCount == 1) && (pObj->delayedOutputQueId <  pObj->createArgs.numOutQue))
    +        {
    +            /* Frame has been freed from all other output queues.So put in delayed output queue now */
    +            DupLink_drvPutFramesInDelayOutQue(pObj,pOrgFrame);
    +        }
         }
     
         pObj->putFrameCount += freeFrameList.numFrames;
    @@ -302,6 +406,15 @@ Void DupLink_tskMain(struct Utils_TskHndl * pTsk, Utils_MsgHndl * pMsg)
     
             switch (cmd)
             {
    +            case DUP_LINK_CMD_SET_DELAY_OUTPUT_QUE_PARAMS:
    +            {
    +                DupLink_DelayParams *params;
    +
    +                params = (DupLink_DelayParams *) Utils_msgGetPrm(pMsg);
    +                status = DupLink_setDelayOutQuePrms(pObj, params);
    +                Utils_tskAckOrFreeMsg(pMsg, status);
    +            }
    +            break;
                 case SYSTEM_CMD_DELETE:
                     done = TRUE;
                     ackMsg = TRUE;