DAVINCI开发原理之三----达芬奇编解码引擎Codec Engine(CE)
1. 編解碼引擎(Codec Engine)
a. 核心引擎API
??? 從應(yīng)用來說,CE就是用來調(diào)用xDAIS算法的一組API的集合,用戶可以通過這些API來實例化和調(diào)用xDAIS算法。達芬奇提供了一組VISA接口,用于給應(yīng)用程序與xDM兼容的xDAIS算法相交互。需要注意,不管算法是運行在本地(ARM端),還是遠端(DSP端),也不管硬件體系是只有ARM或是只有DSP或兩者都有,也不管OS是Linux、VxWorks、DSP/BIOS,還是WinCE,對算法的接口調(diào)用都是一致的。這點通過引擎的配置文件*.cfg可以看出來,而且通過配置文件可以決定自己的codec是運行在ARM端還是DSP端。
??? CE包括核心引擎API和VISA API,核心引擎API相關(guān)接口模塊為:初始化模塊(CERuntime_)、CE運行時模塊(Engine_)、抽象層內(nèi)存模塊(Memory_); VISA API的接口模塊我們常用的有: 視頻編碼接口(VIDENCx_)、視頻解碼接口(VIDDECx_)、音頻編碼接口(AUDENCx_)、音頻解碼接口(AUDDECx_),各模塊分別包含在對應(yīng)的頭文件中。
??? 應(yīng)用程序必須使用CE的核心引擎的三個相關(guān)模塊去打開和關(guān)閉編解碼引擎的實例。 需要注意的是引擎的句柄是非線程保護的,對單獨使用CE的每個線程來說,必須執(zhí)行Engine_open并管理好自己的引擎句柄,而對多線程應(yīng)用來說,也可以順序的訪問一個共享的引擎實例,我們目前采用的就是后者,只定義了一個引擎句柄,多個解碼器共用。編解碼引擎同時還提供相關(guān)的API用以訪問系統(tǒng)的內(nèi)存使用狀況和CPU的負載信息,接口如下:
??? >Engine_open:???????? 打開一個編解碼引擎;
??? >Engine_close:??????? 關(guān)閉一個編解碼引擎,通常是在刪除算法實例后調(diào)用之來釋放相關(guān)資源;
??? >Engine_getCpuLoad:?? 獲取CPU的使用百分比;
??? >Engine_getLastError: 獲取最后一個失敗操作所引發(fā)的錯誤代碼;
??? >Engine_getUsedMem:?? 獲取內(nèi)存使用狀況
具體定義引擎所需要包含的頭文件和如何定義和使用引擎可參考工程實例example_dsp1. 目前我們都是多個解碼器共用一個引擎句柄,比如:
??? static String engineName?? = "videodec"; /*定義引擎名字,ceapp.cfg配置文件中會用到*/
??? Engine_Handle ceHandle_264 = NULL; /*創(chuàng)建一個264解碼器引擎句柄*/
??? Engine_Error errorcode; /*用于返回引擎打開的狀況信息,不同返回值代表的意義可參考相應(yīng)頭文件*/
??? ceHandle_264 = Engine_open(engineName, NULL, &errorcode);
根據(jù)上述理解,我覺得如果多個線程需要單獨使用自己的引擎時,應(yīng)該可以定義多個引擎名字,創(chuàng)建多個引擎句柄,此時每個線程必須單獨執(zhí)行Engine_open(),并管理好自己的引擎句柄。
b. VISA API
??? @創(chuàng)建一個算法實例: *_create()
編解碼引擎ceHandle_264創(chuàng)建完畢后,可以通過它來創(chuàng)建自己的算法實例,需要調(diào)用*_create(),其中*可以是VIDEO或AUDIO的相應(yīng)編解碼模塊的名字,例如:
??? static String decoderName = "h264dec"; /*定義解碼模塊名字,用于標(biāo)識算法名字,ceapp.cfg會用到*/
??? VIDDEC_Handle 264Handle;?????????????? /*創(chuàng)建解碼器句柄*/
??? 264Handle = VIDDEC_create(ceHandle_264, decoderName, NULL); /*在引擎上分配和初始化解碼器,第三個參數(shù)可以用來初始化算法的相關(guān)參數(shù),這些參數(shù)控制著算法的各種行為,參數(shù)結(jié)構(gòu)依VISA中編碼或解碼器的不同而不同,具體結(jié)構(gòu)內(nèi)容可參考頭文件*/
??? @關(guān)閉一個算法實例: *_delete()
??? VIDDEC_delete(264Handle); /*注意:只有當(dāng)與算法相關(guān)的內(nèi)存片清除后,才可以調(diào)用之刪除算法實例*/
??? @控制一個算法實例: *_control()
VIDDEC_control(264Handle, XDM_SETPARAME, dynamicParamsPtr, &encStatus);
??? 第一個參數(shù)是已經(jīng)打開的算法實例句柄; 第二個參數(shù)是一整型的command id,它定義在xdm.h中; 第三個參數(shù)是需要動態(tài)改變算法的參數(shù),比如在create中第三個參數(shù)已經(jīng)為解碼器初始化了一些參數(shù),在這里可以對之做修改,但修改有條件,其具體結(jié)構(gòu)內(nèi)容可以參考頭文件; 第四個參數(shù)是一個結(jié)構(gòu)體變量,不同模塊具有不同的結(jié)構(gòu),具體參考頭文件。
??? @通過算法實例處理數(shù)據(jù): *_process()
??? status = VIDDEC_process(264Handle &inBufDesc,&outBufDesc, &inArgs, &outArgs);
??? 第二和第三個參數(shù)是XDM_BufDesc類型的結(jié)構(gòu)體,其中包含了內(nèi)存片段的數(shù)目和開始地址以及長度信息;第四第五個參數(shù)分別為算法實例提供輸入和輸出地址。
??? 上述所有結(jié)構(gòu)體都可以在: \opt\dvevm_#_#\xdais_#_#\packages\xdais\dm下面找到,并可以做修改。只是現(xiàn)在還不知道這些結(jié)構(gòu)體具體怎么使用。
c. 編譯"一個"編解碼引擎----引擎配置文件(ceapp.cfg)
??? 引擎的配置文件是以*.cfg文件形式存儲的,目前我們工程里面含兩個*.cfg: app里面含ceapp.cfg,里面包含對引擎的配置,還有一個是video_copy.cfg,在server下,是對服務(wù)器的配置文件之一,后面會講到。ceapp.cfg通過Makefile文件使用package.xdc來產(chǎn)生一個*.c文件和一個鏈接命令腳本文件。一個引擎配置文件包含如下內(nèi)容: 引擎的名字以及包含在引擎內(nèi)的編解碼器和它們的名字。從這里可以看出,前面定義"h264dec"等名字的作用,用于應(yīng)用程序中標(biāo)識算法類別,也可以看出一個引擎是可以由幾個編解碼器模塊共用的。我們以ceapp.cfg文件的內(nèi)容為例說明配置參數(shù)的含義:
??? /*--------------set up OSAL----------------*/
??? var osalGlobal = xdc.useModule('ti.sdo.ce.osal.Global');
??? osalGlobal.runtimeEnv = osalGlobal.DSPLINK_LINUX;
注:這兩句是設(shè)置全局的模塊使配置腳本生效,然后是設(shè)置引擎的運行環(huán)境,即需要用的DSP/BIOS Link和Linux OS).
??? /*--------------get codec modules;i.e.implementation of codecs-------*/
var H264DEC = xdc.useModule('codecs.h264dec.H264DEC');
??? 注:設(shè)置需要用到的編解碼器,即我們將要用到給定目錄下的H264DEC。注意我們目前使用的都是codec目錄下ti提供的videnc_copy,實際上我們可以修改的,另前面我們定義解碼器的名字時用的小寫的'h264dec',這里配置改成大寫.
??? /*---------------Engine Cofiguation---------------*/
??? var Engine = xdc.useModule('ti.sdo.ce.Engine');
??? var demoEngine = Engine.create("videodec", [
??? {name: "h264dec", mod: H264DEC, local: false},
??? /* {name: "h264enc", mod: H264ENC, local: false} ... 如果有的話*/
]);
??? 注:首先使ti.sdo.ce目錄下的引擎可用,然后用create()創(chuàng)建一個引擎。每個引擎都有一個名字,這個名字會被開發(fā)人員用到(如打開引擎的時候,前面我們定義的引擎名字是"h264dec")。create()的參數(shù)是一關(guān)于算法描述的數(shù)組,每個算法描述包含下面幾個字段:
??? >name: 算法實例的名字,在標(biāo)識算法時要用到,VIDEC_creat()等VISA API的參數(shù),如前面定義264解碼器名字"h264dec";
??? >mod: 用來標(biāo)識實際的算法實現(xiàn)模塊,通常就是name的大寫,如H264DEC.
??? >local: 如果為真,算法實例在ARM端實現(xiàn),否則通過codec server來創(chuàng)建DSP端的算法實例。
??? demoEngine.server = "./encodeCombo.x64P";
??? 注:用于指明Codec Server.
-----------------------------------------------------------------------------------------------------------------------------------
兩個cfg的比較:
??? 從ARM與DSP的通訊調(diào)用機制可看出,ARM端客戶應(yīng)用程序指令通過CE打包由OSAL層經(jīng)DSPLINK發(fā)送到遠端DSP服務(wù)器,在服務(wù)器端,先有server骨架經(jīng)OSAL層解包獲得指令及特定codec的申請,DSP codec處理完畢再經(jīng)server打包經(jīng)OSAL層由DSPLINK返回到本地ARM端CE,由此,兩個cfg配置文件都需要設(shè)置OSAL及通訊環(huán)境DSPLINK,并申明好所使用到的各種編解碼器,被申明的各編碼器或各解碼器(通常編碼器s與解碼器s分別放在兩個文件夾下),兩cfg文件中被聲明的編碼器或解碼器路徑是一致的,如: var VIDDEC_COPY = xdc.useModule('codecs.viddec_copy.VIDDEC_COPY');(.表示目錄路徑, viddec_copy目錄下有個VIDDEC_COPY.xs文件)
-
-
-另一個人的介紹:
??? 編解碼服務(wù)器(CS)就是一個二進制文件,它集成了編解碼器,框架組件和一些系統(tǒng)代碼,當(dāng)CS運行在DSP上時,它使用了DSP/BIOS作為其內(nèi)核。CS同時包括了對客戶請求的相關(guān)DSP/BIOS線程。CS可以代表實際的DSP硬件、導(dǎo)入到DSP上的鏡像文件以及正在運行的任務(wù),其配置需要兩個步驟:
?? >通過TCF腳本語言配置DSP/BIOS;
?? >通過XDC配置剩下的組件,比如:FC組件、DSP/BIOS Link、Codec Engine等。
?? 配置完成的服務(wù)器鏡像文件是在引擎配置文件(ceapp.cfg)中使用的,如前所述的demoEngine.server = "./encodeCombo.x64P";
a. 編譯一個編解碼服務(wù)器
?????? CS鏡像文件的創(chuàng)建過程是通過前面介紹的XDC工具來完成的,所不同的是,CS在創(chuàng)建時需要一個main.c和相關(guān)的BIOS配置腳本.tcf文件.
>tcf: 腳本文件主要是對DSP/BIOS內(nèi)核進行配置,如: 定義DSP的內(nèi)存映射,設(shè)置DSP的中斷向量表,創(chuàng)建和初始化其他DSP/BIOS數(shù)據(jù)對象等,具體可參見video_copy.tcf,注意我在里面添了一個關(guān)于trace的參數(shù)配置是原來沒有的。
>main.c: 只要你的算法實現(xiàn)了XDM接口,就需要一個main.c的程序去初始化CE,然后用其他配置腳本來創(chuàng)建一個服務(wù)器鏡像*.x64P. 在main.c里面除了調(diào)用CERuntime_init()初始化CE外,就是對于trace相關(guān)函數(shù)的初始化和處理,這部分暫時沒有細究。另有一點值得注意,在這里可以實現(xiàn)對cache的重新配置,因為在tcf文件里面對cache的配置可能會不起作用,這是可以在這里以函數(shù)代碼的方式來配,這點以前沒有注意過。這里有點不明白的是,在ceapp_init()中已經(jīng)做了一次CERuntime_init(),為何在CS處還要做一次?(我覺得是因為先編譯CS,生成*.x64P,然后才編譯app端,這樣就可以理解成: 只要你的算法實現(xiàn)了XDM接口,就需要對CE做初始化CERuntime_init(),而CS的編譯是調(diào)用了經(jīng)XDM封裝后的codec生成的*.a64P的)
>XDC相關(guān)文件:
>>>package.xdc
??? /*--------------聲明包名-----------------*/
??? package server{}??
??? (我們目前的.xdc是: package server.video.copy, 此即\server\video_copy\..xdc,應(yīng)該無需改動)
>>>package.bld: 聲明所必須包含的包,鏈接命令腳本,tcf文件和一些源文件,定義編譯屬性、平臺和對象等。
>>>server.cfg: 這是CS配置的重點,說明如下。
/*第一部分: 聲明運行環(huán)境和各種編解碼模塊, 與CE.cfg類似*/
/*--------------set up OSAL----------------*/
var osalGlobal = xdc.useModule('ti.sdo.ce.osal.Global');
osalGlobal.runtimeEnv = osalGlobal.DSPLINK_BIOS;
注:這兩句是設(shè)置全局的模塊使配置腳本生效,然后是設(shè)置引擎的運行環(huán)境,即需要用的DSP/BIOS Link,與CE.cfg有點區(qū)別).
/*---------------server Cofiguation---------------*/
var Server = xdc.useModule('tisdo.ce.Server');
Server.threadAttrs.stackSize = 16384;
Server.threadAttrs.priority = Server.MINPRI;
/*--------------get codec modules;i.e.implementation of codecs-------*/
var H264DEC = xdc.useModule('codecs.h264dec.H264DEC'); //與CE.cfg同,注意H264DEC標(biāo)識的使用。
Server.algs = [
{name:"h264dec", mod:H264DEC,threadAttrs:{stackSize:4096,stackMemId:0,priority:Server.MINPRI+1} }, {...if have..},
?? ];
/*第二部分: DSKT2 and DMAN3的配置:XDAIS算法內(nèi)存和DMA的分配,參考配置文件*/
總結(jié)
以上是生活随笔為你收集整理的DAVINCI开发原理之三----达芬奇编解码引擎Codec Engine(CE)的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 每天学点Linux命令:倒叙打印文件第二
- 下一篇: 路畅安卓最新固件升级_路畅导航系统固件升