网络摄像机设计模块
1 软件模块设计
FVID模块为基于DSP/BIOS的应用程序提供API函数,该模块以芯片支持库(CSL)和设备驱动为基础,实现帧图像的获取和显示。模块集中完成了CSL中EDMA、VP、IRQ和IIC四个模块的配置和控制,实现了VP口与L2之间固定周期的EDMA传输/中断以及VP口中断这些固定操作,极大地简化了编程工作,而FVID的API主要任务是管理设备驱动和程序之间缓冲区的所有权。大多数DSP/BIOS设备驱动的数据缓冲区的最初所有权都由应用程序掌握,数据的输入/输出通过传递缓冲区的地址到设备驱动实现;而FVID模块的设备驱动掌握数据缓冲区的最初所有权,应用程序按需求来分配缓冲区,这是因为视频采集/显示系统通常需要较大且复杂的缓冲区,而且对数据读取速度的要求远高于对缓冲区分配灵活性的要求所致。模块首先用FVID_create创建并初始化一个FVID通道,之后通过FVID_control发送控制命令到设备驱动以配置相应的视频解码器(TVP5150)并启动视频帧图像的采集,设备驱动工作后,利用FVID_alloc为应用程序分配视频帧缓冲区,当应用程序处理完成后,再用FVID_exchange完成应用程序与设备驱动间缓冲区的交换以为后续处理作准备。
Cache模块用于配置和管理数据及程序Cache,由于CPU对Cache进行直接访问,因此L2中Cache的设置及使用直接影响系统性能,其中Cache_setL2Mode用于设置二级Cache大小;而Cache_enableCaching则设置二级Cache可映射的外部存储器的地址空间。
DAT模块是CSL的一个抽象模块,其实现的功能是通过DMA/EDMA进行数据传递。对于有EDMA的DSP,模块则用QDMA进行传输,DM642使用的就是QDMA。使用该模块需要首先用DAT_open打开模块,之后用DAT_copy完成线性数据块的拷贝传送。
SCOM模块是RF5中不同任务间传递消息的通信模块。SCOM消息在任务间的传递通过SCOM队列实现,SCOM队列由SCOM_create创建,任务用SCOM_putMsg把消息放到SCOM队列中完成消息的发送,而接收消息的任务则用SCOM_getMsg将消息从队列中取出,由此实现任务间的通信。
2 网络功能的软件实现
NDK的结构框架:系统使用NDK(network developer Kit)开发网络功能,NDK是TI公司配合其推出的TMS320C6000系列DSP的TCP/IP协议栈而开发的新型网络开发工具包,其目的是提供一个完整的TCP/IP功能环境。NDK采用紧凑的设计方法,实现了用较少的资源耗费支持TCP/IP,仅用200-250KB的程序空间和95KB的数据空间即可支持常规的TCP/IP服务,是DSP网络开发的上等之选。
NDK中TCP/IP协议栈的五个网络功能模块对应的函数库分别为OS.LIB、HAL.LIB、STACK.LIB、NETTOOL.LIB和NETCTRL.LIB。NDK通过编程接口与本地操作系统(DSP/BIOS)和底层硬件相互隔离,其中DSP/BIOS被抽象为一个操作系统适应层,底层硬件抽象为一个硬件抽象层,它们是NDK与本地操作系统和底层硬件的接口;TCP/IP协议栈库是主要的TCP/IP网络功能库,该库针对DSP/BIOS,实现了从上层套接口层至底层链路层的所有功能;网络工具库包含了NDK提供的所有基于套接字的网络功能及一些开发网络程序的其它工具;网络控制及调度模块是协议栈的配置、初始化和事件调度的核心,它控制着TCP/IP与外界的联系及互动,它负责初始化协议栈和底层设备驱、加载并保存系统的配置与底层设备驱动接口并安排底层事件传递进入协议栈以及退出时将系统配置导出并清理底层驱动。
TCP/IP协议栈的配置和初始化:协议栈的正确配置及初始化是应用程序网路功能正确执行的前提。通常用DSP/BIOS配置工具静态或者用DSP/BIOS的API函数动态创建一个“网络主线程”,它作为网络的入口,首先在其中进行协议栈的配置和初始化,之后它最终成为协议栈的事件调度线程,只有在应用程序结束时该线程才返回。该线程并不是真正意义上的网络任务线程,而应用程序的任务,无论是否网络相关,都要开辟新的线程,而不会在该线程中执行。协议栈的典型配置和初始化流程为:
NC_SystemOpen->CfgNew()->CfgLoad()/CfgAddEntry()->NC_NetStart();
其中NC_SystemOpen()用来初始化协议栈及其使用的存储器环境;CfgNew()产生新创建配置的句柄,该句柄是配置信息的入口;之后用CfgLoad()将已有的配置从非易失性存储器中加载至配置入口或用CfgAddEntry()向配置入口逐条添加配置信息。典型的配置参数包括:网络主机名、IP地址、子网掩码、默认路由器IP地址、需要的服务(HTTP、DHCP、DNS)等。
当需要的配置被装载后,通过NC_NetStart()启动网络事件调度,该函数会自动调用"开始"、“结束”和“IP地址事件”三个函数,“开始”函数只在系统初始化后准备执行网络程序时调用一次;“结束”函数在系统要结束时调用一次;而“IP地址事件”函数可被多次调用,例如本地的IP地址从系统中添加或删除时,都会被调用。
除非系统关系,否则NC_Start()不会返回,该函数的返回值是一个关闭代码,系统的关闭方式会决定协议栈是否需要重新启动。例如,以下代码可以实现配置改变后的自动启动:
Do
{
rc = NC_NetStart(hcfg,NetworkOpen, NetworkClose, NetWorkIpAddr);
} while(rc>0);
该例子中,如果NC_NetStart()的返回值大于0,就重新启动协议栈。
若是协议栈关闭,还需要用CfgFree()和NC_SystemClose()来删除配置和关闭系统。
3 网络通信模块设计
“网络主线程”用于完成协议栈的配置、初始化及网络事件调度,而真正的网络任务线程则通过NDK的API函数TaskCreate()创建,这里称为“服务器任务”线程,该线程用“客户端/服务器”网络通信模式实现,将DM642设计为视频服务器端,利用套接字(Socket)编程实现,服务器负责响应客户端请求并发送编码流。
由于数字视频的数据量大,传输层协议若采用可靠的、面向连接的TCP协议必然会消耗过多的网络资源,且不能保证实时性;采用不可靠的、无连接的UDP协议传输数字视频信号则符合实际应用的实时性要求,因此系统采用UDP协议,相应的套接字使用数据报套接字。
对于“服务器任务”:首先用socket建立一个套接字以进行数据传输,再用bind将本地IP地址和通信使用的端口号与该套接字绑定,之后通过recvfrom阻塞等待客户端的服务请求,当收到客户端的请求后,再将编码后的数据流利用sendto发送给客户端。客户端也要先建立套接字并将本地IP及通信的端口号与其绑定,之后使用sendto向服务器发送服务器请求,服务器应答后,再通过recvfrom接收服务器发来的数据流。
4 程序流程
系统采用DM642实现网络视频编码器,软件框架采用RF5,利用DSP/BIOS创建输入任务、JPEG编码任务和网络任务。在进入DSP/BIOS的调度程序之前,需要执行三种类别的初始化:1,处理器和系统板的初始化,包括初始化BIOS环境、CSL以及Cache和EDMA的设置;2,RF5模块的初始化,包括通道模块、SCOM模块等。3,FVID通道的建立和启动;4,JPEG编码XDAIS算法实例对象的建立。初始化完成后即进入DSP/BIOS调度程序管理下的任务,任务之间通过SCOM模块传递消息。输入任务负责从输入设备获得视频图像,利用FVID_exchange从输入设备获得一帧最新的4:2:2格式的YUV图像,并将其采样为YUV4:2:0格式,将包含图像数据指针的消息发送给编码任务。编码任务将接收到的4:2:0格式的YUV图像利用XDAIS算法进行JPEG编码,之后将包含编码流大小和指针的消息发送给网络任务。网络任务包括“网络主线程”和在其中创建的“服务器任务”,前者作为后者的基础和准备,真正的数据发送则后者完成。系统软件流程如下所示:
摄像头->输入任务<-->SCOM<-->编码任务<-->SCOM<-->网络任务