【Linux开发】IO streaming DMA buffer importing
http://linuxtv.org/downloads/v4l-dvb-apis/dmabuf.html
I/O流 (DMA缓存引用)
这是一个实验性接口,将来可能发生改变
DMABUF框架提供了在多设备见共享缓存的通用方法,支持DMABUF的设备驱动可以将一个DMA缓存以文件句柄的方式输出到用户空间(输出者规则),以文件句柄的方式从用户空间获取一个DMA缓存,这个文件句柄是之前其他或相同的设备所输出的(引入者规则),或都是。此章节描述在V4L2中DMABUF的引入者规则。
V4L2缓存以DMABUF文件句柄方式进行DMABUF输出。
支持I/O流方法的输入和输出设备在通过VIDIOC_QUERYCAP ioctl查询时,返回的struct v4l2_capability中capabilities成员会包含V4L2_CAP_STREAMING标签。是否支持通过DMABUF文件句柄引入DMABUF缓存决定了在调用VIDIOC_REQBUFS时内存类型是否要设定为V4L2_MEMORY_DMABUF。
这种I/O方法专用于在不同设备间共享DMA缓存,这些设备可以是V4L设备或是其他视频相关设备(如DRM)。缓存(面)通过应用程序控制驱动来申请。然后,这些缓存通过使用特殊API以文件句柄的方式输出给应用程序,交换的只有文件句柄。句柄和信息存在于struct v4l2_buffer(多平面API中是struct v4l2_plane)。在VIDIOC_REQBUFS ioctl执行后驱动必须切换到DMABUF I/O模式中。
例3.4 通过DMABUF文件句柄初始化I/O流
struct v4l2_requestbuffers reqbuf;
memset(&reqbuf, 0, sizeof (reqbuf));
reqbuf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
reqbuf.memory = V4L2_MEMORY_DMABUF;
reqbuf.count = 1;
if (ioctl(fd, VIDIOC_REQBUFS, &reqbuf) == -1) {
if (errno == EINVAL)
printf("Video capturing or DMABUF streaming is not supported\n");
else
perror("VIDIOC_REQBUFS");
exit(EXIT_FAILURE);
}
缓存(面)文件描述符通过VIDIOC_QBUF ioctl传输。在多平面中,每个面都申请了一个不同的DMABUF描述符,尽管缓存通常是循环的,应用程序也要每次通过不同的DMABUF描述符进行VIDIOC_QBUF请求处理。
例3.5 单一平面API中入列DMABUF
int buffer_queue(int v4lfd, int index, int dmafd)
{
struct v4l2_buffer buf;
memset(&buf, 0, sizeof buf);
buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
buf.memory = V4L2_MEMORY_DMABUF;
buf.index = index;
buf.m.fd = dmafd;
if (ioctl(v4lfd, VIDIOC_QBUF, &buf) == -1) {
perror("VIDIOC_QBUF");
return -1;
}
return 0;
}
例3.6 多平面API中入列DMABUF
int buffer_queue_mp(int v4lfd, int index, int dmafd[], int n_planes)
{
struct v4l2_buffer buf;
struct v4l2_plane planes[VIDEO_MAX_PLANES];
int i;
memset(&buf, 0, sizeof buf);
buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
buf.memory = V4L2_MEMORY_DMABUF;
buf.index = index;
buf.m.planes = planes;
buf.length = n_planes;
memset(&planes, 0, sizeof(planes));
for (i = 0; i < n_planes; ++i)
buf.m.planes[i].m.fd = dmafd[i];
if (ioctl(v4lfd, VIDIOC_QBUF, &buf) == -1) {
perror("VIDIOC_QBUF");
return -1;
}
return 0;
}
捕捉或显示缓存都通过VIDIOC_DQBUF ioctl进行出列操作。驱动在这个ioctl和DMA完成的期间可以在任何时候对缓存进行解锁。当VIDIOC_STREAMOFF或VIDIOC_REQBUFS调用,以及设备关闭的时候内存都会被解锁。
对于捕捉应用程序来说,在开始捕捉及进入读循环前通常要入列一定数量的空缓存。一旦已填充过的缓存可以出列,应用程序在其数据不再需要的时候会将此缓存重新入列。而输出程序对缓存进行填充和入列操作,当堆积了足够的缓存后输出就开始了,在写循环中,当程序没有空闲缓存可用了,它需要等待有可出列的空缓存然后对其重新利用。两种方法都会阻塞程序的执行直到有缓存可以出列为止。VIDIOC_DQBUF当输出序列中没有可用缓存时默认是阻塞的,若open()时带有O_NONBLOCK标签,在出现这种情况的时候VIDIOC_DQBUF会直接返回EAGAIN错误码。而select()和poll()函数一直都是有效的。
通过调用VIDIOC_STREAMON和VIDIOC_STREAMOFF ioctl可以开始及停止程序进行捕捉或输出,这里请注意,VIDIOC_STREAMOFF会将所有序列中的缓存都移除,并且解锁。因为在多任务系统中没有“当前”的概念,所以如果程序需要与其他事件进行同步,需要通过捕捉或输出缓存的struct v4l2_buffer中的timestamp成员进行。
声明了DMABUF流方法的驱动必须支持VIDIOC_REQBUFS,VIDIOC_QBUF,VIDIOC_DQBUF,VIDIOC_STREAMON,VIDIOC_STREAMOFF这些ioctl,以及select()和poll()函数。
同步I/O
此方法尚未定义。
Streaming I/O (DMA buffer importing)
The DMABUF framework provides a generic method for sharing buffers between multiple devices. Device drivers that support DMABUF can export a DMA buffer to userspace as a file descriptor (known as the exporter role),
import a DMA buffer from userspace using a file descriptor previously exported for a different or the same device (known as the importer role), or both. This section describes the DMABUF importer role API in V4L2.
Refer to DMABUF exporting for details about exporting V4L2 buffers as DMABUF file
descriptors.
Input and output devices support the streaming I/O method when the V4L2_CAP_STREAMING
flag in the capabilities
field
of struct v4l2_capability returned by the VIDIOC_QUERYCAP
ioctl
is set. Whether importing DMA buffers through DMABUF file descriptors is supported is determined by calling the VIDIOC_REQBUFS
ioctl
with the memory type set to V4L2_MEMORY_DMABUF
.
This I/O method is dedicated to sharing DMA buffers between different devices, which may be V4L devices or other video-related devices (e.g. DRM). Buffers (planes) are allocated by a driver on behalf of an application.
Next, these buffers are exported to the application as file descriptors using an API which is specific for an allocator driver. Only such file descriptor are exchanged. The descriptors and meta-information are passed in struct v4l2_buffer (or
in struct v4l2_plane in the multi-planar API case). The driver must be switched into DMABUF I/O mode by calling
the VIDIOC_REQBUFS
with the desired buffer type.
Example 3.4. Initiating streaming I/O with DMABUF file descriptors
struct v4l2_requestbuffers reqbuf; memset(&reqbuf, 0, sizeof (reqbuf));
reqbuf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
reqbuf.memory = V4L2_MEMORY_DMABUF;
reqbuf.count = 1; if (ioctl(fd,VIDIOC_REQBUFS
, &reqbuf) == -1) {
if (errno == EINVAL)
printf("Video capturing or DMABUF streaming is not supported\n");
else
perror("VIDIOC_REQBUFS"); exit(EXIT_FAILURE);
}
The buffer (plane) file descriptor is passed on the fly with the VIDIOC_QBUF
ioctl.
In case of multiplanar buffers, every plane can be associated with a different DMABUF descriptor. Although buffers are commonly cycled, applications can pass a different DMABUF descriptor at each VIDIOC_QBUF
call.
Example 3.5. Queueing DMABUF using single plane API
int buffer_queue(int v4lfd, int index, int dmafd)
{
struct v4l2_buffer buf; memset(&buf, 0, sizeof buf);
buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
buf.memory = V4L2_MEMORY_DMABUF;
buf.index = index;
buf.m.fd = dmafd; if (ioctl(v4lfd,VIDIOC_QBUF
, &buf) == -1) {
perror("VIDIOC_QBUF");
return -1;
} return 0;
}
Example 3.6. Queueing DMABUF using multi plane API
int buffer_queue_mp(int v4lfd, int index, int dmafd[], int n_planes)
{
struct v4l2_buffer buf;
struct v4l2_plane planes[VIDEO_MAX_PLANES];
int i; memset(&buf, 0, sizeof buf);
buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
buf.memory = V4L2_MEMORY_DMABUF;
buf.index = index;
buf.m.planes = planes;
buf.length = n_planes; memset(&planes, 0, sizeof planes); for (i = 0; i < n_planes; ++i)
buf.m.planes[i].m.fd = dmafd[i]; if (ioctl(v4lfd,VIDIOC_QBUF
, &buf) == -1) {
perror("VIDIOC_QBUF");
return -1;
} return 0;
}
Captured or displayed buffers are dequeued with the VIDIOC_DQBUF
ioctl.
The driver can unlock the buffer at any time between the completion of the DMA and this ioctl. The memory is also unlocked when VIDIOC_STREAMOFF
is
called, VIDIOC_REQBUFS
, or when the device is closed.
For capturing applications it is customary to enqueue a number of empty buffers, to start capturing and enter the read loop. Here the application waits until a filled buffer can be dequeued, and re-enqueues the
buffer when the data is no longer needed. Output applications fill and enqueue buffers, when enough buffers are stacked up output is started. In the write loop, when the application runs out of free buffers it must wait until an empty buffer can be dequeued
and reused. Two methods exist to suspend execution of the application until one or more buffers can be dequeued. By default VIDIOC_DQBUF
blocks when no buffer is in the outgoing queue. When the O_NONBLOCK
flag
was given to the open()
function, VIDIOC_DQBUF
returns immediately with an EAGAIN error
code when no buffer is available. The select()
and poll()
functions
are always available.
To start and stop capturing or displaying applications call the VIDIOC_STREAMON
and VIDIOC_STREAMOFF
ioctls.
Note that VIDIOC_STREAMOFF
removes all buffers from both queues and unlocks all buffers as a side effect. Since there is no notion of doing anything "now" on a multitasking system, if an application needs to synchronize with another
event it should examine the struct v4l2_buffer timestamp
of
captured or outputted buffers.
Drivers implementing DMABUF importing I/O must support the VIDIOC_REQBUFS
, VIDIOC_QBUF
, VIDIOC_DQBUF
, VIDIOC_STREAMON
and VIDIOC_STREAMOFF
ioctls,
and the select()
and poll()
functions
【Linux开发】IO streaming DMA buffer importing的更多相关文章
- 【linux开发】IO端口和IO内存的区别及分别使用的函数接口
IO端口和IO内存的区别及分别使用的函数接口 每个外设都是通过读写其寄存器来控制的.外设寄存器也称为I/O端口,通常包括:控制寄存器.状态寄存器和数据寄存器三大类.根据访问外设寄存器的不同方式,可以把 ...
- Linux非阻塞IO(三)非阻塞IO中缓冲区Buffer的实现
本文我们来实现回射服务器的Buffer. Buffer的实现 上节提到了非阻塞IO必须具备Buffer.再次将Buffer的设计描述一下: 这里必须补充一点,writeIndex指向空闲空间的 ...
- 转 漫谈linux文件IO
在Linux 开发中,有几个关系到性能的东西,技术人员非常关注:进程,CPU,MEM,网络IO,磁盘IO.本篇文件打算详细全面,深入浅出.剖析文件IO的细节.从多个角度探索如何提高IO性能.本文尽量用 ...
- 漫谈linux文件IO
在Linux 开发中,有几个关系到性能的东西,技术人员非常关注:进程,CPU,MEM,网络IO,磁盘IO.本篇文件打算详细全面,深入浅出.剖析文件IO的细节.从多个角度探索如何提高IO性能.本文尽量用 ...
- <摘录>linux文件IO
这篇文章写的比较全面,也浅显易懂,备份下.转载自:http://blog.chinaunix.net/uid-27105712-id-3270102.html 在Linux 开发中,有几个关系到性能的 ...
- Linux就这个范儿 第15章 七种武器 linux 同步IO: sync、fsync与fdatasync Linux中的内存大页面huge page/large page David Cutler Linux读写内存数据的三种方式
Linux就这个范儿 第15章 七种武器 linux 同步IO: sync.fsync与fdatasync Linux中的内存大页面huge page/large page David Cut ...
- linux标准io的copy
---恢复内容开始--- 1.linux标准io的copy #include<stdio.h> int main(int argc,char **argv) { if(argc<3) ...
- 嵌入式Linux开发板
嵌入式Linux开发板开发介绍: iTOP-4412嵌入式Linux开发板搭载三星Exynos四核处理器,配备1GB内存,4GB固态硬盘EMMC存储,独家配备三星S5M8767电源管理,配备Andro ...
- Linux Network IO Model、Socket IO Model - select、poll、epoll
目录 . 引言 . IO机制简介 . 阻塞式IO模型(blocking IO model) . 非阻塞式IO模型(noblocking IO model) . IO复用式IO模型(IO multipl ...
随机推荐
- Lengauer-Tarjan算法的相关证明
Lengauer-Tarjan算法的相关证明 0. 约定 为简单起见,下文中的路径均指简单路径(事实上非简单路径不会对结论造成影响). \(V\)代表图的点集,\(E\)代表图的边集,\(T\)代表图 ...
- hashmap分解大法--tableSizeFor方法
tableSizeFor方法 /** * 根据容量参数,返回一个2的n次幂的table长度. */ private static final int tableSizeFor(int c) { int ...
- urllib详细版
urllib是python内置的处理HTTP请求的库,主要包含以下四个模块 request 模块,是最基本的处理HTTP请求的模块. error 异常处理模块,如果出现请求错误,可以捕获这些错误,保证 ...
- jmeter测试文件上传功能
最近为了完成自动化KPI开始慢慢接触jmeter,其中遇到了不少问题,今天就遇到了文件上传的问题,在这里记录下加深记忆,也可供jmeter初级使用者作为一个参考.另外论坛上已有同事发过关于jmeter ...
- vue3作业
""" 1.按照上方 知识点总结 模块,总结今天所学知识点: 2.有以下广告数据(实际数据命名可以略做调整) ad_data = { tv: [ {img: 'img/t ...
- 【java】并发执行ExecutorService的sumbit返回值的顺序问题
ArrayList<Future> fl = new ArrayList<Future>(); for (int i = 0; i < 10; i++) { Future ...
- Java面试题系列(六)优化tomcat配置
序言 资料 如何优化tomcat配置(从内存.并发.缓存3个方面)优化
- 文件操作:rewind()
函数名: rewind() 功 能: 将文件内部的位置指针重新指向一个流(数据流/文件)的开头 注意:不是文件指针而是文件内部的位置指针,随着对文件的读写文件的位置指针(指向当前读写字节)向后移动 ...
- CSV文件在Python中的几种处理方式
Comma Separated Values,简称CSV,它是一种以逗号分隔数值的文件类型.在数据库或电子表格中,它是最常见的导入导出格式,它以一种简单而明了的方式存储和共享数据,CSV文件通常以纯文 ...
- [BZOJ4695]最假女选手:segment tree beats!
分析 segment tree beats!模板题. 看了gxz的博客突然发现自己写的mxbt和mnbt两个标记没用诶. 代码 #include <bits/stdc++.h> #defi ...