图像采集--V4L2
2014-03-05 16:36
211 查看
这是我很久以前写的一个程序,如今需要使用,由于东西太多,差点就没有找到。为了以后方便使用,所以把它粘出来。
我这个程序,使用的是USB camera,采集到的图像是以YUV形式的存在的,所以在查看的时候需要使用YUV格式查看工具。
我这个程序,使用的是USB camera,采集到的图像是以YUV形式的存在的,所以在查看的时候需要使用YUV格式查看工具。
//图像采集 #include <stdio.h> #include <stdlib.h> #include <string.h> #include <assert.h> #include <getopt.h> #include <fcntl.h> #include <unistd.h> #include <errno.h> #include <malloc.h> #include <sys/stat.h> #include <sys/types.h> #include <sys/time.h> #include <sys/mman.h> #include <sys/ioctl.h> #include <time.h> #include <asm/types.h> #include <linux/videodev2.h> #include <linux/fb.h> #include <time.h> //要访问的camera设备 #define CAMERA_DEVICE "/dev/video0" //图片最大边界 #define MAXWIDTH 2560 #define MAXHEIGHT 1920 //默认图片的大小 #define DEFWIDTH 720 #define DEFHEIGHT 576 //采集图像的大小 #define WIDTH 640 #define HEIGHT 480 //申请缓冲区的个数 #define BUFFER_COUNT 4 //保存图片的数目 #define NUMBER 10 static int fd; static struct v4l2_capability cap; struct v4l2_fmtdesc fmtdesc; struct v4l2_format fmt; struct v4l2_streamparm setfps; struct v4l2_requestbuffers req; struct v4l2_cropcap cropcap; struct v4l2_crop crop; //用户空间 typedef struct buffer { void * start; unsigned int length; }BUFFERS; BUFFERS *buffers; struct v4l2_buffer buf; enum v4l2_buf_type type; //初始化 v4l2 int init_v4l2(void) { int i; int ret = 0; //opendev fd = open(CAMERA_DEVICE, O_RDWR|O_NONBLOCK, 0); if (fd < 0) { printf("Error opening V4L2 interface\n"); return fd; } else { printf("Open camera device %d\n ", fd); } //query cap ret = ioctl(fd, VIDIOC_QUERYCAP, &cap); if(ret < 0) { printf("Error: unable to query device.\n"); return ret; } else { printf("\ndriver:\t\t%s\n",cap.driver); printf("card:\t\t%s\n",cap.card); printf("bus_info:\t%s\n",cap.bus_info); printf("version:\t%d\n",cap.version); printf("capabilities:\t%x\n",cap.capabilities); if ((cap.capabilities & V4L2_CAP_VIDEO_CAPTURE) == V4L2_CAP_VIDEO_CAPTURE) { printf("Camera Device: supports capture.\n"); } else { printf("The camera not support capture.\n"); } if ((cap.capabilities & V4L2_CAP_STREAMING) == V4L2_CAP_STREAMING) { printf("Camera Device: supports streaming.\n"); } else { printf("The camera not support streaming.\n"); } if ((cap.capabilities & V4L2_CAP_READWRITE) == V4L2_CAP_READWRITE) { printf("Camera Device: supports read/writ.\n"); } else { printf("The camera support not read/write.\n"); } } //emu all support fmt fmtdesc.index=0; fmtdesc.type=V4L2_BUF_TYPE_VIDEO_CAPTURE; printf("\nSupport format:\n"); while(ioctl(fd,VIDIOC_ENUM_FMT,&fmtdesc)!=-1) { printf("\t%d.%s\n",fmtdesc.index+1,fmtdesc.description); fmtdesc.index++; } //set fmt memset(&fmt, 0, sizeof(fmt)); fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; fmt.fmt.pix.pixelformat = V4L2_PIX_FMT_YUYV; fmt.fmt.pix.height = HEIGHT; fmt.fmt.pix.width = WIDTH; fmt.fmt.pix.field = V4L2_FIELD_INTERLACED; ret = ioctl(fd, VIDIOC_S_FMT, &fmt); if(ret < 0) { printf("\nUnable to set format\n"); return ret; } //check the fmt is set to sucessed if(ioctl(fd, VIDIOC_G_FMT, &fmt) == -1) { printf("Unable to get format\n"); return ret; } else { printf("\nfmt.type:\t\t%d\n",fmt.type); printf("pix.pixelformat:\t%c%c%c%c\n",fmt.fmt.pix.pixelformat & 0xFF, (fmt.fmt.pix.pixelformat >> 8) & 0xFF, (fmt.fmt.pix.pixelformat >> 16) & 0xFF, (fmt.fmt.pix.pixelformat >> 24) & 0xFF); printf("pix.height:\t\t%d\n",fmt.fmt.pix.height); printf("pix.width:\t\t%d\n",fmt.fmt.pix.width); printf("pix.field:\t\t%d\n",fmt.fmt.pix.field); } //set fps (stream) setfps.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; setfps.parm.capture.timeperframe.numerator = 10; setfps.parm.capture.timeperframe.denominator = 10; ret = ioctl(fd,VIDIOC_S_PARM,&setfps); if(ret < 0) { printf("set streamparm error\n"); exit(EXIT_FAILURE); } //检查驱动的修剪能力 ret = ioctl(fd, VIDIOC_CROPCAP, &cropcap); if(ret < 0) { printf("set VIDIOC_CROPCAP failed. errno = %s\n", strerror(errno)); } else { printf("The camera: max_width = %d\n\t\tmax_height = %d\n", cropcap.bounds.width, cropcap.bounds.height); //设置缩放 memset(&crop, 0, sizeof(crop)); crop.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; crop.c.width = WIDTH; crop.c.height = HEIGHT; ret = ioctl(fd, VIDIOC_S_CROP, &crop); if(ret < 0) { printf("set VIDIOC_S_CROP failed. errno = %s\n", strerror(errno)); exit(EXIT_FAILURE); } printf("VIDIOC_S_CROP sucessful.\n"); } printf("\ninit %s \t[OK]\n\n",CAMERA_DEVICE); return 1; } //mmap int mmap_v4l2() { int ret; unsigned int n_buffers; //request for 4 buffers req.count=BUFFER_COUNT; req.type=V4L2_BUF_TYPE_VIDEO_CAPTURE; req.memory=V4L2_MEMORY_MMAP; ret = ioctl(fd,VIDIOC_REQBUFS,&req); if(ret < 0) { printf("request for buffers error\n"); exit(EXIT_FAILURE); } //mmap for buffers buffers = (BUFFERS*)calloc(req.count, sizeof (BUFFERS)); if (!buffers) { printf ("Out of memory\n"); exit(EXIT_FAILURE); } for (n_buffers = 0; n_buffers < req.count; n_buffers++) { memset(&buf, 0, sizeof(buf)); buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; buf.memory = V4L2_MEMORY_MMAP; buf.index = n_buffers; //query buffers 读取缓存 ret = ioctl (fd, VIDIOC_QUERYBUF, &buf); if(ret < 0) { printf("query buffer error\n"); exit(EXIT_FAILURE); } buffers[n_buffers].length = buf.length; //map buffers[n_buffers].start = mmap(NULL,buf.length, PROT_READ |PROT_WRITE, MAP_SHARED, fd, buf.m.offset); if (buffers[n_buffers].start == MAP_FAILED) { printf("buffer map error\n"); exit(EXIT_FAILURE); } //Queen buffer if(-1 == ioctl(fd, VIDIOC_QBUF, &buf)) { printf("%d queue fail\n", n_buffers + 1); exit(EXIT_FAILURE); } } printf("mmap_v4l2\t\t[OK]\n\n"); return 1; } //Need to file number time_t rawtime[NUMBER]; //把获得的图片 写进文件 int process_file(int m, int n) { int ret; char file_name[128]; time(&rawtime ); sprintf(file_name, "%ld%d", rawtime , n); ret = creat(file_name, 0777); if( ret < 0 ) { printf("create %d file failed\n", n+1); exit(EXIT_FAILURE); } FILE *fp; fp = fopen(file_name, "rb+"); if( !fp ) { printf("open %d error\n", n); exit(EXIT_FAILURE); } //fwrite(frame_buffer, sizeof(frame_buffer), 1,fp); fwrite(buffers[m].start, buffers[m].length, 1,fp); fclose(fp); return 1; } //图像采集 image acquisition int image_acq() { int ret; //开始视频采集 type = V4L2_BUF_TYPE_VIDEO_CAPTURE; ret = ioctl (fd, VIDIOC_STREAMON, &type); if(ret < 0) { printf("Fail to VIDIOC_STERAMON\n"); exit(EXIT_FAILURE); } int nu, times = 0; /*select的最后一个参数,表示该调用在返回前等待多久 struct timeval time; //Timeout time.tv_sec = TimeOut; time.tv_usec = 0; */ while(1) { //select fd_set fds; FD_ZERO(&fds); FD_SET(fd, &fds); nu = select(fd + 1, &fds, NULL, NULL, NULL); if(nu < 0) { if(EINTR == errno) continue; printf("Fail to select, errno = %s\n", strerror(errno)); exit(EXIT_FAILURE); } //把数据拿出来 ret = ioctl(fd, VIDIOC_DQBUF, &buf); if(ret < 0) { printf("Fail to VIDIOC_DQBUF, errno = %s\n", strerror(errno)); exit(EXIT_FAILURE); } // printf("buffer index=%d, times=%d\n", buf.index, times % 4); //Data processing process_file(buf.index, times); //Queen buffer again ret = ioctl(fd, VIDIOC_QBUF, &buf); if(ret < 0) { printf("Fail to VIDIOC_QBUF, errno = %s\n", strerror(errno)); exit(EXIT_FAILURE); } // printf("bytesuesd = %d\n", buf.bytesused);/* 判断采集的图>像以什么方式存储 */ printf(" %d VIDIOC_QBUF again\t [OK]\n", times + 1); times ++ ; if(times >= 10) break; //sleep(1); } printf("image_acq \t\t[OK]\n\n"); return 1; } //停止采集 及 关闭设备 void close_v4l2( void ) { //stop_capturing int ret; type = V4L2_BUF_TYPE_VIDEO_CAPTURE; ret == ioctl(fd,VIDIOC_STREAMOFF,&type); if(ret < 0) { perror("Fail to ioctl 'VIDIOC_STREAMOFF'"); exit(EXIT_FAILURE); } //release mmap unsigned int i; for(i = 0; i < BUFFER_COUNT; i++) { if(-1 == munmap(buffers[i].start, buffers[i].length)) { exit(EXIT_FAILURE); } } free(buffers); //close camera device if(-1 == close(fd)) { printf("Fail to close fd\n"); exit(EXIT_FAILURE); } printf("close_v4l2\t\t[OK]\n"); } int main() { if(1 != init_v4l2()) { return -1; } mmap_v4l2(); image_acq(); close_v4l2(); printf("\n"); return 0; }
相关文章推荐
- V4L2采集图像基本流程
- Linux下基于v4l2框架的图像采集
- linux下usb camera图像采集(V4l2)
- V4L2采集图像入门例子讲解
- 基于V4L2的摄像头图像采集
- linux下usb camera图像采集(V4l2)
- 用V4L2采集图像经常卡死在VIDIOC_DQBUF
- Linux下用V4L2采集摄像头图像和视频
- Linux 之V4L2图像采集程序设计
- V4L2采集图像入门例子讲解
- v4l2图像数据采集 x264笔记
- Linux下基于v4l2框架的图像采集
- v4l2图像采集经典
- [IOS OpenCV]摄像头采集图片用 CreateIplImageFromUIImage 转换后图像被旋转、变形解决方案
- Python+Opencv+Qt4编写Windows下摄像头图像采集显示程序
- UVC、V4L2、读取图像时的设置格式YUV、MPJG的联系和区别
- V4L2视频采集设备应用程序编程总结
- 采集用户的图像
- 基于Video4Linux 的USB 摄像头图像采集实现
- 无人机采集图像的相关知识