首页 > 代码库 > 使用 Codec Engine 的 API 函数(二)

使用 Codec Engine 的 API 函数(二)

 本文翻译自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

<span style="font-family:Arial, Helvetica, sans-serif;color:#ff0000;"><span style="background-color: rgb(255, 255, 255);">// 正文</span></span>
<span style="font-family:Arial, Helvetica, sans-serif;color:#ff0000;"><span style="background-color: rgb(255, 255, 255);"></span></span>

4.2.1 Codec Engine 配置代码

使用 Codec Engine 的应用程序应该包括下面的头文件,这些目录路径是相对于软件包路径,其中包括 CE_INSTALL_DIR 和 XDC_ROOT。

<span style="font-size:14px;color:#ff0000;">#include <xdc/std.h>
#include <ti/sdo/ce/Engine.h>
#include <ti/sdo/ce/CERuntime.h></span>

此外,应用程序必须包括任何 VISA 模块使用的头文件,例如:

<span style="font-size:14px;color:#ff0000;">#include <ti/sdo/ce/audio/auddec.h></span>

注意,头文件的路径完全对应于表4-2中,Codec Engine Modules 中所示的软件包的路径。

Table 4–2 Codec Engine Modules

技术分享

使用 Codec Engine 的所有应用程序必须运行 CERuntime_init。通常情况下,这是从应用程序的 main() 函数运行。

此外,建立一个使用 Codec Engine 的 GPP+DSP 应用程序时,您必须加载依赖的模块 DSP/BIOS Link 和 CMEM (连续内存分配器)。检查 examples/apps/system_files/davinci/loadmodules.sh 文件,可以看到这是如何实现的。详情参见 build_instructions.html 文件。


4.2.2 打开一个引擎

当你打开一个引擎,可以指定你要打开的引擎的名称。例如:

<span style="font-size:14px;color:#ff0000;">static String engineName = "auddec";
Engine_Handle ce;
Engine_Error errorcode;

ce = Engine_open(engineName, NULL, &errorcode);</span>

注:注意引擎句柄( handles )不是线程保护。使用一个引擎实例的每个线程应该执行自己的 Engine_open() 函数调用,并使用自己的引擎句柄。这样在多线程环境中,保护了每个引擎实例被其他线程访问。

引擎由您的引擎工程师来配置,引擎工程师决定把哪些算法配置和编译到每个引擎。见第5章,“集成一个引擎”,可以了解到引擎工程师需要建立这样的引擎的信息。

例如,在双 CPU 的系统,例如 DM644x 的设备,算法可以在本地(在 GPP )或“远程”(在 DSP )运行。对于远程算法,透明引擎采用了" DSP Server "和 DSP Link 通道运行高速算法。这里,Engine_open() 的第一次调用导致以下基本操作:

1. 打开 DSP (如果 ti.sdo.ce.osal.Global 配置文件支持可配置)

2. 初始化 DSP 和通道需要调用 Link API 函数:PROC_Setup(), PROC_Attach(), POOL_Open(), PROC_Load(), PROC_Start(), and MSGQ_TransportOpen()。

3. 从 GPP 侧到 DSP 上的远程分配器进行初始握手。

Engine_open() 函数可以让你传递 Engine_Attrs 结构到引擎。这种类型在 Engine.h 定义,该头文件由应用程被应用程序包含。目前,这种结构允许您指定运行该引擎的DSP服务器的进程的 ID。如果有一个以上的处理器,只需提供相同服务和当前正在使用的服务 ID 即可,默认 procID 为0。

<span style="font-size:14px;color:#ff0000;">typedef struct Engine_Attrs {
   String procId; 
} Engine_Attrs;</span>

如果通过 Engine_open() 返回的 Engine_Handle 是 NULL,那么该引擎无法打开。如果错误码参数为非空,则Engine_Error值被设置为以下值之一:

1. Engine_EOK. 打开成功。
2. Engine_EEXIST. 引擎名称不存在。
3. Engine_ENOMEM. 无法分配内存。
4. Engine_EDSPLOAD. 无法加载 DSP. 
5. Engine_ENOCOMM. 无法与 DSP 建立通信链接。 
6. Engine_ENOSERVER. 无法找到 DSP 上的服务器。 
7. Engine_ECOMALLOC. 不能分配通信缓冲区。 

您的应用程序可以处理此错误。例如:

<span style="font-size:14px;color:#ff0000;">ce = Engine_open(engineName, NULL, &errorCode);
if (ce == NULL) {
    printf("Error: could not open engine \"%s\"; 
            Error code %d.\n", engineName, errorCode);
}</span>

4.2.3 关闭一个引擎

要关闭一个引擎实例和释放其使用的内存,您的应用程序应该调用 Engine_close()。例如:

<span style="font-size:14px;color:#ff0000;">Engine_close(ce);</span>

你应该在已经删除了该引擎创建的任何算法实例,并释放所有的缓冲区或其他内存相关的算法实例之后这样做。

例如,在上一节中所描述的的基于 DM644x 的示例:在DSP上执行远程算法,Engine_close() 的最后一次调用导致以下基本操作:

1. 调用需要 "finalize" DSP和传输链路的 API:MSGQ_TransportClose(), PROC_Stop(), POOL_Close(), PROC_Detach(), and PROC_Destroy()。

2. 关闭 DSP (如果 ti.sdo.ce.osal.Global 配置文件支持可配置)。


4.2.4 从引擎中获取内存和 CPU 的信息

您可以使用 Engine_getUsedMem() 函数来获取有关使用一个引擎实例内存的信息。返回的值是从当前可用的堆中可分配的的内存总量(在 MAUs )。请注意,此值根据DSP Server活动,可以在调用之间发生变化。例如,当第一个算法被实例化在 DSP 服务器上,除了那些需要的个体算法实例之外,数据结构可以被分配。这些额外的内存分配给"第一次需要的请求",即使该算法被删除,仍保持全局状态的分配,

除了 Engine_getUsedMem()之外,服务器 API 函数也可用于获取在 DSP 上有关个别堆的内存使用信息,参见4.4节对这些函数的说明。

可以使用 Engine_getCpuLoad() 函数来获得 DSP 服务器的 CPU 使用率,从 0 到 100 的整数。此值显示了 DSP 服务器被测量一段约 1 秒时间,历时百分比。


4.2.5 获取在一个引擎中算法配置的信息

应用程序可确定的配置到引擎中的算法的数量和算法的特性,如该算法的名称,是本地还是远程的算法。

可以用下面的 API 函数来获得算法的数量:

<span style="font-size:14px;color:#ff0000;">Engine_Error Engine_getNumAlgs(String name, Int *numAlgs)</span>

参数 "name",是引擎的名称,该函数返回下列值:

1. Engine_EOK. 成功. 在这种情况下, *numAlgs 返回配置到引擎中算法的数量。

2. Engine_EEXIST. 没有给定名称的引擎。

一旦引擎中的算法数量是已知的,应用程序可以反复调用函数 Engine_getAlgInfo(),以获得关于每个的算法的信息。该信息被放入 Engine_AlgInfo 结构体,其定义如下:

<span style="font-size:14px;color:#ff0000;">typedef struct Engine_AlgInfo {
    Int         algInfoSize;    /* Size of this structure */
    String      name;           /* Name of algorithm */
    String      *typeTab;       /* inheritance hierarchy */
    Bool        isLocal;        /* if TRUE, run locally */
} Engine_AlgInfo;</span>

Engine_AlgInfo 结构的第一个成员 "algInfoSize",必须由应用程序来设置该结构的大小;它将被用于支持将来增强该结构。下面的示例演示这些 API 函数的使用(不对可读性进行错误检查):

<span style="font-size:14px;color:#ff0000;">Int                 numAlgs, i;
Engine_AlgInfo      algInfo;
Engine_Error        err;

err = Engine_getNumAlgs("audio_copy", &numAlgs);

for (i = 0; i < numAlgs; i++) {
    err = Engine_getAlgInfo(name, &algInfo, i);
    printf("alg[%d]: name = %s typeTab = %s local = %d\n",
        i, algInfo.name, *(algInfo.typeTab), algInfo.isLo-
cal);
}</span>

输出可能如下所示:

<span style="font-size:14px;color:#ff0000;">alg[0]: name = auddec_copy typeTab = ti.sdo.ce.audio.IAUDDEC local = 0
alg[1]: name = audenc_copy typeTab = ti.sdo.ce.audio.IAUDENC local = 0
</span>

结构体成员 typeTab,实际上是预留给继承层次的 NULL 结尾的字符串数组。

Engine_getAlgInfo() 的返回值如下:

1. Engine_EOK. 成功。
2. Engine_EEXIST. 没有给定名称的引擎。
3. Engine_EINVAL. 传递给此函数的 Engine_AlgInfo 对象 algInfoSize 的值与编解码器引擎库中 Engine_AlgInfo 对象的大小不相匹配。
4. Engine_ENOTFOUND. 该算法的索引超出范围。


使用 Codec Engine 的 API 函数(二)