尝试在 C 上编写 UDP 流式网络摄像头服务
Trying to write a UDP streaming webcam service on C
伙计们。
我不完全确定应该如何通过 UDP 数据报发送编码图像。一旦建立了 UDP 服务,我就是 运行 这个循环:
服务器端:
FrameCapture = cvCaptureFromCAM(-1);
frameORG = cvQueryFrame(FrameCapture);
small = cvCreateImage(cvSize(frameORG->width / 2, frameORG->height / 2), frameORG->depth, 3);
while((cvWaitKey(40) & 0xFF) != ESC_KEY)
{
frameORG = cvQueryFrame(FrameCapture);
VideoBuffer = cvEncodeImage(bufUDP, &small, 0);
memcpy(bufUDP, VideoBuffer, UDPMAX);
if (sendto(sockUDP, bufUDP, strlen(bufUDP), 0, (struct sockaddr *)&servUDP, length) < 0)
{
if (errno == EPIPE)
{
printf("Connection lost.);
}
else
{
perror("Transmission failed.");
}
exit(1);
}
}
客户端:
bufUDP = (char*) malloc(UDPMAX);
VideoBuffer = (CvMat *) malloc(UDPMAX);
cvNamedWindow("UDP Streaming from Server", CV_WINDOW_AUTOSIZE);
while ((cvWaitKey(40) & 0xFF) != ESC_KEY)
{
if (recvfrom(sockUDP, bufUDP, strlen(bufUDP), 0, (struct sockaddr *)&servUDP, &length) < 0)
{
if (errno == EPIPE)
{
printf("Connection lost.\n");
}
else
{
perror("Problem recieving data.");
}
exit(1);
}
memcpy(VideoBuffer, bufUDP, UDPMAX);
img = cvDecodeImage(VideoBuffer,CV_LOAD_IMAGE_COLOR);
cvShowImage("UDP Video Receiver", &img);
}
程序编译时没有任何警告(使用 -Wall),但服务器端的输出是 OpenCV 函数的异常。
OpenCV Error: Bad argument (Unknown array type) in cvarrToMat, file /../../../../../../../matrix.cpp, line 698
terminate called after throwing an instance of 'cv::Exception'
what(): /../../../../../../../matrix.cpp:698: error: (-5) Unknown array type in function cvarrToMat
我不完全确定我应该如何处理时间,所以我尝试每 40 毫秒 (25fps) 发送一次数据包。
提前致谢
我终于自己找到了答案。希望这对那些在 UDP+OpenCV+CapturefromCAM 上苦苦挣扎的人有所帮助。
cvEncodeImage 和 cvDecodeImage 的全部使用并不是真正必要的。因为结构 IplImage 已经在 image->imageData 中保存了它的数据。
因此以下代码:
服务器端:
cvNamedWindow("Webcam from Server", CV_WINDOW_AUTOSIZE);
FrameCapture = cvCaptureFromCAM(0);
frameORG = cvQueryFrame(FrameCapture);
small = cvCreateImage(cvSize(frameORG->width, frameORG->height), frameORG->depth, 3);
if(!FrameCapture) {
printf("Could not iniciate webcam\n");
return;
}
while((cvWaitKey(40) & 0xFF) != ESC_KEY)
{
small = cvQueryFrame(FrameCapture);
for(times = 0; times < MAX_PAQS; times++)
{
memset(bufUDP, 0, UDPMAX);
memcpy(bufUDP, small->imageData + UDPMAX*times, UDPMAX);
if (sendto(sockUDP, bufUDP, UDPMAX, 0, (struct sockaddr *)&servUDP, length) < 0)
{
// check errno for the problem or conection lost
}
}
}
cvShowImage("Webcam from Server", small); // feedback on server webcam
}
客户端:
cvNamedWindow("UDP Streaming from Server", CV_WINDOW_AUTOSIZE);
img = cvCreateImage(cvSize(640, 480), IPL_DEPTH_8U, 3);
while((cvWaitKey(40) & 0xFF) != ESC_KEY)
{
for(times = 0; times < MAX_PAQS; times++)
{
if (recvfrom(sockUDP, bufUDP, UDPMAX, 0, (struct sockaddr *)&servUDP, &length) < 0)
{
// check errno for the problem or conection lost
}
memcpy(img->imageData + UDPMAX*times, bufUDP, UDPMAX);
}
cvShowImage("UDP Streaming from Server", img);
}
注意这里没有帧同步(我没有复制那部分)。 UDPMAX 必须保持等于 widthheightchannels/MAX_PAQS 的数量。大家可以看到,我用的是640*480-3的通道框
伙计们。
我不完全确定应该如何通过 UDP 数据报发送编码图像。一旦建立了 UDP 服务,我就是 运行 这个循环:
服务器端:
FrameCapture = cvCaptureFromCAM(-1);
frameORG = cvQueryFrame(FrameCapture);
small = cvCreateImage(cvSize(frameORG->width / 2, frameORG->height / 2), frameORG->depth, 3);
while((cvWaitKey(40) & 0xFF) != ESC_KEY)
{
frameORG = cvQueryFrame(FrameCapture);
VideoBuffer = cvEncodeImage(bufUDP, &small, 0);
memcpy(bufUDP, VideoBuffer, UDPMAX);
if (sendto(sockUDP, bufUDP, strlen(bufUDP), 0, (struct sockaddr *)&servUDP, length) < 0)
{
if (errno == EPIPE)
{
printf("Connection lost.);
}
else
{
perror("Transmission failed.");
}
exit(1);
}
}
客户端:
bufUDP = (char*) malloc(UDPMAX);
VideoBuffer = (CvMat *) malloc(UDPMAX);
cvNamedWindow("UDP Streaming from Server", CV_WINDOW_AUTOSIZE);
while ((cvWaitKey(40) & 0xFF) != ESC_KEY)
{
if (recvfrom(sockUDP, bufUDP, strlen(bufUDP), 0, (struct sockaddr *)&servUDP, &length) < 0)
{
if (errno == EPIPE)
{
printf("Connection lost.\n");
}
else
{
perror("Problem recieving data.");
}
exit(1);
}
memcpy(VideoBuffer, bufUDP, UDPMAX);
img = cvDecodeImage(VideoBuffer,CV_LOAD_IMAGE_COLOR);
cvShowImage("UDP Video Receiver", &img);
}
程序编译时没有任何警告(使用 -Wall),但服务器端的输出是 OpenCV 函数的异常。
OpenCV Error: Bad argument (Unknown array type) in cvarrToMat, file /../../../../../../../matrix.cpp, line 698 terminate called after throwing an instance of 'cv::Exception' what(): /../../../../../../../matrix.cpp:698: error: (-5) Unknown array type in function cvarrToMat
我不完全确定我应该如何处理时间,所以我尝试每 40 毫秒 (25fps) 发送一次数据包。
提前致谢
我终于自己找到了答案。希望这对那些在 UDP+OpenCV+CapturefromCAM 上苦苦挣扎的人有所帮助。 cvEncodeImage 和 cvDecodeImage 的全部使用并不是真正必要的。因为结构 IplImage 已经在 image->imageData 中保存了它的数据。 因此以下代码:
服务器端:
cvNamedWindow("Webcam from Server", CV_WINDOW_AUTOSIZE);
FrameCapture = cvCaptureFromCAM(0);
frameORG = cvQueryFrame(FrameCapture);
small = cvCreateImage(cvSize(frameORG->width, frameORG->height), frameORG->depth, 3);
if(!FrameCapture) {
printf("Could not iniciate webcam\n");
return;
}
while((cvWaitKey(40) & 0xFF) != ESC_KEY)
{
small = cvQueryFrame(FrameCapture);
for(times = 0; times < MAX_PAQS; times++)
{
memset(bufUDP, 0, UDPMAX);
memcpy(bufUDP, small->imageData + UDPMAX*times, UDPMAX);
if (sendto(sockUDP, bufUDP, UDPMAX, 0, (struct sockaddr *)&servUDP, length) < 0)
{
// check errno for the problem or conection lost
}
}
}
cvShowImage("Webcam from Server", small); // feedback on server webcam
}
客户端:
cvNamedWindow("UDP Streaming from Server", CV_WINDOW_AUTOSIZE);
img = cvCreateImage(cvSize(640, 480), IPL_DEPTH_8U, 3);
while((cvWaitKey(40) & 0xFF) != ESC_KEY)
{
for(times = 0; times < MAX_PAQS; times++)
{
if (recvfrom(sockUDP, bufUDP, UDPMAX, 0, (struct sockaddr *)&servUDP, &length) < 0)
{
// check errno for the problem or conection lost
}
memcpy(img->imageData + UDPMAX*times, bufUDP, UDPMAX);
}
cvShowImage("UDP Streaming from Server", img);
}
注意这里没有帧同步(我没有复制那部分)。 UDPMAX 必须保持等于 widthheightchannels/MAX_PAQS 的数量。大家可以看到,我用的是640*480-3的通道框