
Int32 NsfLink_drvDoNsfFilter(NsfLink_Obj * pObj)
{
    FVID2_FrameList inFrameList[2], outFrameList;
    FVID2_ProcessList processList;
    FVID2_Frame *pFullFrame;
    FVID2_Frame *pEmptyFrame;
    Int32 status;
    UInt32 chId, frameId, queueId = 0, chPerQueue;
    FVID2_Frame *pFrame;
    UInt32 sendMsgToTsk = 0;
    UInt32 perChCount, numFrames;
    System_FrameInfo *pInFrameInfo;
    System_FrameInfo *pOutFrameInfo;
    NsfLink_ChObj *pChObj;
    Vps_M2mNsfRtParams *rtParams;
    Vps_NsfDataFormat *rtParamDataFmt;
    NsfLink_ChObj *nsfChObj;
    Bool rtParamUpdatePerFrame;

    /* Initialize the process list with different frame lists */
    processList.inFrameList[0] = &inFrameList[0];
    processList.inFrameList[1] = &inFrameList[1];
    processList.outFrameList[0] = &outFrameList;

    processList.numInLists = 2;
    processList.numOutLists = 1;

    processList.drvData = NULL;
    processList.reserved = NULL;

    numFrames = 0;

    pObj->getFrames++;

    /** For all the available channels, look into the respective
     * bufInQue.fullQueue and take the frames out of that queue and add them
     * to the inFrameList.
     * Take the same number of frames from the respective bufInQue.emptyQueue
     * and add them to the outFrameList.
     * This process will make the desired processList, ready for noise
     * filtering.
     */
    for (chId = 0; chId < pObj->nsfCreateParams.numCh; chId++)
    {
        /* While there are captured frames... and less than what NSF could
         * consume per request per channel. */
        perChCount = 0u;
        while (1)
        {
            status = Utils_bufGetFullFrame(&pObj->linkChInfo[chId].bufInQue,
                                           &pFullFrame, BIOS_NO_WAIT);
            if (status != FVID2_SOK)
                break;

            pInFrameInfo = (System_FrameInfo *) pFullFrame->appData;

            /* First check whether it can be accomodated or not */
            status = Utils_bufGetEmptyFrame(&pObj->linkChInfo[chId].bufInQue,
                                            &pEmptyFrame, BIOS_WAIT_FOREVER);
            UTILS_assert(status == FVID2_SOK);

            //Vps_printf("pEmptyFrame->addr[0][0] = 0x%08x, pEmptyFrame->addr[0][1] = 0x%08x\n",pEmptyFrame->addr[0][0], pEmptyFrame->addr[0][1]);

            switch (numFrames)
            {
                case 0:
                   pEmptyFrame->addr[0][0] = (Ptr)0x00010000;
                   pEmptyFrame->addr[0][1] = (Ptr)0x08000000;
                   Vps_printf(" 0 pEmptyFrame->addr[0][0] = 0x%08x, pEmptyFrame->addr[0][1] = 0x%08x\n",pEmptyFrame->addr[0][0], pEmptyFrame->addr[0][1]);
                   break;
                case 1:
                   pEmptyFrame->addr[0][0] = (Ptr)0x00011420;
                   pEmptyFrame->addr[0][1] = (Ptr)0x08001420;
                   Vps_printf(" 1 pEmptyFrame->addr[0][0] = 0x%08x, pEmptyFrame->addr[0][1] = 0x%08x\n",pEmptyFrame->addr[0][0], pEmptyFrame->addr[0][1]);
                   break;
                case 2:
                   pEmptyFrame->addr[0][0] = (Ptr)0x00012840;
                   pEmptyFrame->addr[0][1] = (Ptr)0x08002840;
                   Vps_printf(" 2 pEmptyFrame->addr[0][0] = 0x%08x, pEmptyFrame->addr[0][1] = 0x%08x\n",pEmptyFrame->addr[0][0], pEmptyFrame->addr[0][1]);
                   break;
                case 3:
                   pEmptyFrame->addr[0][0] = (Ptr)0x00013c60;
                   pEmptyFrame->addr[0][1] = (Ptr)0x08003c60;
                   Vps_printf(" 3 pEmptyFrame->addr[0][0] = 0x%08x, pEmptyFrame->addr[0][1] = 0x%08x\n",pEmptyFrame->addr[0][0], pEmptyFrame->addr[0][1]);
                   break;
                default:
                   break;
            }

            pOutFrameInfo = (System_FrameInfo *) pEmptyFrame->appData;

            /* Add both the frames in the respective frame lists */
            inFrameList[0].frames[numFrames] = pFullFrame;
            inFrameList[1].frames[numFrames] =
                pObj->linkChInfo[chId].pPrevOutFrame;

            pFullFrame->perFrameCfg = NULL;
            rtParamUpdatePerFrame = FALSE;
            UTILS_assert (pFullFrame->channelNum == chId);
            nsfChObj = &pObj->linkChInfo[chId];

            rtParamDataFmt = &nsfChObj->nsfRtParamDataFormat;
            if ((pInFrameInfo != NULL) && (pInFrameInfo->rtChInfoUpdate == TRUE))
            {
                if (pInFrameInfo->rtChInfo.height != rtParamDataFmt->inFrameHeight)
                {
                    rtParamDataFmt->inFrameHeight = pInFrameInfo->rtChInfo.height;
                    rtParamUpdatePerFrame = TRUE;
                }
                if (pInFrameInfo->rtChInfo.width != rtParamDataFmt->inFrameWidth)
                {
                    rtParamDataFmt->inFrameWidth = pInFrameInfo->rtChInfo.width;
                    rtParamUpdatePerFrame = TRUE;
                }
                if (pInFrameInfo->rtChInfo.pitch[0] != rtParamDataFmt->inPitch)
                {
                    rtParamDataFmt->inPitch = pInFrameInfo->rtChInfo.pitch[0];
                    rtParamUpdatePerFrame = TRUE;
                }
            }
            if (rtParamUpdatePerFrame == TRUE)
            {
                rtParams = &nsfChObj->nsfRtParams;
                rtParams->dataFormat = &nsfChObj->nsfRtParamDataFormat;
                rtParams->processingCfg = NULL;
                pFullFrame->perFrameCfg = rtParams;
            }

            pOutFrameInfo->rtChInfo.width    = rtParamDataFmt->inFrameWidth;
            pOutFrameInfo->rtChInfo.height   = rtParamDataFmt->inFrameHeight;
            pOutFrameInfo->rtChInfo.pitch[0] = rtParamDataFmt->outPitch[0];
            pOutFrameInfo->rtChInfo.pitch[1] = rtParamDataFmt->outPitch[1];
            pOutFrameInfo->rtChInfo.dataFormat = FVID2_DF_YUV420SP_UV;
            pOutFrameInfo->rtChInfo.memType    = rtParamDataFmt->outMemType;
            pOutFrameInfo->rtChInfoUpdate    = TRUE;

            outFrameList.frames[numFrames] = pEmptyFrame;

            /* next previous output frame is current output frame */
            pObj->linkChInfo[chId].pPrevOutFrame = pEmptyFrame;

            pEmptyFrame->timeStamp = pFullFrame->timeStamp;
            if (pInFrameInfo != NULL)
                pOutFrameInfo->ts64  = pInFrameInfo->ts64;

            nsfChObj->inFrameProcessCount++;
            numFrames++;
            perChCount++;
            if (perChCount >
                0 /* pObj->nsfCreateStatus.maxFramesPerChInQueue */ )
                break;
        }
    }

    pObj->getFrames--;

    inFrameList[0].numFrames = numFrames;
    inFrameList[1].numFrames = numFrames;
    outFrameList.numFrames = numFrames;

    /* Start noise filtering */
    if (inFrameList[0].numFrames)
    {
#ifdef SYSTEM_DEBUG_NSF_RT
        Vps_printf(" %d: NSF: Noise Filtering %d frames !!!\n",
                   Utils_getCurTimeInMsec(), inFrameList[0].numFrames);
#endif

        pObj->processFrameReqCount++;

        pObj->curTime = Utils_getCurTimeInMsec();

        status = FVID2_processFrames(pObj->fvidHandleNsf, &processList);
        UTILS_assert(status == FVID2_SOK);

        Semaphore_pend(pObj->complete, BIOS_WAIT_FOREVER);

        status = FVID2_getProcessedFrames(pObj->fvidHandleNsf, &processList,
                                          BIOS_NO_WAIT);
        UTILS_assert(status == FVID2_SOK);

        pObj->curTime = Utils_getCurTimeInMsec() - pObj->curTime;

        pObj->totalTime += pObj->curTime;

        pObj->processFrameCount += processList.outFrameList[0]->numFrames;

        pObj->getProcessFrameReqCount++;

#ifdef SYSTEM_DEBUG_NSF_RT
        Vps_printf(" %d: NSF: Noise Filtering of %d frames Done !!!\n",
                   Utils_getCurTimeInMsec(), inFrameList[0].numFrames);
#endif

            /* Put the processed frames in the appropriate output queue */
////////////////////////////////////////////////////////////////////////////////////////////////////////////
            //ch0
            if (outFrameList.numFrames > 0)
            {
                frameId = 0;
                pFrame = outFrameList.frames[frameId];

                if (pFrame)
                {
                    pChObj = &pObj->linkChInfo[pFrame->channelNum];
                    /** Split the frames into both the output queues,
                     * if they are enabled. Else use output queue 0 only.
                     * Also, if output queue 1 is used, frames sent to this queue
                     * should be modified before submitting so that the
                     * pFrame->channelNum should start with 0 and not with
                     * (pObj->nsfCreateParams.numCh / 2).
                    */
                    chPerQueue =
                        (pObj->nsfCreateParams.numCh / pObj->createArgs.numOutQue);
                    queueId = (pFrame->channelNum / chPerQueue);
                    pFrame->channelNum = pFrame->channelNum % chPerQueue;
                    pChObj->outFrameCount++;
                    Vps_printf("frameId=%d\n",frameId);
                    Vps_printf("pFrame->addr[0][0]= 0x%08x, pFrame->addr[0][1]= 0x%08x\n",pFrame->addr[0][0], pFrame->addr[0][1]);
                    pFrame->addr[0][0] = (Ptr)Utils_tilerGetOriAddr((UInt32)pFrame->addr[0][0], UTILS_TILER_CNT_8BIT, 1,  720,288);
                    pFrame->addr[0][1] = (Ptr)Utils_tilerGetOriAddr((UInt32)pFrame->addr[0][1], UTILS_TILER_CNT_16BIT, 1, 720,288/2);
                    Vps_printf("pFrame->addr[0][0]= 0x%08x, pFrame->addr[0][1]= 0x%08x\n",pFrame->addr[0][0], pFrame->addr[0][1]);

                    /* Set the flag whether queue is filled or not */
                    sendMsgToTsk |= (1 << queueId);

                    status = Utils_bufPutFullFrame(&pObj->bufOutQue[queueId], pFrame);
                    UTILS_assert(status == FVID2_SOK);
                } /* end of if (pFrame) */
            }

            //ch1
            if (outFrameList.numFrames > 1)
            {
                frameId = 1;
                pFrame = outFrameList.frames[frameId];

                if (pFrame)
                {
                    pChObj = &pObj->linkChInfo[pFrame->channelNum];
                    /** Split the frames into both the output queues,
                     * if they are enabled. Else use output queue 0 only.
                     * Also, if output queue 1 is used, frames sent to this queue
                     * should be modified before submitting so that the
                     * pFrame->channelNum should start with 0 and not with
                     * (pObj->nsfCreateParams.numCh / 2).
                    */
                    chPerQueue =
                        (pObj->nsfCreateParams.numCh / pObj->createArgs.numOutQue);
                    queueId = (pFrame->channelNum / chPerQueue);
                    pFrame->channelNum = pFrame->channelNum % chPerQueue;
                    pChObj->outFrameCount++;
                    Vps_printf("frameId=%d\n",frameId);
                    Vps_printf("pFrame->addr[0][0]= 0x%08x, pFrame->addr[0][1]= 0x%08x\n",pFrame->addr[0][0], pFrame->addr[0][1]);
                    pFrame->addr[0][0] = (Ptr)Utils_tilerGetOriAddr((UInt32)pFrame->addr[0][0], UTILS_TILER_CNT_8BIT, 1,  720,288);
                    pFrame->addr[0][1] = (Ptr)Utils_tilerGetOriAddr((UInt32)pFrame->addr[0][1], UTILS_TILER_CNT_16BIT, 1, 720,288/2);
                    Vps_printf("pFrame->addr[0][0]= 0x%08x, pFrame->addr[0][1]= 0x%08x\n",pFrame->addr[0][0], pFrame->addr[0][1]);

                    /* Set the flag whether queue is filled or not */
                    sendMsgToTsk |= (1 << queueId);

                    status = Utils_bufPutFullFrame(&pObj->bufOutQue[queueId], pFrame);
                    UTILS_assert(status == FVID2_SOK);
                } /* end of if (pFrame) */
            }
            //ch2
            if (outFrameList.numFrames > 2)
            {
                frameId = 2;
                pFrame = outFrameList.frames[frameId];

                if (pFrame)
                {
                    pChObj = &pObj->linkChInfo[pFrame->channelNum];
                    /** Split the frames into both the output queues,
                     * if they are enabled. Else use output queue 0 only.
                     * Also, if output queue 1 is used, frames sent to this queue
                     * should be modified before submitting so that the
                     * pFrame->channelNum should start with 0 and not with
                     * (pObj->nsfCreateParams.numCh / 2).
                    */
                    chPerQueue =
                        (pObj->nsfCreateParams.numCh / pObj->createArgs.numOutQue);
                    queueId = (pFrame->channelNum / chPerQueue);
                    pFrame->channelNum = pFrame->channelNum % chPerQueue;
                    pChObj->outFrameCount++;
                    Vps_printf("frameId=%d\n",frameId);
                    Vps_printf("pFrame->addr[0][0]= 0x%08x, pFrame->addr[0][1]= 0x%08x\n",pFrame->addr[0][0], pFrame->addr[0][1]);
                    pFrame->addr[0][0] = (Ptr)Utils_tilerGetOriAddr((UInt32)pFrame->addr[0][0], UTILS_TILER_CNT_8BIT, 0,  720,288);
                    pFrame->addr[0][1] = (Ptr)Utils_tilerGetOriAddr((UInt32)pFrame->addr[0][1], UTILS_TILER_CNT_16BIT, 0, 720,288/2);
                    Vps_printf("pFrame->addr[0][0]= 0x%08x, pFrame->addr[0][1]= 0x%08x\n",pFrame->addr[0][0], pFrame->addr[0][1]);

                    /* Set the flag whether queue is filled or not */
                    sendMsgToTsk |= (1 << queueId);

                    status = Utils_bufPutFullFrame(&pObj->bufOutQue[queueId], pFrame);
                    UTILS_assert(status == FVID2_SOK);
                } /* end of if (pFrame) */
            }

            //ch3
            if (outFrameList.numFrames > 3)
            {
                frameId = 3;
                pFrame = outFrameList.frames[frameId];

                if (pFrame)
                {
                    pChObj = &pObj->linkChInfo[pFrame->channelNum];
                    /** Split the frames into both the output queues,
                     * if they are enabled. Else use output queue 0 only.
                     * Also, if output queue 1 is used, frames sent to this queue
                     * should be modified before submitting so that the
                     * pFrame->channelNum should start with 0 and not with
                     * (pObj->nsfCreateParams.numCh / 2).
                    */
                    chPerQueue =
                        (pObj->nsfCreateParams.numCh / pObj->createArgs.numOutQue);
                    queueId = (pFrame->channelNum / chPerQueue);
                    pFrame->channelNum = pFrame->channelNum % chPerQueue;
                    pChObj->outFrameCount++;
                    Vps_printf("frameId=%d\n",frameId);
                    Vps_printf("pFrame->addr[0][0]= 0x%08x, pFrame->addr[0][1]= 0x%08x\n",pFrame->addr[0][0], pFrame->addr[0][1]);
                    pFrame->addr[0][0] = (Ptr)Utils_tilerGetOriAddr((UInt32)pFrame->addr[0][0], UTILS_TILER_CNT_8BIT, 0,  720,288);
                    pFrame->addr[0][1] = (Ptr)Utils_tilerGetOriAddr((UInt32)pFrame->addr[0][1], UTILS_TILER_CNT_16BIT, 0, 720,288/2);
                    Vps_printf("pFrame->addr[0][0]= 0x%08x, pFrame->addr[0][1]= 0x%08x\n",pFrame->addr[0][0], pFrame->addr[0][1]);

                    /* Set the flag whether queue is filled or not */
                    sendMsgToTsk |= (1 << queueId);

                    status = Utils_bufPutFullFrame(&pObj->bufOutQue[queueId], pFrame);
                    UTILS_assert(status == FVID2_SOK);
                } /* end of if (pFrame) */
            }
////////////////////////////////////////////////////////////////////////////

        /* Send new data available command to the next link */
        for (queueId = 0; queueId < NSF_LINK_MAX_OUT_QUE; queueId++)
        {
            if (sendMsgToTsk & 0x1)
            {
                pObj->outFrameGivenCount += outFrameList.numFrames;
                /* Send data available message to next task */
                System_sendLinkCmd(pObj->createArgs.outQueParams[queueId].
                                   nextLink, SYSTEM_CMD_NEW_DATA);
            }

            sendMsgToTsk >>= 1;
            if (sendMsgToTsk == 0)
                break;
        }

        pObj->inFrameGivenCount += inFrameList[0].numFrames;

        /* Return frames back to the capture link as well */
        System_putLinksEmptyFrames(pObj->createArgs.inQueParams.prevLinkId,
                                   pObj->createArgs.inQueParams.prevLinkQueId,
                                   &inFrameList[0]);
        status = FVID2_SOK;
    }
    else
    {
#ifdef SYSTEM_DEBUG_NSF_RT
        Vps_printf(" %d: NSF: No frames available for filtering !!!\n",
                   Utils_getCurTimeInMsec());
#endif

        /* no more frame availble so exit the loop outside of this function */
        status = FVID2_EFAIL;
    }
    return status;
}