最近要把那个usb摄像头简单做成一个网络摄像头
板子里的服务端暂时用的c,客户端用的qt
现在的传输方式是:
两个线程,一个负责采集图像数据,然后转换格式压缩成jpeg文件,一个320*240的图片平均4k,如果图像鲜明会多一点。另一个线程负责建立
socket然后传输图像数据,图像数据首先传输这帧图像的大小,blocksize,然后传输图像数据,在这个连接上不停地循环发送
客户端就进行接受显示就行了,没什么问题
采集图像的处理大致如下:
convmap = malloc ( 320 * 240 * bytes );
v4l_yuv420p2rgb (convmap, map + grab_buf.offsets[frame], 320, 240, bytes * 8);
//map + grab_buf.offsets[frame]为usb摄像头采集的一帧图像地址,convmap为处理后的格式地址
out = fopen ("grab.jpeg", "wb");
if (!out) {
perror ("grab.jpeg");
return 1;
}
put_image_jpeg (out, convmap, 320, 240, 50, 4);//用libjpeg处理后压缩存为grab.jpeg文件
free(convmap);
fclose(out);
在数据发送线程程序如下:
while(1)
{
//判断grab.jpeg是否存在,存在则用rename改名然后传输,防止在传输过程中图片数据被采集线程修改
while( stat("grab.jpeg", &buf) < 0)
{
// perror("stat");
usleep(40000);
}
if( (fd = rename("grab.jpeg","temp.jpeg")) < 0)
perror( "rename" );
if( (fd = stat("temp.jpeg",&buf)) < 0 )
perror("stat temp.jpeg");
printf("buf.size=%d\n",buf.st_size);
//发送此帧图片的blocksize,new_fd为socket文件描述符
if( (fd = send( new_fd, &buf.st_size, sizeof(off_t), 0 )) < 0 )
perror("send blocksize");
//发送图片数据
if( (fd = open( "temp.jpeg", O_RDONLY )) < 0 )
perror("open img");
while( ( nread = read( fd, buff, MAXDATASIZE ) ) > 0 )
{
if( send( new_fd, buff, nread, 0 ) == -1 )
perror( "send\n" );
}
close( fd );
}//不关闭socket继续发送数据
这段程序在我的pc机上测试没有问题,昨天测试了一夜数据传输都没有错,只不过在有时候blocksize为0,我估计原因是在采集线程
fopen之后还没来得及写数据就被我rename了,还没时间测试,今天早上出来的路上想起的这个原因,晚上回去看看,将while(
stat("grab.jpeg", &buf) < 0)改为while( (stat("grab.jpeg",
&buf) < 0) && (buf.st_size == 0) )
但在我的板子上采集问题就大了,传输的blocksize总为0或者4096,也就是当temp.jpeg的大小不为4096的时候stat得
到的值为0,如果大小为4096又正确。我在板子上采集的同时写了个小程序每隔一秒钟stat
temp.jpeg然后输出大小的值又正确不总是4096是正常值,所以就迷惑了
我不知道4096是个什么特殊的值,并且有个问题就是用libjpeg库压缩的时候如果得到的size为4096时是一帧不完整的图像,其他都是好的,也还没有时间去分析
用rename是为了文件互斥,用信号量应该好一些不过我暂时不会,所以昨天找到rename这个函数作为权宜之计,有时间再来研究信号量什么的
还有几个问题想问一下
1.在一般的网络条件下,我先发送的数据应该会先到基本不会数据错误吧。因为我没有加任何校验位什么的,这个如果有必要再来研究。我们校园网网络条件好,昨天测试了一夜没有出问题
2.有没有什么提高效率的方式?我在这个版本之前写的是一个socket传送一帧图像然后在client显示,在板子上采集时可以看到图像就是比
较慢,大约只有3fps,现在一个socket上一直不停地传送就是为了试验效率的,结果遇到了这个问题。现在我感觉是在图像压缩和转换上花费的时间多,
准备找时间去买一个支持RGB格式的摄像头,然后可以省掉v4l_yuv420p2rgb这步,不过需要移植驱动了,所以一直没有去做。由于编程经验很有
限,也刚涉及编程领域,所以请大家多多指教
多谢
-------------------- 最光荣的牺牲,是英雄的宿命。
文章选项:
|