blob: f7fe26e7ca43e12f6d8f3179615cc50717143f40 [file] [log] [blame]
Markus Heiser5377d912016-06-30 15:18:56 +02001.. -*- coding: utf-8; mode: rst -*-
2
3.. _mmap:
4
5******************************
6Streaming I/O (Memory Mapping)
7******************************
8
9Input 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
Mauro Carvalho Chehab73470812016-07-01 13:58:44 -030012:ref:`VIDIOC_QUERYCAP` ioctl is set. There are two
Markus Heiser5377d912016-06-30 15:18:56 +020013streaming methods, to determine if the memory mapping flavor is
Mauro Carvalho Chehab071dedf2016-07-08 15:47:00 -030014supported applications must call the :ref:`VIDIOC_REQBUFS` ioctl
15with the memory type set to ``V4L2_MEMORY_MMAP``.
Markus Heiser5377d912016-06-30 15:18:56 +020016
17Streaming is an I/O method where only pointers to buffers are exchanged
18between application and driver, the data itself is not copied. Memory
19mapping is primarily intended to map buffers in device memory into the
20application's address space. Device memory can be for example the video
21memory on a graphics card with a video capture add-on. However, being
22the most efficient I/O method available for a long time, many other
23drivers support streaming as well, allocating buffers in DMA-able main
24memory.
25
26A driver can support many sets of buffers. Each set is identified by a
27unique buffer type value. The sets are independent and each set can hold
28a different type of data. To access different sets at the same time
29different file descriptors must be used. [1]_
30
31To allocate device buffers applications call the
Mauro Carvalho Chehab73470812016-07-01 13:58:44 -030032:ref:`VIDIOC_REQBUFS` ioctl with the desired number
Markus Heiser5377d912016-06-30 15:18:56 +020033of buffers and buffer type, for example ``V4L2_BUF_TYPE_VIDEO_CAPTURE``.
34This ioctl can also be used to change the number of buffers or to free
35the allocated memory, provided none of the buffers are still mapped.
36
37Before applications can access the buffers they must map them into their
38address space with the :ref:`mmap() <func-mmap>` function. The
39location of the buffers in device memory can be determined with the
Mauro Carvalho Chehab73470812016-07-01 13:58:44 -030040:ref:`VIDIOC_QUERYBUF` ioctl. In the single-planar
Markus Heiser5377d912016-06-30 15:18:56 +020041API case, the ``m.offset`` and ``length`` returned in a struct
42:ref:`v4l2_buffer <v4l2-buffer>` are passed as sixth and second
Mauro Carvalho Chehab760c7012016-07-04 12:56:17 -030043parameter to the :ref:`mmap() <func-mmap>` function. When using the
Markus Heiser5377d912016-06-30 15:18:56 +020044multi-planar API, struct :ref:`v4l2_buffer <v4l2-buffer>` contains an
45array of struct :ref:`v4l2_plane <v4l2-plane>` structures, each
46containing its own ``m.offset`` and ``length``. When using the
47multi-planar API, every plane of every buffer has to be mapped
48separately, so the number of calls to :ref:`mmap() <func-mmap>` should
49be equal to number of buffers times number of planes in each buffer. The
50offset and length values must not be modified. Remember, the buffers are
51allocated in physical memory, as opposed to virtual memory, which can be
52swapped out to disk. Applications should free the buffers as soon as
53possible with the :ref:`munmap() <func-munmap>` function.
54
55
56.. code-block:: c
Mauro Carvalho Chehab5c591aa2016-07-04 15:47:55 -030057 :caption: Example 3.1. Mapping buffers in the single-planar API
Markus Heiser5377d912016-06-30 15:18:56 +020058
59 struct v4l2_requestbuffers reqbuf;
60 struct {
Mauro Carvalho Chehab6970f292016-07-04 15:58:05 -030061 void *start;
62 size_t length;
Markus Heiser5377d912016-06-30 15:18:56 +020063 } *buffers;
64 unsigned int i;
65
66 memset(&reqbuf, 0, sizeof(reqbuf));
67 reqbuf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
68 reqbuf.memory = V4L2_MEMORY_MMAP;
69 reqbuf.count = 20;
70
71 if (-1 == ioctl (fd, VIDIOC_REQBUFS, &reqbuf)) {
Mauro Carvalho Chehab6970f292016-07-04 15:58:05 -030072 if (errno == EINVAL)
73 printf("Video capturing or mmap-streaming is not supported\\n");
74 else
75 perror("VIDIOC_REQBUFS");
Markus Heiser5377d912016-06-30 15:18:56 +020076
Mauro Carvalho Chehab6970f292016-07-04 15:58:05 -030077 exit(EXIT_FAILURE);
Markus Heiser5377d912016-06-30 15:18:56 +020078 }
79
80 /* We want at least five buffers. */
81
82 if (reqbuf.count < 5) {
Mauro Carvalho Chehab6970f292016-07-04 15:58:05 -030083 /* You may need to free the buffers here. */
84 printf("Not enough buffer memory\\n");
85 exit(EXIT_FAILURE);
Markus Heiser5377d912016-06-30 15:18:56 +020086 }
87
88 buffers = calloc(reqbuf.count, sizeof(*buffers));
89 assert(buffers != NULL);
90
91 for (i = 0; i < reqbuf.count; i++) {
Mauro Carvalho Chehab6970f292016-07-04 15:58:05 -030092 struct v4l2_buffer buffer;
Markus Heiser5377d912016-06-30 15:18:56 +020093
Mauro Carvalho Chehab6970f292016-07-04 15:58:05 -030094 memset(&buffer, 0, sizeof(buffer));
95 buffer.type = reqbuf.type;
96 buffer.memory = V4L2_MEMORY_MMAP;
97 buffer.index = i;
Markus Heiser5377d912016-06-30 15:18:56 +020098
Mauro Carvalho Chehab6970f292016-07-04 15:58:05 -030099 if (-1 == ioctl (fd, VIDIOC_QUERYBUF, &buffer)) {
100 perror("VIDIOC_QUERYBUF");
101 exit(EXIT_FAILURE);
102 }
Markus Heiser5377d912016-06-30 15:18:56 +0200103
Mauro Carvalho Chehab6970f292016-07-04 15:58:05 -0300104 buffers[i].length = buffer.length; /* remember for munmap() */
Markus Heiser5377d912016-06-30 15:18:56 +0200105
Mauro Carvalho Chehab6970f292016-07-04 15:58:05 -0300106 buffers[i].start = mmap(NULL, buffer.length,
107 PROT_READ | PROT_WRITE, /* recommended */
108 MAP_SHARED, /* recommended */
109 fd, buffer.m.offset);
Markus Heiser5377d912016-06-30 15:18:56 +0200110
Mauro Carvalho Chehab6970f292016-07-04 15:58:05 -0300111 if (MAP_FAILED == buffers[i].start) {
112 /* If you do not exit here you should unmap() and free()
113 the buffers mapped so far. */
114 perror("mmap");
115 exit(EXIT_FAILURE);
116 }
Markus Heiser5377d912016-06-30 15:18:56 +0200117 }
118
119 /* Cleanup. */
120
121 for (i = 0; i < reqbuf.count; i++)
Mauro Carvalho Chehab6970f292016-07-04 15:58:05 -0300122 munmap(buffers[i].start, buffers[i].length);
Markus Heiser5377d912016-06-30 15:18:56 +0200123
124
125.. code-block:: c
Mauro Carvalho Chehab5c591aa2016-07-04 15:47:55 -0300126 :caption: Example 3.2. Mapping buffers in the multi-planar API
Markus Heiser5377d912016-06-30 15:18:56 +0200127
128 struct v4l2_requestbuffers reqbuf;
129 /* Our current format uses 3 planes per buffer */
130 #define FMT_NUM_PLANES = 3
131
132 struct {
Mauro Carvalho Chehab6970f292016-07-04 15:58:05 -0300133 void *start[FMT_NUM_PLANES];
134 size_t length[FMT_NUM_PLANES];
Markus Heiser5377d912016-06-30 15:18:56 +0200135 } *buffers;
136 unsigned int i, j;
137
138 memset(&reqbuf, 0, sizeof(reqbuf));
139 reqbuf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
140 reqbuf.memory = V4L2_MEMORY_MMAP;
141 reqbuf.count = 20;
142
143 if (ioctl(fd, VIDIOC_REQBUFS, &reqbuf) < 0) {
Mauro Carvalho Chehab6970f292016-07-04 15:58:05 -0300144 if (errno == EINVAL)
145 printf("Video capturing or mmap-streaming is not supported\\n");
146 else
147 perror("VIDIOC_REQBUFS");
Markus Heiser5377d912016-06-30 15:18:56 +0200148
Mauro Carvalho Chehab6970f292016-07-04 15:58:05 -0300149 exit(EXIT_FAILURE);
Markus Heiser5377d912016-06-30 15:18:56 +0200150 }
151
152 /* We want at least five buffers. */
153
154 if (reqbuf.count < 5) {
Mauro Carvalho Chehab6970f292016-07-04 15:58:05 -0300155 /* You may need to free the buffers here. */
156 printf("Not enough buffer memory\\n");
157 exit(EXIT_FAILURE);
Markus Heiser5377d912016-06-30 15:18:56 +0200158 }
159
160 buffers = calloc(reqbuf.count, sizeof(*buffers));
161 assert(buffers != NULL);
162
163 for (i = 0; i < reqbuf.count; i++) {
Mauro Carvalho Chehab6970f292016-07-04 15:58:05 -0300164 struct v4l2_buffer buffer;
165 struct v4l2_plane planes[FMT_NUM_PLANES];
Markus Heiser5377d912016-06-30 15:18:56 +0200166
Mauro Carvalho Chehab6970f292016-07-04 15:58:05 -0300167 memset(&buffer, 0, sizeof(buffer));
168 buffer.type = reqbuf.type;
169 buffer.memory = V4L2_MEMORY_MMAP;
170 buffer.index = i;
171 /* length in struct v4l2_buffer in multi-planar API stores the size
172 * of planes array. */
173 buffer.length = FMT_NUM_PLANES;
174 buffer.m.planes = planes;
Markus Heiser5377d912016-06-30 15:18:56 +0200175
Mauro Carvalho Chehab6970f292016-07-04 15:58:05 -0300176 if (ioctl(fd, VIDIOC_QUERYBUF, &buffer) < 0) {
177 perror("VIDIOC_QUERYBUF");
178 exit(EXIT_FAILURE);
179 }
Markus Heiser5377d912016-06-30 15:18:56 +0200180
Mauro Carvalho Chehab6970f292016-07-04 15:58:05 -0300181 /* Every plane has to be mapped separately */
182 for (j = 0; j < FMT_NUM_PLANES; j++) {
183 buffers[i].length[j] = buffer.m.planes[j].length; /* remember for munmap() */
Markus Heiser5377d912016-06-30 15:18:56 +0200184
Mauro Carvalho Chehab6970f292016-07-04 15:58:05 -0300185 buffers[i].start[j] = mmap(NULL, buffer.m.planes[j].length,
186 PROT_READ | PROT_WRITE, /* recommended */
187 MAP_SHARED, /* recommended */
188 fd, buffer.m.planes[j].m.offset);
Markus Heiser5377d912016-06-30 15:18:56 +0200189
Mauro Carvalho Chehab6970f292016-07-04 15:58:05 -0300190 if (MAP_FAILED == buffers[i].start[j]) {
191 /* If you do not exit here you should unmap() and free()
192 the buffers and planes mapped so far. */
193 perror("mmap");
194 exit(EXIT_FAILURE);
195 }
196 }
Markus Heiser5377d912016-06-30 15:18:56 +0200197 }
198
199 /* Cleanup. */
200
201 for (i = 0; i < reqbuf.count; i++)
Mauro Carvalho Chehab6970f292016-07-04 15:58:05 -0300202 for (j = 0; j < FMT_NUM_PLANES; j++)
203 munmap(buffers[i].start[j], buffers[i].length[j]);
Markus Heiser5377d912016-06-30 15:18:56 +0200204
205Conceptually streaming drivers maintain two buffer queues, an incoming
206and an outgoing queue. They separate the synchronous capture or output
207operation locked to a video clock from the application which is subject
208to random disk or network delays and preemption by other processes,
209thereby reducing the probability of data loss. The queues are organized
210as FIFOs, buffers will be output in the order enqueued in the incoming
211FIFO, and were captured in the order dequeued from the outgoing FIFO.
212
213The driver may require a minimum number of buffers enqueued at all times
214to function, apart of this no limit exists on the number of buffers
215applications can enqueue in advance, or dequeue and process. They can
216also enqueue in a different order than buffers have been dequeued, and
217the driver can *fill* enqueued *empty* buffers in any order. [2]_ The
218index number of a buffer (struct :ref:`v4l2_buffer <v4l2-buffer>`
219``index``) plays no role here, it only identifies the buffer.
220
221Initially all mapped buffers are in dequeued state, inaccessible by the
222driver. For capturing applications it is customary to first enqueue all
223mapped buffers, then to start capturing and enter the read loop. Here
224the application waits until a filled buffer can be dequeued, and
225re-enqueues the buffer when the data is no longer needed. Output
226applications fill and enqueue buffers, when enough buffers are stacked
Mauro Carvalho Chehab6970f292016-07-04 15:58:05 -0300227up the output is started with :ref:`VIDIOC_STREAMON <VIDIOC_STREAMON>`.
228In the write loop, when the application runs out of free buffers, it
229must wait until an empty buffer can be dequeued and reused.
Markus Heiser5377d912016-06-30 15:18:56 +0200230
Mauro Carvalho Chehab6970f292016-07-04 15:58:05 -0300231To enqueue and dequeue a buffer applications use the :ref:`VIDIOC_QBUF`
232and :ref:`VIDIOC_DQBUF <VIDIOC_QBUF>` ioctl. The status of a buffer
233being mapped, enqueued, full or empty can be determined at any time
234using the :ref:`VIDIOC_QUERYBUF` ioctl. Two methods exist to suspend
235execution of the application until one or more buffers can be dequeued.
236By default :ref:`VIDIOC_DQBUF <VIDIOC_QBUF>` blocks when no buffer is
237in the outgoing queue. When the ``O_NONBLOCK`` flag was given to the
238:ref:`open() <func-open>` function, :ref:`VIDIOC_DQBUF <VIDIOC_QBUF>`
239returns immediately with an ``EAGAIN`` error code when no buffer is
240available. The :ref:`select() <func-select>` or :ref:`poll()
241<func-poll>` functions are always available.
Markus Heiser5377d912016-06-30 15:18:56 +0200242
243To start and stop capturing or output applications call the
Mauro Carvalho Chehab6970f292016-07-04 15:58:05 -0300244:ref:`VIDIOC_STREAMON <VIDIOC_STREAMON>` and :ref:`VIDIOC_STREAMOFF
245<VIDIOC_STREAMON>` ioctl. Note :ref:`VIDIOC_STREAMOFF <VIDIOC_STREAMON>`
246removes all buffers from both queues as a side effect. Since there is
247no notion of doing anything "now" on a multitasking system, if an
248application needs to synchronize with another event it should examine
249the struct ::ref:`v4l2_buffer <v4l2-buffer>` ``timestamp`` of captured
250or outputted buffers.
Markus Heiser5377d912016-06-30 15:18:56 +0200251
252Drivers implementing memory mapping I/O must support the
Mauro Carvalho Chehab6970f292016-07-04 15:58:05 -0300253:ref:`VIDIOC_REQBUFS <VIDIOC_REQBUFS>`, :ref:`VIDIOC_QUERYBUF
254<VIDIOC_QUERYBUF>`, :ref:`VIDIOC_QBUF <VIDIOC_QBUF>`, :ref:`VIDIOC_DQBUF
255<VIDIOC_QBUF>`, :ref:`VIDIOC_STREAMON <VIDIOC_STREAMON>`
256and :ref:`VIDIOC_STREAMOFF <VIDIOC_STREAMON>` ioctls, the :ref:`mmap()
257<func-mmap>`, :ref:`munmap() <func-munmap>`, :ref:`select()
258<func-select>` and :ref:`poll() <func-poll>` function. [3]_
Markus Heiser5377d912016-06-30 15:18:56 +0200259
260[capture example]
261
262.. [1]
263 One could use one file descriptor and set the buffer type field
Mauro Carvalho Chehab73470812016-07-01 13:58:44 -0300264 accordingly when calling :ref:`VIDIOC_QBUF` etc.,
Mauro Carvalho Chehab760c7012016-07-04 12:56:17 -0300265 but it makes the :ref:`select() <func-select>` function ambiguous. We also
Markus Heiser5377d912016-06-30 15:18:56 +0200266 like the clean approach of one file descriptor per logical stream.
267 Video overlay for example is also a logical stream, although the CPU
268 is not needed for continuous operation.
269
270.. [2]
271 Random enqueue order permits applications processing images out of
272 order (such as video codecs) to return buffers earlier, reducing the
273 probability of data loss. Random fill order allows drivers to reuse
274 buffers on a LIFO-basis, taking advantage of caches holding
275 scatter-gather lists and the like.
276
277.. [3]
Mauro Carvalho Chehab760c7012016-07-04 12:56:17 -0300278 At the driver level :ref:`select() <func-select>` and :ref:`poll() <func-poll>` are
279 the same, and :ref:`select() <func-select>` is too important to be optional.
Markus Heiser5377d912016-06-30 15:18:56 +0200280 The rest should be evident.