厦门 外贸商城网站,浙江门户网站建设公司,微信网站模块,医院网站建设多少钱前面主要介绍的是#xff1a;V4L2 的一些设置接口#xff0c;如亮度#xff0c;饱和度#xff0c;曝光时间#xff0c;帧数#xff0c;增益#xff0c;白平衡等。今天看看V4L2 得到数据的几个关键ioctl#xff0c;Buffer的申请和数据的抓取。1. 初始化 Memory Mapping … 前面主要介绍的是V4L2 的一些设置接口如亮度饱和度曝光时间帧数增益白平衡等。今天看看V4L2 得到数据的几个关键ioctlBuffer的申请和数据的抓取。 1. 初始化 Memory Mapping 或 User Pointer I/O. 申请数据Buffer。 int ioctl(int fd, int requestbuf, struct v4l2_requestbuffers * argp); 参数一open所产生的句柄。 参数二VIDIOC_REQBUFS 参数三in/out结构体。 struct v4l2_requestbuffers { __u32 count; enum v4l2_buf_type type; enum v4l2_memory memory; //Applications set this field to V4L2_MEMORY_MMAP or V4L2_MEMORY_USERPTR __u32 reserved[2]; }; 注意有两种方式的I/O。 Memory Mapping 和User Pointer。 Memory Mapping的Buffer由Driver申请为物理连续的内存空间(Kernel空间)。在此ioctl调用时被分配需要早于mmap()动作将他们映射到用户空间。 1.1Memory Mapping模式详解 在使用Memory Mapping模式时参数三中结构体内每个field都需要设置。 __u32 count; //当memoryV4L2_MEMORY_MMAP时此处才有效。表明要申请的buffer个数。 enum v4l2_buf_type type; //Stream 或者Buffer的类型。此处肯定为V4L2_BUF_TYPE_VIDEO_CAPTURE enum v4l2_memory memory; //既然是Memory Mapping模式则此处设置为V4L2_MEMORY_MMAP 注意count是个输入输出函数。因为你所申请到的Buffer个数不一定就是你所输入的Number。所以在ioctl执行后driver会将真实申请到的buffer个数填充到此field. 这个数目有可能大于你想要申请的也可能小与甚至可能是0个。 应用程序可以再次调用ioctl--VIDIOC_REQBUFS 来修改buffer个数。但前提是必须先释放已经 mapped 的 buffer 可以先 munmap 然后设置参数 count 为 0 来释放所有的 buffer。 支持Memory Mapping I/O方式的前提是v4l2_capability 中支持V4L2_CAP_STREAMING。 在这个模式下数据本身不会被Copy只是在Kernel和用户态之间交换。在应用程序想要访问到这些数据之前它必须调用mmap()影射到用户态。 同时也要注意通过ioctl申请的内存是物理内存无法被交换入Disk所以一定要释放munmap()。 1.2User Pointer模式 User Pointer模式时应用程序实现申请。 只需要填充TypeV4L2_BUF_TYPE_VIDEO_CAPTURE memoryV4L2_MEMORY_USERPTR 2. 询问Buffer状态 int ioctl(int fd, int request, struct v4l2_buffer* argp); 参数一open所产生的句柄。 参数二VIDIOC_QUERYBUF 参数三v4l2_buffer 结构体。(IN/OUT参数) 注意此ioctl是Memory Mapping的I/O方法之一。User Pointer模式不需要。在Buffer在ioctl-VIDIOC_REQBUFS执行时创建后随时都可以调用此Ioctl得到buffer信息。 视频缓冲区的使用状态、在内核空间的偏移地址、缓冲区长度等。在应用程序设计中通过调VIDIOC_QUERYBUF来获取内核空间的视频缓冲区信息然后调用函数mmap把内核空间地址映射到用户空间这样应用程序才能够访问位于内核空间的视频缓冲区 我们首先通过v4l2_buffer结构体看看参数三这个输入输出参数需要输入些什么以及能够得到什么信息。 struct v4l2_buffer { __u32 index; enum v4l2_buf_type type; __u32 bytesused; __u32 flags; enum v4l2_field field; struct timeval timestamp; struct v4l2_timecode timecode; __u32 sequence; enum v4l2_memory memory; union { __u32 offset; unsigned long userptr; } m; __u32 length; __u32 input; __u32 reserved; }; 在调用ioctl--VIDIOC_QUERYBUF时需要写入的项目有 enum v4l2_buf_type type; //V4L2_BUF_TYPE_VIDEO_CAPTURE __u32 index; // 这里需要解释一下因为在调用ioctl-VIDIOC_REQBUFS时建立了count个Buffer。所以这里index的有效范围是0到count-1. 在调用ioctl-VIDIOC_QUERYBUF后Driver会填充v4l2_buffer 结构体内所有信息供用户使用。 如果一些正常 1. flags 中V4L2_BUF_FLAG_MAPPED, V4L2_BUF_FLAG_QUEUED and V4L2_BUF_FLAG_DONE被设置。 2. memory中V4L2_MEMORY_MMAP被设置。 3. m.offset中从将要mapping 的device memory头到数据头的offset. 4. length 中填充当前Buffer长度。 5。其它的Field有可能设置也有可能不被设置。 这样mmap想要有的信息就全了。而mmap()之后Device Driver 申请的或者Device Memory就能映射到用户空间。数据就可以被应用程序使用了。这才是ioctl-VIDIOC_QUERYBUF的关键作用。 3.和Driver交换buffer: 对Camera这样的捕获设备来说Device将数据放到Buffer中用户得到数据。Device再次将数据放到Buffer中。 那么Device Driver 怎样知道哪个Buffer是可以存放数据的呢这就用到当前这两个ioctl-VIDIOC_QBUF, ioctl-VIDIOC_DQBUF. ioctl-VIDIOC_QBUF: 将指定的Buffer放到输入队列中即向Device表明这个Buffer可以存放东西。 ioctl-VIDIOC_DQBUF: 将输出队列中的数据 buffer取出。 在 driver 内部管理着两个 buffer queues 一个输入队列一个输出队列。对于 capture device 来说当输入队列中的 buffer 被塞满数据以后会自动变为输出队列等待调用 VIDIOC_DQBUF 将数据进行处理以后重新调用 VIDIOC_QBUF 将 buffer 重新放进输入队列. 用法 ioctl--VIDIOC_QBUF int ioctl(int fd, int request, struct v4l2_buffer* argp); 参数一open所产生的句柄。 参数二VIDIOC_QBUF 参数三v4l2_buffer 结构体。(IN/OUT参数) 参数三是IN/OUT 参数。需要填充 enum v4l2_buf_type type; //V4L2_BUF_TYPE_VIDEO_CAPTURE __u32 index; // 这里需要解释一下因为在调用ioctl-VIDIOC_REQBUFS时建立了count个Buffer。所以这里index的有效范围是0到count-1. memory: V4L2_MEMORY_MMAP. 则这个结构体指明的buffer被送入输出队列表明此Buffer可以被device 填充数据。 用法 ioctl--VIDIOC_DQBUF int ioctl(int fd, int request, struct v4l2_buffer* argp); 参数一open所产生的句柄。 参数二VIDIOC_DQBUF 参数三v4l2_buffer 结构体。(IN/OUT参数) 从输出队列中取出一个有数据的Buffer。这个Buffer中的数据被处理后此Buffer可以通过ioctl-VIDIOC_QBUF再次放入输入队列中去。 4. 开始和结束捕获 ioctl--VIDIOC_STREAMON. ioctl--VIDIOC_STREAMOFF 非常简单的调用。就是开始和结束。 转载于:https://www.cnblogs.com/huty/p/8518249.html