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