Linux下实现视频读取(三)---Buffer的准备和数据读取
前面主要介绍的是:V4L2 的一些设置接口,如亮度,饱和度。曝光时间,帧数,增益。白平衡等。今天看看V4L2 得到数据的几个关键ioctl,Buffer的申请和数据的抓取。
1. 初始化 Memory Mapping 或 User Pointer I/O.
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信息。
我们首先通过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再次放入输入队列中去。
Linux下实现视频读取(三)---Buffer的准备和数据读取的更多相关文章
- Linux下实现视频读取
V4L(video4linux是一些视频系统,视频软件.音频软件的基础,经常时候在需要采集图像的场合,如视频监控,webcam,可视电话,经常使用在embedded linux中是linux嵌入式开发 ...
- Linux下的视频字幕编辑
一.Linux下的字幕编辑软件 常用的有subtitleeditor, gnome-subtitles, gaupol 1.gnome-subtitles:不支持多字幕文件批量处理2.gaupol:全 ...
- 嵌入式Linux下MP4视频录制库MP4V2移植和简单介绍
**************************************************************************************************** ...
- Linux下从视频提取音频的方法
Linux下可以利用mencoder将视频里的音频提取出来.方法如下: 1.首先安装mencoder.对于Ubuntu来说,软件仓库里就有mencoder,可直接输入如下命令安装 sudo apt-g ...
- V4L2 API详解 Buffer的准备和数据读取
1. 初始化 Memory Mapping 或 User Pointer I/O. int ioctl(int fd, int requestbuf, struct v4l2_requestbuffe ...
- 【原创】xenomai内核解析--xenomai与普通linux进程之间通讯XDDP(三)--实时与非实时数据交互
版权声明:本文为本文为博主原创文章,转载请注明出处.如有问题,欢迎指正.博客地址:https://www.cnblogs.com/wsg1100/ 目录 1.概述 1.概述 [原创]实时IPC概述 [ ...
- 【Qt开发】V4L2 API详解 Buffer的准备和数据读取
前面主要介绍的是:V4L2 的一些设置接口,如亮度,饱和度,曝光时间,帧数,增益,白平衡等.今天看看V4L2 得到数据的几个关键ioctl,Buffer的申请和数据的抓取. 1. 初始化 Memory ...
- 4.windows和Linux下创建oracleusername表空间,表,插入数据,用户管理表等操作
进入超级管理员,运行下面命令 Window下创建数据库.表空间,用户,插入数据等操作 -- 01 创建表空间 -- 注意表空间的路径 依据实际安装环境进行调整 CREATE TABLESPACE ts ...
- Linux下实现视频读取(二)---camera參数设定
Camera的可设置项极多,V4L2 支持了不少.但Sam之前对这些设置的使用方法和涵义都是在看videodev2.h中边看边理解.感觉很生涩. 直到写这篇blog时,才发现v4l2有专门的SPEC来 ...
随机推荐
- 启动Apache出现问题:一直停留在启动界面
问题描述: 由于需要php_curl模块,因此直接在php.ini文件将前面的分号去掉 ,但是重启Apache时出现:一直停留在启动界面,Apache无法正常启动,查看错误日志,显示如下: 解决方 ...
- jQuery添加删除节点例子第十节"员工增删表"
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/ ...
- PHP面向对象摘要
一.面向对象的三种特性,分别是封装性,继承性和多态性. 1.封装性:封装是面向对象的核心思想,将对象的属性和行为封装起来,不需要让外界知道具体的实现细节,这就是封装思想. 2.继承性:继承性主要是描述 ...
- 通讯框架 t-io 学习——websocket 部分源码解析
前言 前端时间看了看t-io的websocket部分源码,于是抽时间看了看websocket的握手和他的通讯机制.本篇只是简单记录一下websocket握手部分. WebSocket握手 好多人都用过 ...
- IE浏览器中用Firebug调试网站的方法
对于大部分做前端设计者而言应该都使用过Firefox浏览器下一款调试网站的扩展插件firebug吧,功能非常的强大,对于我们找出网页兼容性的问题非常的有效.不过对于很多不喜欢使用Firefox浏览器的 ...
- 重构手法之Replace Temp with Query(以查询取代临时变量)
返回总目录 6.4Replace Temp with Query(以查询取代临时变量) 概要 你的程序以一个临时变量保存某一表达式的运算结果. 将这个表达式提炼到一个独立函数中.将这个临时变量的所有引 ...
- Python待分析的模块
fcntl 文件控制模块 http://docs.python.org/2.7/library/fcntl.html#module-fcntl struct 二进制文本处理模块 http://docs ...
- PHP设计模式之组合模式
当我们的一个对象可能代表一个单一的实体,或者一个组合的实体,但是仍然需要通过同样的方式被使用时,这种情形则适合使用组合模式的设计. 组合模式是一种结构型模式. 当看了书上的解释之后,并不是很理解,遂去 ...
- 【机器学习】DNN训练中的问题与方法
感谢中国人民大学的胡鹤老师,人工智能课程讲的很有深度,与时俱进 由于深度神经网络(DNN)层数很多,每次训练都是逐层由后至前传递.传递项<1,梯度可能变得非常小趋于0,以此来训练网络几乎不会有什 ...
- ssh密钥登录
一.生成密钥对(两种方式)并配置 方式1:使用ssh-keygen(1)生成并配置 (1)生成密钥对 [root@iZwz9catu2mrq92b07d1d0Z ~]# ssh-keygen -t r ...