使用 Codec Engine 的 API 函數(四),codecengine
本文翻譯自TI的手冊,該手冊是學習GPP+DSP開發的金典文檔,希望對各位入門有所協助,有理解不當之處望請賜教。
Codec Engine Application Developer User's Guide.pdf (Literature Number: SPRUE67D)
《Codec Engine 應用開發使用手冊》 http://blog.csdn.net/dyzok88/article/details/42154487
《第一章 Codec Engine 概要》 http://blog.csdn.net/dyzok88/article/details/42214813
《第二章 Codec Engine 安裝和設定》 http://blog.csdn.net/dyzok88/article/details/42278109
《第三章 使用 Codec Engine 的應用程式範例》http://blog.csdn.net/dyzok88/article/details/42302793
// 本文
4.4 Codec 伺服器 API 函數
在雙 CPU 的系統中,被配置的引擎“遠程”運行(在 DSP 中)演算法,透明地使用一個“DSP伺服器”。DSP 的伺服器是一個整合演算法及其架構的可執行程式(例如,DSP/BIOS,架構組件,轉碼器,和 DSP Link 驅動程式),當引擎被開啟時,這些組件將在 DSP 上被載入並開始運行。
伺服器 API 函數能被在 GPP 上啟動並執行應用程式調用,可以訪問有關DSP的伺服器的資訊,並控制DSP伺服器。更具體地說,這些 API 函數允許 GPP 應用程式擷取有關 DSP 伺服器中配置的記憶體堆數量,一個單獨的記憶體堆的當前使用狀況等資訊。以及重新設定 DSP 伺服器的演算法堆的基址和大小。
涉及到伺服器的 API 函數是:
1. Engine_getServer(). 獲得伺服器的控制代碼。
2. Server_getNumMemSegs(). 獲得在一個伺服器中的堆數。
3. Server_getMemStat(). 擷取有關伺服器的堆統計資訊。
4. Server_redefineHeap(). 設定伺服器堆的基址和大小。
5. Server_restoreHeap(). 重設伺服器堆到預設基址和大小。
4.4.1 擷取伺服器控制代碼
要訪問 DSP 伺服器的引擎,GPP 應用程式必須通過調用 Engine_getServer() API 首先獲得一個伺服器控制代碼,例如:
static String engineName = "auddec";Engine_Handle engine;Server_Handle server;Engine_Error err;engine = Engine_open(engineName, NULL, &err);server = Engine_getServer(engine);
註:引擎控制代碼,伺服器控制代碼都不是線程保護。每個線程使用伺服器控制代碼必須執行自己的 Engine_getServer() 調用(使用自己的引擎控制代碼),或保證共用伺服器控制代碼的同步訪問的。
如果 Engine_getServer() 返回值是 NULL,那麼引擎沒有伺服器。
4.4.2 擷取記憶體堆資訊
GPP 應用程式可以通過調用 Server_getNumMemSegs() 函數,獲得配置到DSP伺服器中記憶體堆的數量,例如:
Server_Handle server;Server_Status status;Int numSegs;/* Get the server handle from a previously opened Engine */server = Engine_getServer(engine);status = Server_getNumMemSegs(server, &numSegs);
這些 API 函數返回以下錯誤的代碼:
1. Server_EOK - 成功。在這種情況下, numSegs 包含 DSP 伺服器中的堆數。
2. Server_ERUNTIME - 發生內部執行階段錯誤。
一旦堆的數目是已知的,GPP 應用程式使用 Server_getMemStat() 函數,然後可以通過此數迭代,獲得每個堆統計資訊。記憶體統計資料返回到 Server_MemStat 結構體:
typedef struct Server_MemStat { Char name[Server_MAXSEGNAMELENTH+1]; /* Name of heap segment */ Uint32 base; /* Base address of heap */ Uint32 size; /* Original heap size */ Uint32 used; /* DSP MAUs of heap used */ Uint32 maxBlockLen; /* Length of largest free block */} Server_MemStat;
下面的範例程式碼顯示了這些 API 函數的用法(為了可讀性,忽略錯誤檢查)
Server_Handle server;Int numSegs, i;Server_MemStat stat;Server_Status status;status = Server_getNumMemSegs(server, &numSegs);for (i = 0; i < numSegs; i++) { status = Server_getMemStat(server, i, &stat); printf("%s: base: 0x%x size: 0x%x used: 0x%x max free block: 0x%x", stat.name, stat.base, stat.size, stat.used, stat.maxBlockLen);}
Server_getMemStat() 的返回值如下:
1. Server_EOK. 成功。
2. Server_ENOTFOUND. 段號超出範圍。
3. Server_ERUNTIME. 發生內部執行階段錯誤。
4.4.3 重新設定DSP伺服器的演算法堆
DSP 伺服器可以被配置為專門用於演算法堆的記憶體段。在某些情況下,DSP 伺服器被配置小演算法堆,GPP 應用程式在運行時,可能需要為演算法堆提供較大的,被 DSP 伺服器使用的連續記憶體塊。然後,當堆不被 DSP 使用時,該記憶體可以從 DSP 回收,進而被 GPP 使用。下面的伺服器 API 函數提供了重新設定 DSP 演算法堆的手段:
Server_Status Server_redefineHeap(Server_Handle server, String name, Uint32 base, Uint32 size);Server_Status Server_restoreHeap(Server_Handle server, String name);
傳遞給這些函數的參數" name "是要重新設定堆的名稱;它必須不大於 Server_MAXSEGNAMELENGTH 字元長。傳遞給 Server_redefineHeap() 的" base "地址,必須為DSP的地址,從 base 到 base + size 的記憶體必須是連續的實體記憶體。參數" size "在 DSP MADUs(minimum addressable data units,可定址的最小資料單元)中給出的。基址應為8位元組對齊,但對大小沒有對齊限制;大小的值為 0 是可接受的。
當堆上沒有記憶體被當前分配時,在 DSP 演算法堆只能被重新設定。 Server_restoreHeap() 函數重設演算法堆的基地址和大小,回到它們的原始值(任何調用 Server_redefineHeap() 之前的值)。成功調用 Server_restoreHeap() 後,記憶體先前的“重新定義”到堆,可被該系統再次使用。
Server_redefineHeap() 的返回值如下:
1. Server_EOK. 成功。
2. Server_EINVAL. 改變到新的基地址和大小導致與另一堆重疊。
3. Server_EINUSE. 記憶體被當前分配在演算法堆。
4. Server_ENOTFOUND. 沒有發現給定的名稱的堆。
5. Server_ERUNTIME. 發生內部執行階段錯誤。
Server_restoreHeap() 返回下列任何的值:
1. Server_EOK. 成功。
2. Server_EINVAL. 改變到新的基地址和大小導致與另一堆重疊。
3. Server_EINUSE. 記憶體被當前分配在演算法堆。
4. Server_ENOTFOUND. 沒有發現給定的名稱的堆。
5. Server_ERUNTIME. 發生內部執行階段錯誤。
下面的代碼說明,這兩個 API 如何可以在 DM644x (一個 GPP+DSP 器件)上使用,在這個樣本中,GPP 應用程式使用 Memory_contigAlloc() 函數分配一個連續的記憶體塊。然而,通過此函數返回的地址是對 GPP 的虛擬位址,因此必須將其傳遞到 Server_redefineHeap() 前轉換到 DSP 地址,Memory_getBufferPhysicalAddress() 函數可以將虛擬位址轉換為 GPP 的物理地址,這樣在 DM644x 的的情況下,就是相同的 DSP 的地址。
演算法運行後,該演算法堆被複位到其原來的大小和位置,為了更好的可讀性,錯誤檢查被省略。
Server_Handle server = NULL;Server_Status status;Engine_Handle ce = NULL;XDAS_Int8 *buf;Uint32 base;String decoderName = "auddec_copy";String encoderName = "audenc_copy";String engineName = "audio_copy";/* Open the Engine and get Server handle. Note, the * Engine_open() call will load and start the DSP. */ce = Engine_open(engineName, NULL, NULL);server = Engine_getServer(ce);/* Allocate block of memory, contiguous in physical memory */buf = (XDAS_Int8 *)Memory_contigAlloc(BUFSIZE, ALIGNMENT);/* Convert virtual address to physical address, which on * DM644x, happens to be the same as the DSP address. */ base = Memory_getBufferPhysicalAddress(buf, BUFSIZE, NULL);/* Reconfigure the algorithm heap */status = Server_redefineHeap(server, "DDRALGHEAP", base, BUFSIZE);'Create and run codecs''Delete codecs'/* Reconfigure algorithm heap back to its original state. */status = Server_restoreHeap(server, "DDRALGHEAP");/* Free the buffer */Memory_contigFree(buf, BUFSIZE);
在其他情況下,應用程式可能需要重新設定演算法堆到一個地址,在 ARM 上分配緩衝區不能獲得該地址。例如,假設在 DSP 上有固定的記憶體空間,該空間給應用程式用於演算法堆之間的交替,取決運行什麼演算法。在這種情況下,應用程式可以直接傳遞 DSP 的地址給 Server_redefineHeap() 函數。