Commit | Line | Data |
---|---|---|
5377d91f MH |
1 | .. -*- coding: utf-8; mode: rst -*- |
2 | ||
3 | .. _mmap: | |
4 | ||
5 | ****************************** | |
6 | Streaming I/O (Memory Mapping) | |
7 | ****************************** | |
8 | ||
9 | Input and output devices support this I/O method when the | |
10 | ``V4L2_CAP_STREAMING`` flag in the ``capabilities`` field of struct | |
11 | :ref:`v4l2_capability <v4l2-capability>` returned by the | |
7347081e | 12 | :ref:`VIDIOC_QUERYCAP` ioctl is set. There are two |
5377d91f MH |
13 | streaming methods, to determine if the memory mapping flavor is |
14 | supported applications must call the | |
7347081e | 15 | :ref:`VIDIOC_REQBUFS` ioctl. |
5377d91f MH |
16 | |
17 | Streaming is an I/O method where only pointers to buffers are exchanged | |
18 | between application and driver, the data itself is not copied. Memory | |
19 | mapping is primarily intended to map buffers in device memory into the | |
20 | application's address space. Device memory can be for example the video | |
21 | memory on a graphics card with a video capture add-on. However, being | |
22 | the most efficient I/O method available for a long time, many other | |
23 | drivers support streaming as well, allocating buffers in DMA-able main | |
24 | memory. | |
25 | ||
26 | A driver can support many sets of buffers. Each set is identified by a | |
27 | unique buffer type value. The sets are independent and each set can hold | |
28 | a different type of data. To access different sets at the same time | |
29 | different file descriptors must be used. [1]_ | |
30 | ||
31 | To allocate device buffers applications call the | |
7347081e | 32 | :ref:`VIDIOC_REQBUFS` ioctl with the desired number |
5377d91f MH |
33 | of buffers and buffer type, for example ``V4L2_BUF_TYPE_VIDEO_CAPTURE``. |
34 | This ioctl can also be used to change the number of buffers or to free | |
35 | the allocated memory, provided none of the buffers are still mapped. | |
36 | ||
37 | Before applications can access the buffers they must map them into their | |
38 | address space with the :ref:`mmap() <func-mmap>` function. The | |
39 | location of the buffers in device memory can be determined with the | |
7347081e | 40 | :ref:`VIDIOC_QUERYBUF` ioctl. In the single-planar |
5377d91f MH |
41 | API case, the ``m.offset`` and ``length`` returned in a struct |
42 | :ref:`v4l2_buffer <v4l2-buffer>` are passed as sixth and second | |
43 | parameter to the :c:func:`mmap()` function. When using the | |
44 | multi-planar API, struct :ref:`v4l2_buffer <v4l2-buffer>` contains an | |
45 | array of struct :ref:`v4l2_plane <v4l2-plane>` structures, each | |
46 | containing its own ``m.offset`` and ``length``. When using the | |
47 | multi-planar API, every plane of every buffer has to be mapped | |
48 | separately, so the number of calls to :ref:`mmap() <func-mmap>` should | |
49 | be equal to number of buffers times number of planes in each buffer. The | |
50 | offset and length values must not be modified. Remember, the buffers are | |
51 | allocated in physical memory, as opposed to virtual memory, which can be | |
52 | swapped out to disk. Applications should free the buffers as soon as | |
53 | possible with the :ref:`munmap() <func-munmap>` function. | |
54 | ||
55 | ||
56 | .. code-block:: c | |
57 | ||
58 | struct v4l2_requestbuffers reqbuf; | |
59 | struct { | |
60 | void *start; | |
61 | size_t length; | |
62 | } *buffers; | |
63 | unsigned int i; | |
64 | ||
65 | memset(&reqbuf, 0, sizeof(reqbuf)); | |
66 | reqbuf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; | |
67 | reqbuf.memory = V4L2_MEMORY_MMAP; | |
68 | reqbuf.count = 20; | |
69 | ||
70 | if (-1 == ioctl (fd, VIDIOC_REQBUFS, &reqbuf)) { | |
71 | if (errno == EINVAL) | |
72 | printf("Video capturing or mmap-streaming is not supported\\n"); | |
73 | else | |
74 | perror("VIDIOC_REQBUFS"); | |
75 | ||
76 | exit(EXIT_FAILURE); | |
77 | } | |
78 | ||
79 | /* We want at least five buffers. */ | |
80 | ||
81 | if (reqbuf.count < 5) { | |
82 | /* You may need to free the buffers here. */ | |
83 | printf("Not enough buffer memory\\n"); | |
84 | exit(EXIT_FAILURE); | |
85 | } | |
86 | ||
87 | buffers = calloc(reqbuf.count, sizeof(*buffers)); | |
88 | assert(buffers != NULL); | |
89 | ||
90 | for (i = 0; i < reqbuf.count; i++) { | |
91 | struct v4l2_buffer buffer; | |
92 | ||
93 | memset(&buffer, 0, sizeof(buffer)); | |
94 | buffer.type = reqbuf.type; | |
95 | buffer.memory = V4L2_MEMORY_MMAP; | |
96 | buffer.index = i; | |
97 | ||
98 | if (-1 == ioctl (fd, VIDIOC_QUERYBUF, &buffer)) { | |
99 | perror("VIDIOC_QUERYBUF"); | |
100 | exit(EXIT_FAILURE); | |
101 | } | |
102 | ||
103 | buffers[i].length = buffer.length; /* remember for munmap() */ | |
104 | ||
105 | buffers[i].start = mmap(NULL, buffer.length, | |
106 | PROT_READ | PROT_WRITE, /* recommended */ | |
107 | MAP_SHARED, /* recommended */ | |
108 | fd, buffer.m.offset); | |
109 | ||
110 | if (MAP_FAILED == buffers[i].start) { | |
111 | /* If you do not exit here you should unmap() and free() | |
112 | the buffers mapped so far. */ | |
113 | perror("mmap"); | |
114 | exit(EXIT_FAILURE); | |
115 | } | |
116 | } | |
117 | ||
118 | /* Cleanup. */ | |
119 | ||
120 | for (i = 0; i < reqbuf.count; i++) | |
121 | munmap(buffers[i].start, buffers[i].length); | |
122 | ||
123 | ||
124 | .. code-block:: c | |
125 | ||
126 | struct v4l2_requestbuffers reqbuf; | |
127 | /* Our current format uses 3 planes per buffer */ | |
128 | #define FMT_NUM_PLANES = 3 | |
129 | ||
130 | struct { | |
131 | void *start[FMT_NUM_PLANES]; | |
132 | size_t length[FMT_NUM_PLANES]; | |
133 | } *buffers; | |
134 | unsigned int i, j; | |
135 | ||
136 | memset(&reqbuf, 0, sizeof(reqbuf)); | |
137 | reqbuf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE; | |
138 | reqbuf.memory = V4L2_MEMORY_MMAP; | |
139 | reqbuf.count = 20; | |
140 | ||
141 | if (ioctl(fd, VIDIOC_REQBUFS, &reqbuf) < 0) { | |
142 | if (errno == EINVAL) | |
143 | printf("Video capturing or mmap-streaming is not supported\\n"); | |
144 | else | |
145 | perror("VIDIOC_REQBUFS"); | |
146 | ||
147 | exit(EXIT_FAILURE); | |
148 | } | |
149 | ||
150 | /* We want at least five buffers. */ | |
151 | ||
152 | if (reqbuf.count < 5) { | |
153 | /* You may need to free the buffers here. */ | |
154 | printf("Not enough buffer memory\\n"); | |
155 | exit(EXIT_FAILURE); | |
156 | } | |
157 | ||
158 | buffers = calloc(reqbuf.count, sizeof(*buffers)); | |
159 | assert(buffers != NULL); | |
160 | ||
161 | for (i = 0; i < reqbuf.count; i++) { | |
162 | struct v4l2_buffer buffer; | |
163 | struct v4l2_plane planes[FMT_NUM_PLANES]; | |
164 | ||
165 | memset(&buffer, 0, sizeof(buffer)); | |
166 | buffer.type = reqbuf.type; | |
167 | buffer.memory = V4L2_MEMORY_MMAP; | |
168 | buffer.index = i; | |
169 | /* length in struct v4l2_buffer in multi-planar API stores the size | |
170 | * of planes array. */ | |
171 | buffer.length = FMT_NUM_PLANES; | |
172 | buffer.m.planes = planes; | |
173 | ||
174 | if (ioctl(fd, VIDIOC_QUERYBUF, &buffer) < 0) { | |
175 | perror("VIDIOC_QUERYBUF"); | |
176 | exit(EXIT_FAILURE); | |
177 | } | |
178 | ||
179 | /* Every plane has to be mapped separately */ | |
180 | for (j = 0; j < FMT_NUM_PLANES; j++) { | |
181 | buffers[i].length[j] = buffer.m.planes[j].length; /* remember for munmap() */ | |
182 | ||
183 | buffers[i].start[j] = mmap(NULL, buffer.m.planes[j].length, | |
184 | PROT_READ | PROT_WRITE, /* recommended */ | |
185 | MAP_SHARED, /* recommended */ | |
186 | fd, buffer.m.planes[j].m.offset); | |
187 | ||
188 | if (MAP_FAILED == buffers[i].start[j]) { | |
189 | /* If you do not exit here you should unmap() and free() | |
190 | the buffers and planes mapped so far. */ | |
191 | perror("mmap"); | |
192 | exit(EXIT_FAILURE); | |
193 | } | |
194 | } | |
195 | } | |
196 | ||
197 | /* Cleanup. */ | |
198 | ||
199 | for (i = 0; i < reqbuf.count; i++) | |
200 | for (j = 0; j < FMT_NUM_PLANES; j++) | |
201 | munmap(buffers[i].start[j], buffers[i].length[j]); | |
202 | ||
203 | Conceptually streaming drivers maintain two buffer queues, an incoming | |
204 | and an outgoing queue. They separate the synchronous capture or output | |
205 | operation locked to a video clock from the application which is subject | |
206 | to random disk or network delays and preemption by other processes, | |
207 | thereby reducing the probability of data loss. The queues are organized | |
208 | as FIFOs, buffers will be output in the order enqueued in the incoming | |
209 | FIFO, and were captured in the order dequeued from the outgoing FIFO. | |
210 | ||
211 | The driver may require a minimum number of buffers enqueued at all times | |
212 | to function, apart of this no limit exists on the number of buffers | |
213 | applications can enqueue in advance, or dequeue and process. They can | |
214 | also enqueue in a different order than buffers have been dequeued, and | |
215 | the driver can *fill* enqueued *empty* buffers in any order. [2]_ The | |
216 | index number of a buffer (struct :ref:`v4l2_buffer <v4l2-buffer>` | |
217 | ``index``) plays no role here, it only identifies the buffer. | |
218 | ||
219 | Initially all mapped buffers are in dequeued state, inaccessible by the | |
220 | driver. For capturing applications it is customary to first enqueue all | |
221 | mapped buffers, then to start capturing and enter the read loop. Here | |
222 | the application waits until a filled buffer can be dequeued, and | |
223 | re-enqueues the buffer when the data is no longer needed. Output | |
224 | applications fill and enqueue buffers, when enough buffers are stacked | |
225 | up the output is started with ``VIDIOC_STREAMON``. In the write loop, | |
226 | when the application runs out of free buffers, it must wait until an | |
227 | empty buffer can be dequeued and reused. | |
228 | ||
229 | To enqueue and dequeue a buffer applications use the | |
7347081e | 230 | :ref:`VIDIOC_QBUF` and |
af4a4d0d | 231 | :ref:`VIDIOC_DQBUF <VIDIOC_QBUF>` ioctl. The status of a buffer being |
5377d91f | 232 | mapped, enqueued, full or empty can be determined at any time using the |
7347081e | 233 | :ref:`VIDIOC_QUERYBUF` ioctl. Two methods exist to |
5377d91f MH |
234 | suspend execution of the application until one or more buffers can be |
235 | dequeued. By default ``VIDIOC_DQBUF`` blocks when no buffer is in the | |
236 | outgoing queue. When the ``O_NONBLOCK`` flag was given to the | |
237 | :ref:`open() <func-open>` function, ``VIDIOC_DQBUF`` returns | |
238 | immediately with an EAGAIN error code when no buffer is available. The | |
239 | :ref:`select() <func-select>` or :ref:`poll() <func-poll>` functions | |
240 | are always available. | |
241 | ||
242 | To start and stop capturing or output applications call the | |
7347081e | 243 | :ref:`VIDIOC_STREAMON` and |
af4a4d0d | 244 | :ref:`VIDIOC_STREAMOFF <VIDIOC_STREAMON>` ioctl. Note |
5377d91f MH |
245 | ``VIDIOC_STREAMOFF`` removes all buffers from both queues as a side |
246 | effect. Since there is no notion of doing anything "now" on a | |
247 | multitasking system, if an application needs to synchronize with another | |
248 | event it should examine the struct :ref:`v4l2_buffer <v4l2-buffer>` | |
249 | ``timestamp`` of captured or outputted buffers. | |
250 | ||
251 | Drivers implementing memory mapping I/O must support the | |
252 | ``VIDIOC_REQBUFS``, ``VIDIOC_QUERYBUF``, ``VIDIOC_QBUF``, | |
253 | ``VIDIOC_DQBUF``, ``VIDIOC_STREAMON`` and ``VIDIOC_STREAMOFF`` ioctl, | |
254 | the :c:func:`mmap()`, :c:func:`munmap()`, :c:func:`select()` and | |
255 | :c:func:`poll()` function. [3]_ | |
256 | ||
257 | [capture example] | |
258 | ||
259 | .. [1] | |
260 | One could use one file descriptor and set the buffer type field | |
7347081e | 261 | accordingly when calling :ref:`VIDIOC_QBUF` etc., |
5377d91f MH |
262 | but it makes the :c:func:`select()` function ambiguous. We also |
263 | like the clean approach of one file descriptor per logical stream. | |
264 | Video overlay for example is also a logical stream, although the CPU | |
265 | is not needed for continuous operation. | |
266 | ||
267 | .. [2] | |
268 | Random enqueue order permits applications processing images out of | |
269 | order (such as video codecs) to return buffers earlier, reducing the | |
270 | probability of data loss. Random fill order allows drivers to reuse | |
271 | buffers on a LIFO-basis, taking advantage of caches holding | |
272 | scatter-gather lists and the like. | |
273 | ||
274 | .. [3] | |
275 | At the driver level :c:func:`select()` and :c:func:`poll()` are | |
276 | the same, and :c:func:`select()` is too important to be optional. | |
277 | The rest should be evident. | |
278 | ||
279 | ||
280 | .. ------------------------------------------------------------------------------ | |
281 | .. This file was automatically converted from DocBook-XML with the dbxml | |
282 | .. library (https://github.com/return42/sphkerneldoc). The origin XML comes | |
283 | .. from the linux kernel, refer to: | |
284 | .. | |
285 | .. * https://github.com/torvalds/linux/tree/master/Documentation/DocBook | |
286 | .. ------------------------------------------------------------------------------ |