ti8148 dvrrdk开发小结

从接触这个平台到现在已接近一年时间,之前很多时间虽然一直在这个平台做应用还有部分的驱动,但是一直没真正理解这个平台到底真正的优势和技术难点在哪里,其实也就是最近搞这个平台的SWMS时才有了更进一步的认识,从底层的硬件到上层的dvrrdk的学习,学习了这个四核视频协处理平台的软件框架。

一、下面我就从TI提供的DM81xx DVR_RDK Overview来引入一些概念:

介绍

DVR RDK是一个为ti816x,ti814x,ti810x平台设计的多处理器的软件开发框架,专门优化了多路视频主要应用在DVR, NVR, Hybrid-DVR, HD-DVR 。在DVR RDK软件框架允许用户创建不同的多路视频数据流包括:视频采集、视频处理(DEI、缩放、噪声滤波、软件拼接,SWMS, OSD,运动检测等),视频编码(H264,MJPEG)、视频解码(H264、MPEG4、mpjeg)和视频显示(HDMI,hddac,CVBS等)。

DVR RDK的用户接口或API叫做McFW(多通道框架)。软件本身是建立在一个称为“Links and chains”的多处理器框架。该框架优化的多通道视频,因而成千上万的视频帧需要在不同的视频处理任务交换的应用程序。这个框架的内部接口被称为““Link API”。

DVR RDK组件

DVR RDK关键部件的总结:


软件框架

软件组件分布在四个处理器之间去共享处理:

• VPSS M3 - is used for Video capture, display, scaling, de-interlacing
• Video M3 - is used H264, MPEG4, MJPEG encode/decode
• DSP - is used for additional SW based video processing and video analytics
• A8 - is used for system control, GUI, SATA, Ethernet, USB and other IO





编程接口



McFW API

这个接口将视频系统分为四个主要子系统:

视频采集、显示、编码、解码




Link API

(1)、link api的概念

link在上图中的视频数据流中是最基本的单元模块,每个link中包含了一个基于BIOS6/Linux的任务、线程、消息盒(使用操作系统的信号量实现)。由于每个link运行一个独立的现成,因此link之间可以并行运行。消息盒是关联用户指定的link,让link之间有个互相对话的机制,用来传递信令。而对于视频流数据、帧数据的传递link实现了专门的接口来实现,只传递指针,而不是数据。
在实现上节所介绍的数据流可以通过将多个link连接来实现chain,link API允许用户Create、Start、Stop、Delete、Control各个link。在Rdk中TI基于link API进行再次封装,用于特定的应用场合,其各种参数均是为特定的产品定制,可以是相关业务的开发更迅速。

(2)、link内部结构


(3)、link的特性

视频处理的工作量可以均衡到每个核心上去执行,如下表:


-每个link都有自己独立的任务/线程用于完成视频采集或播放等处理;
-每个link都可以处理来自多个通道的视频帧数据,每个通道的视频宽高和数据格式都可以不同;
-A8作为HOST可以用来连接多个link形成数据流的链并对其进行控制;
-数据链被建立并启动时,数据链中的每个link将和它的下游link进行帧数据的交互;
-links之间的帧数据交互可以在多个核心之间进行,并且并不需要A8 HOST的干涉,从而降低A8的开销;
-在数据链运行过程中用户可以发送控制信令给任意link来动态设置相关的link参数;

(4)、link接口

link接口可以分成以下几类:
-link API——被用户调用来配置和控制link的接口;
-Inter link API——被其他links调用来交换帧数据的接口;
-link output queue——被其他links通过Inter Link API接口实用的帧buffer队列;

(5)、link间的消息传递

每个Link通过一个32位的该LinkId来识别,ID高4位标识了这个Link是在哪个核上运行,低24位标识了该Link的名称:


每个Link API都需要这个LinkID参数来发送消息,当用户发送消息到一个Link时,根据这ID函数内部判断这个消息是发给本地的Link还是远端核心的Link;如果是本地的直接调用BIOS/LINUX API函数,否则就通过Syslink模块的MessageQ发送这个消息到指定的核心,让对端的核心调用对应的函数处理。

(6)、link API


(7)、Inter link API


在每个link中必须实现一些函数并在初始化时注册这些函数指针给link管理的核心模块,用于帧数据的获取、释放、dump相关状态等。
对于任一个link想从它的上游link获取帧数据都需要调用link管理核心函数System_getLinksFullFrames(),该函数内部会发送消息到对应的上游link,触发该link向管理模块注册的回调函数System_LinkGetOutputFramesCb()将帧数据传递给该link;
同样的,在当一个link想释放处理完毕的帧buffer给上游link时需要调用link管理核心函数System_putLinksEmptyFrames(),该函数内部会发送消息到对应的上游link,触发它注册的回调函数System_LinkPutEmptyFramesCb()将帧buffer回收,用于后续的数据处理;
建立chain时,你肯定还会关注一个信息,那就是上游link的相关参数如何传递给下游的link,从源程序仔细琢磨琢磨就可以看出来,和上面的处理类似,所有有下游link的link都会注册一个System_GetLinkInfoCb()的回调函数,在下游link的driver中会在创建driver时调用System_linkGetInfo()函数来获取上游link的相关参数。
通过上述的方法,对于一个link来说就不需要关心和它交互的是哪一个link,所有的寻址都通过linkID来自动查找,并且同一个link实现可以和不同的link交互,而不需要改变函数的实现。

(8)、Link Output Queues 的管理

一个Link可以有一个或多个输出队列用来存放采集到的或处理完毕的帧数据,每个Link的输出队列内存由自己分配;
大多数Links只有一个输出队列,但是有些link有多个,从而可以实现多路不同的输出数据流满足不同的应用需求,例如,Noise filter Link可以输出16路帧数据到2个输出队列,每个输出队列输出8路通道数据跟别给2个DEI Links模块处理。
一个输出队列中可以有多个视频channels的数据,每个channel可以有不同的大小和数据格式;
数据结构 FVID2_Frame是在VPSS驱动中定义的,Links之间就通过该结构参数传递帧数据的信息,如帧数据的Buf指针,而帧数据本身并不会被拷贝,从而节省内存开销;
当一个Link采集完或处理完一帧数据后会发送一个消息“SYSTEM_CMD_NEW_DATA”给下游的Link,从而通知它有数据可取;当下游Link收到该消息后会调用System_getLinksFullFrames()函数来获取对用的帧数据,处理完后再调用System_putLinksEmptyFrames()函数来归还给上游Link继续使用。
因此一个Link需要知道:
--上游Link的LinkID和QueID,从而从该队列里面获取帧数据
--下游LinkID,从而在有新数据产生时通知下游Link来取
上游Link的LinkID和QueID 以及下游LinkID 都是在System_linkCreate()时由A8 HOST端来指定的。

(9)、IPC link核间帧数据交互

IPC Link,是用来多核之间的帧数据传递的。
如VPSS上的采集Link想把帧数据发送给Video Link处理,先将帧数据传递给本地的IPC Link,然后IPC Link再通过Syslink/IPC发送到Video Link上的IPC Link,然后再转发给Video Link,这样的话对于采集Link的实现来说就非常清晰简单,它的实现都是发送给本地的另一个Link;
IPC Link的实现有点复杂,因为它涉及的帧数据传递是在多个核之间,这里面就牵扯到cache的一致性问题,考虑到每个核的特性以及高效性,总共设计了3个内部Links用于帧数据的传递机制:
Intra-processor links
即同一核心内部的link,如采集与降噪之间的帧数据传递,这种内部的link间传递帧数据都是在VPSS M3内部完成,因此采用简单且高效的队列机制实现。
Inter M3 (Video / VPSS) links
即M3内部核心之间的link,由于Video和Vpss所在的2个M3核心是同属于一个双核M3处理器,它们的cache是共享的;如降噪模块(VPSS NF)到编码模块(VIDEO Enc)之间传递帧数据,带有Notify的IPC ListMP机制被用来在这2个M3核心之间传递帧信息(FVID2_Frame),该过程中不需要任何cache操作和地址转换。
Inter processor (M3 to A8 or DSP)
即处理器内部核心之间,如编码(VideoM3)到BitStream In(HostA8)之间传递帧数据,同样使用带Notify的IPC ListMP机制在2个核心之间传递帧信息(FVID2_Frame),但该过程中需要做cache同步和地址转换操作。

(10)、chain数据链路的建立

一个Chain是由多个links按照一定的应用需求按顺序连接成一条视频处理的数据流。
一个Chain可以销毁后重新按照新的需求组成新的Chain,不需要重启系统。
Chain创建是特别需要相关link的顺序
-通过System_linkCreate()函数按照由source>>sink 的顺序创建需要的Links,Source Link即没有上游Link的Link,如:视频采集;Sink Link是没有下游Link的Link,如:视频播放;这个创建顺序是非常重要的,因为一个Link创建时它会查询上游Link的一些信息,如上游Link需要的channel的个数和属性,从而按照这些参数配置自己。
-下一步调用System_linkStart()函数启动每个Link,启动顺序一般从Sink Link往前到Sorce Link,当然你也可以不按照这个顺序,不过不推荐,因为这样可以保证每个Link在它的上游Link启动前准备好接收数据,避免过多的缓冲引入额外的时延。
-当一个Chain运行后控制命令就可以发送到各个Links来控制它,如调用System_linkControl()函数发送改变画面合成风格的命令给相应的Link,具体的命令定义由每个Link的功能实现来决定;
-注意:一般来说System_linkControl()函数是在System_linkCreate()创建了Link之后才能调用,不过有些控制命令可以在System_linkCreate()调用之前调用,以完成Link创建之前必须的一些初始化,如复位;
-当Chain工作完成或销毁时可以调用System_linkStop()函数先停止每个Link,注意:停止的顺序必须从Source开始依次到Sink结束;因为一个Link可能阻塞着等待下游Link释放当前Link的输出Buffer,如果下游Link先停止的话当前Link可能会出于wait for ever的状态而永久退不出来,因此上游Link必须先停止,之后才能停止下游Link;
-最后等所有Link全部停止后,可以调用System_linkDelete()函数删除所有Links,删除顺序没有要求;
-当Chain销毁后就可以按照之前的顺序重新创建一个新的Chain来完成另一个工作了。


关键术语




二、实例

基于rdk框架的一个四库输入两路输出的一个实例:

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

/* This usecase assumes that all 3 outputs - D1 <h.264> + CIF <h.264> + D1 <MJPEG> are enabled */
/*------------------------------ D1 <h.264> + CIF <h.264> + D1 <MJPEG> -------------------------------------


                  Capture (YUV422I) 4CH D1 60fps
                              |
                              |
                              |
                              |
                              DEI
                              |+------------------------------------------------------------------------
                              |                                            |                           |
                       (DEI-SC YUV422I)                              (VIP-SC YUV420 )            (VIP-SC1 YUV420 )
                              D1                                        D1 |                        CIF|
                              |                                            |                           |
                              |                                            |                           |
                              |                                            |                           |
                        -----------------                                  |                           |
                         D1_DUP_LINK_IDX                                   |                           |
                        -----------------                                  |                           |
                              |     |                                      |                           |
                              |     |                                      |                           |
                              |     |                                      |                           |
                              |    NSF                                     |                           |
                              |  (YUV420)                                  |                           |
                              |     |                                      |                           |
                              |     |                                      |          |-----------------
                              |     |-----------------------------         |          |
                              |                                  |         |          |
                              |                      <D1-MJPEG> 2|         |0         | 1
                              |                                  |         |<D1-H.264>| <CIF-H.264>
                              |                                  |         |          |
                              |                                  |         |          |
                              |                            ---------------------------------
                              |                                   D1_CIF_MERGE_LINK_IDX
                              |                            ---------------------------------
                              |                                            |
                              |                                            |
                              |                                            |
                              |                                     FRAMESOUT(VPSS)---------------<<<processLink>>>----FramesInDSP--------ALG_LINK <OSD, SCD Algs>
                              |                                            |
                              |                                            |
                              |                                            |
                              |                                            |
                              |                                       IPCM3OUT(VPSS)------IPCM3IN(VID)----ENC-----IPCBITS_RTOSOUT(VID)-----IPCBITS_HLOSIN(HOST)-----FILEOUT
                              |                                                                                                                                  |
                              |                                                                                                                                  |
                              |                                                                                                                                  |
                              |                                                                                                                                  |
                              |+--------------------------IPCM3IN(VPSS)---------IPCM3OUT(VID)---------DEC---------------IPCBITS_RTOSIN(VID)-----------IPCBITS_HLOSOUT(HOST)
                              |
                              |
                      LIVE_DECODE_MERGE_LINK_IDX
                              |
                              |
                              |
                        LIVE_DECODE_DUP_LINK_IDX
                             |||
                             |||
                             |||
             +---------------+|+----------------+
             |                                  |
             |                                  |
          SW Mosaic 1                       SW Mosaic 0
         (SC2 YUV422I)                     (SC5 YUV422I)
             |                                  |
             |                                  |
             |                                  |
             |                                  |
             |                                  |
             |                                  |
       -------------                       -------------
          DISPLAY 1                           DISPLAY 0
       -------------                       -------------   <tied>
          <SDTV>                          <On-Chip HDMI> --------- <Off-Chip HDMI>
         PAL/NTSC                            1080p60                 1080p60


*/


#include "mcfw/src_linux/mcfw_api/usecases/multich_common.h"
#include "mcfw/src_linux/mcfw_api/usecases/multich_ipcbits.h"

// Keeping TILER disabled for 4D1 usecase
#define TILER_ENABLE    FALSE



/* =============================================================================
 * Use case code
 * =============================================================================
 */
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  = 16,
        .DecChList = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13 , 14, 15},
    },

};

// #define     ADD_NSF_AFTER_CAPTURE

#define     NUM_MERGE_LINK                          2
#define     D1_CIF_MERGE_LINK_IDX                  0
#define     LIVE_DECODE_MERGE_LINK_IDX             1

#define     NUM_DUP_LINK                            2
#define     D1_DUP_LINK_IDX                         0
#define     LIVE_DECODE_DUP_LINK_IDX                1

#if(defined(TI_814X_BUILD) || defined(DDR_MEM_256M))
#define     NUM_CAPTURE_BUFFERS          8
#define     NUM_NSF_BUFFERS              4
#define     NUM_ENCODE_D1_BUFFERS       4
#define     NUM_ENCODE_CIF_BUFFERS       4
#define     NUM_DECODE_BUFFERS           4
#define     NUM_SWMS_MAX_BUFFERS         8
#define     BIT_BUF_LENGTH_LIMIT_FACTOR_SD    4
#else
#define     NUM_CAPTURE_BUFFERS          8
#define     NUM_NSF_BUFFERS              6
#define     NUM_ENCODE_D1_BUFFERS       6
#define     NUM_ENCODE_CIF_BUFFERS       6
#define     NUM_DECODE_BUFFERS           6
#define     NUM_SWMS_MAX_BUFFERS         8
#define     BIT_BUF_LENGTH_LIMIT_FACTOR_SD    6
#endif

#define     MAX_BUFFERING_QUEUE_LEN_PER_CH    (50)


#define     NUM_CAPTURE_DEVICES          1

/* This usecase assumes CIF <secondary out>, MJPEG are enabled */
Void MultiCh_createProgressive4D1VcapVencVdecVdis()
{
    CaptureLink_CreateParams    capturePrm;
    NsfLink_CreateParams        nsfPrm;
    DeiLink_CreateParams        deiPrm;
    MergeLink_CreateParams      mergePrm[NUM_MERGE_LINK];
    DupLink_CreateParams        dupPrm[NUM_DUP_LINK];
    static SwMsLink_CreateParams       swMsPrm[VDIS_DEV_MAX];
    DisplayLink_CreateParams    displayPrm[VDIS_DEV_MAX];
    IpcLink_CreateParams        ipcOutVpssPrm;
    IpcLink_CreateParams        ipcInVpssPrm;
    IpcLink_CreateParams        ipcOutVideoPrm;
    IpcLink_CreateParams        ipcInVideoPrm;
    EncLink_CreateParams        encPrm;
    DecLink_CreateParams        decPrm;
    IpcBitsOutLinkHLOS_CreateParams   ipcBitsOutHostPrm;
    IpcBitsOutLinkRTOS_CreateParams   ipcBitsOutVideoPrm;
    IpcBitsInLinkHLOS_CreateParams    ipcBitsInHostPrm[2];

    IpcBitsInLinkRTOS_CreateParams    ipcBitsInVideoPrm;
    CaptureLink_VipInstParams         *pCaptureInstPrm;
    CaptureLink_OutParams             *pCaptureOutPrm;
    IpcFramesInLinkRTOS_CreateParams  ipcFramesInDspPrm;
    IpcFramesOutLinkRTOS_CreateParams ipcFramesOutVpssPrm;
    AlgLink_CreateParams              dspAlgPrm;

    System_LinkInfo                   bitsProducerLinkInfo;
    UInt32 mergeId[NUM_MERGE_LINK];
    UInt32 dupId[NUM_DUP_LINK];
    UInt32 ipcOutVpssId, ipcInVpssId;
    UInt32 ipcOutVideoId, ipcInVideoId;

    IpcBitsOutLinkRTOS_CreateParams   ipcBitsOutDspPrm;

    VCAP_DEVICE_CREATE_PARAM_S        vidDecVideoModeArgs[NUM_CAPTURE_DEVICES];

    UInt32 vipInstId;
    UInt32 i, j;
    Bool   enableAlgLink;
    Bool   enableScd     = gVsysModuleContext.vsysConfig.enableScd;
    Bool   enableOsd     = gVsysModuleContext.vsysConfig.enableOsd;
    UInt32 chId;

 #ifdef     ADD_NSF_AFTER_CAPTURE
    NsfLink_CreateParams        nsfPrm2;
#endif

    enableScd = TRUE;

    enableAlgLink = FALSE;
    if(enableOsd||enableScd)
        enableAlgLink = TRUE;

    MULTICH_INIT_STRUCT(IpcLink_CreateParams,ipcOutVpssPrm);
    MULTICH_INIT_STRUCT(IpcLink_CreateParams,ipcInVpssPrm);
    MULTICH_INIT_STRUCT(IpcLink_CreateParams,ipcOutVideoPrm);
    MULTICH_INIT_STRUCT(IpcLink_CreateParams,ipcInVideoPrm);
    MULTICH_INIT_STRUCT(IpcBitsOutLinkHLOS_CreateParams,ipcBitsOutHostPrm);
    MULTICH_INIT_STRUCT(IpcBitsOutLinkRTOS_CreateParams,ipcBitsOutVideoPrm);
    MULTICH_INIT_STRUCT(IpcBitsOutLinkRTOS_CreateParams,ipcBitsOutDspPrm);

    MULTICH_INIT_STRUCT(IpcBitsInLinkHLOS_CreateParams,ipcBitsInHostPrm[0]);
    MULTICH_INIT_STRUCT(IpcBitsInLinkHLOS_CreateParams,ipcBitsInHostPrm[1]);
    MULTICH_INIT_STRUCT(IpcBitsInLinkRTOS_CreateParams,ipcBitsInVideoPrm);
    MULTICH_INIT_STRUCT(DecLink_CreateParams, decPrm);
    MULTICH_INIT_STRUCT(IpcFramesInLinkRTOS_CreateParams,ipcFramesInDspPrm);
    MULTICH_INIT_STRUCT(IpcFramesOutLinkRTOS_CreateParams,ipcFramesOutVpssPrm);
    MULTICH_INIT_STRUCT(EncLink_CreateParams, encPrm);
    MULTICH_INIT_STRUCT(AlgLink_CreateParams, dspAlgPrm);
    for (i = 0; i < VDIS_DEV_MAX;i++)
    {
        MULTICH_INIT_STRUCT(DisplayLink_CreateParams,
                            displayPrm[i]);
        MULTICH_INIT_STRUCT(SwMsLink_CreateParams ,swMsPrm[i]);
    }

    MULTICH_INIT_STRUCT(NsfLink_CreateParams, nsfPrm);
    MULTICH_INIT_STRUCT(DeiLink_CreateParams, deiPrm);

    printf("\n********* Entered usecase 4CH <814x> Enc/Dec OSD %s SCD %s \n\n",
            enableOsd == TRUE ? "Enabled" : "Disabled",
            enableScd == TRUE ? "Enabled" : "Disabled"
            );

    MultiCh_detectBoard();



    System_linkControl(
        SYSTEM_LINK_ID_M3VPSS,
        SYSTEM_M3VPSS_CMD_RESET_VIDEO_DEVICES,
        NULL,
        0,
        TRUE
        );



    System_linkControl(
        SYSTEM_LINK_ID_M3VIDEO,
        SYSTEM_COMMON_CMD_SET_CH2IVAHD_MAP_TBL,
        &systemVid_encDecIvaChMapTbl,
        sizeof(SystemVideo_Ivahd2ChMap_Tbl),
        TRUE
    );




    vipInstId = 0;

    gVcapModuleContext.captureId    = SYSTEM_LINK_ID_CAPTURE;

    if(enableAlgLink)
    {
        gVcapModuleContext.dspAlgId[0] = SYSTEM_LINK_ID_VIDEO_ALG_0  ;
    }



    gVcapModuleContext.nsfId[0]     = SYSTEM_LINK_ID_NSF_0;
#ifdef     ADD_NSF_AFTER_CAPTURE
    gVcapModuleContext.nsfId[1]     =SYSTEM_LINK_ID_NSF_1;
#endif
    gVcapModuleContext.deiId[0]     = SYSTEM_LINK_ID_DEI_0;
    gVencModuleContext.encId        = SYSTEM_LINK_ID_VENC_0;
    gVdecModuleContext.decId        = SYSTEM_LINK_ID_VDEC_0;

    gVdisModuleContext.swMsId[0]      = SYSTEM_LINK_ID_SW_MS_MULTI_INST_0;
    gVdisModuleContext.swMsId[1]      = SYSTEM_LINK_ID_SW_MS_MULTI_INST_1;

    swMsPrm[0].numSwMsInst = 1;
    swMsPrm[1].numSwMsInst = 1;

    /* use AUX scaler (SC2), since SC1 is used for DEI */
    swMsPrm[0].swMsInstId[0] = SYSTEM_SW_MS_SC_INST_DEI_SC_NO_DEI;
    swMsPrm[1].swMsInstId[0] = SYSTEM_SW_MS_SC_INST_SC5;

    gVdisModuleContext.displayId[0] = SYSTEM_LINK_ID_DISPLAY_0; /* ON AND OFF CHIP HDMI */
    gVdisModuleContext.displayId[1] = SYSTEM_LINK_ID_DISPLAY_2; /* SDTV */

    mergeId[LIVE_DECODE_MERGE_LINK_IDX]     = SYSTEM_VPSS_LINK_ID_MERGE_0;
    mergeId[D1_CIF_MERGE_LINK_IDX]          = SYSTEM_VPSS_LINK_ID_MERGE_1;

    dupId[D1_DUP_LINK_IDX]              = SYSTEM_VPSS_LINK_ID_DUP_0;
    dupId[LIVE_DECODE_DUP_LINK_IDX]     = SYSTEM_VPSS_LINK_ID_DUP_1;

    ipcOutVpssId = SYSTEM_VPSS_LINK_ID_IPC_OUT_M3_0;
    ipcInVideoId = SYSTEM_VIDEO_LINK_ID_IPC_IN_M3_0;
    ipcOutVideoId= SYSTEM_VIDEO_LINK_ID_IPC_OUT_M3_0;
    ipcInVpssId  = SYSTEM_VPSS_LINK_ID_IPC_IN_M3_0;

    gVencModuleContext.ipcBitsOutRTOSId  = SYSTEM_VIDEO_LINK_ID_IPC_BITS_OUT_0;
    gVencModuleContext.ipcBitsInHLOSId   = SYSTEM_HOST_LINK_ID_IPC_BITS_IN_0;
    gVdecModuleContext.ipcBitsOutHLOSId  = SYSTEM_HOST_LINK_ID_IPC_BITS_OUT_0;
    gVdecModuleContext.ipcBitsInRTOSId  = SYSTEM_VIDEO_LINK_ID_IPC_BITS_IN_0;



    CaptureLink_CreateParams_Init(&capturePrm);
#ifdef     ADD_NSF_AFTER_CAPTURE
    capturePrm.outQueParams[0].nextLink   = gVcapModuleContext.nsfId[1];
#else
    capturePrm.outQueParams[0].nextLink   = gVcapModuleContext.deiId[0];
#endif
    capturePrm.numVipInst                 = 1;
    capturePrm.tilerEnable                = FALSE;
    capturePrm.numBufsPerCh               = NUM_CAPTURE_BUFFERS;
    capturePrm.maxBlindAreasPerCh         = 4;

    pCaptureInstPrm                     = &capturePrm.vipInst[0];
    pCaptureInstPrm->vipInstId          = (SYSTEM_CAPTURE_INST_VIP0_PORTA+
                                          vipInstId)%SYSTEM_CAPTURE_INST_MAX;
    pCaptureInstPrm->videoDecoderId     = SYSTEM_DEVICE_VID_DEC_TVP5158_DRV;
    pCaptureInstPrm->inDataFormat       = SYSTEM_DF_YUV422P;
    pCaptureInstPrm->standard           = SYSTEM_STD_MUX_4CH_D1;
    pCaptureInstPrm->numOutput          = 1;

    pCaptureOutPrm                      = &pCaptureInstPrm->outParams[0];
    pCaptureOutPrm->dataFormat          = SYSTEM_DF_YUV422I_YUYV;
    pCaptureOutPrm->scEnable            = FALSE;
    pCaptureOutPrm->scOutWidth          = 0;
    pCaptureOutPrm->scOutHeight         = 0;
    pCaptureOutPrm->outQueId            = 0;

    for(i = 0; i < NUM_CAPTURE_DEVICES; i++)
    {
        vidDecVideoModeArgs[i].vipInstId        = SYSTEM_CAPTURE_INST_VIP0_PORTA+i;
        vidDecVideoModeArgs[i].deviceId         = DEVICE_VID_DEC_TVP5158_DRV;
        vidDecVideoModeArgs[i].numChInDevice    = 4;

        vidDecVideoModeArgs[i].modeParams.videoIfMode        = DEVICE_CAPT_VIDEO_IF_MODE_8BIT;
        vidDecVideoModeArgs[i].modeParams.videoDataFormat    = SYSTEM_DF_YUV422P;
        vidDecVideoModeArgs[i].modeParams.standard           = SYSTEM_STD_MUX_4CH_D1;
        vidDecVideoModeArgs[i].modeParams.videoCaptureMode   =
                    DEVICE_CAPT_VIDEO_CAPTURE_MODE_MULTI_CH_PIXEL_MUX_EMBEDDED_SYNC;
        vidDecVideoModeArgs[i].modeParams.videoSystem        =
                                      DEVICE_VIDEO_DECODER_VIDEO_SYSTEM_AUTO_DETECT;
        vidDecVideoModeArgs[i].modeParams.videoCropEnable    = FALSE;
        vidDecVideoModeArgs[i].modeParams.videoAutoDetectTimeout = -1;
    }

    Vcap_configVideoDecoder(vidDecVideoModeArgs, NUM_CAPTURE_DEVICES);


#ifdef     ADD_NSF_AFTER_CAPTURE
    nsfPrm2.bypassNsf                          = TRUE;
    nsfPrm2.tilerEnable                          = FALSE;
    nsfPrm2.inQueParams.prevLinkId          = gVcapModuleContext.captureId;
    nsfPrm2.inQueParams.prevLinkQueId     = 0;
    nsfPrm2.numOutQue                        = 1;
    nsfPrm2.outQueParams[0].nextLink      = gVcapModuleContext.deiId[0];
    nsfPrm2.numBufsPerCh                     = NUM_NSF_BUFFERS;
    nsfPrm2.inputFrameRate                    = 30;
    nsfPrm2.outputFrameRate                  = 30;

    deiPrm.inQueParams.prevLinkId = gVcapModuleContext.nsfId[1];
#else
    deiPrm.inQueParams.prevLinkId = gVcapModuleContext.captureId;
#endif
    deiPrm.inQueParams.prevLinkQueId  = 0;

    /* Set Output Scaling at DEI based on ratio */
    deiPrm.outScaleFactor[DEI_LINK_OUT_QUE_DEI_SC][0].scaleMode = DEI_SCALE_MODE_RATIO;
    deiPrm.outScaleFactor[DEI_LINK_OUT_QUE_DEI_SC][0].ratio.widthRatio.numerator = 1;
    deiPrm.outScaleFactor[DEI_LINK_OUT_QUE_DEI_SC][0].ratio.widthRatio.denominator = 1;
    deiPrm.outScaleFactor[DEI_LINK_OUT_QUE_DEI_SC][0].ratio.heightRatio.numerator = 1;
    deiPrm.outScaleFactor[DEI_LINK_OUT_QUE_DEI_SC][0].ratio.heightRatio.denominator = 1;
    for (i=1; i < DEI_LINK_MAX_CH; i++)
        deiPrm.outScaleFactor[DEI_LINK_OUT_QUE_DEI_SC][i] = deiPrm.outScaleFactor[DEI_LINK_OUT_QUE_DEI_SC][0];

    deiPrm.outScaleFactor[DEI_LINK_OUT_QUE_VIP_SC][0].scaleMode = DEI_SCALE_MODE_RATIO;
    deiPrm.outScaleFactor[DEI_LINK_OUT_QUE_VIP_SC][0].ratio.heightRatio.numerator = 1;
    deiPrm.outScaleFactor[DEI_LINK_OUT_QUE_VIP_SC][0].ratio.heightRatio.denominator = 1;
    deiPrm.outScaleFactor[DEI_LINK_OUT_QUE_VIP_SC][0].ratio.widthRatio.numerator = 1;
    deiPrm.outScaleFactor[DEI_LINK_OUT_QUE_VIP_SC][0].ratio.widthRatio.denominator = 1;
    for (i=1; i < DEI_LINK_MAX_CH; i++)
        deiPrm.outScaleFactor[DEI_LINK_OUT_QUE_VIP_SC][i] = deiPrm.outScaleFactor[DEI_LINK_OUT_QUE_VIP_SC][0];

    deiPrm.outScaleFactor[DEI_LINK_OUT_QUE_VIP_SC_SECONDARY_OUT][0].scaleMode = DEI_SCALE_MODE_RATIO;
    deiPrm.outScaleFactor[DEI_LINK_OUT_QUE_VIP_SC_SECONDARY_OUT][0].ratio.heightRatio.numerator = 1;
    deiPrm.outScaleFactor[DEI_LINK_OUT_QUE_VIP_SC_SECONDARY_OUT][0].ratio.heightRatio.denominator = 2;
    deiPrm.outScaleFactor[DEI_LINK_OUT_QUE_VIP_SC_SECONDARY_OUT][0].ratio.widthRatio.numerator = 1;
    deiPrm.outScaleFactor[DEI_LINK_OUT_QUE_VIP_SC_SECONDARY_OUT][0].ratio.widthRatio.denominator = 2;
    for (i=1; i < DEI_LINK_MAX_CH; i++)
        deiPrm.outScaleFactor[DEI_LINK_OUT_QUE_VIP_SC_SECONDARY_OUT][i] = deiPrm.outScaleFactor[DEI_LINK_OUT_QUE_VIP_SC_SECONDARY_OUT][0];

    deiPrm.enableOut[DEI_LINK_OUT_QUE_DEI_SC]                        = TRUE;
    deiPrm.enableOut[DEI_LINK_OUT_QUE_VIP_SC]                        = TRUE;
    deiPrm.enableOut[DEI_LINK_OUT_QUE_VIP_SC_SECONDARY_OUT]          = TRUE;

    deiPrm.outQueParams[DEI_LINK_OUT_QUE_DEI_SC].nextLink                   = dupId[D1_DUP_LINK_IDX];
    deiPrm.outQueParams[DEI_LINK_OUT_QUE_VIP_SC].nextLink                   = mergeId[D1_CIF_MERGE_LINK_IDX];
    deiPrm.outQueParams[DEI_LINK_OUT_QUE_VIP_SC_SECONDARY_OUT].nextLink     = mergeId[D1_CIF_MERGE_LINK_IDX];

    deiPrm.tilerEnable[DEI_LINK_OUT_QUE_VIP_SC]          = TILER_ENABLE;
    deiPrm.comprEnable                                   = FALSE;
    deiPrm.setVipScYuv422Format                          = FALSE;

    dupPrm[D1_DUP_LINK_IDX].inQueParams.prevLinkId         = gVcapModuleContext.deiId[0];
    dupPrm[D1_DUP_LINK_IDX].inQueParams.prevLinkQueId      = DEI_LINK_OUT_QUE_DEI_SC;
    dupPrm[D1_DUP_LINK_IDX].numOutQue                      = 2;
    dupPrm[D1_DUP_LINK_IDX].outQueParams[0].nextLink       = mergeId[LIVE_DECODE_MERGE_LINK_IDX];
    dupPrm[D1_DUP_LINK_IDX].outQueParams[1].nextLink       = gVcapModuleContext.nsfId[0];
    dupPrm[D1_DUP_LINK_IDX].notifyNextLink                 = TRUE;

    nsfPrm.bypassNsf                        = TRUE;
    nsfPrm.tilerEnable                      = TILER_ENABLE;
    nsfPrm.inQueParams.prevLinkId           = dupId[D1_DUP_LINK_IDX];
    nsfPrm.inQueParams.prevLinkQueId        = 1;
    nsfPrm.numOutQue                        = 1;
    nsfPrm.outQueParams[0].nextLink         = mergeId[D1_CIF_MERGE_LINK_IDX];
    nsfPrm.numBufsPerCh                     = NUM_NSF_BUFFERS;
    nsfPrm.inputFrameRate = 30;
    nsfPrm.outputFrameRate = 1;

    /* Merge Q0 - D1 <from VIP-SC>, Q1 - CIF <from VIP-SC_SECONDARY>, Q2 -D1 for MJPEG <from DEI-SC>  */
    mergePrm[D1_CIF_MERGE_LINK_IDX].inQueParams[0].prevLinkId       = gVcapModuleContext.deiId[0];
    mergePrm[D1_CIF_MERGE_LINK_IDX].inQueParams[0].prevLinkQueId    = DEI_LINK_OUT_QUE_VIP_SC;
    mergePrm[D1_CIF_MERGE_LINK_IDX].inQueParams[1].prevLinkId       = gVcapModuleContext.deiId[0];
    mergePrm[D1_CIF_MERGE_LINK_IDX].inQueParams[1].prevLinkQueId    = DEI_LINK_OUT_QUE_VIP_SC_SECONDARY_OUT;
    mergePrm[D1_CIF_MERGE_LINK_IDX].inQueParams[2].prevLinkId       = gVcapModuleContext.nsfId[0];
    mergePrm[D1_CIF_MERGE_LINK_IDX].inQueParams[2].prevLinkQueId    = 0;

    mergePrm[D1_CIF_MERGE_LINK_IDX].notifyNextLink                  = TRUE;
    mergePrm[D1_CIF_MERGE_LINK_IDX].numInQue = 3;

    ipcOutVpssPrm.inQueParams.prevLinkQueId    = 0;
        mergePrm[D1_CIF_MERGE_LINK_IDX].outQueParams.nextLink  = ipcOutVpssId;
        ipcOutVpssPrm.inQueParams.prevLinkId                   = mergeId[D1_CIF_MERGE_LINK_IDX];

    ipcOutVpssPrm.numOutQue = 1;
    ipcOutVpssPrm.outQueParams[0].nextLink     = ipcInVideoId;
    ipcOutVpssPrm.notifyNextLink               = TRUE;
    ipcOutVpssPrm.notifyPrevLink               = TRUE;
    ipcOutVpssPrm.noNotifyMode                 = FALSE;

    ipcInVideoPrm.inQueParams.prevLinkId       = ipcOutVpssId;
    ipcInVideoPrm.inQueParams.prevLinkQueId    = 0;
    ipcInVideoPrm.numOutQue                    = 1;
    if (enableAlgLink)
    {
		ipcInVideoPrm.outQueParams[0].nextLink     = gVcapModuleContext.dspAlgId[0];

		dspAlgPrm.inQueParams.prevLinkId           = ipcInVideoId;
		dspAlgPrm.inQueParams.prevLinkQueId        = 0;
		dspAlgPrm.outQueParams[ALG_LINK_FRAMES_OUT_QUE].nextLink = gVencModuleContext.encId;
    }
	else {
		ipcInVideoPrm.outQueParams[0].nextLink     = gVencModuleContext.encId;
	}
    ipcInVideoPrm.notifyNextLink               = TRUE;
    ipcInVideoPrm.notifyPrevLink               = TRUE;
    ipcInVideoPrm.noNotifyMode                 = FALSE;


    {
        EncLink_ChCreateParams *pLinkChPrm;
        EncLink_ChDynamicParams *pLinkDynPrm;
        VENC_CHN_DYNAMIC_PARAM_S *pDynPrm;
        VENC_CHN_PARAMS_S *pChPrm;

        EncLink_CreateParams_Init(&encPrm);

        encPrm.numBufPerCh[0] = NUM_ENCODE_D1_BUFFERS;
        encPrm.numBufPerCh[1] = NUM_ENCODE_CIF_BUFFERS;

        /* Primary Stream Params - D1 */
        for (i=0; i<gVencModuleContext.vencConfig.numPrimaryChn; i++)
        {
            pLinkChPrm  = &encPrm.chCreateParams[i];
            pLinkDynPrm = &pLinkChPrm->defaultDynamicParams;

            pChPrm      = &gVencModuleContext.vencConfig.encChannelParams[i];
            pDynPrm     = &pChPrm->dynamicParam;

            pLinkChPrm->format                  = IVIDEO_H264HP;
            pLinkChPrm->profile                 = gVencModuleContext.vencConfig.h264Profile[i];
            pLinkChPrm->dataLayout              = VCODEC_FIELD_SEPARATED;
            pLinkChPrm->fieldMergeEncodeEnable  = FALSE;
            pLinkChPrm->enableAnalyticinfo      = pChPrm->enableAnalyticinfo;
            pLinkChPrm->enableWaterMarking      = pChPrm->enableWaterMarking;
            pLinkChPrm->maxBitRate              = pChPrm->maxBitRate;
            pLinkChPrm->encodingPreset          = pChPrm->encodingPreset;
            pLinkChPrm->rateControlPreset       = pChPrm->rcType;
            pLinkChPrm->enableSVCExtensionFlag  = pChPrm->enableSVCExtensionFlag;
            pLinkChPrm->numTemporalLayer        = pChPrm->numTemporalLayer;

            pLinkDynPrm->intraFrameInterval     = pDynPrm->intraFrameInterval;
            pLinkDynPrm->targetBitRate          = pDynPrm->targetBitRate;
            pLinkDynPrm->interFrameInterval     = 1;
            pLinkDynPrm->mvAccuracy             = IVIDENC2_MOTIONVECTOR_QUARTERPEL;
            pLinkDynPrm->inputFrameRate         = pDynPrm->inputFrameRate;
            pLinkDynPrm->rcAlg                  = pDynPrm->rcAlg;
            pLinkDynPrm->qpMin                  = pDynPrm->qpMin;
            pLinkDynPrm->qpMax                  = pDynPrm->qpMax;
            pLinkDynPrm->qpInit                 = pDynPrm->qpInit;
            pLinkDynPrm->vbrDuration            = pDynPrm->vbrDuration;
            pLinkDynPrm->vbrSensitivity         = pDynPrm->vbrSensitivity;
        }
        /* Secondary Out <CIF> Params */
        for (i=gVencModuleContext.vencConfig.numPrimaryChn, j=VENC_PRIMARY_CHANNELS;
              i<(gVencModuleContext.vencConfig.numPrimaryChn
                       + gVencModuleContext.vencConfig.numSecondaryChn);
                i++, j++)
        {
            pLinkChPrm  = &encPrm.chCreateParams[i];
            pLinkDynPrm = &pLinkChPrm->defaultDynamicParams;

            pChPrm      = &gVencModuleContext.vencConfig.encChannelParams[j];
            pDynPrm     = &pChPrm->dynamicParam;

            pLinkChPrm->format                  = IVIDEO_H264HP;
            pLinkChPrm->profile                 = gVencModuleContext.vencConfig.h264Profile[i];
            pLinkChPrm->dataLayout              = VCODEC_FIELD_SEPARATED;
            pLinkChPrm->fieldMergeEncodeEnable  = FALSE;
            pLinkChPrm->enableAnalyticinfo      = pChPrm->enableAnalyticinfo;
            pLinkChPrm->enableWaterMarking      = pChPrm->enableWaterMarking;
            pLinkChPrm->maxBitRate              = pChPrm->maxBitRate;
            pLinkChPrm->encodingPreset          = pChPrm->encodingPreset;
            pLinkChPrm->rateControlPreset       = pChPrm->rcType;
            pLinkChPrm->enableSVCExtensionFlag  = pChPrm->enableSVCExtensionFlag;
            pLinkChPrm->numTemporalLayer        = pChPrm->numTemporalLayer;

            pLinkDynPrm->intraFrameInterval     = pDynPrm->intraFrameInterval;
            pLinkDynPrm->targetBitRate          = pDynPrm->targetBitRate;
            pLinkDynPrm->interFrameInterval     = 1;
            pLinkDynPrm->mvAccuracy             = IVIDENC2_MOTIONVECTOR_QUARTERPEL;
            pLinkDynPrm->inputFrameRate         = pDynPrm->inputFrameRate;
            pLinkDynPrm->qpMin                  = pDynPrm->qpMin;
            pLinkDynPrm->qpMax                  = pDynPrm->qpMax;
            pLinkDynPrm->qpInit                 = pDynPrm->qpInit;
            pLinkDynPrm->vbrDuration            = pDynPrm->vbrDuration;
            pLinkDynPrm->vbrSensitivity         = pDynPrm->vbrSensitivity;
        }

        /* MJPEG  Params */
        for (i=gVencModuleContext.vencConfig.numPrimaryChn + gVencModuleContext.vencConfig.numSecondaryChn;
                  i<(VENC_CHN_MAX); i++)
        {
             pLinkChPrm  = &encPrm.chCreateParams[i];
             pLinkDynPrm = &pLinkChPrm->defaultDynamicParams;

             pChPrm      = &gVencModuleContext.vencConfig.encChannelParams[i];
             pDynPrm     = &pChPrm->dynamicParam;

             pLinkChPrm->format                 = IVIDEO_MJPEG;
             pLinkChPrm->profile                = 0;
             pLinkChPrm->dataLayout             = VCODEC_FIELD_SEPARATED;
             pLinkChPrm->fieldMergeEncodeEnable = FALSE;
             pLinkChPrm->enableAnalyticinfo     = 0;
             pLinkChPrm->enableWaterMarking     = 0;
             pLinkChPrm->maxBitRate             = 0;
             pLinkChPrm->encodingPreset         = 0;
             pLinkChPrm->rateControlPreset      = 0;
             pLinkChPrm->enableSVCExtensionFlag = 0;
             pLinkChPrm->numTemporalLayer       = 0;

             pLinkDynPrm->intraFrameInterval    = 0;
             pLinkDynPrm->targetBitRate         = 100*1000;
             pLinkDynPrm->interFrameInterval    = 0;
             pLinkDynPrm->mvAccuracy            = 0;
             pLinkDynPrm->inputFrameRate        = pDynPrm->inputFrameRate;
             pLinkDynPrm->qpMin                 = 0;
             pLinkDynPrm->qpMax                 = 0;
             pLinkDynPrm->qpInit                = -1;
             pLinkDynPrm->vbrDuration           = 0;
             pLinkDynPrm->vbrSensitivity        = 0;
        }

	    if (enableAlgLink)
	    {
			encPrm.inQueParams.prevLinkId    = gVcapModuleContext.dspAlgId[0];
			encPrm.inQueParams.prevLinkQueId = ALG_LINK_FRAMES_OUT_QUE;
	    }
		else {
			encPrm.inQueParams.prevLinkId    = ipcInVideoId;
			encPrm.inQueParams.prevLinkQueId = 0;
		}
        encPrm.outQueParams.nextLink     = gVencModuleContext.ipcBitsOutRTOSId;
    }



    ipcBitsOutVideoPrm.baseCreateParams.inQueParams.prevLinkId = gVencModuleContext.encId;
    ipcBitsOutVideoPrm.baseCreateParams.inQueParams.prevLinkQueId = 0;
    ipcBitsOutVideoPrm.baseCreateParams.numOutQue                 = 1;
    ipcBitsOutVideoPrm.baseCreateParams.outQueParams[0].nextLink = gVencModuleContext.ipcBitsInHLOSId;
    MultiCh_ipcBitsInitCreateParams_BitsOutRTOS(&ipcBitsOutVideoPrm,
                                               TRUE);

    ipcBitsInHostPrm[0].baseCreateParams.inQueParams.prevLinkId = gVencModuleContext.ipcBitsOutRTOSId;
    ipcBitsInHostPrm[0].baseCreateParams.inQueParams.prevLinkQueId = 0;
    MultiCh_ipcBitsInitCreateParams_BitsInHLOS(&ipcBitsInHostPrm[0]);


    dspAlgPrm.enableOSDAlg = enableOsd;

    if(enableOsd)
    {
        int chId;

        for(chId = 0; chId < ALG_LINK_OSD_MAX_CH; chId++)
        {
            AlgLink_OsdChWinParams * chWinPrm = &dspAlgPrm.osdChCreateParams[chId].chDefaultParams;

            /* set osd window max width and height */
            dspAlgPrm.osdChCreateParams[chId].maxWidth  = EXAMPLE_OSD_WIN_MAX_WIDTH;
            dspAlgPrm.osdChCreateParams[chId].maxHeight = EXAMPLE_OSD_WIN_MAX_HEIGHT;

            chWinPrm->chId = chId;
            chWinPrm->numWindows = 0;
        }
    }

    dspAlgPrm.enableSCDAlg              = enableScd;
    dspAlgPrm.outQueParams[ALG_LINK_SCD_OUT_QUE].nextLink     = SYSTEM_LINK_ID_INVALID;

    if (enableScd)
    {
        UInt32 i, startChId;

        AlgLink_ScdCreateParams *pScdCreatePrm;
        AlgLink_ScdChParams *pScdChPrm;

        pScdCreatePrm = &dspAlgPrm.scdCreateParams;

        pScdCreatePrm->maxWidth               = 352;
        pScdCreatePrm->maxHeight              = 288;
        pScdCreatePrm->maxStride              = 352;
        pScdCreatePrm->numValidChForSCD       = 4;
        pScdCreatePrm->numSecs2WaitB4Init     = 3;
        pScdCreatePrm->numSecs2WaitB4FrmAlert = 1;
        pScdCreatePrm->inputFrameRate         = 30;
        pScdCreatePrm->outputFrameRate        = 5;
        pScdCreatePrm->numSecs2WaitAfterFrmAlert = 1;

        pScdCreatePrm->enableTamperNotify = FALSE;

        /* enable SCD only for CIF CHs */
        startChId = 4;
        for(i=0; i<pScdCreatePrm->numValidChForSCD; i++)
        {
            pScdChPrm = &pScdCreatePrm->chDefaultParams[i];

            pScdChPrm->chId = startChId;
            pScdChPrm->mode                = ALG_LINK_SCD_DETECTMODE_MONITOR_FULL_FRAME;
            pScdChPrm->frmIgnoreLightsON   = FALSE;
            pScdChPrm->frmIgnoreLightsOFF  = FALSE;
            pScdChPrm->frmSensitivity      = ALG_LINK_SCD_SENSITIVITY_VERYHIGH;
            pScdChPrm->frmEdgeThreshold    = 0;
            pScdChPrm->blkNumBlksInFrame   = 0;

            startChId++;
        }
    }



    capturePrm.isPalMode = Vcap_isPalMode();

    System_linkCreate (gVcapModuleContext.captureId, &capturePrm, sizeof(capturePrm));

#ifdef     ADD_NSF_AFTER_CAPTURE
    System_linkCreate(gVcapModuleContext.nsfId[1], &nsfPrm2, sizeof(nsfPrm2));
#endif
    System_linkCreate(gVcapModuleContext.deiId[0], &deiPrm, sizeof(deiPrm));

    System_linkCreate(dupId[D1_DUP_LINK_IDX], &dupPrm[D1_DUP_LINK_IDX], sizeof(dupPrm[D1_DUP_LINK_IDX]));
    System_linkCreate(gVcapModuleContext.nsfId[0] , &nsfPrm, sizeof(nsfPrm));
    System_linkCreate(mergeId[D1_CIF_MERGE_LINK_IDX], &mergePrm[D1_CIF_MERGE_LINK_IDX], sizeof(mergePrm[D1_CIF_MERGE_LINK_IDX]));

    System_linkCreate(ipcOutVpssId , &ipcOutVpssPrm , sizeof(ipcOutVpssPrm) );
    System_linkCreate(ipcInVideoId , &ipcInVideoPrm , sizeof(ipcInVideoPrm) );

    if(enableAlgLink)
    {
        /* only create OSD alg */
        System_linkCreate(gVcapModuleContext.dspAlgId[0] , &dspAlgPrm, sizeof(dspAlgPrm));
    }

    System_linkCreate(gVencModuleContext.encId, &encPrm, sizeof(encPrm));

    System_linkCreate(gVencModuleContext.ipcBitsOutRTOSId, &ipcBitsOutVideoPrm, sizeof(ipcBitsOutVideoPrm));
    System_linkCreate(gVencModuleContext.ipcBitsInHLOSId, &ipcBitsInHostPrm[0], sizeof(ipcBitsInHostPrm[0]));

    System_linkGetInfo(gVencModuleContext.ipcBitsInHLOSId,&bitsProducerLinkInfo);
    OSA_assert(bitsProducerLinkInfo.numQue == 1);
    ipcBitsOutHostPrm.baseCreateParams.outQueParams[0].nextLink = gVdecModuleContext.ipcBitsInRTOSId;

    printf ("\n\n========bitsProducerLinkInfo============\n");
    printf ("numQ %d, numCh %d\n",
                    bitsProducerLinkInfo.numQue,
                    bitsProducerLinkInfo.queInfo[0].numCh);
    {
        int i;
        for (i=0; i<bitsProducerLinkInfo.queInfo[0].numCh; i++)
        {
            printf ("Ch [%d] Width %d, Height %d\n",
                i,
                bitsProducerLinkInfo.queInfo[0].chInfo[i].width,
                bitsProducerLinkInfo.queInfo[0].chInfo[i].height
                );
        }
    }
    printf ("\n====================\n\n");

    if (bitsProducerLinkInfo.queInfo[0].numCh > gVencModuleContext.vencConfig.numPrimaryChn)
        bitsProducerLinkInfo.queInfo[0].numCh = gVencModuleContext.vencConfig.numPrimaryChn;

    printf ("Reducing bitsProducerLinkInfo.numCh to %d\n", bitsProducerLinkInfo.queInfo[0].numCh);

    MultiCh_ipcBitsInitCreateParams_BitsOutHLOS(&ipcBitsOutHostPrm,
                                               &bitsProducerLinkInfo.queInfo[0]);

    if(gVdecModuleContext.vdecConfig.forceUseDecChannelParams)
    {
        /* use channel info provided by user instead of from encoder */
        System_LinkChInfo *pChInfo;

        ipcBitsOutHostPrm.inQueInfo.numCh = gVdecModuleContext.vdecConfig.numChn;

        for(chId=0; chId<ipcBitsOutHostPrm.inQueInfo.numCh; chId++)
        {
            pChInfo = &ipcBitsOutHostPrm.inQueInfo.chInfo[chId];

            /* Not Used - Start */
            pChInfo->bufType        = 0;
            pChInfo->codingformat   = 0;
            pChInfo->dataFormat     = 0;
            pChInfo->memType        = 0;
            pChInfo->startX         = 0;
            pChInfo->startY         = 0;
            pChInfo->pitch[0]       = 0;
            pChInfo->pitch[1]       = 0;
            pChInfo->pitch[2]       = 0;
            /* Not Used - End */

            pChInfo->width          = gVdecModuleContext.vdecConfig.decChannelParams[chId].maxVideoWidth;
            pChInfo->height         = gVdecModuleContext.vdecConfig.decChannelParams[chId].maxVideoHeight;
            pChInfo->scanFormat     = SYSTEM_SF_PROGRESSIVE;
        }
    }

    /* ipcBitsOut params - num of buffers, bitstream buffer size */
    for (chId=0; chId<ipcBitsOutHostPrm.inQueInfo.numCh; chId++)
    {
        ipcBitsOutHostPrm.maxQueueDepth[chId] = MAX_BUFFERING_QUEUE_LEN_PER_CH    ;
        ipcBitsOutHostPrm.chMaxReqBufSize[chId] = IPC_BITBUF_SIZE(
                                        ipcBitsOutHostPrm.inQueInfo.chInfo[chId].width,
                                        ipcBitsOutHostPrm.inQueInfo.chInfo[chId].height
                                         );

        ipcBitsOutHostPrm.totalBitStreamBufferSize [chId] =
                (ipcBitsOutHostPrm.chMaxReqBufSize[chId] * BIT_BUF_LENGTH_LIMIT_FACTOR_SD );
    }

    ipcBitsInVideoPrm.baseCreateParams.inQueParams.prevLinkId       = gVdecModuleContext.ipcBitsOutHLOSId;
    ipcBitsInVideoPrm.baseCreateParams.inQueParams.prevLinkQueId    = 0;
    ipcBitsInVideoPrm.baseCreateParams.numOutQue                    = 1;
    ipcBitsInVideoPrm.baseCreateParams.outQueParams[0].nextLink     = gVdecModuleContext.decId;
    MultiCh_ipcBitsInitCreateParams_BitsInRTOS(&ipcBitsInVideoPrm, TRUE);

    for (i=0; i<gVdecModuleContext.vdecConfig.numChn; i++) {
        decPrm.chCreateParams[i].format                 = IVIDEO_H264HP;
        decPrm.chCreateParams[i].profile                = IH264VDEC_PROFILE_ANY;
        decPrm.chCreateParams[i].processCallLevel       = VDEC_FRAMELEVELPROCESSCALL;
        decPrm.chCreateParams[i].targetMaxWidth         = ipcBitsOutHostPrm.inQueInfo.chInfo[i].width;
        decPrm.chCreateParams[i].targetMaxHeight        = ipcBitsOutHostPrm.inQueInfo.chInfo[i].height;
        decPrm.chCreateParams[i].defaultDynamicParams.targetFrameRate = gVdecModuleContext.vdecConfig.decChannelParams[i].dynamicParam.frameRate;
        decPrm.chCreateParams[i].defaultDynamicParams.targetBitRate   = gVdecModuleContext.vdecConfig.decChannelParams[i].dynamicParam.targetBitRate;
        /* Max ref frames is only 2 as this is closed loop decoder */
        decPrm.chCreateParams[i].dpbBufSizeInFrames                   = 2;
        decPrm.chCreateParams[i].numBufPerCh = NUM_DECODE_BUFFERS;
        decPrm.chCreateParams[i].tilerEnable = TILER_ENABLE;
        decPrm.chCreateParams[i].enableWaterMarking = gVdecModuleContext.vdecConfig.decChannelParams[i].enableWaterMarking;
    }
    decPrm.inQueParams.prevLinkId    = gVdecModuleContext.ipcBitsInRTOSId;
    decPrm.inQueParams.prevLinkQueId = 0;
    decPrm.outQueParams.nextLink  = ipcOutVideoId;

    ipcOutVideoPrm.inQueParams.prevLinkId    = gVdecModuleContext.decId;
    ipcOutVideoPrm.inQueParams.prevLinkQueId = 0;
    ipcOutVideoPrm.numOutQue                 = 1;
    ipcOutVideoPrm.outQueParams[0].nextLink  = ipcInVpssId;
    ipcOutVideoPrm.notifyNextLink            = TRUE;
    ipcOutVideoPrm.notifyPrevLink            = TRUE;
    ipcOutVideoPrm.noNotifyMode              = FALSE;

    ipcInVpssPrm.inQueParams.prevLinkId    = ipcOutVideoId;
    ipcInVpssPrm.inQueParams.prevLinkQueId = 0;
    ipcInVpssPrm.numOutQue                 = 1;
    ipcInVpssPrm.outQueParams[0].nextLink  = mergeId[LIVE_DECODE_MERGE_LINK_IDX];
    ipcInVpssPrm.notifyNextLink            = TRUE;
    ipcInVpssPrm.notifyPrevLink            = TRUE;
    ipcInVpssPrm.noNotifyMode              = FALSE;

    mergePrm[LIVE_DECODE_MERGE_LINK_IDX].numInQue                     = 2;
    mergePrm[LIVE_DECODE_MERGE_LINK_IDX].inQueParams[0].prevLinkId    = dupId[D1_DUP_LINK_IDX];
    mergePrm[LIVE_DECODE_MERGE_LINK_IDX].inQueParams[0].prevLinkQueId = 0;
    mergePrm[LIVE_DECODE_MERGE_LINK_IDX].inQueParams[1].prevLinkId    = ipcInVpssId;
    mergePrm[LIVE_DECODE_MERGE_LINK_IDX].inQueParams[1].prevLinkQueId = 0;
    mergePrm[LIVE_DECODE_MERGE_LINK_IDX].outQueParams.nextLink        = dupId[LIVE_DECODE_DUP_LINK_IDX];
    mergePrm[LIVE_DECODE_MERGE_LINK_IDX].notifyNextLink               = TRUE;

    dupPrm[LIVE_DECODE_DUP_LINK_IDX].inQueParams.prevLinkId         = mergeId[LIVE_DECODE_MERGE_LINK_IDX];
    dupPrm[LIVE_DECODE_DUP_LINK_IDX].inQueParams.prevLinkQueId      = 0;
    dupPrm[LIVE_DECODE_DUP_LINK_IDX].numOutQue                      = 2;
    dupPrm[LIVE_DECODE_DUP_LINK_IDX].outQueParams[0].nextLink       = gVdisModuleContext.swMsId[0];
    dupPrm[LIVE_DECODE_DUP_LINK_IDX].outQueParams[1].nextLink       = gVdisModuleContext.swMsId[1];
    dupPrm[LIVE_DECODE_DUP_LINK_IDX].notifyNextLink                 = TRUE;

    for(i=0; i<2; i++)
    {
        swMsPrm[i].includeVipScInDrvPath     = FALSE;
        swMsPrm[i].inQueParams.prevLinkId    = dupId[LIVE_DECODE_DUP_LINK_IDX];
        swMsPrm[i].inQueParams.prevLinkQueId = i;
        swMsPrm[i].outQueParams.nextLink     = gVdisModuleContext.displayId[i];
        swMsPrm[i].maxInputQueLen            = 4; // KC: changed to 4 to make the display smooth
        swMsPrm[i].maxOutRes                 = VSYS_STD_1080P_60;
        swMsPrm[i].initOutRes                = gVdisModuleContext.vdisConfig.deviceParams[i].resolution;
        swMsPrm[i].numOutBuf                 = 8;
        if (i == 1)
		{
            swMsPrm[i].maxOutRes  = VSYS_STD_PAL;
            swMsPrm[i].initOutRes = gVdisModuleContext.vdisConfig.deviceParams[VDIS_DEV_SD].resolution;
		}


#ifdef  SYSTEM_USE_TILER
        swMsPrm[i].lineSkipMode = FALSE; // Double pitch not possible in tiler mode; so Line skip not possible
#else
        swMsPrm[i].lineSkipMode = TRUE; // Set to TRUE for Enable low cost scaling
#endif
        swMsPrm[i].enableLayoutGridDraw = gVdisModuleContext.vdisConfig.enableLayoutGridDraw;

        MultiCh_swMsGetDefaultLayoutPrm(VDIS_DEV_HDMI, &swMsPrm[0], TRUE);
        MultiCh_swMsGetDefaultLayoutPrm(VDIS_DEV_SD, &swMsPrm[1], TRUE);

        displayPrm[i].inQueParams[0].prevLinkId    = gVdisModuleContext.swMsId[i];
        displayPrm[i].inQueParams[0].prevLinkQueId = 0;
        displayPrm[i].displayRes                = swMsPrm[i].initOutRes;
        if (i == 1)
        {
            displayPrm[i].displayRes            = gVdisModuleContext.vdisConfig.deviceParams[VDIS_DEV_SD].resolution;
            displayPrm[i].forceFieldSeparatedInputMode = TRUE;
        }
    }

    System_linkCreate(gVdecModuleContext.ipcBitsOutHLOSId,&ipcBitsOutHostPrm,sizeof(ipcBitsOutHostPrm));
    System_linkCreate(gVdecModuleContext.ipcBitsInRTOSId,&ipcBitsInVideoPrm,sizeof(ipcBitsInVideoPrm));
    System_linkCreate(gVdecModuleContext.decId, &decPrm, sizeof(decPrm));

    System_linkCreate(ipcOutVideoId, &ipcOutVideoPrm, sizeof(ipcOutVideoPrm));
    System_linkCreate(ipcInVpssId  , &ipcInVpssPrm  , sizeof(ipcInVpssPrm)  );
    System_linkCreate(mergeId[LIVE_DECODE_MERGE_LINK_IDX], &mergePrm[LIVE_DECODE_MERGE_LINK_IDX], sizeof(mergePrm[LIVE_DECODE_MERGE_LINK_IDX]));
    System_linkCreate(dupId[LIVE_DECODE_DUP_LINK_IDX], &dupPrm[LIVE_DECODE_DUP_LINK_IDX], sizeof(dupPrm[LIVE_DECODE_DUP_LINK_IDX]));

    for(i=0; i<2; i++)
        System_linkCreate(gVdisModuleContext.swMsId[i]  , &swMsPrm[i], sizeof(swMsPrm[i]));

    for(i=0; i<2; i++)  /* Both tied VENCs HDMI and DVO2 are handled by single link instance */
        System_linkCreate(gVdisModuleContext.displayId[i], &displayPrm[i], sizeof(displayPrm[i]));

    {
        MergeLink_InLinkChInfo inChInfo;

        MergeLink_InLinkChInfo_Init(&inChInfo);
        inChInfo.inLinkID = ipcInVpssId;
        System_linkControl(mergeId[LIVE_DECODE_MERGE_LINK_IDX],
                           MERGE_LINK_CMD_GET_INPUT_LINK_CHINFO,
                           &inChInfo,
                           sizeof(inChInfo),
                           TRUE);
        OSA_assert(inChInfo.numCh == gVdecModuleContext.vdecConfig.numChn);
        MultiCh_setDec2DispMap(VDIS_DEV_HDMI,gVdecModuleContext.vdecConfig.numChn,0,inChInfo.startChNum);
        MultiCh_setDec2DispMap(VDIS_DEV_SD,gVdecModuleContext.vdecConfig.numChn,0,inChInfo.startChNum);
   }

}

Void MultiCh_deleteProgressive4D1VcapVencVdecVdis()
{
    UInt32 i;
    Bool enableAlgLink = gVsysModuleContext.vsysConfig.enableOsd;

    UInt32 mergeId[NUM_MERGE_LINK];
    UInt32 dupId[NUM_DUP_LINK];
    UInt32 ipcOutVpssId, ipcInVpssId;
    UInt32 ipcOutVideoId, ipcInVideoId;

    mergeId[LIVE_DECODE_MERGE_LINK_IDX]     = SYSTEM_VPSS_LINK_ID_MERGE_0;
    mergeId[D1_CIF_MERGE_LINK_IDX]          = SYSTEM_VPSS_LINK_ID_MERGE_1;

    dupId[D1_DUP_LINK_IDX]              = SYSTEM_VPSS_LINK_ID_DUP_0;
    dupId[LIVE_DECODE_DUP_LINK_IDX]     = SYSTEM_VPSS_LINK_ID_DUP_1;

    ipcOutVpssId = SYSTEM_VPSS_LINK_ID_IPC_OUT_M3_0;
    ipcInVideoId = SYSTEM_VIDEO_LINK_ID_IPC_IN_M3_0;
    ipcOutVideoId= SYSTEM_VIDEO_LINK_ID_IPC_OUT_M3_0;
    ipcInVpssId  = SYSTEM_VPSS_LINK_ID_IPC_IN_M3_0;

    gVdecModuleContext.ipcBitsOutHLOSId = SYSTEM_HOST_LINK_ID_IPC_BITS_OUT_0;
    gVdecModuleContext.ipcBitsInRTOSId = SYSTEM_VIDEO_LINK_ID_IPC_BITS_IN_0;

    System_linkDelete(gVcapModuleContext.captureId);
#ifdef     ADD_NSF_AFTER_CAPTURE
    System_linkDelete(gVcapModuleContext.nsfId[1]);
#endif
    System_linkDelete(gVcapModuleContext.deiId[0]);
    System_linkDelete(gVcapModuleContext.nsfId[0]);

    System_linkDelete(ipcOutVpssId );
    System_linkDelete(ipcInVideoId );

    if(enableAlgLink)
    {
        System_linkDelete(gVcapModuleContext.dspAlgId[0]);
    }

    System_linkDelete(gVencModuleContext.encId);
    System_linkDelete(gVencModuleContext.ipcBitsOutRTOSId);
    System_linkDelete(gVencModuleContext.ipcBitsInHLOSId);
    System_linkDelete(gVdecModuleContext.ipcBitsOutHLOSId);
    System_linkDelete(gVdecModuleContext.ipcBitsInRTOSId);
    System_linkDelete(gVdecModuleContext.decId);

    System_linkDelete(ipcOutVideoId);
    System_linkDelete(ipcInVpssId  );

    for(i=0; i<2; i++)
        System_linkDelete(gVdisModuleContext.swMsId[i] );

    for(i=0; i<2; i++)
        System_linkDelete(gVdisModuleContext.displayId[i]);

    for(i=0; i<NUM_DUP_LINK; i++)
        System_linkDelete(dupId[i]);

    for(i=0; i<NUM_MERGE_LINK; i++)
    {
        if (mergeId[i] != SYSTEM_LINK_ID_INVALID )
           System_linkDelete(mergeId[i]);
    }

    /* Print the HWI, SWI and all tasks load */
    /* Reset the accumulated timer ticks */
    MultiCh_prfLoadCalcEnable(FALSE, TRUE, FALSE);

}




三、总结

我这次主要做了标清的swms,所以主要做的也就是对link的一些修改,结合本文其实主要是两个方面mcfw api和link api,mcfw我仅仅是结合 TI给的文档简单说了一下他的大致框架,并没有深入每个code去讲解,而link我是结合一位大神发表的博客:http://blog.csdn.net/crushonme/article/details/10245169

他的博客说的很详细,基本上link的语句都分析了一下,在此我只是借用自己来学习,谢谢!

其实link就是对几个核怎么运作进行设计,凡是用这个平台的link没有太大的区别,都是按照自己的需求进行定制,单是修改link也会很费工夫。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值