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