[media] Documentation: media: description of DMABUF importing in V4L2
This patch adds description and usage examples for importing DMABUF file descriptor in V4L2. Signed-off-by: Tomasz Stanislawski <t.stanislaws@samsung.com> Signed-off-by: Kyungmin Park <kyungmin.park@samsung.com> Acked-by: Hans Verkuil <hans.verkuil@cisco.com> Signed-off-by: Mauro Carvalho Chehab <mchehab@redhat.com>
This commit is contained in:
Родитель
051c7788bc
Коммит
4b9c1cb641
|
@ -2586,6 +2586,10 @@ ioctls.</para>
|
||||||
<para>Vendor and device specific media bus pixel formats.
|
<para>Vendor and device specific media bus pixel formats.
|
||||||
<xref linkend="v4l2-mbus-vendor-spec-fmts" />.</para>
|
<xref linkend="v4l2-mbus-vendor-spec-fmts" />.</para>
|
||||||
</listitem>
|
</listitem>
|
||||||
|
<listitem>
|
||||||
|
<para>Importing DMABUF file descriptors as a new IO method described
|
||||||
|
in <xref linkend="dmabuf" />.</para>
|
||||||
|
</listitem>
|
||||||
</itemizedlist>
|
</itemizedlist>
|
||||||
</section>
|
</section>
|
||||||
|
|
||||||
|
|
|
@ -331,7 +331,7 @@ application until one or more buffers can be dequeued. By default
|
||||||
outgoing queue. When the <constant>O_NONBLOCK</constant> flag was
|
outgoing queue. When the <constant>O_NONBLOCK</constant> flag was
|
||||||
given to the &func-open; function, <constant>VIDIOC_DQBUF</constant>
|
given to the &func-open; function, <constant>VIDIOC_DQBUF</constant>
|
||||||
returns immediately with an &EAGAIN; when no buffer is available. The
|
returns immediately with an &EAGAIN; when no buffer is available. The
|
||||||
&func-select; or &func-poll; function are always available.</para>
|
&func-select; or &func-poll; functions are always available.</para>
|
||||||
|
|
||||||
<para>To start and stop capturing or output applications call the
|
<para>To start and stop capturing or output applications call the
|
||||||
&VIDIOC-STREAMON; and &VIDIOC-STREAMOFF; ioctl. Note
|
&VIDIOC-STREAMON; and &VIDIOC-STREAMOFF; ioctl. Note
|
||||||
|
@ -472,6 +472,162 @@ rest should be evident.</para>
|
||||||
</footnote></para>
|
</footnote></para>
|
||||||
</section>
|
</section>
|
||||||
|
|
||||||
|
<section id="dmabuf">
|
||||||
|
<title>Streaming I/O (DMA buffer importing)</title>
|
||||||
|
|
||||||
|
<note>
|
||||||
|
<title>Experimental</title>
|
||||||
|
<para>This is an <link linkend="experimental"> experimental </link>
|
||||||
|
interface and may change in the future.</para>
|
||||||
|
</note>
|
||||||
|
|
||||||
|
<para>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.</para>
|
||||||
|
|
||||||
|
<para>Input and output devices support the streaming I/O method when the
|
||||||
|
<constant>V4L2_CAP_STREAMING</constant> flag in the
|
||||||
|
<structfield>capabilities</structfield> field of &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
|
||||||
|
<constant>V4L2_MEMORY_DMABUF</constant>.</para>
|
||||||
|
|
||||||
|
<para>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 &v4l2-buffer; (or
|
||||||
|
in &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.</para>
|
||||||
|
|
||||||
|
<example>
|
||||||
|
<title>Initiating streaming I/O with DMABUF file descriptors</title>
|
||||||
|
|
||||||
|
<programlisting>
|
||||||
|
&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);
|
||||||
|
}
|
||||||
|
</programlisting>
|
||||||
|
</example>
|
||||||
|
|
||||||
|
<para>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
|
||||||
|
<constant>VIDIOC_QBUF</constant> call.</para>
|
||||||
|
|
||||||
|
<example>
|
||||||
|
<title>Queueing DMABUF using single plane API</title>
|
||||||
|
|
||||||
|
<programlisting>
|
||||||
|
int buffer_queue(int v4lfd, int index, int dmafd)
|
||||||
|
{
|
||||||
|
&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;
|
||||||
|
}
|
||||||
|
</programlisting>
|
||||||
|
</example>
|
||||||
|
|
||||||
|
<example>
|
||||||
|
<title>Queueing DMABUF using multi plane API</title>
|
||||||
|
|
||||||
|
<programlisting>
|
||||||
|
int buffer_queue_mp(int v4lfd, int index, int dmafd[], int n_planes)
|
||||||
|
{
|
||||||
|
&v4l2-buffer; buf;
|
||||||
|
&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;
|
||||||
|
}
|
||||||
|
</programlisting>
|
||||||
|
</example>
|
||||||
|
|
||||||
|
<para>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.</para>
|
||||||
|
|
||||||
|
<para>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
|
||||||
|
<constant>VIDIOC_DQBUF</constant> blocks when no buffer is in the
|
||||||
|
outgoing queue. When the <constant>O_NONBLOCK</constant> flag was
|
||||||
|
given to the &func-open; function, <constant>VIDIOC_DQBUF</constant>
|
||||||
|
returns immediately with an &EAGAIN; when no buffer is available. The
|
||||||
|
&func-select; and &func-poll; functions are always available.</para>
|
||||||
|
|
||||||
|
<para>To start and stop capturing or displaying applications call the
|
||||||
|
&VIDIOC-STREAMON; and &VIDIOC-STREAMOFF; ioctls. Note that
|
||||||
|
<constant>VIDIOC_STREAMOFF</constant> 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 &v4l2-buffer;
|
||||||
|
<structfield>timestamp</structfield> of captured buffers, or set the field
|
||||||
|
before enqueuing buffers for output.</para>
|
||||||
|
|
||||||
|
<para>Drivers implementing DMABUF importing I/O must support the
|
||||||
|
<constant>VIDIOC_REQBUFS</constant>, <constant>VIDIOC_QBUF</constant>,
|
||||||
|
<constant>VIDIOC_DQBUF</constant>, <constant>VIDIOC_STREAMON</constant> and
|
||||||
|
<constant>VIDIOC_STREAMOFF</constant> ioctls, and the
|
||||||
|
<function>select()</function> and <function>poll()</function> functions.</para>
|
||||||
|
|
||||||
|
</section>
|
||||||
|
|
||||||
<section id="async">
|
<section id="async">
|
||||||
<title>Asynchronous I/O</title>
|
<title>Asynchronous I/O</title>
|
||||||
|
|
||||||
|
@ -672,6 +828,14 @@ memory, set by the application. See <xref linkend="userp" /> for details.
|
||||||
in the <structfield>length</structfield> field of this
|
in the <structfield>length</structfield> field of this
|
||||||
<structname>v4l2_buffer</structname> structure.</entry>
|
<structname>v4l2_buffer</structname> structure.</entry>
|
||||||
</row>
|
</row>
|
||||||
|
<row>
|
||||||
|
<entry></entry>
|
||||||
|
<entry>int</entry>
|
||||||
|
<entry><structfield>fd</structfield></entry>
|
||||||
|
<entry>For the single-plane API and when
|
||||||
|
<structfield>memory</structfield> is <constant>V4L2_MEMORY_DMABUF</constant> this
|
||||||
|
is the file descriptor associated with a DMABUF buffer.</entry>
|
||||||
|
</row>
|
||||||
<row>
|
<row>
|
||||||
<entry>__u32</entry>
|
<entry>__u32</entry>
|
||||||
<entry><structfield>length</structfield></entry>
|
<entry><structfield>length</structfield></entry>
|
||||||
|
@ -743,6 +907,15 @@ should set this to 0.</entry>
|
||||||
pointer to the memory allocated for this plane by an application.
|
pointer to the memory allocated for this plane by an application.
|
||||||
</entry>
|
</entry>
|
||||||
</row>
|
</row>
|
||||||
|
<row>
|
||||||
|
<entry></entry>
|
||||||
|
<entry>int</entry>
|
||||||
|
<entry><structfield>fd</structfield></entry>
|
||||||
|
<entry>When the memory type in the containing &v4l2-buffer; is
|
||||||
|
<constant>V4L2_MEMORY_DMABUF</constant>, this is a file
|
||||||
|
descriptor associated with a DMABUF buffer, similar to the
|
||||||
|
<structfield>fd</structfield> field in &v4l2-buffer;.</entry>
|
||||||
|
</row>
|
||||||
<row>
|
<row>
|
||||||
<entry>__u32</entry>
|
<entry>__u32</entry>
|
||||||
<entry><structfield>data_offset</structfield></entry>
|
<entry><structfield>data_offset</structfield></entry>
|
||||||
|
@ -964,6 +1137,12 @@ pointer</link> I/O.</entry>
|
||||||
<entry>3</entry>
|
<entry>3</entry>
|
||||||
<entry>[to do]</entry>
|
<entry>[to do]</entry>
|
||||||
</row>
|
</row>
|
||||||
|
<row>
|
||||||
|
<entry><constant>V4L2_MEMORY_DMABUF</constant></entry>
|
||||||
|
<entry>4</entry>
|
||||||
|
<entry>The buffer is used for <link linkend="dmabuf">DMA shared
|
||||||
|
buffer</link> I/O.</entry>
|
||||||
|
</row>
|
||||||
</tbody>
|
</tbody>
|
||||||
</tgroup>
|
</tgroup>
|
||||||
</table>
|
</table>
|
||||||
|
|
|
@ -6,7 +6,8 @@
|
||||||
|
|
||||||
<refnamediv>
|
<refnamediv>
|
||||||
<refname>VIDIOC_CREATE_BUFS</refname>
|
<refname>VIDIOC_CREATE_BUFS</refname>
|
||||||
<refpurpose>Create buffers for Memory Mapped or User Pointer I/O</refpurpose>
|
<refpurpose>Create buffers for Memory Mapped or User Pointer or DMA Buffer
|
||||||
|
I/O</refpurpose>
|
||||||
</refnamediv>
|
</refnamediv>
|
||||||
|
|
||||||
<refsynopsisdiv>
|
<refsynopsisdiv>
|
||||||
|
@ -55,11 +56,11 @@
|
||||||
</note>
|
</note>
|
||||||
|
|
||||||
<para>This ioctl is used to create buffers for <link linkend="mmap">memory
|
<para>This ioctl is used to create buffers for <link linkend="mmap">memory
|
||||||
mapped</link> or <link linkend="userp">user pointer</link>
|
mapped</link> or <link linkend="userp">user pointer</link> or <link
|
||||||
I/O. It can be used as an alternative or in addition to the
|
linkend="dmabuf">DMA buffer</link> I/O. It can be used as an alternative or in
|
||||||
<constant>VIDIOC_REQBUFS</constant> ioctl, when a tighter control over buffers
|
addition to the <constant>VIDIOC_REQBUFS</constant> ioctl, when a tighter
|
||||||
is required. This ioctl can be called multiple times to create buffers of
|
control over buffers is required. This ioctl can be called multiple times to
|
||||||
different sizes.</para>
|
create buffers of different sizes.</para>
|
||||||
|
|
||||||
<para>To allocate device buffers applications initialize relevant fields of
|
<para>To allocate device buffers applications initialize relevant fields of
|
||||||
the <structname>v4l2_create_buffers</structname> structure. They set the
|
the <structname>v4l2_create_buffers</structname> structure. They set the
|
||||||
|
@ -109,7 +110,8 @@ information.</para>
|
||||||
<entry>__u32</entry>
|
<entry>__u32</entry>
|
||||||
<entry><structfield>memory</structfield></entry>
|
<entry><structfield>memory</structfield></entry>
|
||||||
<entry>Applications set this field to
|
<entry>Applications set this field to
|
||||||
<constant>V4L2_MEMORY_MMAP</constant> or
|
<constant>V4L2_MEMORY_MMAP</constant>,
|
||||||
|
<constant>V4L2_MEMORY_DMABUF</constant> or
|
||||||
<constant>V4L2_MEMORY_USERPTR</constant>. See <xref linkend="v4l2-memory"
|
<constant>V4L2_MEMORY_USERPTR</constant>. See <xref linkend="v4l2-memory"
|
||||||
/></entry>
|
/></entry>
|
||||||
</row>
|
</row>
|
||||||
|
|
|
@ -109,6 +109,23 @@ they cannot be swapped out to disk. Buffers remain locked until
|
||||||
dequeued, until the &VIDIOC-STREAMOFF; or &VIDIOC-REQBUFS; ioctl is
|
dequeued, until the &VIDIOC-STREAMOFF; or &VIDIOC-REQBUFS; ioctl is
|
||||||
called, or until the device is closed.</para>
|
called, or until the device is closed.</para>
|
||||||
|
|
||||||
|
<para>To enqueue a <link linkend="dmabuf">DMABUF</link> buffer applications
|
||||||
|
set the <structfield>memory</structfield> field to
|
||||||
|
<constant>V4L2_MEMORY_DMABUF</constant> and the <structfield>m.fd</structfield>
|
||||||
|
field to a file descriptor associated with a DMABUF buffer. When the
|
||||||
|
multi-planar API is used the <structfield>m.fd</structfield> fields of the
|
||||||
|
passed array of &v4l2-plane; have to be used instead. When
|
||||||
|
<constant>VIDIOC_QBUF</constant> is called with a pointer to this structure the
|
||||||
|
driver sets the <constant>V4L2_BUF_FLAG_QUEUED</constant> flag and clears the
|
||||||
|
<constant>V4L2_BUF_FLAG_MAPPED</constant> and
|
||||||
|
<constant>V4L2_BUF_FLAG_DONE</constant> flags in the
|
||||||
|
<structfield>flags</structfield> field, or it returns an error code. This
|
||||||
|
ioctl locks the buffer. Locking a buffer means passing it to a driver for a
|
||||||
|
hardware access (usually DMA). If an application accesses (reads/writes) a
|
||||||
|
locked buffer then the result is undefined. Buffers remain locked until
|
||||||
|
dequeued, until the &VIDIOC-STREAMOFF; or &VIDIOC-REQBUFS; ioctl is called, or
|
||||||
|
until the device is closed.</para>
|
||||||
|
|
||||||
<para>Applications call the <constant>VIDIOC_DQBUF</constant>
|
<para>Applications call the <constant>VIDIOC_DQBUF</constant>
|
||||||
ioctl to dequeue a filled (capturing) or displayed (output) buffer
|
ioctl to dequeue a filled (capturing) or displayed (output) buffer
|
||||||
from the driver's outgoing queue. They just set the
|
from the driver's outgoing queue. They just set the
|
||||||
|
|
|
@ -48,28 +48,30 @@
|
||||||
<refsect1>
|
<refsect1>
|
||||||
<title>Description</title>
|
<title>Description</title>
|
||||||
|
|
||||||
<para>This ioctl is used to initiate <link linkend="mmap">memory
|
<para>This ioctl is used to initiate <link linkend="mmap">memory mapped</link>,
|
||||||
mapped</link> or <link linkend="userp">user pointer</link>
|
<link linkend="userp">user pointer</link> or <link
|
||||||
I/O. Memory mapped buffers are located in device memory and must be
|
linkend="dmabuf">DMABUF</link> based I/O. Memory mapped buffers are located in
|
||||||
allocated with this ioctl before they can be mapped into the
|
device memory and must be allocated with this ioctl before they can be mapped
|
||||||
application's address space. User buffers are allocated by
|
into the application's address space. User buffers are allocated by
|
||||||
applications themselves, and this ioctl is merely used to switch the
|
applications themselves, and this ioctl is merely used to switch the driver
|
||||||
driver into user pointer I/O mode and to setup some internal structures.</para>
|
into user pointer I/O mode and to setup some internal structures.
|
||||||
|
Similarly, DMABUF buffers are allocated by applications through a device
|
||||||
|
driver, and this ioctl only configures the driver into DMABUF I/O mode without
|
||||||
|
performing any direct allocation.</para>
|
||||||
|
|
||||||
<para>To allocate device buffers applications initialize all
|
<para>To allocate device buffers applications initialize all fields of the
|
||||||
fields of the <structname>v4l2_requestbuffers</structname> structure.
|
<structname>v4l2_requestbuffers</structname> structure. They set the
|
||||||
They set the <structfield>type</structfield> field to the respective
|
<structfield>type</structfield> field to the respective stream or buffer type,
|
||||||
stream or buffer type, the <structfield>count</structfield> field to
|
the <structfield>count</structfield> field to the desired number of buffers,
|
||||||
the desired number of buffers, <structfield>memory</structfield>
|
<structfield>memory</structfield> must be set to the requested I/O method and
|
||||||
must be set to the requested I/O method and the <structfield>reserved</structfield> array
|
the <structfield>reserved</structfield> array must be zeroed. When the ioctl is
|
||||||
must be zeroed. When the ioctl
|
called with a pointer to this structure the driver will attempt to allocate the
|
||||||
is called with a pointer to this structure the driver will attempt to allocate
|
requested number of buffers and it stores the actual number allocated in the
|
||||||
the requested number of buffers and it stores the actual number
|
<structfield>count</structfield> field. It can be smaller than the number
|
||||||
allocated in the <structfield>count</structfield> field. It can be
|
requested, even zero, when the driver runs out of free memory. A larger number
|
||||||
smaller than the number requested, even zero, when the driver runs out
|
is also possible when the driver requires more buffers to function correctly.
|
||||||
of free memory. A larger number is also possible when the driver requires
|
For example video output requires at least two buffers, one displayed and one
|
||||||
more buffers to function correctly. For example video output requires at least two buffers,
|
filled by the application.</para>
|
||||||
one displayed and one filled by the application.</para>
|
|
||||||
<para>When the I/O method is not supported the ioctl
|
<para>When the I/O method is not supported the ioctl
|
||||||
returns an &EINVAL;.</para>
|
returns an &EINVAL;.</para>
|
||||||
|
|
||||||
|
@ -102,7 +104,8 @@ as the &v4l2-format; <structfield>type</structfield> field. See <xref
|
||||||
<entry>__u32</entry>
|
<entry>__u32</entry>
|
||||||
<entry><structfield>memory</structfield></entry>
|
<entry><structfield>memory</structfield></entry>
|
||||||
<entry>Applications set this field to
|
<entry>Applications set this field to
|
||||||
<constant>V4L2_MEMORY_MMAP</constant> or
|
<constant>V4L2_MEMORY_MMAP</constant>,
|
||||||
|
<constant>V4L2_MEMORY_DMABUF</constant> or
|
||||||
<constant>V4L2_MEMORY_USERPTR</constant>. See <xref linkend="v4l2-memory"
|
<constant>V4L2_MEMORY_USERPTR</constant>. See <xref linkend="v4l2-memory"
|
||||||
/>.</entry>
|
/>.</entry>
|
||||||
</row>
|
</row>
|
||||||
|
|
Загрузка…
Ссылка в новой задаче