linux下usb camera图像采集(V4l2)

时间:2022-06-18 06:37:51
head.h
  1. #include <stdio.h>
  2. #include <stdlib.h>
  3. #include <string.h>
  4. #include <fcntl.h>/* low-level i/o*/
  5. #include <unistd.h>
  6. #include <errno.h>
  7. #include <malloc.h>
  8. #include <sys/stat.h>
  9. #include <sys/types.h>
  10. #include <sys/time.h>
  11. #include <sys/mman.h>
  12. #include <sys/ioctl.h>
  13. #include <linux/videodev2.h>
  14. #define DEVICE "/dev/video"
  15. static struct v4l2_requestbuffers req;
  16. struct buffer
  17. {
  18.     void* start;
  19.     unsigned int length;
  20. };
  21. static struct buffer *buffers;
  22. static struct v4l2_buffer buf;

usb_camera.c
  1. #include "head.h"
  2. int main()
  3. {
  4.     int fd;
  5.     fd=open_device();
  6.     get_device_info(fd);
  7.     get_frame_fmt(fd);
  8.     get_current_frame_info(fd);
  9.     try_format_support(fd);
  10.     set_frame_format(fd);
  11.     apply_memory_buf(fd);
  12.     memory_mapping(fd);
  13.     buffer_enqueue(fd);
  14.     close(fd);
  15.     return 0;
  16. }
  17. int open_device()
  18. {
  19.     int fd;
  20.     if(-1==(fd=open(DEVICE,O_RDWR)))
  21.         printf("info:Can't open video device\n");
  22.     else
  23.         printf("info:Open the device :%d\n",fd);
  24.     return fd;
  25. }
  26. int get_device_info(int fd)
  27. {
  28.     struct v4l2_capability cap;
  29.     if(-1==ioctl(fd,VIDIOC_QUERYCAP,&cap))
  30.         printf("info:VIDIOC_QUERYCAP ERROR\n");
  31.     else
  32.         printf("info:Driver Name:%s....Card Name:%s....Bus info:%s....Driver Version:%u.%u.%u\n",
  33.         cap.driver,cap.card,cap.bus_info,(cap.version>>16)&0XFF,(cap.version>>8)&0XFF,cap.version&0XFF);
  34.     return 1;
  35. }
  36. int get_frame_fmt(int fd)
  37. {
  38.     struct v4l2_fmtdesc fmtdesc;
  39.     fmtdesc.index=0;
  40.     fmtdesc.type=V4L2_BUF_TYPE_VIDEO_CAPTURE;
  41.     printf("info:Support format:");
  42.     while(ioctl(fd,VIDIOC_ENUM_FMT,&fmtdesc)!=-1)
  43.     {
  44.         printf("\t%d.%s",fmtdesc.index+1,fmtdesc.description);
  45.         fmtdesc.index++;
  46.     }
  47.     printf("\n");
  48.     return 1;
  49. }
  50. int get_current_frame_info(int fd)
  51. {
  52.     struct v4l2_format fmt;
  53.     fmt.type=V4L2_BUF_TYPE_VIDEO_CAPTURE;
  54.     ioctl(fd,VIDIOC_G_FMT,&fmt);
  55.     printf("info:Current data format information:\n\twidth:%d\n\theight:%d\n",fmt.fmt.pix.width,fmt.fmt.pix.height);
  56.     struct v4l2_fmtdesc fmtdesc;
  57.     fmtdesc.index=0;
  58.     fmtdesc.type=V4L2_BUF_TYPE_VIDEO_CAPTURE;
  59.     while(ioctl(fd,VIDIOC_ENUM_FMT,&fmtdesc)!=-1)
  60.     {
  61.         if(fmtdesc.pixelformat& fmt.fmt.pix.pixelformat)
  62.         {
  63.             printf("\tformat:%s\n",fmtdesc.description);
  64.             break;
  65.         }
  66.         fmtdesc.index++;
  67.     }
  68.     return 1;
  69. }
  70. int try_format_support(int fd)
  71. {
  72.     struct v4l2_format fmt;
  73.     fmt.type=V4L2_BUF_TYPE_VIDEO_CAPTURE;
  74.     //fmt.fmt.pix.pixelformat=V4L2_PIX_FMT_RGB32;
  75.     fmt.fmt.pix.pixelformat=V4L2_PIX_FMT_YUYV;
  76.     if(ioctl(fd,VIDIOC_TRY_FMT,&fmt)==-1)
  77.     if(errno==EINVAL)
  78.     printf("info:not support format RGB32!\n");
  79.     return 1;
  80. }
  81. int set_frame_format(int fd)
  82. {
  83.     struct v4l2_format fmt;
  84.     fmt.type=V4L2_BUF_TYPE_VIDEO_CAPTURE;
  85.     fmt.fmt.pix.width=640;
  86.     fmt.fmt.pix.height=480;
  87.     fmt.fmt.pix.pixelformat= V4L2_PIX_FMT_YUYV;
  88.     fmt.fmt.pix.field= V4L2_FIELD_INTERLACED;
  89.     if(ioctl(fd,VIDIOC_S_FMT,&fmt)==-1)
  90.     if(errno==EINVAL)
  91.     printf("info:set frame format error!\n");
  92.     return 1;
  93. }
  94. int apply_memory_buf(int fd)
  95. {
  96.     //struct v4l2_requestbuffers req;
  97.     req.count=4;
  98.     req.type=V4L2_BUF_TYPE_VIDEO_CAPTURE;
  99.     req.memory=V4L2_MEMORY_MMAP;
  100.     if(-1==ioctl(fd,VIDIOC_REQBUFS,&req))
  101.         printf("info:VIDIOC_REQBUFS FAILED\n");
  102.     else
  103.         printf("info:VIDIOC_REQBUFS SUCCESS\n");
  104.     return 1;
  105. }
  106. int memory_mapping(int fd)
  107. {
  108.     unsigned int n_buffers;
  109.     buffers =(struct buffer*)calloc(req.count,sizeof(struct buffer));
  110.     if (!buffers){
  111.         fprintf (stderr, "Out of memory\n");
  112.         exit(EXIT_FAILURE);
  113.     }
  114.     // 映射
  115.     for (n_buffers = 0; n_buffers< req.count;++n_buffers){
  116.         //struct v4l2_buffer buf;
  117.         memset(&buf,0,sizeof(buf));
  118.         buf.type= V4L2_BUF_TYPE_VIDEO_CAPTURE;
  119.         buf.memory= V4L2_MEMORY_MMAP;
  120.         buf.index= n_buffers;
  121.         // 查询序号为n_buffers 的缓冲区,得到其起始物理地址和大小
  122.         if(-1 == ioctl (fd, VIDIOC_QUERYBUF,&buf))
  123.             exit(-1);
  124.         buffers[n_buffers].length= buf.length;
  125.         // 映射内存
  126.         buffers[n_buffers].start=mmap (NULL,buf.length,PROT_READ| PROT_WRITE ,MAP_SHARED,fd, buf.m.offset);
  127.         if(MAP_FAILED == buffers[n_buffers].start)
  128.             exit(-1);
  129.     }
  130.     printf("info:memory mapping success\n");
  131.     return 1;
  132. }
  133. int buffer_enqueue(int fd)
  134. {
  135.     unsigned int i;
  136.     enum v4l2_buf_type type;
  137.     // 将缓冲帧放入队列
  138.     for (i = 0; i< 4; ++i)
  139.     {
  140.         struct v4l2_buffer buf;
  141.         buf.type= V4L2_BUF_TYPE_VIDEO_CAPTURE;
  142.         buf.memory= V4L2_MEMORY_MMAP;
  143.         buf.index= i;
  144.         if(-1==ioctl(fd, VIDIOC_QBUF,&buf))
  145.             printf("buffer enqueue failed\n");
  146.     }
  147.     type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
  148.     //open stream
  149.     if(-1==ioctl(fd, VIDIOC_STREAMON,&type))
  150.         printf("info:open stream failed\n");
  151.     else
  152.         printf("info:open stream success\n");
  153.     return 1;
  154. }