基于DM6446的视频采集回放
一、 引言
TI提供的达芬奇参考软件框架分为应用层、信号处理层和I/O层三部分,如下图所示。
图1 davinci软件框架
Davinci的应用工程师可以在系统的用户空间,即应用层,在系统功能性上添加和发挥自己的特 {MOD}。信号处理层通常都运行在DSP端,负责信号处理,包括音视频变价么算法、Codec Engine、DSP的实时操作系统DSP/BIOS及和ARM通信的模块。I/O层就是我们通常所说的驱动,是针对Davinci外设模块的驱动程序。其中应用层通过Codec Engine的VISA API来调用DSP端的算法,通过EPSIAPI来访问和操作Davinci的外设。
1.1 CodecEngine概述
应用工程师通过调用Codec Engine的API来调用和运行符合xDAIS的算法。在Davinci软件中,符合xDAIS的音视频编解码算法的调用是通过Codec Engine的VISA API完成的。Codec Engine通过这套API为算法的执行提供了一个标准的软件架构和接口,体现在以下几个方面:
l 通过Codec Engine API调用的算法可以运行在本地(ARM侧)或者远端(DSP侧);
l Codec Engine可以基于ARM+DSP 、DSP或ARM上运行;
l 无论Codec Engine运行在ARM还是DSP上,对应的Codec Engine API都是完全一致的;
Codec Engine的API与操作系统无关。比如Linux、VxWorks和WinCE环境下的Codec Engine API都是完全一致的。Codec Engine是介于应用程序和具体算法之间的软件模块,其中的VISA API通过stub和skeleton访问Engine SPI最终调用具体的算法。因此,Codec Engine的工作室通过完成VISA API的任务来实现的。VISA API分为四部分VISAcreate/control/process/delete。
图2 Codec Engine原理
在调用VISA API之前需要在应用程序中通过Engine_open()这个Engine API把DSP的可执行程序加载到DSP的memory,同时把DSP从复位状态释放,这时DSP开始运行DSP Server的初始化程序在DSP端创建一个优先级最低的任务RMS,RMS负责管理和维护对应到具体codec算法的instances。如下图所示,应用程序调用VISA create API,相应的VISA create函数到Engine SPI中的Codec table中查到这个codec运行在远端DSP侧。接着Engine
SPI通过OSAL、DSP Link把VISA create的命令传到DSP侧的RMS。RMS通过DSP侧的Engine SPI的codec table找到要调用的codec算法后,就会在RMS中创建一个相应的instance。VISA create会返回一个instance的Handle,以便于给这个Instance做后续的VISA control/process/delete提供信息。VISA delete和VISA create原理类似,只是RMS删除掉相应的codec算法的instance和执行codec算法的任务。
概括来说,VISA control用来动态的修改codec instance的属性,VISA process用来对算法的输入流做处理并返回一个输出数据流。应用程序在调用VISAprocess/control时会通过xDM Stub把传递给codec算法的参数收集起来,并且转换成DSP可以识别的物理地址。Stub把这些参数和相关的命令通过Engine SPI、OSAL和DSP Link传递到DSP侧的instance。Instance再通过Skeleton把传递过来的参数和命令解析出来,通过DSP侧VISA
control/process对codec算法执行control/process。
1.2 xDC简介
达芬奇的软件开发环境中,有一个DSP工程师比较陌生的工具xDC。和gmake类似,xDC根据一套build指令build生成可执行文件。xDC同时也会build以来文件,并且可以一次build多个目标对象的可执行文件。xDC的源文件可以使C程序、C++程序、汇编程序和库文件等。
1.3 Davinci的软件开发步骤
图3 davinci开发步骤
第一步,工程师需要基于DSP利用CCS开发自己的音视频编解码算法,编译生成一个编解码算法的库文件*.lib。如果要通过Codec Engine调用这个库文件中的算法函数,那么这些算法实现需要符合xDM标准。
第二步,生成一个在DSP上运行的可执行程序*.x64p,也就是DSP Server。
第三步,根据DSP Server的名字及其中包含的具体的音视频编解码算法创建CodecEngine的配置文件*.cfg。这个文件定义Engine的不同配置,包括Engine的名字、每个Engine里包括的codecs及每个codec运行在ARM还是DSP侧等。
最后,应用工程师收到不同的codec包、DSP Server和Engine配置文件*.cfg,把自己的应用程序通过编译、连接,最终生成ARM侧可执行文件。
二、 程序分析
对于视频采集回放来说需要三个程序包,分别为
1、 video_app:ARM端应用程序
2、 servers:算法封装包
3、 codecs:包含了codec算法包
2.1 video_app
video_app所包含文件所示:
图3 video_app make前所包含文件
ARM端通过Engine配置文件video_app.cfg来配置使用的codec包、DSP Server,APP 通过Codec Engine的VISA API完成对DSP端算法的调用。ARM端创建的应用程序分为三类:源文件(.c .h文件)、video_app.cfg、makefile文件。其中video_app.cfg文件中定义了各种Engine的配置,包括Engine的名称、编码/解码器等。对于应用程序是在本地执行还是在远端执行,通过配置脚本即可实现。附上video_app.cfg部分源码:
图4 video_app.cfg部分源码
ARM端应用程序中还有很重要的一部分是V4L2采集驱动和FBdev显示驱动应用程序的编写即capture.c和display.c。V4L2驱动和FBdev显示驱动都属于linux底层驱动的一部分,也就是说两者是嵌在操作系统里的驱动,具体文件可以到内核文件中的drivers文件中查看。但是内核驱动只是给出的接口函数,也就是说我们要在linux应用程序中控制TVP5150和CCD的采集以及显示部分。下面我们以采集为例说明一下具体的工作流程,V4L2负责对采集到的视频数据进行管理,V4L2一般操作流程如下:
1、打开设备文件
2、取得设备的capability,看看设备具有什么功能,比如是否具有视频输入等
3、选择视频输入,一个视频设备可以有多个视频视频输入
4、设置视频的制式和帧格式,制式包括PAL,NTSC,帧的格式包括高度和宽度等
5、向驱动申请帧缓冲,一般不超过5个
6、将申请到的帧缓冲映射到用户空间,这样就可以直接操作系统采集到的帧了,而不必去复制
7、将申请到的帧缓冲全部入队列,以便存放采集到的数据
8、开始视频的采集
9、出队列以取得已采集数据的帧缓冲,取得原始采集数据
10、将缓冲重新入列队尾,这样就可以循环采集
11、停止视频的采集
12、关闭视频设备
这里需要说明的是,第六步中“将申请到的帧缓冲映射到用户空间”,操作系统一般把系统使用的内存划分成为用户空间和内核空间,分别由应用程序管理和操作系统管理。应用程序可以直接访问内存的地址,而内核空间存放的是供内核访问的代码和数据,用户不能直接访问。V4L2捕获的数据,最初是存放在内核空间的,这意味着用户不能直接访问该段内存,必须通过某些手段来转换地址。
在main.c文件中主要有三个线程,分别负责采集、处理和显示,即文件中的capture、video和display,capture和display之前已经介绍过,而具体的数据处理都在video.c文件中。这里所说的数据处理,对于我们现在作用的程序,是一种抽象层,是通过VISA API这些函数去调用算法接口,去create 、process,但只是去调用了这些算法,因为算法真正的实现是在远端即DSP端,这些也是配置文件video_app.cfg配置好的。也就是说我们做了一个符合xDAIS标准的算法,然后在APP端调用,而APP端决定了算法的实现以及在近端还是远端实现,只不过是具体的实现过程没有在APP端得到体现。
最后Makefile文件将这些文件打包生成可在达芬奇平台上运行的可执行文件。如图所示:
图5 video_app make后所包含文件
2.2 servers
Server集成了容纳编码器,解码器所需的各种成分(例如 DSP/BIOS、框架成分,连接驱动器和编码/解码器等),并产生一个DSP端的可执行程序。Codec Server的配置需要两个步骤:
1、通过tcf脚本语言配置DSP/BIOS
2、通过XDC配置剩下的组件:如FC组件、DSP/BIOS Link、Codec Engine等。
下图为servers中所包含的文件:
图6 servers make前所包含文件
对DSP Server的源文件进行build(类似于make)生成DSP Server.x64p文件分为三部分:
创建DSP Server的源文件 main.c
.tcf :DSP/BIOS配置文件
ink.cmd
源文件一:main.c
main函数中主要工作为初始化codec Engine,初始化trace,并创建trace
源文件二:video_cpoy.tcf
DSP/BIOS的配置文件,定义DSP的memory map,设置DSP的复位/中断向量表并且创建和初始化BIOS程序需要的各种数据对象,在.tcf中我们只能定义编译器默认的sections(如.text和.bss等),但是我们可以在link.cmd中定义自己的section。其实我们参考在做纯DSP开发时的配置,在调用DSP/BIOS时同样需要配置.tcf文件和.cmd文件。
源文件三:link.cmd
如果我们有自己定义的section,要指定所在的位置,在link.cmd中声明。
package.bld
l 设置XDC的配置文件 package.xdc
video_copy.cfg
package.bld:功能类似于linux中的makefile文件,它会告诉xDC怎么样build DSP Server的源文件。
package.xdc:声明DSP Server的名字,它的路径及server的依赖文件
video_copy.cfg:负责系统级的管理,包括了codec的配置、DSKT2配置和DMAN3配置。Codec配置:每一个codec都被包含在各自的线程中,配置每一个codec线程的属性(线程优先级、堆栈大小和堆栈的memory资源);DSKT2配置:把所有的IALG memory类型结合到可用的DSP memory,定义缺省的scratch组的memory的大小;DMAN3配置:定义DMAN3可以管理的DMA通道号,定义DMAN3可以提供给算法的TCC号。
l 执行“make”生成可执行文件
执行xDC后先产生package.mak,xDC再运行package.mak生成包含可执行文件的package。
图7 servers make后所包含文件
2.3 codecs
Codec主要用于生成算法并将其打包,其中必不可少的是算法的定义、具体的调用以及相应的服务配置等。每一个Codec都必须包括以下源文件:package.bld文件、package.xdc文件、package.xs文件、
.xdc文件、.xs文件以及相应算法的.h文件和.c文件等。
图8 codecs make前所包含文件
package.bld:主要定义和package编译相关的属性,即一个包应该如何被编译。文件内容用Iavascript描述。package.bld文件中包含目标平台集的定义、编译版本的定义、确定源文件集合生成的可执行文件信息。
package.xdc:包定义文件,同时也是一个XDC文件。它定义了包的名称及其依赖。文件中主要包含与package有关的静态特性信息,如依赖信息、模块信息、版本信息等。
package.xs:动态属性配置文件,指出了由于平台和配置不同而不同的包属性。
package.mak:根据XDC文件生成的文件(类似于makefile),并最终通过运行它生成包括可执行文件的package。
VIDENC_COPY.xdc:具体算法的静态配置文件,包括具体模型的定义和声明。文件中具体指明了该codec的名称、类型以及用户希望说明的附加特性。最重要的就是指明算法接口的名称,因为我们去调用算法时,就是利用的这个接口的名称。
VIDEENC_COPY.xs:定义了算法的一些动态属性,包括.xdc文件中的接口方法的实现以及模块的实现。VIDEENC_COPY.xdc与VIDEENC_COPY.xs的关系类似于.h和.c的关系,即VIDEENC_COPY.xs是具体的实现,如接口的功能和编解码线程的堆栈大小。
*.h文件:videnc_copy_ti.h和videnc_copy_ti_priv.h分别是公共头文件和私有头文件。
*.c文件:是对.h文件中涉及的所有算法接口的具体实现。需注意的是,这个文件的编写需要满足 XDAIS-DM标准。而且我们移植较小的算法时可以直接修改.c文件,而其他地方不动,这样就不用修改算法接口,以及其他的配置文件。
图9 codecs make后所包含的文件
三、 系统工作流程
3.1 Nandflash烧写
前期准备工作:安装redhat操作系统配置好交叉编译环境和nfs服务器等,安装好CCS软件开发环境并配置好gel文件,将实验箱网口通过网线与PC端连接,将J2,J17,J23,J24跳线短接,通过仿真器将J1仿真器插头与PC端连接,给系统上电。
u-boot编译:
因为实验箱默认是从硬盘启动,现在我们想让实验箱通过NFS挂载PC端的文件系统进行启动。需要修改配置文件configs/davinci_dtk6446.h,需要修改为如下所示,然后重新编译,生成u-boot.bin文件。这里的mem是指分配给ARM的内存空间,从nfs启动,实验箱的IP地址设为192.168.1.197,PC端IP地址为192.168.1.196,保证两者的IP地址再同一网段内。
图10 启动项配置文件
ubl、u-boot和uImage的烧写:
CCStudio v3.3启动后选择ARM端打开,连接,加载nandflash.out文件,运行根据提示依次烧写ubl_nand.bin文件、u-boot.bin文件和uImage文件,等待烧写完毕。
图11 系统启动流程
3.2 视频采集回放程序的烧写
1、加载cmem.ko和dsplink.ko模块
root@192.168.1.196:~#./loadmodules.sh
因为DSP需要连续的物理地址空间分配以及ARM与DSP之间的通信依赖于cmem.ko和dsplink.ko,因此在运行所有程序之前需要加载这两个模块。
2、执行应用程序
root@192.168.1.196:~#./video_app
视频显示设备上将实时显示采集的图像。