Chinaunix首页 | 论坛 | 博客
  • 博客访问: 1308042
  • 博文数量: 860
  • 博客积分: 425
  • 博客等级: 下士
  • 技术积分: 1464
  • 用 户 组: 普通用户
  • 注册时间: 2011-08-20 19:57
个人简介

对技术执着

文章分类

全部博文(860)

文章存档

2019年(16)

2018年(12)

2015年(732)

2013年(85)

2012年(15)

我的朋友

分类: LINUX

2015-03-14 17:07:12


(stranger)
06-10-13 12:00
用网络查看usb摄像头的图像  

最近要把那个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这步,不过需要移植驱动了,所以一直没有去做。由于编程经验很有 限,也刚涉及编程领域,所以请大家多多指教
多谢


--------------------
最光荣的牺牲,是英雄的宿命。

文章选项: 打印


(journeyman)
07-03-05 15:05
Re: 用网络查看usb摄像头的图像 新 [] 

哥们
我在研究这个
能不能把你的源代码共享一下
如果能的话
发我邮箱把



--------------------
主要做嵌入式linux,结交同行好友,共同进步

文章选项: 打印


(member)
07-03-07 11:02
Re: 用网络查看usb摄像头的图像 新 [] 

看你的本意,应该是想用
while((stat("grab.jpeg", &buf) < 0) || (buf.st_size == 0) )
usleep(xxx);
while里的逻辑搞错了,应该是“或”而不是“与”。

另外即使你改过来,这样做也是很不严格的。还有牵涉到效率问题,
建议你直接用内存缓冲而不要用文件。用循环缓冲或者双缓冲,共享变量来同步即可。



--------------------
一切有为法,如梦幻泡影,如露亦如电,应作如是观

文章选项: 打印

  打印
阅读(693) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~