这两天对TI的Codec Engine框架进行了进一步的学习,这里总结一下通过XDC工具创建基于Codec Engine的双核(ARM+DSP)工程的建立和生成可执行文件的过程。如有不对的地方,请不吝赐教。
1.由于工程的算法将在DSP端执行,因此需要创建DSP server可执行文件供ARM端的应用程序调用,可以采用以下文件结构。图上还写出了每个文件夹内需要包含的文件(注:runxdc.sh、setpaths.sh文件并不一定要存在,二者存在的目的在于提供XDC命令所需的搜索路径环境变量“XDCPATH”和config.bld文件所在路径环境变量“XDCBUILDCFG”。从而可知config.bld的位置不一定要在工程根目录中,只要XDC工具能找到的位置都行,通过设置XDCBUILDCFG得到)。
2.虽说是自己创建工程,有些文件是可以借用TI的例子通过修改归为己用的。这里就把setpaths.sh、runxdc.sh、config.bld以及APP文件夹中的packag.xdc、package.bld、engine.cfg还有Server文件夹从TI的workshop“lab12a_build_server”中拿来用了。
3.DSP端运行的算法是TI提供的例子videnc_copy,即将输入数据拷贝到输出。APP端通过申请到的输入输出两片连续内存空间,先将给输入输出空间存值并打印,将输入端和输出端通过调用DSP端的videnc_copy算法将输入拷贝的输出看结果。
4.设置好目录并拷贝相应的文件。
l 修改setpaths.sh使其中的环境变量全部指向现在系统中的相应位置。
l 修改config.bld设置三个平台(MVArm、C64P、Linux86)对应开发工具的个目录(rootDir),编译器包含的额外头文件includeOpts,编译器编译选项ccOpts.prefix,库链接关系.lnkOpts.suffix等等参数。最关键的是要把开发工具所在根目录设置正确!
l 修改runxdc.sh,设定正确的路径。(setpahs.sh…………)
5.由于SERVER端只需要video_encoder这个算法,因此在server.cfg中将其他三个算法去掉(只留下“var VIDENC = xdc.useModule('codecs.videnc_copy.VIDENC_COPY');”)。同理,Server对象(不知道怎么称呼JavaScript的变量,按自己理解称之为对象)中其他三个算法的线程参数也要删去。
6..在APP端编写应用程序代码需要用到以下头文件:
算法调用一般流程为:
这里既可以直接调用Engine_open()、VIDENC_create()、VIDENC_process()等函数实现Codec Engine。也可以通过简单的封装函数实现访问。此处选择后者,将“lab12a_build_server/app”下的engine.h、engine.c、debug.h、video_encoder.c、video_encoder.h文件直接拿来使用。
7.修改app中engine.cfg文件,只保留viddec_copy相关内容。将Engine.create中该算法的local参数改为false。同时要指明arm程序执行engine_open时要打开的DSP端SERVER程序所在位置和文件名称:
demoEngine.server = "./server_release.x64P";
8.编写应用程序时需要注意的问题:
l Memory_contigAlloc()需要在CERuntime_init()函数执行后才能执行,否则运行程序后会显示“Segment Fault;
l 出现xxx.h头文件中莫名错误要检查是否包含该文件所有数据结构声明的头文件。如果没有则该头文件不能识别该数据结构;
l Engine_open()使用的Engine名称要和engine.cfg文件中定义的一致,同理VIDENC_create()函数打开的算法名称也要和engine.cfg中定义的一致;
9.TI代码学习收获:
l 通过initMask和对应的宏来标志程序中每一个创建和销毁必须成对出现的步骤,如果创建或打开成功,initMask中对应的位置1,在程序退出时根据initMask置1的情况进行销毁或关闭。同时由于创建有一定的先后顺序,即必须先创建A然后才能创建B这种,因此销毁是创建的倒序。类似一个压栈弹栈的过程。
l 使用status指示状态,一旦出错就将指示状态设置为EXIT_FAILD,然后使用goto转入销毁阶段;
l 使用DBG()定义,若定义了_DEBUG_则会编译时DBG等同于printf,否则为空。
l 每一个算法使用一个线程,对于线程的调度属性和优先级等通过实际调成观察运行情况。
l CERuntime_init()每一个进程只能使用一次。因此需在main函数中执行。而engine_open可以在多个线程中使用。
l 通过线程参数传入quit标志,线程通过检查标志位决定是否退出本线程的操作,main函数线程绑定“CTL+C”消息处理函数,在处理函数中将标志位置1.