dmabuf.rst 6.1 KB
Newer Older
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
.. -*- coding: utf-8; mode: rst -*-

.. _dmabuf:

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

17
Refer to :ref:`DMABUF exporting <VIDIOC_EXPBUF>` for details about
18 19 20 21 22
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
:ref:`v4l2_capability <v4l2-capability>` returned by the
23
:ref:`VIDIOC_QUERYCAP <VIDIOC_QUERYCAP>` ioctl is set. Whether
24
importing DMA buffers through DMABUF file descriptors is supported is
25
determined by calling the :ref:`VIDIOC_REQBUFS <VIDIOC_REQBUFS>`
26 27 28 29 30 31 32 33 34 35 36
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 :ref:`v4l2_buffer <v4l2-buffer>` (or in struct
:ref:`v4l2_plane <v4l2-plane>` in the multi-planar API case). The
driver must be switched into DMABUF I/O mode by calling the
37
:ref:`VIDIOC_REQBUFS <VIDIOC_REQBUFS>` with the desired buffer type.
38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58


.. code-block:: c

    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
59
:ref:`VIDIOC_QBUF <VIDIOC_QBUF>` ioctl. In case of multiplanar
60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114
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.


.. code-block:: c

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


.. code-block:: c

    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
115
:ref:`VIDIOC_DQBUF <VIDIOC_QBUF>` ioctl. The driver can unlock the
116 117
buffer at any time between the completion of the DMA and this ioctl. The
memory is also unlocked when
118 119
:ref:`VIDIOC_STREAMOFF <VIDIOC_STREAMON>` is called,
:ref:`VIDIOC_REQBUFS <VIDIOC_REQBUFS>`, or when the device is closed.
120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136

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 :ref:`open() <func-open>` function, ``VIDIOC_DQBUF`` returns
immediately with an EAGAIN error code when no buffer is available. The
:ref:`select() <func-select>` and :ref:`poll() <func-poll>`
functions are always available.

To start and stop capturing or displaying applications call the
137 138
:ref:`VIDIOC_STREAMON <VIDIOC_STREAMON>` and
:ref:`VIDIOC_STREAMOFF <VIDIOC_STREAMON>` ioctls. Note that
139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158
``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
:ref:`v4l2_buffer <v4l2-buffer>` ``timestamp`` of captured or
outputted buffers.

Drivers implementing DMABUF importing I/O must support the
``VIDIOC_REQBUFS``, ``VIDIOC_QBUF``, ``VIDIOC_DQBUF``,
``VIDIOC_STREAMON`` and ``VIDIOC_STREAMOFF`` ioctls, and the
:c:func:`select()` and :c:func:`poll()` functions.


.. ------------------------------------------------------------------------------
.. This file was automatically converted from DocBook-XML with the dbxml
.. library (https://github.com/return42/sphkerneldoc). The origin XML comes
.. from the linux kernel, refer to:
..
.. * https://github.com/torvalds/linux/tree/master/Documentation/DocBook
.. ------------------------------------------------------------------------------