1.. SPDX-License-Identifier: GFDL-1.1-no-invariants-or-later
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:c:type:`v4l2_capability` returned by the
12:ref:`VIDIOC_QUERYCAP` ioctl is set. There are two
13streaming methods, to determine if the memory mapping flavor is
14supported applications must call the :ref:`VIDIOC_REQBUFS` ioctl
15with the memory type set to ``V4L2_MEMORY_MMAP``.
16
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. [#f1]_
30
31To allocate device buffers applications call the
32:ref:`VIDIOC_REQBUFS` ioctl with the desired number
33of 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
40:ref:`VIDIOC_QUERYBUF` ioctl. In the single-planar
41API case, the ``m.offset`` and ``length`` returned in a struct
42:c:type:`v4l2_buffer` are passed as sixth and second
43parameter to the :ref:`mmap() <func-mmap>` function. When using the
44multi-planar API, struct :c:type:`v4l2_buffer` contains an
45array of struct :c:type:`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
55Example: Mapping buffers in the single-planar API
56=================================================
57
58.. code-block:: c
59
60    struct v4l2_requestbuffers reqbuf;
61    struct {
62	void *start;
63	size_t length;
64    } *buffers;
65    unsigned int i;
66
67    memset(&reqbuf, 0, sizeof(reqbuf));
68    reqbuf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
69    reqbuf.memory = V4L2_MEMORY_MMAP;
70    reqbuf.count = 20;
71
72    if (-1 == ioctl (fd, VIDIOC_REQBUFS, &reqbuf)) {
73	if (errno == EINVAL)
74	    printf("Video capturing or mmap-streaming is not supported\\n");
75	else
76	    perror("VIDIOC_REQBUFS");
77
78	exit(EXIT_FAILURE);
79    }
80
81    /* We want at least five buffers. */
82
83    if (reqbuf.count < 5) {
84	/* You may need to free the buffers here. */
85	printf("Not enough buffer memory\\n");
86	exit(EXIT_FAILURE);
87    }
88
89    buffers = calloc(reqbuf.count, sizeof(*buffers));
90    assert(buffers != NULL);
91
92    for (i = 0; i < reqbuf.count; i++) {
93	struct v4l2_buffer buffer;
94
95	memset(&buffer, 0, sizeof(buffer));
96	buffer.type = reqbuf.type;
97	buffer.memory = V4L2_MEMORY_MMAP;
98	buffer.index = i;
99
100	if (-1 == ioctl (fd, VIDIOC_QUERYBUF, &buffer)) {
101	    perror("VIDIOC_QUERYBUF");
102	    exit(EXIT_FAILURE);
103	}
104
105	buffers[i].length = buffer.length; /* remember for munmap() */
106
107	buffers[i].start = mmap(NULL, buffer.length,
108		    PROT_READ | PROT_WRITE, /* recommended */
109		    MAP_SHARED,             /* recommended */
110		    fd, buffer.m.offset);
111
112	if (MAP_FAILED == buffers[i].start) {
113	    /* If you do not exit here you should unmap() and free()
114	       the buffers mapped so far. */
115	    perror("mmap");
116	    exit(EXIT_FAILURE);
117	}
118    }
119
120    /* Cleanup. */
121
122    for (i = 0; i < reqbuf.count; i++)
123	munmap(buffers[i].start, buffers[i].length);
124
125
126Example: Mapping buffers in the multi-planar API
127================================================
128
129.. code-block:: c
130
131    struct v4l2_requestbuffers reqbuf;
132    /* Our current format uses 3 planes per buffer */
133    #define FMT_NUM_PLANES = 3
134
135    struct {
136	void *start[FMT_NUM_PLANES];
137	size_t length[FMT_NUM_PLANES];
138    } *buffers;
139    unsigned int i, j;
140
141    memset(&reqbuf, 0, sizeof(reqbuf));
142    reqbuf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
143    reqbuf.memory = V4L2_MEMORY_MMAP;
144    reqbuf.count = 20;
145
146    if (ioctl(fd, VIDIOC_REQBUFS, &reqbuf) < 0) {
147	if (errno == EINVAL)
148	    printf("Video capturing or mmap-streaming is not supported\\n");
149	else
150	    perror("VIDIOC_REQBUFS");
151
152	exit(EXIT_FAILURE);
153    }
154
155    /* We want at least five buffers. */
156
157    if (reqbuf.count < 5) {
158	/* You may need to free the buffers here. */
159	printf("Not enough buffer memory\\n");
160	exit(EXIT_FAILURE);
161    }
162
163    buffers = calloc(reqbuf.count, sizeof(*buffers));
164    assert(buffers != NULL);
165
166    for (i = 0; i < reqbuf.count; i++) {
167	struct v4l2_buffer buffer;
168	struct v4l2_plane planes[FMT_NUM_PLANES];
169
170	memset(&buffer, 0, sizeof(buffer));
171	buffer.type = reqbuf.type;
172	buffer.memory = V4L2_MEMORY_MMAP;
173	buffer.index = i;
174	/* length in struct v4l2_buffer in multi-planar API stores the size
175	 * of planes array. */
176	buffer.length = FMT_NUM_PLANES;
177	buffer.m.planes = planes;
178
179	if (ioctl(fd, VIDIOC_QUERYBUF, &buffer) < 0) {
180	    perror("VIDIOC_QUERYBUF");
181	    exit(EXIT_FAILURE);
182	}
183
184	/* Every plane has to be mapped separately */
185	for (j = 0; j < FMT_NUM_PLANES; j++) {
186	    buffers[i].length[j] = buffer.m.planes[j].length; /* remember for munmap() */
187
188	    buffers[i].start[j] = mmap(NULL, buffer.m.planes[j].length,
189		     PROT_READ | PROT_WRITE, /* recommended */
190		     MAP_SHARED,             /* recommended */
191		     fd, buffer.m.planes[j].m.offset);
192
193	    if (MAP_FAILED == buffers[i].start[j]) {
194		/* If you do not exit here you should unmap() and free()
195		   the buffers and planes mapped so far. */
196		perror("mmap");
197		exit(EXIT_FAILURE);
198	    }
199	}
200    }
201
202    /* Cleanup. */
203
204    for (i = 0; i < reqbuf.count; i++)
205	for (j = 0; j < FMT_NUM_PLANES; j++)
206	    munmap(buffers[i].start[j], buffers[i].length[j]);
207
208Conceptually streaming drivers maintain two buffer queues, an incoming
209and an outgoing queue. They separate the synchronous capture or output
210operation locked to a video clock from the application which is subject
211to random disk or network delays and preemption by other processes,
212thereby reducing the probability of data loss. The queues are organized
213as FIFOs, buffers will be output in the order enqueued in the incoming
214FIFO, and were captured in the order dequeued from the outgoing FIFO.
215
216The driver may require a minimum number of buffers enqueued at all times
217to function, apart of this no limit exists on the number of buffers
218applications can enqueue in advance, or dequeue and process. They can
219also enqueue in a different order than buffers have been dequeued, and
220the driver can *fill* enqueued *empty* buffers in any order.  [#f2]_ The
221index number of a buffer (struct :c:type:`v4l2_buffer`
222``index``) plays no role here, it only identifies the buffer.
223
224Initially all mapped buffers are in dequeued state, inaccessible by the
225driver. For capturing applications it is customary to first enqueue all
226mapped buffers, then to start capturing and enter the read loop. Here
227the application waits until a filled buffer can be dequeued, and
228re-enqueues the buffer when the data is no longer needed. Output
229applications fill and enqueue buffers, when enough buffers are stacked
230up the output is started with :ref:`VIDIOC_STREAMON <VIDIOC_STREAMON>`.
231In the write loop, when the application runs out of free buffers, it
232must wait until an empty buffer can be dequeued and reused.
233
234To enqueue and dequeue a buffer applications use the
235:ref:`VIVIOC_QBUF <VIDIOC_QBUF>` and :ref:`VIDIOC_DQBUF <VIDIOC_QBUF>`
236ioctl. The status of a buffer being mapped, enqueued, full or empty can
237be determined at any time using the :ref:`VIDIOC_QUERYBUF` ioctl. Two
238methods exist to suspend execution of the application until one or more
239buffers can be dequeued.  By default :ref:`VIDIOC_DQBUF <VIDIOC_QBUF>`
240blocks when no buffer is in the outgoing queue. When the ``O_NONBLOCK``
241flag was given to the :ref:`open() <func-open>` function,
242:ref:`VIDIOC_DQBUF <VIDIOC_QBUF>` returns immediately with an ``EAGAIN``
243error code when no buffer is available. The :ref:`select() <func-select>`
244or :ref:`poll() <func-poll>` functions are always available.
245
246To start and stop capturing or output applications call the
247:ref:`VIDIOC_STREAMON <VIDIOC_STREAMON>` and :ref:`VIDIOC_STREAMOFF
248<VIDIOC_STREAMON>` ioctl.
249
250.. note:::ref:`VIDIOC_STREAMOFF <VIDIOC_STREAMON>`
251   removes all buffers from both queues as a side effect. Since there is
252   no notion of doing anything "now" on a multitasking system, if an
253   application needs to synchronize with another event it should examine
254   the struct ::c:type:`v4l2_buffer` ``timestamp`` of captured
255   or outputted buffers.
256
257Drivers implementing memory mapping I/O must support the
258:ref:`VIDIOC_REQBUFS <VIDIOC_REQBUFS>`, :ref:`VIDIOC_QUERYBUF
259<VIDIOC_QUERYBUF>`, :ref:`VIDIOC_QBUF <VIDIOC_QBUF>`, :ref:`VIDIOC_DQBUF
260<VIDIOC_QBUF>`, :ref:`VIDIOC_STREAMON <VIDIOC_STREAMON>`
261and :ref:`VIDIOC_STREAMOFF <VIDIOC_STREAMON>` ioctls, the :ref:`mmap()
262<func-mmap>`, :ref:`munmap() <func-munmap>`, :ref:`select()
263<func-select>` and :ref:`poll() <func-poll>` function. [#f3]_
264
265[capture example]
266
267.. [#f1]
268   One could use one file descriptor and set the buffer type field
269   accordingly when calling :ref:`VIDIOC_QBUF` etc.,
270   but it makes the :ref:`select() <func-select>` function ambiguous. We also
271   like the clean approach of one file descriptor per logical stream.
272   Video overlay for example is also a logical stream, although the CPU
273   is not needed for continuous operation.
274
275.. [#f2]
276   Random enqueue order permits applications processing images out of
277   order (such as video codecs) to return buffers earlier, reducing the
278   probability of data loss. Random fill order allows drivers to reuse
279   buffers on a LIFO-basis, taking advantage of caches holding
280   scatter-gather lists and the like.
281
282.. [#f3]
283   At the driver level :ref:`select() <func-select>` and :ref:`poll() <func-poll>` are
284   the same, and :ref:`select() <func-select>` is too important to be optional.
285   The rest should be evident.
286