xref: /linux/Documentation/userspace-api/media/v4l/mmap.rst (revision 58f6259b7a08f8d47d4629609703d358b042f0fd)
1.. SPDX-License-Identifier: GFDL-1.1-no-invariants-or-later
2.. c:namespace:: V4L
3
4.. _mmap:
5
6******************************
7Streaming I/O (Memory Mapping)
8******************************
9
10Input and output devices support this I/O method when the
11``V4L2_CAP_STREAMING`` flag in the ``capabilities`` field of struct
12:c:type:`v4l2_capability` returned by the
13:ref:`VIDIOC_QUERYCAP` ioctl is set. There are two
14streaming methods, to determine if the memory mapping flavor is
15supported applications must call the :ref:`VIDIOC_REQBUFS` ioctl
16with the memory type set to ``V4L2_MEMORY_MMAP``.
17
18Streaming is an I/O method where only pointers to buffers are exchanged
19between application and driver, the data itself is not copied. Memory
20mapping is primarily intended to map buffers in device memory into the
21application's address space. Device memory can be for example the video
22memory on a graphics card with a video capture add-on. However, being
23the most efficient I/O method available for a long time, many other
24drivers support streaming as well, allocating buffers in DMA-able main
25memory.
26
27A driver can support many sets of buffers. Each set is identified by a
28unique buffer type value. The sets are independent and each set can hold
29a different type of data. To access different sets at the same time
30different file descriptors must be used. [#f1]_
31
32To allocate device buffers applications call the
33:ref:`VIDIOC_REQBUFS` ioctl with the desired number
34of buffers and buffer type, for example ``V4L2_BUF_TYPE_VIDEO_CAPTURE``.
35This ioctl can also be used to change the number of buffers or to free
36the allocated memory, provided none of the buffers are still mapped.
37
38Before applications can access the buffers they must map them into their
39address space with the :c:func:`mmap()` function. The
40location of the buffers in device memory can be determined with the
41:ref:`VIDIOC_QUERYBUF` ioctl. In the single-planar
42API case, the ``m.offset`` and ``length`` returned in a struct
43:c:type:`v4l2_buffer` are passed as sixth and second
44parameter to the :c:func:`mmap()` function. When using the
45multi-planar API, struct :c:type:`v4l2_buffer` contains an
46array of struct :c:type:`v4l2_plane` structures, each
47containing its own ``m.offset`` and ``length``. When using the
48multi-planar API, every plane of every buffer has to be mapped
49separately, so the number of calls to :c:func:`mmap()` should
50be equal to number of buffers times number of planes in each buffer. The
51offset and length values must not be modified. Remember, the buffers are
52allocated in physical memory, as opposed to virtual memory, which can be
53swapped out to disk. Applications should free the buffers as soon as
54possible with the :c:func:`munmap()` function.
55
56Example: Mapping buffers in the single-planar API
57=================================================
58
59.. code-block:: c
60
61    struct v4l2_requestbuffers reqbuf;
62    struct {
63	void *start;
64	size_t length;
65    } *buffers;
66    unsigned int i;
67
68    memset(&reqbuf, 0, sizeof(reqbuf));
69    reqbuf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
70    reqbuf.memory = V4L2_MEMORY_MMAP;
71    reqbuf.count = 20;
72
73    if (-1 == ioctl (fd, VIDIOC_REQBUFS, &reqbuf)) {
74	if (errno == EINVAL)
75	    printf("Video capturing or mmap-streaming is not supported\\n");
76	else
77	    perror("VIDIOC_REQBUFS");
78
79	exit(EXIT_FAILURE);
80    }
81
82    /* We want at least five buffers. */
83
84    if (reqbuf.count < 5) {
85	/* You may need to free the buffers here. */
86	printf("Not enough buffer memory\\n");
87	exit(EXIT_FAILURE);
88    }
89
90    buffers = calloc(reqbuf.count, sizeof(*buffers));
91    assert(buffers != NULL);
92
93    for (i = 0; i < reqbuf.count; i++) {
94	struct v4l2_buffer buffer;
95
96	memset(&buffer, 0, sizeof(buffer));
97	buffer.type = reqbuf.type;
98	buffer.memory = V4L2_MEMORY_MMAP;
99	buffer.index = i;
100
101	if (-1 == ioctl (fd, VIDIOC_QUERYBUF, &buffer)) {
102	    perror("VIDIOC_QUERYBUF");
103	    exit(EXIT_FAILURE);
104	}
105
106	buffers[i].length = buffer.length; /* remember for munmap() */
107
108	buffers[i].start = mmap(NULL, buffer.length,
109		    PROT_READ | PROT_WRITE, /* recommended */
110		    MAP_SHARED,             /* recommended */
111		    fd, buffer.m.offset);
112
113	if (MAP_FAILED == buffers[i].start) {
114	    /* If you do not exit here you should unmap() and free()
115	       the buffers mapped so far. */
116	    perror("mmap");
117	    exit(EXIT_FAILURE);
118	}
119    }
120
121    /* Cleanup. */
122
123    for (i = 0; i < reqbuf.count; i++)
124	munmap(buffers[i].start, buffers[i].length);
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:`VIDIOC_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 :c:func:`open()` function,
242:ref:`VIDIOC_DQBUF <VIDIOC_QBUF>` returns immediately with an ``EAGAIN``
243error code when no buffer is available. The :c:func:`select()`
244or :c: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>`, :c:func:`munmap()`, :ref:`select()
263<func-select>` and :c: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 :c: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 :c:func:`select()` and :c:func:`poll()` are
284   the same, and :c:func:`select()` is too important to be optional.
285   The rest should be evident.
286