您的位置:首页 > 其它

利用V4L2编写的USB摄像头程序2【经OK6410验证成功】

2015-01-22 02:06 615 查看
#include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #define CLEAR(x) memset (&(x), 0, sizeof (x))struct buffer { //缓冲帧结构体 void * start; size_t length;};static char *
dev_name = "/dev/video2";//摄像头设备名static int fd = -1;struct buffer * buffers = NULL;static unsigned int n_buffers = 0;FILE *file_fd;//static unsigned long file_length;static unsigned char *file_name;////////////////////////////////////////////////////////获取帧数据//////////////////////////////////////////////////////static
int read_frame (void){struct v4l2_buffer buf;CLEAR (buf);buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;buf.memory = V4L2_MEMORY_MMAP;ioctl (fd, VIDIOC_DQBUF, &buf); //出列采集的帧缓冲assert (buf.index < n_buffers); printf ("buf.index number is %d.\n",buf.index);fwrite(buffers[buf.index].start,
buffers[buf.index].length, 1, file_fd); //将其写入文件中 ioctl (fd, VIDIOC_QBUF, &buf); //再将其入列return 1;}int main (int argc,char ** argv){enum v4l2_buf_type type;unsigned int i;file_fd = fopen("qin.jpg", "w");//图片文件名fd = open ("/dev/video2", O_RDWR | O_NONBLOCK,
0);//打开设备/* VIDIOC_QUERYCAP */struct v4l2_capability cap; //获取摄像头参数CLEAR(cap);ioctl (fd, VIDIOC_QUERYCAP, &cap); printf("driver:%s\n",cap.driver);printf("card:%s\n",cap.card);printf("bus_info:%s\n",cap.bus_info);printf("version:%d:%d:%d\n",(cap.version>>16)&0xff,(cap.version>>8)&0xff,(cap.version)&0xff);/*
VIDIOC_ENUM_FMT */struct v4l2_fmtdesc fmtdesc; //查看所支持的格式CLEAR(cap);fmtdesc.index=0; //格式序号,可能有多个序号,第一个序号为0;fmtdesc.type=V4L2_BUF_TYPE_VIDEO_CAPTURE; while(-1!=(ioctl(fd,VIDIOC_ENUM_FMT,&fmtdesc))) //检测可以支持哪些格式。{printf("fmtdesc.description:%s\n",fmtdesc.description);printf("fmtdesc.pixelformat:%ld\n",fmtdesc.pixelformat);fmtdesc.index++;}/*
VIDIOC_G_FMT, VIDIOC_S_FMT */struct v4l2_format before_fmt,fmt,after_fmt,test_fmt; //分别查看设置前、中、后的格式情况,以及一个验证例子!!!CLEAR(before_fmt);CLEAR(fmt);CLEAR(after_fmt);//====printf("\nThe initial FMT information:\n");before_fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; //FMT设置前的初始状态ioctl(fd,
VIDIOC_G_FMT, &before_fmt);printf("width:%ld\n",before_fmt.fmt.pix.width);printf("height:%ld\n",before_fmt.fmt.pix.height);printf("pixelformat:%ld\n",before_fmt.fmt.pix.pixelformat);printf("bytesperline:%ld\n",before_fmt.fmt.pix.bytesperline);printf("sizeimage:%ld\n",before_fmt.fmt.pix.sizeimage);//====//printf("\nSetting
FMT information....\n");fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; //设置FMT的格式fmt.fmt.pix.width = 640;fmt.fmt.pix.height = 480;fmt.fmt.pix.pixelformat = V4L2_PIX_FMT_YUYV; //此处随便设,系统会自动修改!!fmt.fmt.pix.field = V4L2_FIELD_INTERLACED;ioctl(fd, VIDIOC_S_FMT, &fmt);//====printf("\nAfter
set FMT information:\n");after_fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; //显示设置后的FMT格式ioctl(fd, VIDIOC_G_FMT, &after_fmt);printf("width:%ld\n",before_fmt.fmt.pix.width); printf("height:%ld\n",before_fmt.fmt.pix.height);printf("pixelformat:%ld\n",before_fmt.fmt.pix.pixelformat);
printf("bytesperline:%ld\n",before_fmt.fmt.pix.bytesperline);printf("sizeimage:%ld\n",before_fmt.fmt.pix.sizeimage);//====if(fmtdesc.pixelformat & fmt.fmt.pix.pixelformat) // 如果格式V4L2_PIX_FMT_YUYV与摄像头本身不一样,系统会自动修改!!!{ printf("\nThis USB camera format:%s\n",fmtdesc.description);
//显示当前帧格式信息!例如:MJPEG}//====printf("\nThis is an example: whether the USB camera support the :V4L2_PIX_FMT_RGB32?\n");test_fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;test_fmt.fmt.pix.pixelformat = V4L2_PIX_FMT_RGB32;if(-1==ioctl(fd, VIDIOC_TRY_FMT, &test_fmt))
//检测是否支持RGB32格式! if(errno==EINVAL) printf("Can not support format RGB32!\n"); /* VIDIOC_REQBUFS */printf("\n To apply the buffer from the memory!\n");struct v4l2_requestbuffers req;CLEAR(req);req.count = 4;req.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;req.memory
= V4L2_MEMORY_MMAP;ioctl(fd, VIDIOC_REQBUFS, &req);//====if (req.count < 2) printf("Insufficient buffer memory!!\n");buffers = calloc (req.count, sizeof (*buffers));//内存中建立对应空间//====for(n_buffers=0;n_buffers<req.count;n_buffers++){struct v4l2_buffer buf;CLEAR
(buf); buf.index = n_buffers; buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; buf.memory = V4L2_MEMORY_MMAP; //区分是MMAP 还是USERPTR if(-1==ioctl(fd, VIDIOC_QUERYBUF, &buf)) //把VIDIOC_QUERYBUF分配的数据缓存转换为物理地址! printf ("VIDIOC_QUERYBUF error/n"); buffers[n_buffers].length
= buf.length; buffers[n_buffers].start = mmap(NULL,buf.length,PROT_READ | PROT_WRITE,MAP_SHARED,fd, buf.m.offset);//通过mmap建立映射关系 if (MAP_FAILED == buffers[n_buffers].start) printf ("mmap failed/n");}for (i = 0; i < n_buffers; ++i) //{struct v4l2_buffer buf;CLEAR
(buf);buf.index = i;buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; buf.memory = V4L2_MEMORY_MMAP; if(-1==ioctl(fd, VIDIOC_QBUF, &buf)) //将申请到的缓冲帧列队! printf ("VIDIOC_QBUF failed/n");}type = V4L2_BUF_TYPE_VIDEO_CAPTURE;if (-1 == ioctl (fd, VIDIOC_STREAMON, &type))
//开始捕捉图像数据 printf ("VIDIOC_STREAMON failed/n");for (;;) //这一段涉及到异步IO{ fd_set fds; struct timeval tv; int r; FD_ZERO (&fds);//将指定的文件描述符集清空 FD_SET (fd, &fds);//在文件描述符集合中增加一个新的文件描述符 /* Timeout. */ tv.tv_sec = 3; tv.tv_usec = 0; r = select (fd + 1, &fds, NULL,
NULL, &tv);//判断是否可读(即摄像头是否准备好),tv是定时 if (-1 == r) { if (EINTR == errno) continue; printf ("select err/n"); } if (0 == r) { fprintf (stderr, "select timeout/n"); exit (EXIT_FAILURE); } if (read_frame ())//如果可读,执行read_frame ()函数,并跳出循环 break;}unmap:for (i = 0;
i < n_buffers; ++i) if (-1 == munmap (buffers[i].start, buffers[i].length)) printf ("munmap error");close (fd);fclose (file_fd);exit (EXIT_SUCCESS);return 0;}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: