Markus Heiser | 5377d91 | 2016-06-30 15:18:56 +0200 | [diff] [blame] | 1 | .. -*- coding: utf-8; mode: rst -*- |
| 2 | |
| 3 | .. _dmabuf: |
| 4 | |
| 5 | ************************************ |
| 6 | Streaming I/O (DMA buffer importing) |
| 7 | ************************************ |
| 8 | |
| 9 | The DMABUF framework provides a generic method for sharing buffers |
| 10 | between multiple devices. Device drivers that support DMABUF can export |
| 11 | a DMA buffer to userspace as a file descriptor (known as the exporter |
| 12 | role), import a DMA buffer from userspace using a file descriptor |
| 13 | previously exported for a different or the same device (known as the |
| 14 | importer role), or both. This section describes the DMABUF importer role |
| 15 | API in V4L2. |
| 16 | |
Mauro Carvalho Chehab | af4a4d0 | 2016-07-01 13:42:29 -0300 | [diff] [blame] | 17 | Refer to :ref:`DMABUF exporting <VIDIOC_EXPBUF>` for details about |
Markus Heiser | 5377d91 | 2016-06-30 15:18:56 +0200 | [diff] [blame] | 18 | exporting V4L2 buffers as DMABUF file descriptors. |
| 19 | |
| 20 | Input and output devices support the streaming I/O method when the |
| 21 | ``V4L2_CAP_STREAMING`` flag in the ``capabilities`` field of struct |
| 22 | :ref:`v4l2_capability <v4l2-capability>` returned by the |
Mauro Carvalho Chehab | 7347081 | 2016-07-01 13:58:44 -0300 | [diff] [blame] | 23 | :ref:`VIDIOC_QUERYCAP` ioctl is set. Whether |
Markus Heiser | 5377d91 | 2016-06-30 15:18:56 +0200 | [diff] [blame] | 24 | importing DMA buffers through DMABUF file descriptors is supported is |
Mauro Carvalho Chehab | 7347081 | 2016-07-01 13:58:44 -0300 | [diff] [blame] | 25 | determined by calling the :ref:`VIDIOC_REQBUFS` |
Markus Heiser | 5377d91 | 2016-06-30 15:18:56 +0200 | [diff] [blame] | 26 | ioctl with the memory type set to ``V4L2_MEMORY_DMABUF``. |
| 27 | |
| 28 | This I/O method is dedicated to sharing DMA buffers between different |
| 29 | devices, which may be V4L devices or other video-related devices (e.g. |
| 30 | DRM). Buffers (planes) are allocated by a driver on behalf of an |
| 31 | application. Next, these buffers are exported to the application as file |
| 32 | descriptors using an API which is specific for an allocator driver. Only |
| 33 | such file descriptor are exchanged. The descriptors and meta-information |
| 34 | are passed in struct :ref:`v4l2_buffer <v4l2-buffer>` (or in struct |
| 35 | :ref:`v4l2_plane <v4l2-plane>` in the multi-planar API case). The |
| 36 | driver must be switched into DMABUF I/O mode by calling the |
Mauro Carvalho Chehab | 7347081 | 2016-07-01 13:58:44 -0300 | [diff] [blame] | 37 | :ref:`VIDIOC_REQBUFS` with the desired buffer type. |
Markus Heiser | 5377d91 | 2016-06-30 15:18:56 +0200 | [diff] [blame] | 38 | |
| 39 | |
| 40 | .. code-block:: c |
| 41 | |
| 42 | struct v4l2_requestbuffers reqbuf; |
| 43 | |
| 44 | memset(&reqbuf, 0, sizeof (reqbuf)); |
| 45 | reqbuf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; |
| 46 | reqbuf.memory = V4L2_MEMORY_DMABUF; |
| 47 | reqbuf.count = 1; |
| 48 | |
| 49 | if (ioctl(fd, VIDIOC_REQBUFS, &reqbuf) == -1) { |
| 50 | if (errno == EINVAL) |
| 51 | printf("Video capturing or DMABUF streaming is not supported\\n"); |
| 52 | else |
| 53 | perror("VIDIOC_REQBUFS"); |
| 54 | |
| 55 | exit(EXIT_FAILURE); |
| 56 | } |
| 57 | |
| 58 | The buffer (plane) file descriptor is passed on the fly with the |
Mauro Carvalho Chehab | 7347081 | 2016-07-01 13:58:44 -0300 | [diff] [blame] | 59 | :ref:`VIDIOC_QBUF` ioctl. In case of multiplanar |
Markus Heiser | 5377d91 | 2016-06-30 15:18:56 +0200 | [diff] [blame] | 60 | buffers, every plane can be associated with a different DMABUF |
| 61 | descriptor. Although buffers are commonly cycled, applications can pass |
| 62 | a different DMABUF descriptor at each ``VIDIOC_QBUF`` call. |
| 63 | |
| 64 | |
| 65 | .. code-block:: c |
| 66 | |
| 67 | int buffer_queue(int v4lfd, int index, int dmafd) |
| 68 | { |
| 69 | struct v4l2_buffer buf; |
| 70 | |
| 71 | memset(&buf, 0, sizeof buf); |
| 72 | buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; |
| 73 | buf.memory = V4L2_MEMORY_DMABUF; |
| 74 | buf.index = index; |
| 75 | buf.m.fd = dmafd; |
| 76 | |
| 77 | if (ioctl(v4lfd, VIDIOC_QBUF, &buf) == -1) { |
| 78 | perror("VIDIOC_QBUF"); |
| 79 | return -1; |
| 80 | } |
| 81 | |
| 82 | return 0; |
| 83 | } |
| 84 | |
| 85 | |
| 86 | .. code-block:: c |
| 87 | |
| 88 | int buffer_queue_mp(int v4lfd, int index, int dmafd[], int n_planes) |
| 89 | { |
| 90 | struct v4l2_buffer buf; |
| 91 | struct v4l2_plane planes[VIDEO_MAX_PLANES]; |
| 92 | int i; |
| 93 | |
| 94 | memset(&buf, 0, sizeof buf); |
| 95 | buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE; |
| 96 | buf.memory = V4L2_MEMORY_DMABUF; |
| 97 | buf.index = index; |
| 98 | buf.m.planes = planes; |
| 99 | buf.length = n_planes; |
| 100 | |
| 101 | memset(&planes, 0, sizeof planes); |
| 102 | |
| 103 | for (i = 0; i < n_planes; ++i) |
| 104 | buf.m.planes[i].m.fd = dmafd[i]; |
| 105 | |
| 106 | if (ioctl(v4lfd, VIDIOC_QBUF, &buf) == -1) { |
| 107 | perror("VIDIOC_QBUF"); |
| 108 | return -1; |
| 109 | } |
| 110 | |
| 111 | return 0; |
| 112 | } |
| 113 | |
| 114 | Captured or displayed buffers are dequeued with the |
Mauro Carvalho Chehab | af4a4d0 | 2016-07-01 13:42:29 -0300 | [diff] [blame] | 115 | :ref:`VIDIOC_DQBUF <VIDIOC_QBUF>` ioctl. The driver can unlock the |
Markus Heiser | 5377d91 | 2016-06-30 15:18:56 +0200 | [diff] [blame] | 116 | buffer at any time between the completion of the DMA and this ioctl. The |
| 117 | memory is also unlocked when |
Mauro Carvalho Chehab | af4a4d0 | 2016-07-01 13:42:29 -0300 | [diff] [blame] | 118 | :ref:`VIDIOC_STREAMOFF <VIDIOC_STREAMON>` is called, |
Mauro Carvalho Chehab | 7347081 | 2016-07-01 13:58:44 -0300 | [diff] [blame] | 119 | :ref:`VIDIOC_REQBUFS`, or when the device is closed. |
Markus Heiser | 5377d91 | 2016-06-30 15:18:56 +0200 | [diff] [blame] | 120 | |
| 121 | For capturing applications it is customary to enqueue a number of empty |
| 122 | buffers, to start capturing and enter the read loop. Here the |
| 123 | application waits until a filled buffer can be dequeued, and re-enqueues |
| 124 | the buffer when the data is no longer needed. Output applications fill |
| 125 | and enqueue buffers, when enough buffers are stacked up output is |
| 126 | started. In the write loop, when the application runs out of free |
| 127 | buffers it must wait until an empty buffer can be dequeued and reused. |
| 128 | Two methods exist to suspend execution of the application until one or |
| 129 | more buffers can be dequeued. By default ``VIDIOC_DQBUF`` blocks when no |
| 130 | buffer is in the outgoing queue. When the ``O_NONBLOCK`` flag was given |
| 131 | to the :ref:`open() <func-open>` function, ``VIDIOC_DQBUF`` returns |
Mauro Carvalho Chehab | cdb4af0 | 2016-07-03 11:53:09 -0300 | [diff] [blame^] | 132 | immediately with an ``EAGAIN`` error code when no buffer is available. The |
Markus Heiser | 5377d91 | 2016-06-30 15:18:56 +0200 | [diff] [blame] | 133 | :ref:`select() <func-select>` and :ref:`poll() <func-poll>` |
| 134 | functions are always available. |
| 135 | |
| 136 | To start and stop capturing or displaying applications call the |
Mauro Carvalho Chehab | 7347081 | 2016-07-01 13:58:44 -0300 | [diff] [blame] | 137 | :ref:`VIDIOC_STREAMON` and |
Mauro Carvalho Chehab | af4a4d0 | 2016-07-01 13:42:29 -0300 | [diff] [blame] | 138 | :ref:`VIDIOC_STREAMOFF <VIDIOC_STREAMON>` ioctls. Note that |
Markus Heiser | 5377d91 | 2016-06-30 15:18:56 +0200 | [diff] [blame] | 139 | ``VIDIOC_STREAMOFF`` removes all buffers from both queues and unlocks |
| 140 | all buffers as a side effect. Since there is no notion of doing anything |
| 141 | "now" on a multitasking system, if an application needs to synchronize |
| 142 | with another event it should examine the struct |
| 143 | :ref:`v4l2_buffer <v4l2-buffer>` ``timestamp`` of captured or |
| 144 | outputted buffers. |
| 145 | |
| 146 | Drivers implementing DMABUF importing I/O must support the |
| 147 | ``VIDIOC_REQBUFS``, ``VIDIOC_QBUF``, ``VIDIOC_DQBUF``, |
| 148 | ``VIDIOC_STREAMON`` and ``VIDIOC_STREAMOFF`` ioctls, and the |
| 149 | :c:func:`select()` and :c:func:`poll()` functions. |
| 150 | |
| 151 | |
| 152 | .. ------------------------------------------------------------------------------ |
| 153 | .. This file was automatically converted from DocBook-XML with the dbxml |
| 154 | .. library (https://github.com/return42/sphkerneldoc). The origin XML comes |
| 155 | .. from the linux kernel, refer to: |
| 156 | .. |
| 157 | .. * https://github.com/torvalds/linux/tree/master/Documentation/DocBook |
| 158 | .. ------------------------------------------------------------------------------ |