Commit 4b9c1cb6 authored by Tomasz Stanislawski's avatar Tomasz Stanislawski Committed by Mauro Carvalho Chehab

[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: default avatarTomasz Stanislawski <t.stanislaws@samsung.com>
Signed-off-by: default avatarKyungmin Park <kyungmin.park@samsung.com>
Acked-by: default avatarHans Verkuil <hans.verkuil@cisco.com>
Signed-off-by: default avatarMauro Carvalho Chehab <mchehab@redhat.com>
parent 051c7788
...@@ -2586,6 +2586,10 @@ ioctls.</para> ...@@ -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 ...@@ -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> ...@@ -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(&amp;reqbuf, 0, sizeof (reqbuf));
reqbuf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
reqbuf.memory = V4L2_MEMORY_DMABUF;
reqbuf.count = 1;
if (ioctl(fd, &VIDIOC-REQBUFS;, &amp;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(&amp;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;, &amp;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(&amp;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(&amp;planes, 0, sizeof planes);
for (i = 0; i &lt; n_planes; ++i)
buf.m.planes[i].m.fd = dmafd[i];
if (ioctl(v4lfd, &VIDIOC-QBUF;, &amp;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. ...@@ -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> ...@@ -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> ...@@ -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 @@ ...@@ -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 @@ ...@@ -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> ...@@ -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 ...@@ -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 @@ ...@@ -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 ...@@ -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>
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment