OSD
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的搬移
?
其中ping?pong?buffer的切換由EDMA參數自動變換,運行過程中無需再手動切換ping?pong?buffer地址。
總結
- 上一篇: “匿名句柄” 是一切皆文件背后功臣……
- 下一篇: 云栖大会展出两款一体机,搭载新一代无影融