前面主要介绍的是:V4L2 的一些设置接口,如亮度,饱和度,曝光时间,帧数,增益,白平衡等。今天看看V4L2 得到数据的几个关键ioctl,Buffer的申请和数据的抓取。


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.1:Memory Mapping模式详解:
在使用Memory Mapping模式时,参数三中结构体内每个field都需要设置。


 __u32 count;   //当memory=V4L2_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.2:User Pointer模式:
User Pointer模式时,应用程序实现申请。
只需要填充Type=V4L2_BUF_TYPE_VIDEO_CAPTURE,
memory=V4L2_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_MAPPEDV4L2_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

非常简单的调用。就是开始和结束。

【Qt开发】V4L2 API详解 Buffer的准备和数据读取的更多相关文章

  1. V4L2 API详解 Buffer的准备和数据读取

    1. 初始化 Memory Mapping 或 User Pointer I/O. int ioctl(int fd, int requestbuf, struct v4l2_requestbuffe ...

  2. 【Qt开发】V4L2 API详解 Camera详细设置

    Camera的可设置项极多,V4L2 支持了不少.但Sam之前对这些设置的用法和涵义都是在看videodev2.h中边看边理解,感觉非常生涩.直到写这篇blog时,才发现v4l2有专门的SPEC来说明 ...

  3. 【Qt开发】V4L2 API详解 背景知识 打开设备设置参数

    www.linuxtv.org下,有篇文档详细讲解了V4L2相关知识和体系结构.是V4L2方面最全面的文档.可以通过它学习V4L2的一些思路和想法. http://www.linuxtv.org/do ...

  4. V4L2 API详解 <二> Camera详细设置【转】

    转自:http://blog.sina.com.cn/s/blog_602f87700101bf36.html 作者: Sam (甄峰)  sam_code@hotmail.com   Camera的 ...

  5. ThinkPHP之中的getField、Find、select、返回数据类型详解(ThinkPHP之中所有数据读取了)

    小李子:用于演示作用的数据库表:customers 官方解读: “ 读取数据集其实就是获取数据表中的多行记录(以及关联数据),使用select方法 ” $customers=D('customers' ...

  6. Android Developer -- Bluetooth篇 开发实例之四 API详解

    http://www.open-open.com/lib/view/open1390879771695.html 这篇文章将会详细解析BluetoothAdapter的详细api, 包括隐藏方法, 每 ...

  7. Linux驱动开发必看详解神秘内核(完全转载)

    Linux驱动开发必看详解神秘内核 完全转载-链接:http://blog.chinaunix.net/uid-21356596-id-1827434.html   IT168 技术文档]在开始步入L ...

  8. 网络编程socket基本API详解(转)

    网络编程socket基本API详解   socket socket是在应用层和传输层之间的一个抽象层,它把TCP/IP层复杂的操作抽象为几个简单的接口供应用层调用已实现进程在网络中通信. socket ...

  9. 转】Mahout推荐算法API详解

    原博文出自于: http://blog.fens.me/mahout-recommendation-api/ 感谢! Posted: Oct 21, 2013 Tags: itemCFknnMahou ...

随机推荐

  1. libpng Cximage图片处理

    跨平台 开源 png图片处理 https://www.cnblogs.com/lidabo/p/6923426.html Cximage BIPro

  2. xavier_uniform/xavier_normal

    import math from torch.autograd import Variable import torch import torch.nn as nn import warnings w ...

  3. spark性能调优点(逐步完善)

    1.使用高性能序列化类库2.优化数据结构3.对多次使用的RDD进行持久化/CheckPoint4.使用序列化的持久化级别5.Java虚拟机垃圾回收调优 降低RDD缓存占用空间的比例:new Spark ...

  4. Java——静态类型 实际类型

    public class test { static class father { void run() { System.out.println("father run"); } ...

  5. 对JavaScript 引擎基础:原型优化的研究 -----------------------引用

    一.优化层级与执行效率的取舍 介绍了现代 JavaScript 引擎通用的工作流程: 我们也指出,尽管从高级抽象层面来看,引擎之间的处理流程都很相似,但他们在优化流程上通常都存在差异.为什么呢?为什么 ...

  6. Missing radix parameter.报错解决方法

    当报“Missing radix parameter.”这个错的时候,是因为使用parseInt没有传第二个参数,以前简写的时候大家几乎都不传,甚至不知道还有第二个参数. 当时候Eslint预发检查时 ...

  7. Shell中Bash的基本功能(二)

    1 历史命令 1)历史命令的查看[root@localhost ~]# history [选项] [历史命令保存文件]选项:-c: 清空历史命令-w: 把缓存中的历史命令写入历史命令保存文件.如果不手 ...

  8. HDU3465--Life is a Line(树状数组求逆序数,离散化)

    Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 131072/65536 K (Java/Others) Total Submission(s ...

  9. Linux小记 -- 更新系统软件包

    系统信息 操作系统:Ubuntu 18.04.2 LTS 内核版本:4.15.0-51-generic 何时需要更新 重新启动Ubuntu发现如下motd(message of tody),此时需要更 ...

  10. mini dc(选做)

    一.题目要求 提交测试截图和码云练习项目链接,实现Linux下dc的功能,计算后缀表达式的值 二.源代码 1.MyDC类 import java.util.StringTokenizer; impor ...