这里简单谈一下我要做的这个任务吧。做一套视频监控软件,分为采集端和用户端。目前的工作呢,是把任务分成了几个部分,分开来完成,为此用MFC实现了一个模拟QQ聊天的工具。采集端和用户端也都已经完成,但是这几个小部分合在一块也是个难题啊。看看半个月能否搞定吧。
视频采集端:
1.与用户端进行文字交互,确认当前是否需要打开视频;
2.根据用户的需要,打开摄像头,并将视频通过网络发送至用户端。
用户端:
1.与采集端进行文字交互,告诉采集端是否需要打开摄像头;
2.如果对方发送视频数据,则接收视频,并在窗口显示。
分两步进行:
1.双方通过文字交流协商是否需要打开摄像头。
2.如果需要,则采集端采集视频发送给用户。
搭建平台:Windows 10 ,Visual Studio 2010,
所用框架:是基于Microsoft MFC框架的编程,以及用到了Socket连接,UDP协议。
流程图:
采集端:采集端有两个主要功能模块,播放功能和发送功能。播放功能是将本地连接的摄像头摄影到的画面播放出
来。发送功能是将摄影到的画面通过压缩为视频流经udp推送给接收端。
播放功能实现依赖于ffplay(ffplay是由ffmpeg+sdl实现的exe文件),播放之前需要获取本地摄像头,获取摄像头函
数由windows的api函数实现。发送功能实现依赖于ffmepeg(开源的可以用来记录、转换数字音频、视频,并能将
其转化为流的计算机程序),程序中调用ffmpeg命令行来推送视频流。
接收端:接收端完成三个功能模块,通过已知物理地址扫描寻找目的ip;发送播放/停止信号,发送端响应推送/关
闭视频流;多路视频独立播放。
扫描ip:因为学校网络动态分配ip,而udp传输需要知道对方ip地址,局域网内可以通过137端口(137 端口的主要
作用是在局域网中提供计算机的名字或IP地址查询服务,一般安装了NetBIOS协议后,该端口会自动处于开放状
态)遍历已连接的计算机信息,解析返回的数据与已知mac匹配,寻找到目的主机的ip。
发送播放/停止:扫描成功后,需要向发送端发送信号,提醒其推送视频流。主要涉及udp传输协议,发送内容为
本地空闲端口,提醒发送端将视频流推送至此端口。这一步骤为多路播放的关键。
模块1:模拟聊天过程(文字交互过程)
注意在Dlg.h文件中添加头文件
#pragma once
#include "winsock2.h"
#include "afxcmn.h"
#include "afxwin.h"
#pragma comment(lib,"ws2_32.lib")
#define WM_SOCKET WM_USER + 30
// CChatFirstDlg 对话框
extern CChatFirstApp theApp;
采集端发送文字主要的代码:
void CChatFirstDlg::OnBnClickedBtnconn()
{
// TODO: 在此添加控件通知处理程序代码
closesocket(theApp.m_LocalSocket);
theApp.m_LocalSocket = socket(AF_INET, SOCK_STREAM, 0);
int nRet = WSAAsyncSelect(theApp.m_LocalSocket, m_hWnd, WM_SOCKET, FD_ACCEPT|FD_CLOSE|FD_READ|FD_WRITE|FD_CONNECT);
UpdateData();
sockaddr_in sockAddr;
sockAddr.sin_family = AF_INET;
u_short m_port = atoi(m_nServerPort);
sockAddr.sin_port = htons(m_port);
sockAddr.sin_addr.S_un.S_addr = inet_addr(m_szServerIP.GetBuffer(0));
connect(theApp.m_LocalSocket, (sockaddr*)&sockAddr, sizeof(sockAddr));
theApp.m_bConnectState = FALSE;
SetTimer(1, 800, NULL);
UpdateData(FALSE);
}
LRESULT CChatFirstDlg::OnSocket(WPARAM wParam, LPARAM lParam)
{
int nError = WSAGETSELECTERROR(lParam);
int nEvent = WSAGETSELECTEVENT(lParam);
char buffer[1024] = {0};
SOCKET sock = wParam;
int nFactLen = recv(sock, buffer, 1024, 0);
switch(nEvent)
{
case FD_READ:
{
m_ChatRecord.SetSel(-1, -1);
m_ChatRecord.ReplaceSel(buffer);
m_ChatRecord.SetSel(-1, -1