RDK_OSD代码走读
2014年11月17日 14:03:47
阅读数:1178
1. 工作原理
1.1 Process link
OSD link是所谓的process link。即,该link没有output queue,而是直接在input queue的buffer上做操作。其数据流向如下图
1. prev link将frame buffer送给process的input queue
2. process link在input queue中取出buffer,对buffer的数据进行操作
3. process link将该buffer归还给prev link的empty queue
4. prev link检测到该buffer是从一个process link还回来的,于是又将其发送到next link去。
1.2 OSD简述
OSD Link功能运行在C67 DSP核上,一般工作在Capture Link之后,用来在采集到的视频帧上叠加一个图片(LOGO或是标题等)。待叠加的图片pic存放在共享内存SR0中(RGB或者YUV点阵格式)。当一帧数据frame从capture link送到OSD link,DSP首先启动EDMA将pic和frame的一部分从共享内存和DDR中搬移到内部L2中去。然后DSP根据预先设置的alpha参数,对pic和frame相应位置的每一点做alpha blend。计算好的结果被EDMA搬回输入的frame buffer中去覆盖原有的数据。由于OSD link属于Process link,该frame buffer会被送到下一个link中去,从而完成OSD效果。
2. 工作流程
1. DSP的
main程序创建system_main线程,system_main中调用AlgLink_init。
2. 进入AlgLink_init,创建两个AlgLink的实例。对于每一个实例,调用System_registerLink和创建task。
System_registerLink主要是为了注册下面几个回调函数
linkObj.linkGetFullFrames = NULL;
linkObj.linkPutEmptyFrames = NULL;
linkObj.linkGetFullBitBufs = AlgLink_getFullBufs;
linkObj.linkPutEmptyBitBufs = AlgLink_putEmptyBufs;
linkObj.getLinkInfo = AlgLink_getInfo;
其中linkGetFullBitBufs是为了给next link从本link的output queue获取bitstream buffer,而linkPutEmptyBitBufs则给next link将用完的buffer归还给本link。
由于OSD本身没有output queue,所以这两个函数实际是给共用Alglink的SCD算法使用的。
3. 创建AlgLink_tskMain线程。
4. 进入AlgLink_tskMain,当收到一条create消息时,进入下列处理,否则直接丢掉该消息返回。
5. 进入AlgLink_algCreate,内部实际是调用AlgLink_OsdalgCreate。
6. 进入AlgLink_OsdalgCreate。该函数主要做了两方面的事,一是根据传入的create arg,设置OSD的运行context(其实就是拷贝到本地的一些变量中保存啦)。二是调用SWOSD_open。
7. SWOSD_open主要为了注册两个数据结构:SWOSD_TI_IALG和SWOSD_TI_IRES。这两个是TI XDAIS标准规定的算法标准接口。前一个主要关注算法的memory需求和分配,后一个关注算法对DMA资源的需求。我们下面分开来说。
l SWOSD_TI_IALG
#define IALGFXNS
&SWOSD_TI_IALG, /* module ID */
NULL, /* activate */
SWOSD_TI_alloc, /* alloc */
NULL, /* control (NULL => no control ops) */
NULL, /* deactivate */
SWOSD_TI_free, /* free */
SWOSD_TI_initObj,/* init */
NULL, /* moved */
SWOSD_TI_numAlloc /* numAlloc (NULL => IALG_MAXMEMRECS) */
这几个函数都是为了让Application来分配算法所需要的memory资源。Application首先调用SWOSD_TI_numAlloc,得到需要的IALG_MemRec个数。每一个memRec代表一个内存块的需求,包括分配区域,内存块大小,对齐等属性。然后Application根据该个数,分配相应个数的IALG_MemRec大小的buffer,将该buffer当做参数调用SWOSD_TI_alloc。算法的SWOSD_TI_alloc函数负责填写各个IALG_MemRec结构的大小,内存区域,对齐等属性,除了base address。Application然后根据填好的各IALG_MemRec从相应的内存区分配memory,并将分配好的memory buffer地址填入base address字段。最后将整个IALG_MemRec数组传入SWOSD_TI_initObj。算法用Application分配好的memory来完成自己的初始化。
实际上,TI为了简化操作,实现了一套framework来完成这些。在SWOSD_OPEN中,我们可以看到,通过调用DSKT2_createAlg函数,将SWOSD_TI_IALG这一套函数指针传入即可完成上面的交互过程。
对于OSD ALG来说,其需要的内存区有两个(memTab[2])。memTab[0]用来存放OSD_obj的内容,也就是运行的一些context。memTab[1]用来进行一行的blend运算。假设一行宽度为N个pixel,每个pixel需要Mbytes,则需要的内存大小为N*M*[1(blend输入1)+1(blend输入2)+ 1( output buffer) +1 (alpha matrix)]*2(ping pong buffer)
其中blend输入1和2分别对应video buffer和osd picture的一行。Alpha matrix暂时并未实现,其目的本来是为了可以对每一个像素点指定一个alpha值。这两个内存区都是从DSP的L2里分配。
l SWOSD_TI_IRES
该结构与SWOSD_TI_IALG类似,只不过其分配的是DMA资源。这里不再详细描述。注意framework也封装了一个类似的RMAN_assignResources来完成交互过程。
OSD alg总共需要5个EDMA通道
#define SWOSD_DMA_CH_IN_A 0x0
#define SWOSD_DMA_CH_IN_B 0x1
#define SWOSD_DMA_CH_ALP 0x2 //传送alpha matrix,暂无试用
#define SWOSD_DMA_CH_OUT 0x3
#define SWOSD_DMA_CH_AUX 0x4 //用来在alpha值为0x80时,用来完成单纯的覆盖而不是blend。暂无使用。
8. SWOSD_open执行完,AlgLink_algCreate执行完,即可进入消息处理循环。与OSD功能相关的是两个消息: ALG_LINK_OSD_CMD_SET_CHANNEL_WIN_PRM和SYSTEM_CMD_NEW_DATA。
9. 一般来说,create后应该先收到ALG_LINK_OSD_CMD_SET_CHANNEL_WIN_PRM消息来设置每一通道的OSD属性。存放OSD图片的SR0 buffer地址也是在这时传入。在demo程序中,这一动作是在Vcap_setDynamicParamChn中完成。
10. 当收到
SYSTEM_CMD_NEW_DATA时,进入AlgLink_algProcessData。该函数首先调用System_getLinksFullFrames,从prev link中取得frame buffers。然后调用AlgLink_OsdalgProcessFrame处理每一个frame buffer,最后调用System_putLinksEmptyFrames将处理完的frame buffer返还前一个link。
11. AlgLink_OsdalgProcessFrame调用SWOSD_blendWindow分别对Y plane(亮度)和C plane(UV通道)进行处理。
12. SWOSD_blendWindow首先调用RMAN_activateAllResources,在OSD算法中,这实际是一个空操作。然后调用SWOSD_TI_algRun核心算法。
13. SWOSD_TI_algRun使用了3个EDMA通道,记为SWOSD_DMA_CH_IN_A,SWOSD_DMA_CH_IN_B,SWOSD_DMA_CH_OUT。SWOSD_DMA_CH_IN_A负责将OSD图像中的一行从SR0搬移到L2的ping-pong buffer中,SWOSD_DMA_CH_IN_B负责将video frame中的一行从frame buffer中搬移到L2的ping-pong buffer,而SWOSD_DMA_CH_OUT负责将blend后的数据从L2 ping pongbuffer中搬移到video frame中。
其流程如下:
等待SWOSD_DMA_CH_IN_A和SWOSD_DMA_CH_IN_B 对ping buffer的搬移完成
SWOSD_DMA_CH_IN_A和SWOSD_DMA_CH_IN_B启动pong buffer的搬移。
DSP计算alpha blend的值,写入L2的out pong buffer。
等待SWOSD_DMA_CH_OUT ping buffer搬移完成
启动SWOSD_DMA_CH_OUT pong buffer的搬移