本文翻译自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. 该算法的索引超出范围。