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