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.

Query on display framework design on TDA2x

Two ADAS algorithms works on images captured by two different cameras on road using Multides kit Interface on TDA2x EVM.

Both the algorithms will be running all the time. However depending on head lamp status (daylamp status)  only one algorithms output shall be displayed on screen.

Please suggest on designing framework for the same. Also please suggest any changes requires in the display drivers?

  • Hi,

    You could select link to select one of the input source and route it to the display link. The input source can be changed whenever you want.

    Rgds,
    Brijesh
  • Hi,

    Probably, your data flow could be something like this
    Requirement
    Capture 1 -> Algo 1 -> Display 1
    Capture 2 - > Algo 2 -> Display 1
    Should be able to display output of Algo 1 or Algo 2

    Data Flow
    Capture 1 -> Algo 1 -> Dup 1 (ouput 0) ->Merge 1 -> Display 1
    Capture 2 -> Algo 2 -> Dup 2 (ouput 0) -> Merge 1 -> Display 1

    Dup 1 (ouput 1) -> Decision Algo
    Dup 2 (ouput 1) -> Decision Algo

    Decision Algo, would receive output of 2 Algos and instruct Display to show output of Capture 1 or Capture 2.

    If you don't require these 2 algo to run all the time, probably you should consider as suggested by Brijesh i.e.

    Capture 1 -> Merge 1 -> Algo 1 -> Dup 1 (ouput 0) -> Select 1 -> Display 1
    Capture 2 -> Merge 1 -> Algo 2 -> Dup 2 (ouput 0) -> Select 1 -> Display 1

    Dup 1 (ouput 1) -> Decision Algo
    Dup 2 (ouput 1) -> Decision Algo

    Decision Algo will instruct Select 1 to send Capture 1 / Capture 2 to Display 1

    Regards,
    Sujith
  • Hi Sujith,Thanks indeed for the suggestion.Our Requirement:
    1. Capture live videos using LVDS Interface from two different cameras
    2. Pass camera #1 video to Algorithm #13. Pass camera #2 video to Algorithm #2
    4. Make decision and display one among the algorithm on HDMI Display(ie either alg #1 or alg #2)
    Capture -> Dup -> Merge Dup -> Alg_1 -> Merge
    Dup -> Alg_2 -> Merge
    Merge -> Sync -> Decision_Algo (Either Alg1 or Alg2 Output) -> Display
    What we did:
    1. As a first step, we did experiment using network interface. We wrote simple use case as below:
    [NullSrc (A15) -> Alg_FrameCopy (A15) -> Display]
    2. We specified number of input channels as 2 for NullSrcObservation:
    We faced some issues in default frame copy plugin when we give 2 channel input, however we had done some changes, with those changes we are able to feed 2 different images through Ethernet and do frame copy of 1st channel input and display it on screen, what change has to be done on frame copy plugin so that I can process channel 2 information and display it on screen, attached is the plugin file for your reference.
    P.S: This is just an experiment, once we are able to implement this on frame copy plugin we will write our final usecase.
  • Hi Sujith,

    Thanks indeed for the suggestion.

    Our Requirement:

    1. Capture live videos using LVDS Interface from two different cameras

    2. Pass camera #1 video to Algorithm #1

    3. Pass camera #2 video to Algorithm #2
    4. Make decision and display one among the algorithm on HDMI Display(ie either alg #1 or alg #2)

    Capture -> Dup -> Merge

    Dup -> Alg_1 -> Merge

    Dup -> Alg_2 -> Merge

    Merge -> Sync -> Decision_Algo (Either Alg1 or Alg2 Output) -> Display

    What we did:

    1. As a first step, we did experiment using network interface. We wrote simple use case as below:

    [NullSrc (A15) -> Alg_FrameCopy (A15) -> Display]

    2. We specified number of input channels as 2 for NullSrc

    Observation:

    We faced some issues in default frame copy plugin when we give 2 channel input, however we had done some changes, with those changes we are able to feed 2 different images through Ethernet and do frame copy of 1st channel input and display it on screen, what change has to be done on frame copy plugin so that I can process channel 2 information and display it on screen, attached is the plugin file for your reference.

    P.S: This is just an experiment, once we are able to implement this on frame copy plugin we will write our final usecase.

    /*
     *******************************************************************************
     *
     * Copyright (C) 2013 Texas Instruments Incorporated - http://www.ti.com/
     * ALL RIGHTS RESERVED
     *
     *******************************************************************************
     */
    
    /**
     *******************************************************************************
     * \file frameCopyLink_algPlugin.c
     *
     * \brief  This file contains plug in functions for frame copy Link
     *
     * \version 0.0 (Aug 2013) : [PS] First version
     * \version 0.1 (Aug 2013) : [PS] Changes to make plug in functions not rely
     *                                on the elements of Algorithm link object.
     *                                Necessary functionality is accomplished via
     *                                API call backs to link skeletal implementation
     * \version 0.2 (Sept 2013) : [PS] Added code for multi channel support
     * \version 0.3 (Sept 2013) : [PS] Added code for stats collector
     *
     *******************************************************************************
    */
    
    /*******************************************************************************
     *  INCLUDE FILES
     *******************************************************************************
     */
    #include "frameCopyLink_priv.h"
    #include <include/link_api/system_common.h>
    #include <src/utils_common/include/utils_mem.h>
    
    /**
     *******************************************************************************
     *
     * \brief Implementation of function to init plugins()
     *
     *        This function will be called by AlgorithmLink_initAlgPlugins, so as
     *        register plugins of frame copy algorithm
     *
     * \return  SYSTEM_LINK_STATUS_SOK on success
     *
     *******************************************************************************
     */
    Int32 AlgorithmLink_FrameCopy_initPlugin()
    {
        AlgorithmLink_FuncTable pluginFunctions;
        UInt32 algId = (UInt32)-1;
    
        pluginFunctions.AlgorithmLink_AlgPluginCreate =
            AlgorithmLink_frameCopyCreate;
        pluginFunctions.AlgorithmLink_AlgPluginProcess =
            AlgorithmLink_frameCopyProcess;
        pluginFunctions.AlgorithmLink_AlgPluginControl =
            AlgorithmLink_frameCopyControl;
        pluginFunctions.AlgorithmLink_AlgPluginStop =
            AlgorithmLink_frameCopyStop;
        pluginFunctions.AlgorithmLink_AlgPluginDelete =
            AlgorithmLink_frameCopyDelete;
    
    #ifdef BUILD_DSP
        algId = ALGORITHM_LINK_DSP_ALG_FRAMECOPY;
    #endif
    
    #ifdef BUILD_ARP32
        algId = ALGORITHM_LINK_EVE_ALG_FRAMECOPY;
    #endif
    
    #ifdef BUILD_A15
        algId = ALGORITHM_LINK_A15_ALG_FRAMECOPY;
    #endif
    
        AlgorithmLink_registerPlugin(algId, &pluginFunctions);
    
        return SYSTEM_LINK_STATUS_SOK;
    }
    
    /**
     *******************************************************************************
     *
     * \brief Implementation of Create Plugin for frame copy algorithm link
     *
     *
     * \param  pObj              [IN] Algorithm link object handle
     * \param  pCreateParams     [IN] Pointer to create time parameters
     *
     * \return  SYSTEM_LINK_STATUS_SOK on success
     *
     *******************************************************************************
     */
    Int32 AlgorithmLink_frameCopyCreate(void * pObj, void * pCreateParams)
    {
        Alg_FrameCopy_Obj          * algHandle;
        Int32                        frameIdx;
        Int32                        status    = SYSTEM_LINK_STATUS_SOK;
        UInt32                       maxHeight;
        UInt32                       maxWidth;
        System_Buffer              * pSystemBuffer;
        System_VideoFrameBuffer    * pSystemVideoFrameBuffer;
        System_LinkInfo              prevLinkInfo;
        Int32                        outputQId;
        Int32                        channelId;
        Int32                        numChannelsUsed;
        Int32                        numInputQUsed;
        Int32                        numOutputQUsed;
        UInt32                       prevLinkQueId;
        UInt32                       dataFormat;
        System_LinkChInfo          * pOutChInfo;
        System_LinkChInfo          * pPrevChInfo;
        UInt32                       prevChInfoFlags;
    
        AlgorithmLink_FrameCopyObj          * pFrameCopyObj;
        AlgorithmLink_FrameCopyCreateParams * pFrameCopyCreateParams;
        AlgorithmLink_OutputQueueInfo       * pOutputQInfo;
        AlgorithmLink_InputQueueInfo        * pInputQInfo;
    
    
        pFrameCopyCreateParams =
            (AlgorithmLink_FrameCopyCreateParams *)pCreateParams;
    
        /*
         * Space for Algorithm specific object gets allocated here.
         * Pointer gets recorded in algorithmParams
         */
        pFrameCopyObj = (AlgorithmLink_FrameCopyObj *)
                            Utils_memAlloc(UTILS_HEAPID_DDR_CACHED_LOCAL,
                                           sizeof(AlgorithmLink_FrameCopyObj), 32);
    
        UTILS_assert(pFrameCopyObj!=NULL);
    
        pOutputQInfo = &pFrameCopyObj->outputQInfo;
        pInputQInfo  = &pFrameCopyObj->inputQInfo;
    
        AlgorithmLink_setAlgorithmParamsObj(pObj, pFrameCopyObj);
    
        /*
         * Taking copy of needed create time parameters in local object for future
         * reference.
         */
        pFrameCopyObj->algLinkCreateParams.maxHeight =
            pFrameCopyCreateParams->maxHeight;
        pFrameCopyObj->algLinkCreateParams.maxWidth  =
            pFrameCopyCreateParams->maxWidth;
        pFrameCopyObj->algLinkCreateParams.numOutputFrames =
            pFrameCopyCreateParams->numOutputFrames;
    
        memcpy((void*)(&pFrameCopyObj->outQueParams),
               (void*)(&pFrameCopyCreateParams->outQueParams),
               sizeof(System_LinkOutQueParams));
        memcpy((void*)(&pFrameCopyObj->inQueParams),
               (void*)(&pFrameCopyCreateParams->inQueParams),
               sizeof(System_LinkInQueParams));
    
        /*
         * Populating parameters corresponding to Q usage of frame copy
         * algorithm link
         */
        numInputQUsed     = 1;
        numOutputQUsed    = 1;
        numChannelsUsed   = 1;
        pInputQInfo->qMode  = ALGORITHM_LINK_QUEUEMODE_NOTINPLACE;
        pOutputQInfo->qMode = ALGORITHM_LINK_QUEUEMODE_NOTINPLACE;
    
        outputQId                 = 0;
        pOutputQInfo->queInfo.numCh = numChannelsUsed;
    
        /*
         * Channel info of current link will be obtained from previous link.
         * If any of the properties get changed in the current link, then those
         * values need to be updated accordingly in
         * pOutputQInfo->queInfo.chInfo[channelId]
         * In frame copy example, only pitch changes. Hence only it is
         * updated. Other parameters are copied from prev link.
         */
        status = System_linkGetInfo(pFrameCopyCreateParams->inQueParams.prevLinkId,
                                    &prevLinkInfo);
    
        prevLinkQueId = pFrameCopyCreateParams->inQueParams.prevLinkQueId;
    
        pFrameCopyObj->numInputChannels = prevLinkInfo.queInfo[prevLinkQueId].numCh;
    
        maxHeight = pFrameCopyObj->algLinkCreateParams.maxHeight;
        maxWidth  = pFrameCopyObj->algLinkCreateParams.maxWidth;
    
        /*
         * Make pitch a multiple of ALGORITHMLINK_FRAME_ALIGN, so that if the frame
         * origin is aligned, then individual lines are also aligned
         * Also note that the pitch is kept same independent of width of
         * individual channels
         */
        pFrameCopyObj->pitch = maxWidth;
        if(maxWidth % ALGORITHMLINK_FRAME_ALIGN)
        {
            pFrameCopyObj->pitch += (ALGORITHMLINK_FRAME_ALIGN -
                                    (maxWidth % ALGORITHMLINK_FRAME_ALIGN));
        }
    
        /*
         * Channel Info Population
         */
        for(channelId =0 ; channelId < 1; /*pFrameCopyObj->numInputChannels;*/ channelId++)
        {
    
          pOutChInfo      = &(pOutputQInfo->queInfo.chInfo[channelId]);
          pPrevChInfo     = &(prevLinkInfo.queInfo[prevLinkQueId].chInfo[channelId]);
          prevChInfoFlags = pPrevChInfo->flags;
    
          /*
           * Certain channel info parameters simply get defined by previous link
           * channel info. Hence copying them to output channel info
           */
          pOutChInfo->startX = pPrevChInfo->startX;
          pOutChInfo->startY = pPrevChInfo->startY;
          pOutChInfo->width  = pPrevChInfo->width;
          pOutChInfo->height = pPrevChInfo->height;
    
          pOutChInfo->flags  = prevChInfoFlags;
    
          dataFormat = SYSTEM_LINK_CH_INFO_GET_FLAG_DATA_FORMAT(prevChInfoFlags);
    
          if((dataFormat != SYSTEM_DF_YUV422I_YUYV)
             &&
             (dataFormat != SYSTEM_DF_YUV420SP_UV)
            )
          {
            return SYSTEM_LINK_STATUS_EFAIL;
          }
    
          if(pPrevChInfo->width > maxWidth || pPrevChInfo->height > maxHeight)
          {
            return SYSTEM_LINK_STATUS_EFAIL;
          }
    
          /*
           * Certain channel info parameters are properties of the current link,
           * They are set here.
           */
          pOutChInfo->pitch[0] = pFrameCopyObj->pitch;
          pOutChInfo->pitch[1] = pFrameCopyObj->pitch;
          pOutChInfo->pitch[2] = pFrameCopyObj->pitch;
    
          if(dataFormat == SYSTEM_DF_YUV422I_YUYV)
          {
            pOutChInfo->pitch[0] = pFrameCopyObj->pitch * 2;
          }
    
          /*
           * Taking a copy of input channel info in the link object for any future
           * use
           */
          memcpy((void *)&(pFrameCopyObj->inputChInfo[channelId]),
                 (void *)&(prevLinkInfo.queInfo[prevLinkQueId].chInfo[channelId]),
                 sizeof(System_LinkChInfo)
                );
        }
    
        /*
         * If any output buffer Q gets used in INPLACE manner, then
         * pOutputQInfo->inQueParams and
         * pOutputQInfo->inputQId need to be populated appropriately.
         */
    
        /*
         * Initializations needed for book keeping of buffer handling.
         * Note that this needs to be called only after setting inputQMode and
         * outputQMode.
         */
        AlgorithmLink_queueInfoInit(pObj,
                                    numInputQUsed,
                                    pInputQInfo,
                                    numOutputQUsed,
                                    pOutputQInfo
                                    );
    
        /*
         * Algorithm creation happens here
         * - Population of create time parameters
         * - Create call for algorithm
         * - Algorithm handle gets recorded inside link object
         */
    
        pFrameCopyObj->createParams.maxHeight    = maxHeight;
        pFrameCopyObj->createParams.maxWidth     = maxWidth;
        pFrameCopyObj->frameDropCounter          = 0;
    
        algHandle = Alg_FrameCopyCreate(&pFrameCopyObj->createParams);
        UTILS_assert(algHandle != NULL);
    
        pFrameCopyObj->algHandle = algHandle;
    
        /*
         * Creation of output buffers for output buffer Q = 0 (Used)
         *  - Connecting video frame buffer to system buffer payload
         *  - Memory allocation for Luma and Chroma buffers (Assume 420 format)
         *  - Put the buffer into empty queue
         */
        outputQId = 0;
    
        for(channelId =0 ; channelId < 1/*pFrameCopyObj->numInputChannels*/; channelId++)
        {
          for(frameIdx = 0;
              frameIdx < pFrameCopyObj->algLinkCreateParams.numOutputFrames;
              frameIdx++)
          {
            pSystemBuffer           =
                                 &(pFrameCopyObj->buffers[channelId][frameIdx]);
            pSystemVideoFrameBuffer =
                                 &(pFrameCopyObj->videoFrames[channelId][frameIdx]);
    
            /*
             * Properties of pSystemBuffer, which do not get altered during
             * run time (frame exchanges) are initialized here
             */
            pSystemBuffer->payload     = pSystemVideoFrameBuffer;
            pSystemBuffer->payloadSize = sizeof(System_VideoFrameBuffer);
            pSystemBuffer->bufType     = SYSTEM_BUFFER_TYPE_VIDEO_FRAME;
            pSystemBuffer->chNum       = channelId;
    
            memcpy((void *)&pSystemVideoFrameBuffer->chInfo,
                   (void *)&pOutputQInfo->queInfo.chInfo[channelId],
                   sizeof(System_LinkChInfo));
    
            /*
             * Buffer allocation done for maxHeight, maxWidth and also assuming
             * worst case num planes = 2, for data Format SYSTEM_DF_YUV422I_YUYV
             * run time (frame exchanges) are initialized here
             */
            pSystemVideoFrameBuffer->bufAddr[0] = Utils_memAlloc(
                                               UTILS_HEAPID_DDR_CACHED_SR,
                                               (maxHeight*(pFrameCopyObj->pitch)*2),
                                               ALGORITHMLINK_FRAME_ALIGN);
    
            /*
             * Carving out memory pointer for chroma which will get used in case of
             * SYSTEM_DF_YUV422SP_UV
             */
            pSystemVideoFrameBuffer->bufAddr[1] = (void*)(
                (UInt32) pSystemVideoFrameBuffer->bufAddr[0] +
                (UInt32)(maxHeight*(pFrameCopyObj->pitch))
                );
    
            UTILS_assert(pSystemVideoFrameBuffer->bufAddr[0] != NULL);
    
            AlgorithmLink_putEmptyOutputBuffer(pObj, outputQId, pSystemBuffer);
          }
        }
    
        pFrameCopyObj->linkStatsInfo = Utils_linkStatsCollectorAllocInst(
            AlgorithmLink_getLinkId(pObj), "ALG_FRAME_COPY");
        UTILS_assert(NULL != pFrameCopyObj->linkStatsInfo);
    
        pFrameCopyObj->isFirstFrameRecv = FALSE;
    
        return status;
    }
    
    /**
     *******************************************************************************
     *
     * \brief Implementation of Process Plugin for frame copy algorithm link
     *
     *        This function executes on the DSP or EVE or IPU or A15 processor.
     *        Hence processor gets
     *        locked with execution of the function, until completion. Only a
     *        link with higher priority can pre-empt this function execution.
     *
     * \param  pObj              [IN] Algorithm link object handle
     *
     * \return  SYSTEM_LINK_STATUS_SOK on success
     *
     *******************************************************************************
     */
    Int32 AlgorithmLink_frameCopyProcess(void * pObj)
    {
        AlgorithmLink_FrameCopyObj * pFrameCopyObj;
        Alg_FrameCopy_Obj          * algHandle;
        Int32                        inputQId;
        Int32                        outputQId;
        UInt32                       channelId;
        Int32                        status    = SYSTEM_LINK_STATUS_SOK;
        UInt32                       bufId;
        System_BufferList            inputBufList;
        System_BufferList            inputBufListReturn;
        System_BufferList            outputBufListReturn;
        System_Buffer              * pSysBufferInput;
        System_VideoFrameBuffer    * pSysVideoFrameBufferInput;
        System_Buffer              * pSysBufferOutput;
        System_VideoFrameBuffer    * pSysVideoFrameBufferOutput;
        UInt32                       dataFormat;
        UInt32                       outPitch[SYSTEM_MAX_PLANES];
        UInt32                       bufSize[SYSTEM_MAX_PLANES];
        UInt32                       bufCntr;
        UInt32                       numBuffs;
        System_LinkChInfo          * pInputChInfo;
        System_LinkChInfo          * pOutputChInfo;
        Bool                         bufDropFlag;
        AlgorithmLink_CopyMode       copyMode;
        System_LinkStatistics      * linkStatsInfo;
    
    
        pFrameCopyObj = (AlgorithmLink_FrameCopyObj *)
                            AlgorithmLink_getAlgorithmParamsObj(pObj);
    
        linkStatsInfo = pFrameCopyObj->linkStatsInfo;
        UTILS_assert(NULL != linkStatsInfo);
    
        algHandle     = pFrameCopyObj->algHandle;
    
        Utils_linkStatsCollectorProcessCmd(linkStatsInfo);
    
        linkStatsInfo->linkStats.newDataCmdCount++;
    
        /*
         * Getting input buffers from previous link
         */
        System_getLinksFullBuffers(pFrameCopyObj->inQueParams.prevLinkId,
                                   pFrameCopyObj->inQueParams.prevLinkQueId,
                                   &inputBufList);
    
        if(inputBufList.numBuf)
        {
            if(pFrameCopyObj->isFirstFrameRecv==FALSE)
            {
                pFrameCopyObj->isFirstFrameRecv = TRUE;
    
                Utils_resetLinkStatistics(
                        &linkStatsInfo->linkStats,
                        pFrameCopyObj->numInputChannels,
                        1);
    
                Utils_resetLatency(&linkStatsInfo->linkLatency);
                Utils_resetLatency(&linkStatsInfo->srcToLinkLatency);
            }
    		Vps_printf("NUMBER OF INPUT BUFFERS=%d\n",inputBufList.numBuf);
            for (bufId = 0; bufId < inputBufList.numBuf; bufId++)
            {
    
              pSysBufferInput           = inputBufList.buffers[bufId];
              pSysVideoFrameBufferInput = pSysBufferInput->payload;
    
              channelId = 0;//pSysBufferInput->chNum;
    
              if(channelId < pFrameCopyObj->numInputChannels)
              {
                linkStatsInfo->linkStats.chStats[channelId].inBufRecvCount++;
              }
    
              /*
               * Error checks can be done on the input buffer and only later,
               * it can be picked for processing
               */
              if((pSysBufferInput->bufType != SYSTEM_BUFFER_TYPE_VIDEO_FRAME)
                 ||
                 (channelId >= pFrameCopyObj->numInputChannels)
                )
              {
                bufDropFlag = TRUE;
                linkStatsInfo->linkStats.inBufErrorCount++;
              }
              else
              {
    
              /*
               * Getting free (empty) buffers from pool of output buffers
               */
              outputQId = 0;
    
    
              status = AlgorithmLink_getEmptyOutputBuffer(pObj,
                                                          outputQId,
                                                          channelId,
                                                          &pSysBufferOutput);
    
              /*
               * Get into algorithm processing only if an output frame is available.
               * Else input buffer will be returned back to sender and its a case
               * of frame drop.
               */
              if(status == SYSTEM_LINK_STATUS_SOK)
              {
    
              pSysVideoFrameBufferOutput = pSysBufferOutput->payload;
              pOutputChInfo = &(pFrameCopyObj->outputQInfo.queInfo.chInfo[channelId]);
              pInputChInfo  = &(pFrameCopyObj->inputChInfo[channelId]);
    
              /*
               * If there is any parameter change on the input channel,
               * then, channel info needs to be read from pSysVideoFrameBufferInput.
               * And then,
               *  - Update the local copies present in OutputQInfo and inputChInfo
               *  - Also update channel info in pSysVideoFrameBufferOutput to
               *    pass on new parameters to next link
               */
    
              if(SYSTEM_LINK_CH_INFO_GET_FLAG_IS_RT_PRM_UPDATE(
                            pSysVideoFrameBufferInput->chInfo.flags))
              {
                pInputChInfo = &(pSysVideoFrameBufferInput->chInfo);
    
                memcpy(&(pFrameCopyObj->inputChInfo[channelId]),
                       pInputChInfo,
                       sizeof(System_LinkChInfo));
    
                memcpy(pOutputChInfo,
                       pInputChInfo,
                       sizeof(System_LinkChInfo));
    
                dataFormat =
                      SYSTEM_LINK_CH_INFO_GET_FLAG_DATA_FORMAT(pInputChInfo->flags);
    
                /*
                 * Upon dataFormat change pitch for plane 0 needs to be updated
                 * Plane 1 is used only for 420 SP case and it need not be altered
                 */
                pOutputChInfo->pitch[0] = pFrameCopyObj->pitch;
                if(dataFormat == SYSTEM_DF_YUV422I_YUYV)
                {
                    pOutputChInfo->pitch[0] = pFrameCopyObj->pitch * 2;
                }
    
                /*
                 * Also update the Channel info in Output System Buffer to pass it
                 * on to next link
                 */
                memcpy(&(pSysVideoFrameBufferOutput->chInfo),
                      pOutputChInfo,
                      sizeof(System_LinkChInfo));
              }
              else
              {
                /*
                 * Indicating to next link that there has been no parameter update
                 */
                SYSTEM_LINK_CH_INFO_SET_FLAG_IS_RT_PRM_UPDATE(
                            pSysVideoFrameBufferOutput->chInfo.flags,
                            0);
              }
    
              /*
               * Call to the algorithm
               */
              outPitch[0] = pOutputChInfo->pitch[0];
              outPitch[1] = pOutputChInfo->pitch[1];
    
              dataFormat = SYSTEM_LINK_CH_INFO_GET_FLAG_DATA_FORMAT(
                            pOutputChInfo->flags);
    
              /*
               * Default
               */
              //copyMode = ALGORITHM_LINK_ALG_CPUFRAMECOPY;
              copyMode = ALGORITHM_LINK_ALG_DMAFRAMECOPY;	//Shailesh:25Aug2015
    
              switch(System_getSelfProcId())
              {
                case SYSTEM_PROC_A15_0:
                    copyMode = ALGORITHM_LINK_ALG_CPUFRAMECOPY;
                    break;
                case SYSTEM_PROC_DSP1:
                case SYSTEM_PROC_DSP2:
                case SYSTEM_PROC_EVE1:
                case SYSTEM_PROC_EVE2:
                case SYSTEM_PROC_EVE3:
                case SYSTEM_PROC_EVE4:
                    copyMode = ALGORITHM_LINK_ALG_DMAFRAMECOPY;
                    break;
              }
    
              switch (dataFormat)
              {
                  case SYSTEM_DF_YUV422I_YUYV:
                      numBuffs = 1;
                      break;
                  case SYSTEM_DF_YUV420SP_UV:
                      numBuffs = 2;
                      break;
                  default:
                      numBuffs = 1;
                      UTILS_assert (0);
                      break;
              }
    
              pSysBufferOutput->srcTimestamp = pSysBufferInput->srcTimestamp;
              pSysBufferOutput->linkLocalTimestamp = Utils_getCurGlobalTimeInUsec();
              /*
               * Cache Invalidate of input buffer
               */
              if(copyMode == ALGORITHM_LINK_ALG_CPUFRAMECOPY)
              {
                bufSize[0]  = ((pInputChInfo->height)*(pInputChInfo->pitch[0]));
                bufSize[1]  = ((pInputChInfo->height)*(pInputChInfo->pitch[1]));
    
                for(bufCntr = 0; bufCntr < numBuffs; bufCntr++)
                {
                    Cache_inv(pSysVideoFrameBufferInput->bufAddr[bufCntr],
                              bufSize[bufCntr],
                              Cache_Type_ALLD,
                              TRUE
                             );
                }
              }
    
              Alg_FrameCopyProcess(algHandle,
                                   (UInt32 **)pSysVideoFrameBufferInput->bufAddr,
                                   (UInt32 **)pSysVideoFrameBufferOutput->bufAddr,
                                   pInputChInfo->width,
                                   pInputChInfo->height,
                                   pInputChInfo->pitch,
                                   outPitch,
                                   dataFormat,
                                   copyMode
                                  );
    
              /*
               * Cache Write back of output buffer to DDR
               */
              if(copyMode == ALGORITHM_LINK_ALG_CPUFRAMECOPY)
              {
                bufSize[0]  = ((pOutputChInfo->height)*(outPitch[0]));
                bufSize[1]  = ((pOutputChInfo->height)*(outPitch[1]));
                for(bufCntr = 0; bufCntr < numBuffs; bufCntr++)
                {
                  Cache_wb(pSysVideoFrameBufferOutput->bufAddr[bufCntr],
                           bufSize[bufCntr],
                           Cache_Type_ALLD,
                           TRUE
                          );
                }
              }
    
              Utils_updateLatency(&linkStatsInfo->linkLatency,
                                  pSysBufferOutput->linkLocalTimestamp);
              Utils_updateLatency(&linkStatsInfo->srcToLinkLatency,
                                  pSysBufferOutput->srcTimestamp);
    
              linkStatsInfo->linkStats.chStats
                        [pSysBufferInput->chNum].inBufProcessCount++;
              linkStatsInfo->linkStats.chStats
                        [pSysBufferInput->chNum].outBufCount[0]++;
    
              /*
               * Putting filled buffer into output full buffer Q
               * Note that this does not mean algorithm has freed the output buffer
               */
              status = AlgorithmLink_putFullOutputBuffer(pObj,
                                                         outputQId,
                                                         pSysBufferOutput);
    
              UTILS_assert(status == SYSTEM_LINK_STATUS_SOK);
    
              /*
               * Informing next link that a new data has peen put for its
               * processing
               */
              System_sendLinkCmd(pFrameCopyObj->outQueParams.nextLink,
                                 SYSTEM_CMD_NEW_DATA,
                                 NULL);
    
              /*
               * Releasing (Free'ing) output buffer, since algorithm does not need
               * it for any future usage.
               * In case of INPLACE computation, there is no need to free output
               * buffer, since it will be freed as input buffer.
               */
              outputQId                      = 0;
              outputBufListReturn.numBuf     = 1;
              outputBufListReturn.buffers[0] = pSysBufferOutput;
    
              AlgorithmLink_releaseOutputBuffer(pObj,
                                                outputQId,
                                                &outputBufListReturn);
    
              bufDropFlag = FALSE;
    
              }
              else
              {
                bufDropFlag = TRUE;
    
                linkStatsInfo->linkStats.outBufErrorCount++;
                linkStatsInfo->linkStats.chStats
                                [pSysBufferInput->chNum].inBufDropCount++;
                linkStatsInfo->linkStats.chStats
                                [pSysBufferInput->chNum].outBufDropCount[0]++;
    
              } /* Output Buffer availability */
    
              } /* Input Buffer validity */
    
              /*
               * Releasing (Free'ing) input buffer, since algorithm does not need
               * it for any future usage.
               */
              inputQId                      = 0;
              inputBufListReturn.numBuf     = 1;
              inputBufListReturn.buffers[0] = pSysBufferInput;
              AlgorithmLink_releaseInputBuffer(
                                          pObj,
                                          inputQId,
                                          pFrameCopyObj->inQueParams.prevLinkId,
                                          pFrameCopyObj->inQueParams.prevLinkQueId,
                                          &inputBufListReturn,
                                          &bufDropFlag);
    
            }
    
        }
    
        return status;
    }
    
    /**
     *******************************************************************************
     *
     * \brief Implementation of Control Plugin for frame copy algorithm link
     *
     *
     * \param  pObj              [IN] Algorithm link object handle
     * \param  pCreateParams     [IN] Pointer to control parameters
     *
     * \return  SYSTEM_LINK_STATUS_SOK on success
     *
     *******************************************************************************
     */
    
    Int32 AlgorithmLink_frameCopyControl(void * pObj, void * pControlParams)
    {
        AlgorithmLink_FrameCopyObj     * pFrameCopyObj;
        AlgorithmLink_ControlParams    * pAlgLinkControlPrm;
        Alg_FrameCopy_Obj              * algHandle;
        Int32                        status    = SYSTEM_LINK_STATUS_SOK;
    
        pFrameCopyObj = (AlgorithmLink_FrameCopyObj *)
                            AlgorithmLink_getAlgorithmParamsObj(pObj);
        algHandle     = pFrameCopyObj->algHandle;
    
        pAlgLinkControlPrm = (AlgorithmLink_ControlParams *)pControlParams;
    
        /*
         * There can be other commands to alter the properties of the alg link
         * or properties of the core algorithm.
         * In this simple example, there is just a control command to print
         * statistics and a default call to algorithm control.
         */
        switch(pAlgLinkControlPrm->controlCmd)
        {
    
            case SYSTEM_CMD_PRINT_STATISTICS:
                AlgorithmLink_frameCopyPrintStatistics(pObj, pFrameCopyObj);
                break;
    
            default:
                status = Alg_FrameCopyControl(algHandle,
                                              &(pFrameCopyObj->controlParams)
                                              );
                break;
        }
    
        return status;
    }
    
    /**
     *******************************************************************************
     *
     * \brief Implementation of Stop Plugin for frame copy algorithm link
     *
     *        For this algorithm there is no locking of frames and hence no
     *        flushing of frames. Also there are no any other functionality to be
     *        done at the end of execution of this algorithm. Hence this function
     *        is an empty function for this algorithm.
     *
     * \param  pObj              [IN] Algorithm link object handle
     *
     * \return  SYSTEM_LINK_STATUS_SOK on success
     *
     *******************************************************************************
     */
    Int32 AlgorithmLink_frameCopyStop(void * pObj)
    {
        return SYSTEM_LINK_STATUS_SOK;
    }
    
    /**
     *******************************************************************************
     *
     * \brief Implementation of Delete Plugin for frame copy algorithm link
     *
     * \param  pObj              [IN] Algorithm link object handle
     *
     * \return  SYSTEM_LINK_STATUS_SOK on success
     *
     *******************************************************************************
     */
    Int32 AlgorithmLink_frameCopyDelete(void * pObj)
    {
        Alg_FrameCopy_Obj          * algHandle;
        Int32                        frameIdx;
        Int32                        status    = SYSTEM_LINK_STATUS_SOK;
        UInt32                       maxHeight;
        UInt32                       channelId;
    
        System_VideoFrameBuffer    * pSystemVideoFrameBuffer;
        AlgorithmLink_FrameCopyObj * pFrameCopyObj;
    
        pFrameCopyObj = (AlgorithmLink_FrameCopyObj *)
                            AlgorithmLink_getAlgorithmParamsObj(pObj);
        algHandle     = pFrameCopyObj->algHandle;
    
        status = Utils_linkStatsCollectorDeAllocInst(pFrameCopyObj->linkStatsInfo);
        UTILS_assert(status == SYSTEM_LINK_STATUS_SOK);
    
        status = Alg_FrameCopyDelete(algHandle);
        UTILS_assert(status == SYSTEM_LINK_STATUS_SOK);
    
        maxHeight = pFrameCopyObj->algLinkCreateParams.maxHeight;
    
        for(channelId =0 ; channelId < 1;/*pFrameCopyObj->numInputChannels;*/ channelId++)
        {
          for(frameIdx = 0;
              frameIdx < (pFrameCopyObj->algLinkCreateParams.numOutputFrames);
              frameIdx++)
          {
            pSystemVideoFrameBuffer =
                                 &(pFrameCopyObj->videoFrames[channelId][frameIdx]);
    
            /*
             * Free'ing up of allocated buffers
             */
            status = Utils_memFree(UTILS_HEAPID_DDR_CACHED_SR,
                                   pSystemVideoFrameBuffer->bufAddr[0],
                                   (maxHeight*pFrameCopyObj->pitch*2)
                                   );
            UTILS_assert(status == SYSTEM_LINK_STATUS_SOK);
          }
        }
    
        status = Utils_memFree(UTILS_HEAPID_DDR_CACHED_LOCAL,
                               pFrameCopyObj, sizeof(AlgorithmLink_FrameCopyObj));
        UTILS_assert(status == SYSTEM_LINK_STATUS_SOK);
    
        return SYSTEM_LINK_STATUS_SOK;
    }
    
    /**
     *******************************************************************************
     *
     * \brief Print link statistics
     *
     * \param  pObj                [IN] Algorithm link object handle
     * \param  pFrameCopyObj       [IN] Frame copy link Object handle
     *
     * \return  SYSTEM_LINK_STATUS_SOK on success
     *
     *******************************************************************************
     */
    Int32 AlgorithmLink_frameCopyPrintStatistics(void *pObj,
                           AlgorithmLink_FrameCopyObj *pFrameCopyObj)
    {
    
        UTILS_assert(NULL != pFrameCopyObj->linkStatsInfo);
    
        Utils_printLinkStatistics(&pFrameCopyObj->linkStatsInfo->linkStats, "ALG_FRAMECOPY", TRUE);
    
        Utils_printLatency("ALG_FRAMECOPY",
                           &pFrameCopyObj->linkStatsInfo->linkLatency,
                           &pFrameCopyObj->linkStatsInfo->srcToLinkLatency,
                            TRUE
                           );
    
        return SYSTEM_LINK_STATUS_SOK;
    }
    
    /* Nothing beyond this point */
    

  • Hi Socrates,

    Easiest way would probably to use Dup link, consider

    NullSrc->Dup->A & B outputs

    A-> Alg/Frame Copy (DSP 1) -> Merge 1

    B-> Alg/Frame Copy (DSP 2) -> Merge 1

    Merge 1 -> Display

    I doubt if we have tested multi-channel processing on Null Source and frame copy.

    Regards, Sujith

  • Hi Sujith,I can not use Dup link as i feed two different types of images.
    1. Omnivision camera captures image 12. IR camera captures image 2
    3. Image 1 and image 2 are processed on TDA2x EVM
    4. Make decision and display one among the image on HDMI Display.
    In order to perform above we do not have live camera setup at office (bench test). And hence we consider NullSrc. We would like to make the following work on bench.
    NullSrc - > Process Image1 and Image 2 -> Decision Making -> Display either Image 1 or Image 2.
    ThanksSocrates
  • Hi Socrates,

    Can you consider having another instance of NullSource on some other core? I don't think we have validated multiple instances of NullSource on same core.

    Probably, your chain might look like

    NullSource (A15) -> Alg_ProcessImageStream1 -> Merge_Src

    NullSource -> Alg_ProcessImageStream2 -> Merge_Src -> Sync_Src -> Alg_StreamSrcDecision -> Display

    Points to note

    • NullSource (A15) : Link will be created & executed on A15
    • NullSource : Link will be created & executed on IPU1_0
    • Alg_StreamSrcDecision will receive a composite frame (System_VideoFrameCompositeBuffer)
    • Merge Link & Sync Link: Required to ensure both sources are available to decision making link, as might require to switch between sources (frequently?)

    Regards, Sujith

  • Hi Sujith,

    Could you please suggest the possible soltion for the issue stated in the attached document?

    Thanks, DisplayFramework_Issues.docxSocrates

  • Hi Socrates,

    This is quite strange indeed, the input & output arguments seem fine.

    Can you please check on the following

    • Data format is not changed runtime :
      • Is the chroma portion missing/ corrupted
      • Dump the output frame as YUV420 SP and check 
    • Input frame : Check if the frame is as expected, put a break point at just before the VPE driver call is made and dump the frame.
    • Check the channel output parameters of VPE, just before the VPE driver call is made, check the output arguments
      • Height, Width & data format

    Ideally, this thread should be closed and you could open a new thread with this specific problem. I agree your complete problem is not solved but if we could keep the questions modular, other users would find it easier to search / understand.

    Regards,

    Sujith