0001 .. SPDX-License-Identifier: GFDL-1.1-no-invariants-or-later
0002 .. c:namespace:: V4L
0003
0004 .. _mmap:
0005
0006 ******************************
0007 Streaming I/O (Memory Mapping)
0008 ******************************
0009
0010 Input and output devices support this I/O method when the
0011 ``V4L2_CAP_STREAMING`` flag in the ``capabilities`` field of struct
0012 :c:type:`v4l2_capability` returned by the
0013 :ref:`VIDIOC_QUERYCAP` ioctl is set. There are two
0014 streaming methods, to determine if the memory mapping flavor is
0015 supported applications must call the :ref:`VIDIOC_REQBUFS` ioctl
0016 with the memory type set to ``V4L2_MEMORY_MMAP``.
0017
0018 Streaming is an I/O method where only pointers to buffers are exchanged
0019 between application and driver, the data itself is not copied. Memory
0020 mapping is primarily intended to map buffers in device memory into the
0021 application's address space. Device memory can be for example the video
0022 memory on a graphics card with a video capture add-on. However, being
0023 the most efficient I/O method available for a long time, many other
0024 drivers support streaming as well, allocating buffers in DMA-able main
0025 memory.
0026
0027 A driver can support many sets of buffers. Each set is identified by a
0028 unique buffer type value. The sets are independent and each set can hold
0029 a different type of data. To access different sets at the same time
0030 different file descriptors must be used. [#f1]_
0031
0032 To allocate device buffers applications call the
0033 :ref:`VIDIOC_REQBUFS` ioctl with the desired number
0034 of buffers and buffer type, for example ``V4L2_BUF_TYPE_VIDEO_CAPTURE``.
0035 This ioctl can also be used to change the number of buffers or to free
0036 the allocated memory, provided none of the buffers are still mapped.
0037
0038 Before applications can access the buffers they must map them into their
0039 address space with the :c:func:`mmap()` function. The
0040 location of the buffers in device memory can be determined with the
0041 :ref:`VIDIOC_QUERYBUF` ioctl. In the single-planar
0042 API case, the ``m.offset`` and ``length`` returned in a struct
0043 :c:type:`v4l2_buffer` are passed as sixth and second
0044 parameter to the :c:func:`mmap()` function. When using the
0045 multi-planar API, struct :c:type:`v4l2_buffer` contains an
0046 array of struct :c:type:`v4l2_plane` structures, each
0047 containing its own ``m.offset`` and ``length``. When using the
0048 multi-planar API, every plane of every buffer has to be mapped
0049 separately, so the number of calls to :c:func:`mmap()` should
0050 be equal to number of buffers times number of planes in each buffer. The
0051 offset and length values must not be modified. Remember, the buffers are
0052 allocated in physical memory, as opposed to virtual memory, which can be
0053 swapped out to disk. Applications should free the buffers as soon as
0054 possible with the :c:func:`munmap()` function.
0055
0056 Example: Mapping buffers in the single-planar API
0057 =================================================
0058
0059 .. code-block:: c
0060
0061 struct v4l2_requestbuffers reqbuf;
0062 struct {
0063 void *start;
0064 size_t length;
0065 } *buffers;
0066 unsigned int i;
0067
0068 memset(&reqbuf, 0, sizeof(reqbuf));
0069 reqbuf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
0070 reqbuf.memory = V4L2_MEMORY_MMAP;
0071 reqbuf.count = 20;
0072
0073 if (-1 == ioctl (fd, VIDIOC_REQBUFS, &reqbuf)) {
0074 if (errno == EINVAL)
0075 printf("Video capturing or mmap-streaming is not supported\\n");
0076 else
0077 perror("VIDIOC_REQBUFS");
0078
0079 exit(EXIT_FAILURE);
0080 }
0081
0082 /* We want at least five buffers. */
0083
0084 if (reqbuf.count < 5) {
0085 /* You may need to free the buffers here. */
0086 printf("Not enough buffer memory\\n");
0087 exit(EXIT_FAILURE);
0088 }
0089
0090 buffers = calloc(reqbuf.count, sizeof(*buffers));
0091 assert(buffers != NULL);
0092
0093 for (i = 0; i < reqbuf.count; i++) {
0094 struct v4l2_buffer buffer;
0095
0096 memset(&buffer, 0, sizeof(buffer));
0097 buffer.type = reqbuf.type;
0098 buffer.memory = V4L2_MEMORY_MMAP;
0099 buffer.index = i;
0100
0101 if (-1 == ioctl (fd, VIDIOC_QUERYBUF, &buffer)) {
0102 perror("VIDIOC_QUERYBUF");
0103 exit(EXIT_FAILURE);
0104 }
0105
0106 buffers[i].length = buffer.length; /* remember for munmap() */
0107
0108 buffers[i].start = mmap(NULL, buffer.length,
0109 PROT_READ | PROT_WRITE, /* recommended */
0110 MAP_SHARED, /* recommended */
0111 fd, buffer.m.offset);
0112
0113 if (MAP_FAILED == buffers[i].start) {
0114 /* If you do not exit here you should unmap() and free()
0115 the buffers mapped so far. */
0116 perror("mmap");
0117 exit(EXIT_FAILURE);
0118 }
0119 }
0120
0121 /* Cleanup. */
0122
0123 for (i = 0; i < reqbuf.count; i++)
0124 munmap(buffers[i].start, buffers[i].length);
0125
0126 Example: Mapping buffers in the multi-planar API
0127 ================================================
0128
0129 .. code-block:: c
0130
0131 struct v4l2_requestbuffers reqbuf;
0132 /* Our current format uses 3 planes per buffer */
0133 #define FMT_NUM_PLANES = 3
0134
0135 struct {
0136 void *start[FMT_NUM_PLANES];
0137 size_t length[FMT_NUM_PLANES];
0138 } *buffers;
0139 unsigned int i, j;
0140
0141 memset(&reqbuf, 0, sizeof(reqbuf));
0142 reqbuf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
0143 reqbuf.memory = V4L2_MEMORY_MMAP;
0144 reqbuf.count = 20;
0145
0146 if (ioctl(fd, VIDIOC_REQBUFS, &reqbuf) < 0) {
0147 if (errno == EINVAL)
0148 printf("Video capturing or mmap-streaming is not supported\\n");
0149 else
0150 perror("VIDIOC_REQBUFS");
0151
0152 exit(EXIT_FAILURE);
0153 }
0154
0155 /* We want at least five buffers. */
0156
0157 if (reqbuf.count < 5) {
0158 /* You may need to free the buffers here. */
0159 printf("Not enough buffer memory\\n");
0160 exit(EXIT_FAILURE);
0161 }
0162
0163 buffers = calloc(reqbuf.count, sizeof(*buffers));
0164 assert(buffers != NULL);
0165
0166 for (i = 0; i < reqbuf.count; i++) {
0167 struct v4l2_buffer buffer;
0168 struct v4l2_plane planes[FMT_NUM_PLANES];
0169
0170 memset(&buffer, 0, sizeof(buffer));
0171 buffer.type = reqbuf.type;
0172 buffer.memory = V4L2_MEMORY_MMAP;
0173 buffer.index = i;
0174 /* length in struct v4l2_buffer in multi-planar API stores the size
0175 * of planes array. */
0176 buffer.length = FMT_NUM_PLANES;
0177 buffer.m.planes = planes;
0178
0179 if (ioctl(fd, VIDIOC_QUERYBUF, &buffer) < 0) {
0180 perror("VIDIOC_QUERYBUF");
0181 exit(EXIT_FAILURE);
0182 }
0183
0184 /* Every plane has to be mapped separately */
0185 for (j = 0; j < FMT_NUM_PLANES; j++) {
0186 buffers[i].length[j] = buffer.m.planes[j].length; /* remember for munmap() */
0187
0188 buffers[i].start[j] = mmap(NULL, buffer.m.planes[j].length,
0189 PROT_READ | PROT_WRITE, /* recommended */
0190 MAP_SHARED, /* recommended */
0191 fd, buffer.m.planes[j].m.offset);
0192
0193 if (MAP_FAILED == buffers[i].start[j]) {
0194 /* If you do not exit here you should unmap() and free()
0195 the buffers and planes mapped so far. */
0196 perror("mmap");
0197 exit(EXIT_FAILURE);
0198 }
0199 }
0200 }
0201
0202 /* Cleanup. */
0203
0204 for (i = 0; i < reqbuf.count; i++)
0205 for (j = 0; j < FMT_NUM_PLANES; j++)
0206 munmap(buffers[i].start[j], buffers[i].length[j]);
0207
0208 Conceptually streaming drivers maintain two buffer queues, an incoming
0209 and an outgoing queue. They separate the synchronous capture or output
0210 operation locked to a video clock from the application which is subject
0211 to random disk or network delays and preemption by other processes,
0212 thereby reducing the probability of data loss. The queues are organized
0213 as FIFOs, buffers will be output in the order enqueued in the incoming
0214 FIFO, and were captured in the order dequeued from the outgoing FIFO.
0215
0216 The driver may require a minimum number of buffers enqueued at all times
0217 to function, apart of this no limit exists on the number of buffers
0218 applications can enqueue in advance, or dequeue and process. They can
0219 also enqueue in a different order than buffers have been dequeued, and
0220 the driver can *fill* enqueued *empty* buffers in any order. [#f2]_ The
0221 index number of a buffer (struct :c:type:`v4l2_buffer`
0222 ``index``) plays no role here, it only identifies the buffer.
0223
0224 Initially all mapped buffers are in dequeued state, inaccessible by the
0225 driver. For capturing applications it is customary to first enqueue all
0226 mapped buffers, then to start capturing and enter the read loop. Here
0227 the application waits until a filled buffer can be dequeued, and
0228 re-enqueues the buffer when the data is no longer needed. Output
0229 applications fill and enqueue buffers, when enough buffers are stacked
0230 up the output is started with :ref:`VIDIOC_STREAMON <VIDIOC_STREAMON>`.
0231 In the write loop, when the application runs out of free buffers, it
0232 must wait until an empty buffer can be dequeued and reused.
0233
0234 To enqueue and dequeue a buffer applications use the
0235 :ref:`VIDIOC_QBUF <VIDIOC_QBUF>` and :ref:`VIDIOC_DQBUF <VIDIOC_QBUF>`
0236 ioctl. The status of a buffer being mapped, enqueued, full or empty can
0237 be determined at any time using the :ref:`VIDIOC_QUERYBUF` ioctl. Two
0238 methods exist to suspend execution of the application until one or more
0239 buffers can be dequeued. By default :ref:`VIDIOC_DQBUF <VIDIOC_QBUF>`
0240 blocks when no buffer is in the outgoing queue. When the ``O_NONBLOCK``
0241 flag was given to the :c:func:`open()` function,
0242 :ref:`VIDIOC_DQBUF <VIDIOC_QBUF>` returns immediately with an ``EAGAIN``
0243 error code when no buffer is available. The :c:func:`select()`
0244 or :c:func:`poll()` functions are always available.
0245
0246 To start and stop capturing or output applications call the
0247 :ref:`VIDIOC_STREAMON <VIDIOC_STREAMON>` and :ref:`VIDIOC_STREAMOFF
0248 <VIDIOC_STREAMON>` ioctl.
0249
0250 .. note:::ref:`VIDIOC_STREAMOFF <VIDIOC_STREAMON>`
0251 removes all buffers from both queues as a side effect. Since there is
0252 no notion of doing anything "now" on a multitasking system, if an
0253 application needs to synchronize with another event it should examine
0254 the struct ::c:type:`v4l2_buffer` ``timestamp`` of captured
0255 or outputted buffers.
0256
0257 Drivers implementing memory mapping I/O must support the
0258 :ref:`VIDIOC_REQBUFS <VIDIOC_REQBUFS>`, :ref:`VIDIOC_QUERYBUF
0259 <VIDIOC_QUERYBUF>`, :ref:`VIDIOC_QBUF <VIDIOC_QBUF>`, :ref:`VIDIOC_DQBUF
0260 <VIDIOC_QBUF>`, :ref:`VIDIOC_STREAMON <VIDIOC_STREAMON>`
0261 and :ref:`VIDIOC_STREAMOFF <VIDIOC_STREAMON>` ioctls, the :ref:`mmap()
0262 <func-mmap>`, :c:func:`munmap()`, :ref:`select()
0263 <func-select>` and :c:func:`poll()` function. [#f3]_
0264
0265 [capture example]
0266
0267 .. [#f1]
0268 One could use one file descriptor and set the buffer type field
0269 accordingly when calling :ref:`VIDIOC_QBUF` etc.,
0270 but it makes the :c:func:`select()` function ambiguous. We also
0271 like the clean approach of one file descriptor per logical stream.
0272 Video overlay for example is also a logical stream, although the CPU
0273 is not needed for continuous operation.
0274
0275 .. [#f2]
0276 Random enqueue order permits applications processing images out of
0277 order (such as video codecs) to return buffers earlier, reducing the
0278 probability of data loss. Random fill order allows drivers to reuse
0279 buffers on a LIFO-basis, taking advantage of caches holding
0280 scatter-gather lists and the like.
0281
0282 .. [#f3]
0283 At the driver level :c:func:`select()` and :c:func:`poll()` are
0284 the same, and :c:func:`select()` is too important to be optional.
0285 The rest should be evident.