]>
Commit | Line | Data |
---|---|---|
5377d91f MH |
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 | ||
af4a4d0d | 17 | Refer to :ref:`DMABUF exporting <VIDIOC_EXPBUF>` for details about |
5377d91f MH |
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 | |
69eee8a5 | 23 | :ref:`VIDIOC_QUERYCAP <VIDIOC_QUERYCAP>` ioctl is set. Whether |
5377d91f | 24 | importing DMA buffers through DMABUF file descriptors is supported is |
69eee8a5 | 25 | determined by calling the :ref:`VIDIOC_REQBUFS <VIDIOC_REQBUFS>` |
5377d91f MH |
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 | |
69eee8a5 | 37 | :ref:`VIDIOC_REQBUFS <VIDIOC_REQBUFS>` with the desired buffer type. |
5377d91f MH |
38 | |
39 | ||
282f02cb MCC |
40 | Example: Initiating streaming I/O with DMABUF file descriptors |
41 | ============================================================== | |
42 | ||
5377d91f MH |
43 | .. code-block:: c |
44 | ||
45 | struct v4l2_requestbuffers reqbuf; | |
46 | ||
47 | memset(&reqbuf, 0, sizeof (reqbuf)); | |
48 | reqbuf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; | |
49 | reqbuf.memory = V4L2_MEMORY_DMABUF; | |
50 | reqbuf.count = 1; | |
51 | ||
52 | if (ioctl(fd, VIDIOC_REQBUFS, &reqbuf) == -1) { | |
0579e6e3 MCC |
53 | if (errno == EINVAL) |
54 | printf("Video capturing or DMABUF streaming is not supported\\n"); | |
55 | else | |
56 | perror("VIDIOC_REQBUFS"); | |
5377d91f | 57 | |
0579e6e3 | 58 | exit(EXIT_FAILURE); |
5377d91f MH |
59 | } |
60 | ||
61 | The buffer (plane) file descriptor is passed on the fly with the | |
69eee8a5 | 62 | :ref:`VIDIOC_QBUF <VIDIOC_QBUF>` ioctl. In case of multiplanar |
5377d91f MH |
63 | buffers, every plane can be associated with a different DMABUF |
64 | descriptor. Although buffers are commonly cycled, applications can pass | |
69eee8a5 | 65 | a different DMABUF descriptor at each :ref:`VIDIOC_QBUF <VIDIOC_QBUF>` call. |
5377d91f | 66 | |
282f02cb MCC |
67 | Example: Queueing DMABUF using single plane API |
68 | =============================================== | |
5377d91f MH |
69 | |
70 | .. code-block:: c | |
71 | ||
72 | int buffer_queue(int v4lfd, int index, int dmafd) | |
73 | { | |
0579e6e3 | 74 | struct v4l2_buffer buf; |
5377d91f | 75 | |
0579e6e3 MCC |
76 | memset(&buf, 0, sizeof buf); |
77 | buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; | |
78 | buf.memory = V4L2_MEMORY_DMABUF; | |
79 | buf.index = index; | |
80 | buf.m.fd = dmafd; | |
5377d91f | 81 | |
0579e6e3 MCC |
82 | if (ioctl(v4lfd, VIDIOC_QBUF, &buf) == -1) { |
83 | perror("VIDIOC_QBUF"); | |
84 | return -1; | |
85 | } | |
5377d91f | 86 | |
0579e6e3 | 87 | return 0; |
5377d91f MH |
88 | } |
89 | ||
282f02cb MCC |
90 | Example 3.6. Queueing DMABUF using multi plane API |
91 | ================================================== | |
5377d91f MH |
92 | |
93 | .. code-block:: c | |
94 | ||
95 | int buffer_queue_mp(int v4lfd, int index, int dmafd[], int n_planes) | |
96 | { | |
0579e6e3 MCC |
97 | struct v4l2_buffer buf; |
98 | struct v4l2_plane planes[VIDEO_MAX_PLANES]; | |
99 | int i; | |
5377d91f | 100 | |
0579e6e3 MCC |
101 | memset(&buf, 0, sizeof buf); |
102 | buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE; | |
103 | buf.memory = V4L2_MEMORY_DMABUF; | |
104 | buf.index = index; | |
105 | buf.m.planes = planes; | |
106 | buf.length = n_planes; | |
5377d91f | 107 | |
0579e6e3 | 108 | memset(&planes, 0, sizeof planes); |
5377d91f | 109 | |
0579e6e3 MCC |
110 | for (i = 0; i < n_planes; ++i) |
111 | buf.m.planes[i].m.fd = dmafd[i]; | |
5377d91f | 112 | |
0579e6e3 MCC |
113 | if (ioctl(v4lfd, VIDIOC_QBUF, &buf) == -1) { |
114 | perror("VIDIOC_QBUF"); | |
115 | return -1; | |
116 | } | |
5377d91f | 117 | |
0579e6e3 | 118 | return 0; |
5377d91f MH |
119 | } |
120 | ||
121 | Captured or displayed buffers are dequeued with the | |
af4a4d0d | 122 | :ref:`VIDIOC_DQBUF <VIDIOC_QBUF>` ioctl. The driver can unlock the |
5377d91f MH |
123 | buffer at any time between the completion of the DMA and this ioctl. The |
124 | memory is also unlocked when | |
af4a4d0d | 125 | :ref:`VIDIOC_STREAMOFF <VIDIOC_STREAMON>` is called, |
69eee8a5 | 126 | :ref:`VIDIOC_REQBUFS <VIDIOC_REQBUFS>`, or when the device is closed. |
5377d91f MH |
127 | |
128 | For capturing applications it is customary to enqueue a number of empty | |
129 | buffers, to start capturing and enter the read loop. Here the | |
130 | application waits until a filled buffer can be dequeued, and re-enqueues | |
131 | the buffer when the data is no longer needed. Output applications fill | |
132 | and enqueue buffers, when enough buffers are stacked up output is | |
133 | started. In the write loop, when the application runs out of free | |
134 | buffers it must wait until an empty buffer can be dequeued and reused. | |
135 | Two methods exist to suspend execution of the application until one or | |
69eee8a5 MCC |
136 | more buffers can be dequeued. By default :ref:`VIDIOC_DQBUF |
137 | <VIDIOC_QBUF>` blocks when no buffer is in the outgoing queue. When the | |
138 | ``O_NONBLOCK`` flag was given to the :ref:`open() <func-open>` function, | |
139 | :ref:`VIDIOC_DQBUF <VIDIOC_QBUF>` returns immediately with an ``EAGAIN`` | |
140 | error code when no buffer is available. The | |
5377d91f MH |
141 | :ref:`select() <func-select>` and :ref:`poll() <func-poll>` |
142 | functions are always available. | |
143 | ||
144 | To start and stop capturing or displaying applications call the | |
69eee8a5 | 145 | :ref:`VIDIOC_STREAMON <VIDIOC_STREAMON>` and |
706f8a99 MCC |
146 | :ref:`VIDIOC_STREAMOFF <VIDIOC_STREAMON>` ioctls. |
147 | ||
148 | .. note:: | |
149 | ||
150 | :ref:`VIDIOC_STREAMOFF <VIDIOC_STREAMON>` removes all buffers from | |
151 | both queues and unlocks all buffers as a side effect. Since there is no | |
152 | notion of doing anything "now" on a multitasking system, if an | |
153 | application needs to synchronize with another event it should examine | |
154 | the struct :ref:`v4l2_buffer <v4l2-buffer>` ``timestamp`` of captured or | |
155 | outputted buffers. | |
5377d91f MH |
156 | |
157 | Drivers implementing DMABUF importing I/O must support the | |
69eee8a5 | 158 | :ref:`VIDIOC_REQBUFS <VIDIOC_REQBUFS>`, :ref:`VIDIOC_QBUF <VIDIOC_QBUF>`, |
c104290b | 159 | :ref:`VIDIOC_DQBUF <VIDIOC_QBUF>`, :ref:`VIDIOC_STREAMON |
69eee8a5 MCC |
160 | <VIDIOC_STREAMON>` and :ref:`VIDIOC_STREAMOFF <VIDIOC_STREAMON>` ioctls, |
161 | and the :ref:`select() <func-select>` and :ref:`poll() <func-poll>` | |
162 | functions. |