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_REQBUFSVIDIOC_QBUFVIDIOC_DQBUFVIDIOC_STREAMON and VIDIOC_STREAMOFF ioctls,
and the select() and poll() functions

【Linux开发】IO streaming DMA buffer importing的更多相关文章

  1. 【linux开发】IO端口和IO内存的区别及分别使用的函数接口

    IO端口和IO内存的区别及分别使用的函数接口 每个外设都是通过读写其寄存器来控制的.外设寄存器也称为I/O端口,通常包括:控制寄存器.状态寄存器和数据寄存器三大类.根据访问外设寄存器的不同方式,可以把 ...

  2. Linux非阻塞IO(三)非阻塞IO中缓冲区Buffer的实现

    本文我们来实现回射服务器的Buffer.   Buffer的实现   上节提到了非阻塞IO必须具备Buffer.再次将Buffer的设计描述一下: 这里必须补充一点,writeIndex指向空闲空间的 ...

  3. 转 漫谈linux文件IO

    在Linux 开发中,有几个关系到性能的东西,技术人员非常关注:进程,CPU,MEM,网络IO,磁盘IO.本篇文件打算详细全面,深入浅出.剖析文件IO的细节.从多个角度探索如何提高IO性能.本文尽量用 ...

  4. 漫谈linux文件IO

    在Linux 开发中,有几个关系到性能的东西,技术人员非常关注:进程,CPU,MEM,网络IO,磁盘IO.本篇文件打算详细全面,深入浅出.剖析文件IO的细节.从多个角度探索如何提高IO性能.本文尽量用 ...

  5. <摘录>linux文件IO

    这篇文章写的比较全面,也浅显易懂,备份下.转载自:http://blog.chinaunix.net/uid-27105712-id-3270102.html 在Linux 开发中,有几个关系到性能的 ...

  6. 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 ...

  7. linux标准io的copy

    ---恢复内容开始--- 1.linux标准io的copy #include<stdio.h> int main(int argc,char **argv) { if(argc<3) ...

  8. 嵌入式Linux开发板

    嵌入式Linux开发板开发介绍: iTOP-4412嵌入式Linux开发板搭载三星Exynos四核处理器,配备1GB内存,4GB固态硬盘EMMC存储,独家配备三星S5M8767电源管理,配备Andro ...

  9. Linux Network IO Model、Socket IO Model - select、poll、epoll

    目录 . 引言 . IO机制简介 . 阻塞式IO模型(blocking IO model) . 非阻塞式IO模型(noblocking IO model) . IO复用式IO模型(IO multipl ...

随机推荐

  1. node模块管理

    淘宝镜像:npm install -g cnpm --registry=https://registry.npm.taobao.org

  2. 安装mysql的步骤并利用mysql原始密码修改自定义密码

    1.给刚下载好的mysql软件tar包,进行解包 命令:tar -xf mysql-5.7.26-1.el7.x86_64.rpm-bundle.tar 然后利用yum装包 命令:yum -y ins ...

  3. Java 指令重排

    Java 指令重排 java 指令重排 package com.feshfans; /** * 用来演示指令重排 * 指令重排会发生在两个阶段: * 1. 编译期(jvm 加载字节码时) * 2. c ...

  4. 两种常用的数据交换格式:XML和JSON

    不同编程语言之间的数据传输,需要一种通用的数据交换格式,它需要简洁.易于数据储存.快速读取,且独立于各种编程语言.我们往往传输的是文本文件,比如我们都知道的csv(comma seperated va ...

  5. 【NOIP2016提高A组模拟9.17】序列

    题目 分析 首先用\(a_i\)表示达到目标的步数\(B_i-A_i(mod 4)\) 根据粉刷栅栏,先不管mod 4的情况,答案就是\(\sum\max(a_i-a_{i+1},0)\) 那我们刚才 ...

  6. html caption标签 语法

    html caption标签 语法 caption是什么标签? 作用:定义表格标题. 说明:caption 标签必须紧随 table 标签之后.您只能对每个表格定义一个标题.通常这个标题会被居中于表格 ...

  7. JPA学习(六、JPA_JPQL)

    框架学习之JPA(六) JPA是Java Persistence API的简称,中文名Java持久层API,是JDK 5.0注解或XML描述对象-关系表的映射关系,并将运行期的实体对象持久化到数据库中 ...

  8. Oracle报Ora01522

    应用服务报错截图 数据库后台日志报错截图 从日志分析应该是回滚异常造成表空间无法使用回滚段,而回滚涉及的表空间为undo表空间 尝试新建UNDO表空间,再将UNDO_TABLESPACE切换到新建的U ...

  9. vue key的作用

    key的作用是什么? 简单来说: key是给每一个vnode的唯一id,可以依靠key,更准确, 更快的拿到oldVnode中对应的vnode节点. 1. 更准确 因为带key就不是就地复用了,在sa ...

  10. 【每日一包0007】array-range

    [github地址:https://github.com/ABCDdouyae...] array-range 生成一个指定起始位置的固定长度的数组 用法:array-range(start, end ...