V4L2驱动程序架构-3

3.6 视频格式查询

v4l2中,有两种查询视频格式的方法,一个是遍历所有视频格式的

一个是查询出一种格式的

/*查询出一种格式*/

ret = ioctl(fd, VIDIOC_G_FMT, &fmt);

/*遍历所有视频格式,查询驱动所支持的格式*/

VIDIOC_ENUM_FMT

[csharp] view plaincopy

  1. 驱动  

  2. static int s3c_fimc_v4l2_g_fmt_vid_cap(struct file *filp, void *fh,  

  3.                     struct v4l2_format *f)  

  4. {  

  5.     struct s3c_fimc_control *ctrl = (struct s3c_fimc_control *) fh;  

  6.     int size = sizeof(struct v4l2_pix_format);  

  7.   

  8.     memset(&f->fmt.pix, 0, size);  

  9.     memcpy(&f->fmt.pix, &(ctrl->v4l2.frmbuf.fmt), size);  

  10.   

  11.     return 0;  

  12. }  

  13. 应用  

  14. static int video_getfmt(int fd)  

  15. {  

  16.     /***********get Stream data format********/  

  17.     int ret= 0;  

  18.     struct v4l2_format fmt;  

  19.     CLEAR(fmt);  

  20.     fmt.type    =   V4L2_BUF_TYPE_VIDEO_CAPTURE;  

  21.     ret = ioctl(fd, VIDIOC_G_FMT, &fmt);  

  22.     if (ret < 0) {  

  23.         perror("VIDIOC_G_FMT");  

  24.         return ret;  

  25.     }  

  26.     printf("/n**********vidioc get stream format informations:****\n");  

  27.     if (fmt.fmt.pix.pixelformat == V4L2_PIX_FMT_YUYV)  

  28.         printf("8-bit YUYVV pixel format\n");  

  29.         printf("Size of the buffer = %d\n", fmt.fmt.pix.sizeimage);  

  30.         printf("Line offset = %d\n", fmt.fmt.pix.bytesperline);  

  31.     if (fmt.fmt.pix.field == V4L2_FIELD_INTERLACED)  

  32.         printf("Storate format is interlaced frame format\n");  

  33.           

  34.     return 0;  

  35. }  


3.7 向驱动申请帧缓冲,内存,一般不超过5,帧缓冲管理

[csharp] view plaincopy

  1. 结构体  

  2. struct v4l2_requestbuffers req;  

  3. ret = ioctl(fd, VIDIOC_REQBUFS, &req);  

  4. ret = ioctl(fd, VIDIOC_QUERYBUF, &buf);//读取缓存  

  5.   

  6. struct v4l2_requestbuffers {  

  7.     __u32           count;  

  8.     enum v4l2_buf_type      type;  

  9.     enum v4l2_memory        memory;  

  10.     __u32           reserved[2];  

  11. };  

  12.       

  13. struct v4l2_buffer {  

  14.     __u32           index;  

  15.     enum v4l2_buf_type      type;  

  16.     __u32           bytesused;  

  17.     __u32           flags;  

  18.     enum v4l2_field     field;  

  19.     struct timeval      timestamp;  

  20.     struct v4l2_timecode    timecode;  

  21.     __u32           sequence;  

  22.   

  23.     /* memory location */  

  24.     enum v4l2_memory        memory;  

  25.     union {  

  26.         __u32           offset;  

  27.         unsigned long   userptr;  

  28.     } m;  

  29.     __u32           length;  

  30.     __u32           input;  

  31.     __u32           reserved;  

  32. };  

  33. 使用VIDIOC_REQBUFS 我们获取了req.count个缓存,下一步通过  

  34. 调用VIDIOC_QUERYBUF 命令来获取这些缓存的地址,然后使用  

  35. mmap函数转换成应用程序中的绝对地址,最后把这些缓存放入  

  36. 缓存队列。  

  37. The main steps that the application must perform for buffer allocation are:   

  38. Allocating Memory   

  39. Getting Physical Address   

  40. Mapping Kernel Space Address to User Space   

  41. 驱动支持  

  42.   

  43. static int s3c_fimc_v4l2_reqbufs(struct file *filp, void *fh,  

  44.                     struct v4l2_requestbuffers *b)  

  45. {  

  46.     if (b->memory != V4L2_MEMORY_MMAP) {  

  47.         err("V4L2_MEMORY_MMAP is only supported\n");  

  48.         return -EINVAL;  

  49.     }  

  50.   

  51.     /* control user input */  

  52.     if (b->count > 4)  

  53.         b->count = 4;  

  54.     else if (b->count < 1)  

  55.         b->count = 1;  

  56.   

  57.     return 0;  

  58. }  

  59. static int s3c_fimc_v4l2_querybuf(struct file *filp, void *fh,  

  60.                     struct v4l2_buffer *b)  

  61. {  

  62.     struct s3c_fimc_control *ctrl = (struct s3c_fimc_control *) fh;  

  63.       

  64.     if (b->type != V4L2_BUF_TYPE_VIDEO_OVERLAY && \  

  65.         b->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)  

  66.         return -EINVAL;  

  67.   

  68.     if (b->memory != V4L2_MEMORY_MMAP)  

  69.         return -EINVAL;  

  70.   

  71.     b->length = ctrl->out_frame.buf_size;  

  72.   

  73.     /* 

  74.      * NOTE: we use the m.offset as an index for multiple frames out. 

  75.      * Because all frames are not contiguous, we cannot use it as 

  76.      * original purpose. 

  77.      * The index value used to find out which frame user wants to mmap. 

  78.      */  

  79.     b->m.offset = b->index * PAGE_SIZE;  

  80.   

  81.     return 0;  

  82. }  

  83. static int s3c_fimc_v4l2_qbuf(struct file *filp, void *fh,  

  84.                 struct v4l2_buffer *b)  

  85. {  

  86.     return 0;  

  87. }  

  88. 应用层  

  89. static int video_mmap(int fd)  

  90. {  

  91.     /*******step 1*****requestbuffers Allocating Memory *******/  

  92.     int ret = 0;  

  93.     struct v4l2_requestbuffers req;  

  94.     CLEAR(req);  

  95.     req.count    = 4;  

  96.     req.type     = V4L2_BUF_TYPE_VIDEO_CAPTURE;  

  97.     req.memory   = V4L2_MEMORY_MMAP;  

  98.       

  99.     ret = ioctl(fd, VIDIOC_REQBUFS, &req);  

  100.     if (ret < 0) {  

  101.         perror("VIDIOC_REQBUFS");  

  102.         return ret;  

  103.     }  

  104.       

  105.     if (req.count < 2)  

  106.         printf("insufficient buffer memory\n");  

  107.         printf("Number of buffers allocated = %d\n", req.count);  

  108.           

  109.     /*******step 2*****Getting Physical Address  *******/  

  110.     buffers = calloc(req.count, sizeof(*buffers));  

  111.     for (n_buffers = 0; n_buffers < req.count; ++n_buffers)  

  112.     {  

  113.         struct v4l2_buffer buf;//驱动中的一帧  

  114.         CLEAR(buf);  

  115.         buf.type    = V4L2_BUF_TYPE_VIDEO_CAPTURE;  

  116.         buf.memory  = V4L2_MEMORY_MMAP;  

  117.         buf.index   = n_buffers;  

  118.           

  119.         ret = ioctl(fd, VIDIOC_QUERYBUF, &buf);  

  120.         if (ret < 0) {  

  121.             perror("VIDIOC_QUERYBUF");  

  122.             return ret;  

  123.         }  

  124.           

  125.     /*******step 3*****Mapping Kernel Space Address to User Space*******/  

  126.         buffers[n_buffers].length = buf.length;  

  127.         buffers[n_buffers].start =   

  128.         mmap(NULL,  

  129.             buf.length,  

  130.             PROT_READ | PROT_WRITE,  

  131.             MAP_SHARED,  

  132.             fd,  

  133.             buf.m.offset);  

  134.               

  135.         //if (MAP_FAILED == buffers[n_buffers].start)  

  136.         //perror("mmap failed \n");  

  137.     }  

  138.       

  139.     /************requestbuffers in queue***********/  

  140.     for (i = 0; i < n_buffers; ++i) {  

  141.         struct v4l2_buffer buf;  

  142.         CLEAR(buf);  

  143.           

  144.         buf.type    = V4L2_BUF_TYPE_VIDEO_CAPTURE;  

  145.         buf.memory  = V4L2_MEMORY_MMAP;  

  146.         buf.index = i;  

  147.           

  148.         ret = ioctl(fd, VIDIOC_QBUF, &buf);//申请的缓冲进入队列  

  149.         if (ret < 0) {  

  150.             perror("VIDIOC_QBUF");  

  151.             return ret;  

  152.         }     

  153.     }  

  154.       

  155.     return 0;  

  156. }     


3.8 开始捕捉图像数据(重要)

[csharp] view plaincopy

  1. <pre name="code" class="csharp"><p>结构体</p><pre name="code" class="csharp">enum v4l2_buf_type type;//开始捕捉图像数据  

  2.     type = V4L2_BUF_TYPE_VIDEO_CAPTURE;  

  3.     ret = ioctl(fd, VIDIOC_STREAMON, &type);  

  4.       

  5. enum v4l2_buf_type {  

  6.     V4L2_BUF_TYPE_VIDEO_CAPTURE        = 1,  

  7.     V4L2_BUF_TYPE_VIDEO_OUTPUT         = 2,  

  8.     V4L2_BUF_TYPE_VIDEO_OVERLAY        = 3,  

  9.     V4L2_BUF_TYPE_VBI_CAPTURE          = 4,  

  10.     V4L2_BUF_TYPE_VBI_OUTPUT           = 5,  

  11.     V4L2_BUF_TYPE_SLICED_VBI_CAPTURE   = 6,  

  12.     V4L2_BUF_TYPE_SLICED_VBI_OUTPUT    = 7,  

  13. #if 1  

  14.     /* Experimental */  

  15.     V4L2_BUF_TYPE_VIDEO_OUTPUT_OVERLAY = 8,  

  16. #endif  

  17.     V4L2_BUF_TYPE_PRIVATE              = 0x80,  

  18. };  

  19.   

  20. 驱动  

  21.   

  22. static int s3c_fimc_v4l2_streamon(struct file *filp, void *fh,  

  23.                     enum v4l2_buf_type i)  

  24. {  

  25.     struct s3c_fimc_control *ctrl = (struct s3c_fimc_control *) fh;  

  26.     if (i != V4L2_BUF_TYPE_VIDEO_CAPTURE)  

  27.         return -EINVAL;  

  28. printk("s3c_fimc_v4l2_streamon is called\n");  

  29.     if (ctrl->in_type != PATH_IN_DMA)  

  30.         s3c_fimc_init_camera(ctrl);  

  31.   

  32.     ctrl->out_frame.skip_frames = 0;  

  33.     FSET_CAPTURE(ctrl);  

  34.     FSET_IRQ_NORMAL(ctrl);  

  35.     s3c_fimc_start_dma(ctrl);  

  36.   

  37.     return 0;  

  38. }  

  39. 硬件控制寄存器的配置  

  40. 应用层  

  41. static int video_streamon(int fd)  

  42. {  

  43.     int ret = 0;  

  44.       

  45.     /************start stream on***********/  

  46.   

  47.     enum v4l2_buf_type types;//开始捕捉图像数据  

  48.     types = V4L2_BUF_TYPE_VIDEO_CAPTURE;  

  49.     ret = ioctl(fd, VIDIOC_STREAMON, &types);  

  50.     if (ret < 0) {  

  51.         perror("VIDIOC_STREAMON");  

  52.         return ret;  

  53.     }  

  54.   

  55.     return 0;  

  56. }

你可能感兴趣的:(V4L)