- 论坛徽章:
- 0
|
本帖最后由 Huntsmen 于 2014-01-24 08:56 编辑
在网上找的一个V4L2编程的经典例子,程序运行后,保存了2张jpg的图片,但是保存图片在windows下无法打开,想请教一下是什么原因?
PS:实验环境是arm9开发板,usb的UVC摄像头;利用开发板自带的usb摄像头测试app是能看到图像的;
[ 8802.695000] usb 1-1.2: new full-speed USB device number 3 using s3c2410-ohci
[ 8802.825000] uvcvideo: Found UVC 1.00 device USB 2.0 CAMERA (1c4f:3002)
[ 8802.890000] input: USB 2.0 CAMERA as /devices/platform/s3c2410-ohci/usb1/1-1/1-1.2/1-1.2:1.0/input/input1- #include <stdio.h>
- #include <string.h>
- #include <errno.h>
- #include <stdlib.h>
- #include <sys/types.h>
- #include <sys/stat.h>
- #include <fcntl.h>
- #include <sys/mman.h>
- #include <assert.h>
- #include <linux/videodev2.h>
- typedef struct
- {
- void *start;
- int length;
- }BUFTYPE;
- BUFTYPE *user_buf;
- int n_buffer = 0;
- //打开摄像头设备
- int open_camer_device()
- {
- int fd;
- if((fd = open("/dev/video0",O_RDWR | O_NONBLOCK)) < 0)
- {
- perror("Fail to open");
- exit(EXIT_FAILURE);
- }
-
- return fd;
- }
- int init_mmap(int fd)
- {
- int i = 0;
- struct v4l2_requestbuffers reqbuf;
- bzero(&reqbuf,sizeof(reqbuf));
- reqbuf.count = 4;
- reqbuf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
- reqbuf.memory = V4L2_MEMORY_MMAP;
-
- //申请视频缓冲区(这个缓冲区位于内核空间,需要通过mmap映射)
- //这一步操作可能会修改reqbuf.count的值,修改为实际成功申请缓冲区个数
- if(-1 == ioctl(fd,VIDIOC_REQBUFS,&reqbuf))
- {
- perror("Fail to ioctl 'VIDIOC_REQBUFS'");
- exit(EXIT_FAILURE);
- }
-
- n_buffer = reqbuf.count;
-
- printf("n_buffer = %d\n",n_buffer);
- user_buf = calloc(reqbuf.count,sizeof(*user_buf));
- if(user_buf == NULL){
- fprintf(stderr,"Out of memory\n");
- exit(EXIT_FAILURE);
- }
- //将内核缓冲区映射到用户进程空间
- for(i = 0; i < reqbuf.count; i ++)
- {
- struct v4l2_buffer buf;
-
- bzero(&buf,sizeof(buf));
- buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
- buf.memory = V4L2_MEMORY_MMAP;
- buf.index = i;
- //查询申请到内核缓冲区的信息
- if(-1 == ioctl(fd,VIDIOC_QUERYBUF,&buf))
- {
- perror("Fail to ioctl : VIDIOC_QUERYBUF");
- exit(EXIT_FAILURE);
- }
- user_buf[i].length = buf.length;
- user_buf[i].start =
- mmap(
- NULL,/*start anywhere*/
- buf.length,
- PROT_READ | PROT_WRITE,
- MAP_SHARED,
- fd,buf.m.offset
- );
- if(MAP_FAILED == user_buf[i].start)
- {
- perror("Fail to mmap");
- exit(EXIT_FAILURE);
- }
- }
- return 0;
- }
- //初始化视频设备
- int init_camer_device(int fd)
- {
- struct v4l2_fmtdesc fmt;
- struct v4l2_capability cap;
- struct v4l2_format stream_fmt;
- int ret;
-
- //当前视频设备支持的视频格式
- memset(&fmt,0,sizeof(fmt));
- fmt.index = 0;
- fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
- while((ret = ioctl(fd,VIDIOC_ENUM_FMT,&fmt)) == 0)
- {
- fmt.index ++ ;
- printf("{pixelformat = %c%c%c%c},description = '%s'\n",
- fmt.pixelformat & 0xff,(fmt.pixelformat >> 8)&0xff,
- (fmt.pixelformat >> 16) & 0xff,(fmt.pixelformat >> 24)&0xff,
- fmt.description);
- }
- //查询视频设备驱动的功能
- ret = ioctl(fd,VIDIOC_QUERYCAP,&cap);
- if(ret < 0){
- perror("FAIL to ioctl VIDIOC_QUERYCAP");
- exit(EXIT_FAILURE);
- }
- //判断是否是一个视频捕捉设备
- if(!(cap.capabilities & V4L2_BUF_TYPE_VIDEO_CAPTURE))
- {
- printf("The Current device is not a video capture device\n");
- exit(EXIT_FAILURE);
-
- }
- //判断是否支持视频流形式
- if(!(cap.capabilities & V4L2_CAP_STREAMING))
- {
- printf("The Current device does not support streaming i/o\n");
- exit(EXIT_FAILURE);
- }
- //设置摄像头采集数据格式,如设置采集数据的
- //长,宽,图像格式(JPEG,YUYV,MJPEG等格式)
- stream_fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
- stream_fmt.fmt.pix.width = 640;
- stream_fmt.fmt.pix.height = 480;
- stream_fmt.fmt.pix.pixelformat = V4L2_PIX_FMT_YUYV;
- stream_fmt.fmt.pix.field = V4L2_FIELD_INTERLACED;
- if(-1 == ioctl(fd,VIDIOC_S_FMT,&stream_fmt))
- {
- perror("Fail to ioctl");
- exit(EXIT_FAILURE);
- }
-
- //初始化视频采集方式(mmap)
- init_mmap(fd);
- return 0;
- }
- int start_capturing(int fd)
- {
- unsigned int i;
- enum v4l2_buf_type type;
- //将申请的内核缓冲区放入一个队列中
- for(i = 0;i < n_buffer;i ++)
- {
- struct v4l2_buffer buf;
- bzero(&buf,sizeof(buf));
- buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
- buf.memory = V4L2_MEMORY_MMAP;
- buf.index = i;
-
- if(-1 == ioctl(fd,VIDIOC_QBUF,&buf))
- {
- perror("Fail to ioctl 'VIDIOC_QBUF'");
- exit(EXIT_FAILURE);
- }
- }
- //开始采集数据
- type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
- if(-1 == ioctl(fd,VIDIOC_STREAMON,&type))
- {
- printf("i = %d.\n",i);
- perror("Fail to ioctl 'VIDIOC_STREAMON'");
- exit(EXIT_FAILURE);
- }
- return 0;
- }
- //将采集好的数据放到文件中
- int process_image(void *addr,int length)
- {
- FILE *fp;
- static int num = 0;
- char picture_name[20];
-
- sprintf(picture_name,"picture_%d.jpg",num ++);
-
- if((fp = fopen(picture_name,"w")) == NULL)
- {
- perror("Fail to fopen");
- exit(EXIT_FAILURE);
- }
- printf("len=%d\n",length);
- fwrite(addr,length,1,fp);
- usleep(500);
- fclose(fp);
- return 0;
- }
- int read_frame(int fd)
- {
- struct v4l2_buffer buf;
- unsigned int i;
- bzero(&buf,sizeof(buf));
- buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
- buf.memory = V4L2_MEMORY_MMAP;
-
- //从队列中取缓冲区
- if(-1 == ioctl(fd,VIDIOC_DQBUF,&buf))
- {
- perror("Fail to ioctl 'VIDIOC_DQBUF'");
- exit(EXIT_FAILURE);
- }
- assert(buf.index < n_buffer);
- //读取进程空间的数据到一个文件中
- process_image(user_buf[buf.index].start,user_buf[buf.index].length);
-
- if(-1 == ioctl(fd,VIDIOC_QBUF,&buf))
- {
- perror("Fail to ioctl 'VIDIOC_QBUF'");
- exit(EXIT_FAILURE);
- }
- return 1;
- }
- int mainloop(int fd)
- {
- int count = 2;
- while(count -- > 0)
- {
- for(;;)
- {
- fd_set fds;
- struct timeval tv;
- int r;
- FD_ZERO(&fds);
- FD_SET(fd,&fds);
- /*Timeout*/
- tv.tv_sec = 2;
- tv.tv_usec = 0;
-
- r = select(fd + 1,&fds,NULL,NULL,&tv);
- if(-1 == r)
- {
- if(EINTR == errno)
- continue;
-
- perror("Fail to select");
- exit(EXIT_FAILURE);
- }
- if(0 == r)
- {
- fprintf(stderr,"select Timeout\n");
- exit(EXIT_FAILURE);
- }
- if(read_frame(fd))
- break;
- }
- }
- return 0;
- }
- void stop_capturing(int fd)
- {
- enum v4l2_buf_type type;
-
- type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
- if(-1 == ioctl(fd,VIDIOC_STREAMOFF,&type))
- {
- perror("Fail to ioctl 'VIDIOC_STREAMOFF'");
- exit(EXIT_FAILURE);
- }
-
- return;
- }
- void uninit_camer_device()
- {
- unsigned int i;
- for(i = 0;i < n_buffer;i ++)
- {
- if(-1 == munmap(user_buf[i].start,user_buf[i].length))
- {
- exit(EXIT_FAILURE);
- }
- }
-
- free(user_buf);
- return;
- }
- void close_camer_device(int fd)
- {
- if(-1 == close(fd))
- {
- perror("Fail to close fd");
- exit(EXIT_FAILURE);
- }
- return;
- }
- int main()
- {
- int fd;
-
- fd = open_camer_device();
- init_camer_device(fd);
-
- start_capturing(fd);
-
- mainloop(fd);
-
- stop_capturing(fd);
- uninit_camer_device(fd);
- close_camer_device(fd);
- return 0;
- }
复制代码 上面程序运行结果如下:
{pixelformat = YUYV},description = 'YUV 4:2:2 (YUYV)'
n_buffer = 4
len=153600
len=153600
|
|