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再次放入输入队列中去。

时间: 2024-08-20 07:01:08

Linux下实现视频读取(三)---Buffer的准备和数据读取的相关文章

linux下查看uuid的三种方法及使用uuid的作用

查看设备的uuid的三种方法,总结如下: 1 命令查看:blkid2 文件查看:ls -l /dev/disk/by-uuid3 命令查看:vol_id /dev/sda1 UUID的作用及意义 1:它是真正的唯一标志符 UUID为系统中的存储设备提供唯一的标识字符串,不管这个设备是什么类型的.如果你在系统中启动的时候,使用盘符挂载时,可能找不到设备而加载失败,而使用UUID挂载时,则不会有这样的问题. 2:设备名并非总是不变的 自动分配的设备名称并非总是一致的,它们依赖于启动时内核加载模块的顺

Linux下实现视频读取

V4L(video4linux是一些视频系统,视频软件.音频软件的基础,经常时候在需要采集图像的场合,如视频监控,webcam,可视电话,经常使用在embedded linux中是linux嵌入式开发中经常使用的系统接口.它是linux内核提供给用户空间的编程接口,各种的视频和音频设备开发相应的驱动程序后,就可以通过v4l提供的系统API来控制视频和音频设备,也就是说v4l分为两层,底层为音视频设备在内核中的驱动,上层为系统提供的API,而对于我们来说需要的就是使用这些系统API. V4L2是V

Linux下的视频字幕编辑

一.Linux下的字幕编辑软件 常用的有subtitleeditor, gnome-subtitles, gaupol 1.gnome-subtitles:不支持多字幕文件批量处理2.gaupol:全英文界面3.subtitleeditor:功能和gnome-subtitles.gaupol差不多,但支持批量处理,界面中文 二.常见视频和字幕不同步原因 网上下载的字幕和视频由于有时来源不一样,造成字幕和音频不同步.常见不同步的原因一般有两个:1.视频桢率(FPS)和字幕桢率(FPS)不一致:例如

Linux下基础命令(三)

本次发这篇博客比较晚,晚上快12点才发的,到今天一直没有,所以又发了一遍,这个篇文章主要有重定向和管道 | tee  find 等实战操作,还有一些命令参数详解等. 重定向及管道 linux下一切皆文件.文件又可分为:普通文件.目录文件.链接文件和设备文件 Linux系统中使用文件来描述各种硬件,设备资源等 例如:硬盘和分区,光盘等设备文件 brw-rw----+ 1 root cdrom    11,   0 6月  24 16:53 sr0 重定向的含义 文件描述符定义: 是内核为了高效管理

嵌入式Linux下MP4视频录制库MP4V2移植和简介

*************************************************************************************************************************** 作者:EasyWave                                                                             时间:2014.10.31 类别:Linux应用-MP4视频录制库MP4V2

嵌入式Linux下MP4视频录制库MP4V2移植和简单介绍

*************************************************************************************************************************** 作者:EasyWave                                                                             时间:2014.10.31 类别:Linux应用-MP4视频录制库MP4V2

Linux下的文件有三个“时间”

实例 先拿实际操作举例. 下面的实例中,关注code.tgz即可(红色的) 可以无视那个 code 下面一张截图是我在 code 目录下,分别执行 ls -l ls -lc ls -lu 后的运行结果: 可以看到,系统分别打印出了3个不同的时间. 接下来改名,执行 mv code.tgz code1.tgz ls -l ls -lc ls -lu 运行结果如下: 可以看出 对文件改名后, -l 出来的结果发生了改变(更新了时间) 接下来访问,执行 vim code1.tgz (进入vim后,退出

4.windows和Linux下创建oracleusername表空间,表,插入数据,用户管理表等操作

进入超级管理员,运行下面命令 Window下创建数据库.表空间,用户,插入数据等操作 -- 01 创建表空间 -- 注意表空间的路径 依据实际安装环境进行调整 CREATE TABLESPACE ts_myscott LOGGING DATAFILE 'F:/app/to-to/oradata/orcl/ts_myscott.dbf' SIZE 10M EXTENT MANAGEMENT LOCAL; CREATE TABLESPACE ts_myscott2 LOGGING DATAFILE

Linux下实现视频读取(二)---camera参数设定

Camera的可设置项极多,V4L2 支持了不少.但Sam之前对这些设置的用法和涵义都是在看videodev2.h中边看边理解,感觉非常生涩.直到写这篇blog时,才发现v4l2有专门的SPEC来说明: http://www.linuxtv.org/downloads/legacy/video4linux/API/V4L2_API/spec-single/v4l2.html 但也基本没有时间仔细看了.先把自己看头文件看出的一些东西记录在这里吧.以实际设置过程为顺序谈谈V4L2 设置. 1. 查询