做项目需要用到网络编程及摄像头捕捉,经过简单学习完成一个简单的视频发送。
发送端:
sender.cpp
#include "stdafx.h"
#include "WinSock2.h"
#include <opencv2\opencv.hpp>
#pragma comment(lib,"ws2_32.lib")
using namespace std;
using namespace cv;
int main()
{
char ip[20];
printf("输入目标IP\n");
scanf("%s", &ip);
printf("目标IP%s\n", ip);
WSADATA wsaData;
int port = 5099;
if (WSAStartup(MAKEWORD(2, 2), &wsaData) != 0)
{
cout << "加载套接字失败" << endl;
return 1;
}
SOCKADDR_IN addrRec;
addrRec.sin_family = AF_INET;
addrRec.sin_port = htons(port);
addrRec.sin_addr.s_addr = inet_addr(ip);
SOCKET sockClient = socket(AF_INET, SOCK_DGRAM, 0);
if (sockClient == SOCKET_ERROR)
{
cout << "创建套接字失败" << endl;
return 1;
}
int nLen = sizeof(SOCKADDR_IN);
VideoCapture capture(0);
Mat capframe, frame;
capture >> capframe;
int framesize = sizeof(frame);
_int64 datasize = capframe.dataend - capframe.datastart;
_int64 shrinksize = datasize / 16;
while (capture.isOpened())
{
capture >> capframe;
imshow("video", capframe);
int sendData;
resize(capframe, frame, Size(), 0.25, 0.25);
sendData = sendto(sockClient, (char*)frame.data, shrinksize, 0, (LPSOCKADDR)&addrRec, nLen);
if (sendData>0)
{
printf("size:%d,send:%d\n", shrinksize, sendData);
}
else
{
printf("发送data错误!%d %d\n", sendData, WSAGetLastError());
}
if (waitKey(20) == 27)//27是键盘摁下esc时,计算机接收到的ascii码值
{
capture.release();
break;
}
}
waitKey();
WSACleanup();
return 0;
}
接收端:
receiver.cpp
#include "stdafx.h"
#include "thread"
#include "WinSock2.h"
#include<opencv2\opencv.hpp>
#pragma comment(lib,"ws2_32.lib")
using namespace cv;
int main()
{
char ip[20];
printf("输入本机ipIP\n");
scanf("%s", ip);
printf("本机IP:%s\n", ip);
WSADATA wsaData;
int port = 5099;
if (WSAStartup(MAKEWORD(2, 2), &wsaData) != 0)
{
printf("加载套接字失败\n");
return 1;
}
SOCKADDR_IN addrRec;
addrRec.sin_family = AF_INET;
addrRec.sin_port = htons(port);
addrRec.sin_addr.s_addr = inet_addr(ip);
SOCKET sockClient = socket(AF_INET, SOCK_DGRAM, 0);
if (sockClient == SOCKET_ERROR)
{
printf("套接字创建失败\n");
return 1;
}
if (bind(sockClient, (LPSOCKADDR)&addrRec, sizeof(SOCKADDR_IN)) == SOCKET_ERROR)
{
printf("套接字绑定失败:%d\n", WSAGetLastError);
return 1;
}
SOCKADDR_IN addrSend;
int nLen = sizeof(SOCKADDR);
Mat frame, rsframe;
VideoCapture capture(0);
capture >> frame;
capture.release();
resize(frame, frame, Size(), 0.25, 0.25);
_int64 datasize = frame.dataend - frame.datastart;
while (1)
{
if (SOCKET_ERROR != recvfrom(sockClient, (char*)frame.data, datasize, 0, (LPSOCKADDR)&addrRec, &nLen))
{
printf("收到Data!\n");
imshow("reciver", frame);
}
if (waitKey(20) == 27)//27是键盘摁下esc时,计算机接收到的ascii码值
{
break;
}
}
WSACleanup();
return 0;
}
使用的都是最基础的功能。
视频帧没有经过压缩,而UDP一个包的大小最大为65536B,所以采集到的图像需要长宽缩小4倍才能发送,接收端接收到的也是缩小后的图像,可以在接受端中再加入一个resize放大,或者在两端加入视频数据压缩与解压,这也是之后的学习方向。
对于Mat的应用还不熟练,且实现环境是两台笔记本电脑之间,因此是在接收端中执行一次capture>>frame来初始化接收端的Mat,这将导致在非笔记本的电脑上接收端初始化Mat失败,今后将尝试利用函数实现可变环境下的Mat初始化。