[PATCHv9 02/25] Documentation: media: description of DMABUF importing in V4L2

Hans Verkuil hverkuil at xs4all.nl
Fri Oct 5 01:05:34 PDT 2012


Hi Tomasz,

Just a few more stylistic issues...

On Tue October 2 2012 16:27:13 Tomasz Stanislawski wrote:
> This patch adds description and usage examples for importing
> DMABUF file descriptor in V4L2.
> 
> Signed-off-by: Tomasz Stanislawski <t.stanislaws at samsung.com>
> Signed-off-by: Kyungmin Park <kyungmin.park at samsung.com>
> CC: linux-doc at vger.kernel.org
> ---
>  Documentation/DocBook/media/v4l/compat.xml         |    4 +
>  Documentation/DocBook/media/v4l/io.xml             |  180 +++++++++++++++++++-
>  .../DocBook/media/v4l/vidioc-create-bufs.xml       |   16 +-
>  Documentation/DocBook/media/v4l/vidioc-qbuf.xml    |   17 ++
>  Documentation/DocBook/media/v4l/vidioc-reqbufs.xml |   47 ++---
>  5 files changed, 234 insertions(+), 30 deletions(-)
> 
> diff --git a/Documentation/DocBook/media/v4l/compat.xml b/Documentation/DocBook/media/v4l/compat.xml
> index faa0fd1..a46f95b 100644
> --- a/Documentation/DocBook/media/v4l/compat.xml
> +++ b/Documentation/DocBook/media/v4l/compat.xml
> @@ -2621,6 +2621,10 @@ ioctls.</para>
>          <listitem>
>  	  <para>Support for frequency band enumeration: &VIDIOC-ENUM-FREQ-BANDS; ioctl.</para>
>          </listitem>
> +        <listitem>
> +	  <para>Importing DMABUF file descriptors as a new IO method described
> +	  in <xref linkend="dmabuf" />.</para>
> +        </listitem>
>        </itemizedlist>
>      </section>
>  
> diff --git a/Documentation/DocBook/media/v4l/io.xml b/Documentation/DocBook/media/v4l/io.xml
> index 1885cc0..5b58657 100644
> --- a/Documentation/DocBook/media/v4l/io.xml
> +++ b/Documentation/DocBook/media/v4l/io.xml
> @@ -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
>  given to the &func-open; function, <constant>VIDIOC_DQBUF</constant>
>  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
>  &VIDIOC-STREAMON; and &VIDIOC-STREAMOFF; ioctl. Note
> @@ -472,6 +472,161 @@ rest should be evident.</para>
>        </footnote></para>
>    </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 for sharing DMA buffers between V4L and
> +other APIs.

It's more accurate to say something along the lines of: "...is dedicated to sharing
DMA buffers between different devices, which may be V4L devices or other
video-related devices (e.g. DRM)."

One of the uses of this API is to share buffers between different V4L devices, so
that's a bit more generic than the original sentence suggests.

> 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));

no space after memset

> +reqbuf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
> +reqbuf.memory = V4L2_MEMORY_DMABUF;
> +reqbuf.count = 1;
> +
> +if (ioctl (fd, &VIDIOC-REQBUFS;, &reqbuf) == -1) {

no space after ioctl

> +	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>Filled or displayed buffers are dequeued with the

Filled -> Captured

> +&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; or &func-poll; function are always available.</para>

or -> and
function -> functions

> +
> +    <para>To start and stop capturing or output applications call the

output -> displaying

> +&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">
>      <title>Asynchronous I/O</title>
>  
> @@ -673,6 +828,14 @@ memory, set by the application. See <xref linkend="userp" /> for details.
>  	    <structname>v4l2_buffer</structname> structure.</entry>
>  	  </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>
>  	    <entry>__u32</entry>
>  	    <entry><structfield>length</structfield></entry>
>  	    <entry></entry>
> @@ -746,6 +909,15 @@ should set this to 0.</entry>
>  	      </entry>
>  	  </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>
>  	    <entry>__u32</entry>
>  	    <entry><structfield>data_offset</structfield></entry>
>  	    <entry></entry>
> @@ -973,6 +1145,12 @@ pointer</link> I/O.</entry>
>  	    <entry>3</entry>
>  	    <entry>[to do]</entry>
>  	  </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>
>        </tgroup>
>      </table>
> diff --git a/Documentation/DocBook/media/v4l/vidioc-create-bufs.xml b/Documentation/DocBook/media/v4l/vidioc-create-bufs.xml
> index a8cda1a..cd99436 100644
> --- a/Documentation/DocBook/media/v4l/vidioc-create-bufs.xml
> +++ b/Documentation/DocBook/media/v4l/vidioc-create-bufs.xml
> @@ -6,7 +6,8 @@
>  
>    <refnamediv>
>      <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>
>  
>    <refsynopsisdiv>
> @@ -55,11 +56,11 @@
>      </note>
>  
>      <para>This ioctl is used to create buffers for <link linkend="mmap">memory
> -mapped</link> or <link linkend="userp">user pointer</link>
> -I/O. It can be used as an alternative or in addition to the
> -<constant>VIDIOC_REQBUFS</constant> ioctl, when a tighter control over buffers
> -is required. This ioctl can be called multiple times to create buffers of
> -different sizes.</para>
> +mapped</link> or <link linkend="userp">user pointer</link> or <link
> +linkend="dmabuf">DMA buffer</link> I/O. It can be used as an alternative or in
> +addition to the <constant>VIDIOC_REQBUFS</constant> ioctl, when a tighter
> +control over buffers is required. This ioctl can be called multiple times to
> +create buffers of different sizes.</para>
>  
>      <para>To allocate device buffers applications initialize relevant fields of
>  the <structname>v4l2_create_buffers</structname> structure. They set the
> @@ -109,7 +110,8 @@ information.</para>
>  	    <entry>__u32</entry>
>  	    <entry><structfield>memory</structfield></entry>
>  	    <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"
>  /></entry>
>  	  </row>
> diff --git a/Documentation/DocBook/media/v4l/vidioc-qbuf.xml b/Documentation/DocBook/media/v4l/vidioc-qbuf.xml
> index 77ff5be..f40dfa0 100644
> --- a/Documentation/DocBook/media/v4l/vidioc-qbuf.xml
> +++ b/Documentation/DocBook/media/v4l/vidioc-qbuf.xml
> @@ -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
>  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 an
> +access by hardware. 

"an access by hardware" -> "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>
>  ioctl to dequeue a filled (capturing) or displayed (output) buffer
>  from the driver's outgoing queue. They just set the
> diff --git a/Documentation/DocBook/media/v4l/vidioc-reqbufs.xml b/Documentation/DocBook/media/v4l/vidioc-reqbufs.xml
> index d7c9505..20f4323 100644
> --- a/Documentation/DocBook/media/v4l/vidioc-reqbufs.xml
> +++ b/Documentation/DocBook/media/v4l/vidioc-reqbufs.xml
> @@ -48,28 +48,30 @@
>    <refsect1>
>      <title>Description</title>
>  
> -    <para>This ioctl is used to initiate <link linkend="mmap">memory
> -mapped</link> or <link linkend="userp">user pointer</link>
> -I/O. Memory mapped buffers are located in device memory and must be
> -allocated with this ioctl before they can be mapped into the
> -application's address space. User buffers are allocated by
> -applications themselves, and this ioctl is merely used to switch the
> -driver into user pointer I/O mode and to setup some internal structures.</para>
> +<para>This ioctl is used to initiate <link linkend="mmap">memory mapped</link>,
> +<link linkend="userp">user pointer</link> or <link
> +linkend="dmabuf">DMABUF</link> based I/O.  Memory mapped buffers are located in
> +device memory and must be allocated with this ioctl before they can be mapped
> +into the application's address space. User buffers are allocated by
> +applications themselves, and this ioctl is merely used to switch the driver
> +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
> -fields of the <structname>v4l2_requestbuffers</structname> structure.
> -They set the <structfield>type</structfield> field to the respective
> -stream or buffer type, the <structfield>count</structfield> field to
> -the desired number of buffers, <structfield>memory</structfield>
> -must be set to the requested I/O method and the <structfield>reserved</structfield> array
> -must be zeroed. When the ioctl
> -is called with a pointer to this structure the driver will attempt to allocate
> -the requested number of buffers and it stores the actual number
> -allocated in the <structfield>count</structfield> field. It can be
> -smaller than the number requested, even zero, when the driver runs out
> -of free memory. A larger number is also possible when the driver requires
> -more buffers to function correctly. For example video output requires at least two buffers,
> -one displayed and one filled by the application.</para>
> +    <para>To allocate device buffers applications initialize all fields of the
> +<structname>v4l2_requestbuffers</structname> structure.  They set the
> +<structfield>type</structfield> field to the respective stream or buffer type,
> +the <structfield>count</structfield> field to the desired number of buffers,
> +<structfield>memory</structfield> must be set to the requested I/O method and
> +the <structfield>reserved</structfield> array must be zeroed. When the ioctl is
> +called with a pointer to this structure the driver will attempt to allocate the
> +requested number of buffers and it stores the actual number allocated in the
> +<structfield>count</structfield> field. It can be smaller than the number
> +requested, even zero, when the driver runs out of free memory. A larger number
> +is also possible when the driver requires more buffers to function correctly.
> +For example video output requires at least two buffers, one displayed and one
> +filled by the application.</para>
>      <para>When the I/O method is not supported the ioctl
>  returns an &EINVAL;.</para>
>  
> @@ -102,7 +104,8 @@ as the &v4l2-format; <structfield>type</structfield> field. See <xref
>  	    <entry>__u32</entry>
>  	    <entry><structfield>memory</structfield></entry>
>  	    <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"
>  />.</entry>
>  	  </row>
> 

Regards,

	Hans


More information about the dri-devel mailing list