2013年3月22日星期五

C++实现视频监控——用C++实现的远程监控系统概述

(一)体系结构1.传输模块
现场摄像机---->视频切换矩阵/编码器---->现场监控主机(将视频流和控制指令传给传输模块)
注意:现场监控主机内含视频采集卡和视频服务软件
2.接受模块
将视频流和控制指令传给监控中心主机,然后在显示器上显示
3.流程图



(二)视频发送和接收1.具体过程
(1) 客户端先启动,并一直处于监听状态
(2)服务器端向客户端发出数据请求
(3)客户端接收到请求之后,将它的IP组播地址和端口号传给服务器
(4)服务器发挥确认信息
(5)客户端收到确认信息后向该组播组发送视频
2.流程图



(三)视频采集卡1.功能
(1)采集视频流到文件或应用程序的缓冲区
(2)通过DirectX等可支持视频流的实时播放
2.二次开发基础
(1)设备的初始化和关闭
a 设备的初始化首先调用OpenDriver()打开视频的驱动
b 调用HVFAssign()检验是否有设备可用,如有,则将设备与驱动程序关联起来
c 如果不允许多个应用程序同时使用该设备,可以调用HVFLock()锁定设备
d 当不再使用设备时,调用HVFUnlock()释放设备,以使其他应用程序可以使用
e 调用CloseDriver()关闭设备的驱动
(2)使用设备
a 通过调用HVFOpen()建立访问视频流数据
b 调用HVFSet()配置流数据以便能适合音频编码(还可以调用HVFGet()来随时得到已建立数据流的各种信息)
c 访问数据流的方法:HVFRecord()采集数据、HVFPause()暂停采集数据、HVFResume()继续采集、HVFStop()停止采集
d 调用HVFClose()关闭对数据流的访问
(3)二次开发流程图


(4)程序实现
视频采集模块(playView.cpp)
(1)InitDriver()函数
实现数据采集的一些初始化工作,包括设备驱动的打开,与设备的关联,锁定设定设备
(2)ClearDriver()函数
实现结束数据采集时所做的一些工作,包括停止采集数据、关闭数据流、释放设备和关闭设备驱动等
(3)MyCallBack()函数
其为一个回调函数,实现对视频采集卡传递过来的数据流的处理。它先将数据压入一个视频流缓冲区队列中;如果系统现在在采集数据,则将数据同时写入到采集文件中去,如果采集文件满,发送停止采集信息。
(4)InitEncodeVideoVxD()函数
其对视频流的相关编码信息进行配置,包括视频的输入/输出大小、比特率、帧速、I帧间隔、P帧间隔、制式、输入源的类型、压缩编码算法、亮度、对比度、色调和饱和度等
(5)InitEncodeAudioVxD()函数
其对视频流中的音频信息进行配置,包括音频的采集率、比特率、压缩编码算法、方式、音量、电平等
(6)OnCaptureSave() 函数
其响应采集文件设置命令
(7)OnBedinCapture()函数
其响应开始采集命令,它调用InitDriver()函数实现数据采集
(8)OnStopCapture()函数
停止采集,调用ClearDriver()
(9)OnPauseCapture()函数
暂停采集
(10)OnResumeCapture()函数
继续采集



(四)实时图像和视频文件的播放(通过DirectShow()组件实现)
1.DirectShow系统框图


(1)过滤器(filter)

a.源过滤器
b.变换过滤器
c.提交过滤器
d.分割过滤器
e.混合过滤器

(2)引脚(pin)
    过滤器可以和一个或多个过滤器相连,连接的接口是COM形式的,成为引脚。
过滤器和引脚连接示意图:


(3)媒体类型(Media Type)
两个过滤器相连时,必须使用一致的媒体类型。

(4)过滤器图表管理器(Filter Graph Manager)
管理过滤器图表中的过滤器,其为COM形式,功能有:协调过滤器间的状态转换、建立参考时钟、把事件传送给应用程序

(5)捕捉图表生成器(Capture Graph Builder)
(6)过滤器图表中的数据流动
(7)系统设备枚举器(System Device Enumerator)
2.程序实现
1.利用COM接口设计一个类CVideoPlay
2.函数
FindDevice():搜索视频设备
RealPlay():实时图像的播放
PlayFromFile():视频文件的播放
PuasePlay():暂停播放
ResumPlay():继续播放
StopPlay():停止播放
DisplayVideoWin():显示视频播放窗口


(五)视频数据发送和接收播放1.设计
建立两个通信通道:控制通道(TCP实现)数据通道(UDP实现)


(1)视频数据发送模块设计a、视频文件发送基本过程:
(1)选择打开一个视频文件
(2)建立Winsok2 Multicast Socket
(3)启动文件发送线程,每次读文件的32KB时由Socket发送出去



b、实时视频发送过程:
(1)从视频采集卡中获得视频数据
(2)设计一个视频缓冲区CAV8Buffer类,其作用是设置一个缓冲区队列,对采集的的数据进行压入和弹出工作
(3)缓冲区满则启动数据发送线程,将缓冲区的视频数据弹出,以IP组播的方式发送出去,同时将缓冲队列清空,以接收新的数据


具体的实时视频发送过程:1.建立Winsock2 Multicast Socket
2.初始化视频采集压缩卡,启动压缩采集
3.建立输出到缓冲区的流,由回调函数将采集的数据送至缓冲区,缓冲区的大小设为32KB。

c、视频数据发送模块流程图






2)视频数据接收播放模块的设计(UI线程技术)每个线程创建一个用户界面窗口,并负责一路视频流的接收和播放
a、 视频流的接收播放具体过程
(1)输入连接发送端的IP地址,向发送端发送数据请求
(2)当得到发送端的确认消息后,启动接收播放数据线程,创建用户界面窗口
(3)建立Winsock2 Multicast Socket,根据发送端传回的组播地址及端口号加入次IP组播组
(4)建立DirectShow Filter Graph,并启动运行
(5)在DirectShow请求数据时,从Socket中读取数据(每个IP数据包为32K)送至DirectShow的Buffer,此后视频流的解码和播放都有DirectShow实现

b、视频数据接收播放模块的流程图


(3)程序实现

(1)视频数据发送模块的程序实现1.控制通道的实现
    控制通道用来在发送端和接收端建立会话,包括发送一些数据请求和确认控制等信息。其选择可靠的TCP协议实现
a、InitSocket()函数(play.cpp)
其首先创建一个监听socket,绑定发送端的主机地址和端口,然后监听接收端的连接请求,当有连接请求到来时,发送WSA_ACCEPT消息给主窗口
b、OnAccept()函数(MainFrm.cpp)
响应WSA_ACCEPT消息,接收连接请求,与接收端进行连接。当有FD_READ或FD_CLOSE网络事件发生时,发送WSA_READ消息给主窗口

c、OnRead()函数( MainFrm.cpp)
响应WSA_READ消息,对FD_READ或FD_CLOSE网络事件进行处理。FD_READ表示发送端读取接收端传过来的数据,如果接收端传过来的 是请求发送数据命令,则发送组播地址和端口给它;FD_CLOSE表示接收端已经接收到组播地址信息,发送端可以关闭监听socket


2.数据通道的实现a、InitMultiSocket()函数(play.cpp)
其初始化一个IP组播套接字
b、SendDate()函数(playView.cpp)
其通过调用WSASendTo()函数发送组播技术


3.视频文件的发送(playView.cpp)a、OnPopFileSend()函数
其响应文件发送命令,创建视频文件发送线程,实现视频文件的发送
b、FileSendThread()函数
视频文件发送线程


4.实时视频的发送(playView.cpp)a、RealSendThread()函数
发送线程呢个
b、OnReadyRealSend()函数
其响应WM_READYSEND消息。视频缓冲区满时发送WM_READYSEND消息。OnReadyRealSend函数将视频流缓冲区的数据弹出,等待实时发送事件就绪,一就绪就开始实时发送线程。
c、OnPopRealSend()函数
弹出缓冲区的视频流数据



(2)视频接收播放模块的程序实现1.多路窗口的实现视频数据接收模块可以通过选择通道接收一路或多路画面,这是一个MDI应用,每一路窗口是一个UI线程,负责一路视频流的接收和实时播放。

2.控制通道的实现a、CRevPlayWnd::Connect()函数
当用户在连接对话框中输入发送端IP地址选择确定后调用该函数。它首先创建一个socket,然后尝试与发送端建立连接,发送WSA_CONNET消息给窗口
b、CRevPlayWnd:OnConnect()函数
其响应WSA_CONNET消息


3.数据通道的实现a、CRevPlayWnd:InitMultiSock()函数
其建立一个组播套接字,根据有控制通道得到的发送端组播IP地址和端口,加入该组播组
b、CRevPlayWnd:ReceiveData()函数
接收组播数据,存放到缓冲区stWSABuf中

4.视频流解码播放的实现a、类CMemStream和CMemReader
b、CRevPlayWnd:InitGraph()函数
其首先创建Source Filter,再创建一个Filter Graph组件,并将Source Filter加入到Filter Graph中,然后获得一系列控制端口
c、CRevPlayWnd:OnRevPlay()函数
接收并播放
d、CRevPlayWnd:OnRead()函数、
相应WSA_READ消息,调用ReceiveData()接收组播数据,并将它存放到接收缓冲区中,供DirectShow实现


附图:

没有评论:

发表评论