转载注明:http://blog.csdn.net/guo8113/article/details/41120491
Netra(DM8168)处理器是个多核处理器,每一个核之间相互独立却又相互关联,怎样高效简洁地利用每一个核完毕一套系统功能是很关键的。RDK这套软件平台就是针对这样的多核平台设计的一套多通道视频应用方案。主要用于DVR、NVR、IPNC之类的产品。
这个软件框架结构同意用户创建不同的多路数据流来实现视频的採集、视频处理(DEI、Noise Filter、Encode、Decode、SwMs、Merge等)和视频播放功能,其框架设计很值得学习。
下面为相关缩写解释:
*****************************************************************************************************
HDVPSS:High Definition Video Processing Subsystem
HDVICP:High Definition Video and Image CoProcessor
Ducati:Dual Core M3 Processors controlling HDVPSS and HDVICP hardware engines
Video M3:ARM Cortex M3 Core(inside Ducati subSystem)controlling HDVICP codecs
VPSS M3:ARM Cortex M3 Core(inside Ducati subSystem)controlling HDVPSS,also called DSS M3
DEI:Deinterlacer
McFW:Multi Channel Framework
IPC:Inter Processor Communication
******************************************************************************************************
1、Rdk平台软件框架图
在Rdk平台软件中做了非常好的分层。例如以下图所看到的:
注意:上图中核间通过Syslink/IPC通信,随意2个核之间都能够直接通信,是一个星型网络。上图画的连接关系描写叙述的是对等层次的概念。
上图中相关层的功能及相关描写叙述例如以下表所看到的:
层 | 处理器 | 描写叙述 | 相关TI软件包 |
Linux | HOST A8 |
Linux OS, includes, filesystems, SATA, Ethernet, USB and other IO drivers |
Linux PSP |
BIOS6 |
VPSS M3 Video M3 DSP |
BIOS RTOS used as OS on Video-M3, VPSS-M3, DSP. Provides features like threads, semaphores, interrupts. Queues and message passing between links is implemented using BIOS semaphores. |
BIOS XDC (used for BIOS and other configuration) |
Syslink / IPC |
HOST A8 VPSS M3 Video M3 DSP |
Software APIs used for communicating between processors. Provides features like processor loading and booting, multiprocessor heaps, multiprocessor linked list (ListMP), message queues, notify etc |
Syslink IPC |
HDVPSS Drivers |
VPSS M3 |
HDVPSS drivers like capture, display, deinterlacer, scaling based on FVID2 interface to control and configure the HDVPSS HW |
HDVPSS |
Video Encode/Decode |
Video M3 |
Video encode / decode APIs based on XDM / XDIAS interface. Uses framework components for resource allocation |
XDIAS Framework components IVAHD HDVICP2 API H264 decoder H264 encoder |
Links |
Links HOST A8 VPSS M3 Video M3 DSP |
Implementation of individual links. Some links are specific to a processor while some links are common across processors |
DVR RDK |
Link API | HOST A8 |
The link API allows users to create , connect, and control links on HOSTA8, VPSS M3, Video M3 and DSP. Link API is used to create a chain of links which forms a user defined use-case. The connection of links to each other is platform dependant. |
McFW |
McFW API | HOST A8 |
Multi-Channel FrameWork API. Multi-Channel Application specific API which allows user to setup and control pre-defined application specific chains for DVR, NVR, using a single simplified API interface. This allows users to directly use the links without having to understand the detailed link API. The McFW API is platform independent and same API will work on DM816x, DM814x, DM810x |
McFW |
User Application |
HOST A8 |
Typically GUI and other application specific components like file read/write, network streaming. |
Customer specific |
2、基于Rdk框架的实例
Capture (YUV422I) 16CH D1 60fps
|
NSF (YUV420SP)
|
dup1---->IPCM3OUT(VPS) -> IPCM3IN(VID) -> ENC -> IPC_BITS_OUT_M3 -> IPC_BITS_IN_A8 -> fwrite() - Write to filesystem
| !
| 。
+-<----IPCM3IN(VPS) <- IPCM3OUT(VID) -> DEC <- IPC_BITS_IN_M3 <- IPC_BITS_OUT_A8 <- fread() - read from harddisk
|
MERGE
|
DUP2
|||
+--------+|+------------+
| | |
| | |
SW Mosaic SW Mosaic SW Moasic
(DEIH YUV422I) (DEI YUV422I) (SC5 YUV422I)
| | |
GRPX0 | GRPX1,2 | |
| | | | |
On-Chip HDMI Off-Chip HDMI SDTV (NTSC)
1080p60 1080p60 480i60
3、Link Api机制
3.1 link api的概念
link在上图中的视频数据流中是最主要的单元模块,每一个link中包括了一个基于BIOS6/Linux的任务、线程、消息盒(使用操作系统的信号量实现)。因为每一个link执行一个独立的现成,因此link之间能够并行执行。消息盒是关联用户指定的link,让link之间有个互相对话的机制。用来传递信令。而对于视频流数据、帧数据的传递link实现了专门的接口来实现。仅仅传递指针,而不是数据。
在实现上节所介绍的数据流能够通过将多个link连接来实现chain。link API同意用户Create、Start、Stop、Delete、Control各个link。在Rdk中TI基于link API进行再次封装,用于特定的应用场合。其各种參数均是为特定的产品定制。能够是相关业务的开发更迅速。
3.2 link内部结构
watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvcm9iaW4xOTg5MDMwNQ==/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/SouthEast" alt="" height="500" width="1000" style="border:none; max-width:100%">
3.3 link的特性
- 视频处理的工作量能够均衡到每一个核心上去运行,例如以下表:
Processor |
OS |
Used for |
HOST A8 | Linux | System setup and control, GUI, IO peripheral control like SATA, Ethernet, USB, Audio |
VPSS M3 | BIOS6 |
HDVPSS control for video capture, video display, scaling, deInterlacing … |
Video M3 | BIOS6 | HDVICP2 Video compression / decompression (H264 encode, H264 decode) |
DSP | BIOS6 | SW OSD, custom video processing algorithms |
- 每一个link都有自己独立的任务/线程用于完毕视频採集或播放等处理;
- 每一个link都能够处理来自多个通道的视频帧数据,每一个通道的视频宽高和数据格式都能够不同;
- A8作为HOST能够用来连接多个link形成数据流的链并对其进行控制;
- 数据链被建立并启动时,数据链中的每一个link将和它的下游link进行帧数据的交互;
- links之间的帧数据交互能够在多个核心之间进行,而且并不须要A8 HOST的干涉,从而减少A8的开销;
- 在数据链执行过程中用户能够发送控制信令给随意link来动态设置相关的link參数;
3.4 link接口
link接口能够分成下面几类:
- link API——被用户调用来配置和控制link的接口;
- Inter link API——被其它links调用来交换帧数据的接口;
- link output queue——被其它links通过Inter Link API接口有用的帧buffer队列。
3.5 link间的消息传递
每一个Link通过一个32位的该LinkId来识别。ID高4位标识了这个Link是在哪个核上执行,低24位标识了该Link的名称:
Bits | Description |
[0..27] | Link ID |
[28..31] | Processor ID on which this link runs 0:DSP 1:Video M3 2:VPSS M3 3:A8 |
每一个Link API都须要这个LinkID參数来发送消息,当用户发送消息到一个Link时。依据这ID函数内部推断这个消息是发给本地的Link还是远端核心的Link;假设是本地的直接调用BIOS/LINUX API函数,否则就通过Syslink模块的MessageQ发送这个消息到指定的核心,让对端的核心调用相应的函数处理。
3.6 link API
以下将通过表格的形式来看看link API的部分接口及相关功能:
API | Description |
System_linkCreate | Creates a link ——allocates driver, codec, memory resources. |
System_linkGetInfo | Get information about a link like number of channels, properties of each channel. MUST be called after System_linkCreate() for a link |
System_linkStart | Start the link ——starts the driver or codec |
System_linkControl | Send a link specific control command with optional arguments |
System_linkStop | Stop the link —— stops the driver or codec |
System_linkDelete | Deletes a link —— free’s driver, codec, memory resources |
3.7 Inter link API
以下的表格介绍了在link内部实现的交换帧数据的API。对于用户来说,这部分API是不须要关心的:
API | Description |
System_GetLinkInfoCb | Function to return information about a link like number of channels, properties of each channel |
System_LinkGetOutputFramesCb |
Function to return captured or generated or output frames to the caller (another link) |
System_LinkPutEmptyFramesCb | Function to release consumed frames back to the original link for reuse |
System_LinkGetOutputBitBufsCb | Function to return generated or output bitstream frame to the caller (another link) –Valid only for Encode Link |
System_LinkPutEmptyBitBufsCb | Function to release consumed bitstream frames back to the original link for reuse –Valid only for Encode Link |
在每一个link中必须实现一些函数并在初始化时注冊这些函数指针给link管理的核心模块,用于帧数据的获取、释放、dump相关状态等。
对于任一个link想从它的上游link获取帧数据都须要调用link管理核心函数System_getLinksFullFrames(),该函数内部会发送消息到相应的上游link,触发该link向管理模块注冊的回调函数System_LinkGetOutputFramesCb()将帧数据传递给该link。
相同的。在当一个link想释放处理完成的帧buffer给上游link时须要调用link管理核心函数System_putLinksEmptyFrames(),该函数内部会发送消息到相应的上游link,触发它注冊的回调函数System_LinkPutEmptyFramesCb()将帧buffer回收,用于兴许的数据处理;
建立chain时。你肯定还会关注一个信息,那就是上游link的相关參数怎样传递给下游的link,从源程序细致琢磨琢磨就能够看出来,和上面的处理类似,全部有下游link的link都会注冊一个System_GetLinkInfoCb()的回调函数,在下游link的driver中会在创建driver时调用System_linkGetInfo()函数来获取上游link的相关參数。
通过上述的方法。对于一个link来说就不须要关心和它交互的是哪一个link,全部的寻址都通过linkID来自己主动查找。而且同一个link实现能够和不同的link交互,而不须要改变函数的实现。
3.8 Link Output Queues 的管理
一个Link能够有一个或多个输出队列用来存放採集到的或处理完成的帧数据,每一个Link的输出队列内存由自己分配。
大多数Links仅仅有一个输出队列,可是有些link有多个。从而能够实现多路不同的输出数据流满足不同的应用需求,比如,Noise filter Link能够输出16路帧数据到2个输出队列,每一个输出队列输出8路通道数据跟别给2个DEI Links模块处理。
一个输出队列中能够有多个视频channels的数据,每一个channel能够有不同的大小和数据格式。
数据结构 FVID2_Frame是在VPSS驱动中定义的,Links之间就通过该结构參数传递帧数据的信息,如帧数据的Buf指针,而帧数据本身并不会被拷贝,从而节省内存开销。
当一个Link採集完或处理完一帧数据后会发送一个消息“SYSTEM_CMD_NEW_DATA”给下游的Link,从而通知它有数据可取。当下游Link收到该消息后会调用System_getLinksFullFrames()函数来获取对用的帧数据。处理完后再调用System_putLinksEmptyFrames()函数来归还给上游Link继续使用。
因此一个Link须要知道:
- 上游Link的LinkID和QueID,从而从该队列里面获取帧数据
- 下游LinkID,从而在有新数据产生时通知下游Link来取
上游Link的LinkID和QueID 以及下游LinkID 都是在System_linkCreate()时由A8
HOST端来指定的。
3.9 IPC link核间帧数据交互
IPC Link。是用来多核之间的帧数据传递的。
如VPSS上的採集Link想把帧数据发送给Video Link处理。先将帧数据传递给本地的IPC Link,然后IPC Link再通过Syslink/IPC发送到Video Link上的IPC Link。然后再转发给Video Link,这种话对于採集Link的实现来说就很清晰简单。它的实现都是发送给本地的还有一个Link;
IPC Link的实现有点复杂,由于它涉及的帧数据传递是在多个核之间。这里面就牵扯到cache的一致性问题,考虑到每一个核的特性以及高效性,总共设计了3个内部Links用于帧数据的传递机制:
- Intra-processor links
即同一核心内部的link。如採集与降噪之间的帧数据传递。这样的内部的link间传递帧数据都是在VPSS M3内部完毕。因此採用简单且高效的队列机制实现。
- Inter M3 (Video / VPSS) links
即M3内部核心之间的link,因为Video和Vpss所在的2个M3核心是同属于一个双核M3处理器,它们的cache是共享的。如降噪模块(VPSS NF)到编码模块(VIDEO Enc)之间传递帧数据,带有Notify的IPC ListMP机制被用来在这2个M3核心之间传递帧信息(FVID2_Frame)。该过程中不须要不论什么cache操作和地址转换。
- Inter processor (M3 to A8 or DSP)
即处理器内部核心之间,如编码(VideoM3)到BitStream In(HostA8)之间传递帧数据,相同使用带Notify的IPC ListMP机制在2个核心之间传递帧信息(FVID2_Frame),但该过程中须要做cache同步和地址转换操作。
4、chain数据链路的建立
一个Chain是由多个links依照一定的应用需求按顺序连接成一条视频处理的数据流。
一个Chain能够销毁后又一次依照新的需求组成新的Chain,不须要重新启动系统。
Chain创建是特别须要相关link的顺序
- 通过System_linkCreate()函数依照由source>>sink 的顺序创建须要的Links,Source Link即没有上游Link的Link,如:视频採集;Sink Link是没有下游Link的Link,如:视频播放。这个创建顺序是很重要的,由于一个Link创建时它会查询上游Link的一些信息,如上游Link须要的channel的个数和属性,从而依照这些參数配置自己。
- 下一步调用System_linkStart()函数启动每一个Link,启动顺序一般从Sink Link往前到Sorce Link。当然你也能够不依照这个顺序。只是不推荐。由于这样能够保证每一个Link在它的上游Link启动前准备好接收数据。避免过多的缓冲引入额外的时延。
- 当一个Chain执行后控制命令就能够发送到各个Links来控制它。如调用System_linkControl()函数发送改变画面合成风格的命令给对应的Link。详细的命令定义由每一个Link的功能实现来决定。
- 注意:一般来说System_linkControl()函数是在System_linkCreate()创建了Link之后才干调用。只是有些控制命令能够在System_linkCreate()调用之前调用,以完毕Link创建之前必须的一些初始化,如复位;
- 当Chain工作完毕或销毁时能够调用System_linkStop()函数先停止每一个Link。注意:停止的顺序必须从Source開始依次到Sink结束;由于一个Link可能堵塞着等待下游Link释放当前Link的输出Buffer,假设下游Link先停止的话当前Link可能会出于wait for ever的状态而永久退不出来,因此上游Link必须先停止,之后才干停止下游Link;
- 最后等全部Link全部停止后,能够调用System_linkDelete()函数删除全部Links。删除顺序没有要求;
- 当Chain销毁后就能够依照之前的顺序又一次创建一个新的Chain来完毕还有一个工作了。
原文地址:http://blog.csdn.net/crushonme/article/details/10245169
感谢robin19890305的分享。
參考文献:
- DVR_RDK_McFW_Link_API_Training.pdf
- DM81xx_DVR_RDK_Overview.pdf
- TI NVR RDK Source Code