V4L2文档翻译(十三)
来源:互联网 发布:去掉excel数据的阴影 编辑:程序博客网 时间:2024/05/18 01:19
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
此方法尚未定义。
- V4L2文档翻译(十三)
- V4L2文档翻译(一)
- V4L2文档翻译(二)
- V4L2文档翻译(三)
- V4L2文档翻译(四)
- V4L2文档翻译(五)
- V4L2文档翻译(六)
- V4L2文档翻译(七)
- V4L2文档翻译(八)
- V4L2文档翻译(九)
- V4L2文档翻译(十)
- V4L2文档翻译(十一)
- V4L2文档翻译(十二)
- V4L2文档翻译(一)
- V4L2文档翻译(二)
- V4L2文档翻译(三)
- V4L2文档翻译(四)
- V4L2文档翻译(六)
- 解决android.view.WindowManager$BadTokenException: Unable to add window -- token .
- hierarchyviewer不能用的解决办法
- CKEditor使用
- windows下mysql忘记root密码的解决方法
- 2014年4月操作系统份额:Windows XP仍然在26%以上,Linux微涨
- V4L2文档翻译(十三)
- Java中Map的三种遍历方法
- 了解更深度的挖掘网站内部数据
- 视差滚动原理及实现
- AFNetwork作用和用法详解
- 利用Smartmontools监控你的硬盘
- 2014年4月操作系统份额:Windows XP仍然在26%以上,Linux微涨
- 让memcached和mysql更好的工作
- codechef Johnny and the Beanstalk 题解