1 .. SPDX-License-Identifier: GFDL-1.1-no-invari 2 .. c:namespace:: V4L 3 4 .. _mmap: 5 6 ****************************** 7 Streaming I/O (Memory Mapping) 8 ****************************** 9 10 Input and output devices support this I/O meth 11 ``V4L2_CAP_STREAMING`` flag in the ``capabilit 12 :c:type:`v4l2_capability` returned by the 13 :ref:`VIDIOC_QUERYCAP` ioctl is set. There are 14 streaming methods, to determine if the memory 15 supported applications must call the :ref:`VID 16 with the memory type set to ``V4L2_MEMORY_MMAP 17 18 Streaming is an I/O method where only pointers 19 between application and driver, the data itsel 20 mapping is primarily intended to map buffers i 21 application's address space. Device memory can 22 memory on a graphics card with a video capture 23 the most efficient I/O method available for a 24 drivers support streaming as well, allocating 25 memory. 26 27 A driver can support many sets of buffers. Eac 28 unique buffer type value. The sets are indepen 29 a different type of data. To access different 30 different file descriptors must be used. [#f1] 31 32 To allocate device buffers applications call t 33 :ref:`VIDIOC_REQBUFS` ioctl with the desired n 34 of buffers and buffer type, for example ``V4L2 35 This ioctl can also be used to change the numb 36 the allocated memory, provided none of the buf 37 38 Before applications can access the buffers the 39 address space with the :c:func:`mmap()` functi 40 location of the buffers in device memory can b 41 :ref:`VIDIOC_QUERYBUF` ioctl. In the single-pl 42 API case, the ``m.offset`` and ``length`` retu 43 :c:type:`v4l2_buffer` are passed as sixth and 44 parameter to the :c:func:`mmap()` function. Wh 45 multi-planar API, struct :c:type:`v4l2_buffer` 46 array of struct :c:type:`v4l2_plane` structure 47 containing its own ``m.offset`` and ``length`` 48 multi-planar API, every plane of every buffer 49 separately, so the number of calls to :c:func: 50 be equal to number of buffers times number of 51 offset and length values must not be modified. 52 allocated in physical memory, as opposed to vi 53 swapped out to disk. Applications should free 54 possible with the :c:func:`munmap()` function. 55 56 Example: Mapping buffers in the single-planar 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, &reqb 74 if (errno == EINVAL) 75 printf("Video capturing or mmap-st 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 he 86 printf("Not enough buffer memory\\n"); 87 exit(EXIT_FAILURE); 88 } 89 90 buffers = calloc(reqbuf.count, sizeof(*buf 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, 102 perror("VIDIOC_QUERYBUF"); 103 exit(EXIT_FAILURE); 104 } 105 106 buffers[i].length = buffer.length; /* 107 108 buffers[i].start = mmap(NULL, buffer.l 109 PROT_READ | PROT_WRITE, /* 110 MAP_SHARED, /* 111 fd, buffer.m.offset); 112 113 if (MAP_FAILED == buffers[i].start) { 114 /* If you do not exit here you sho 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].le 125 126 Example: Mapping buffers in the multi-planar A 127 ============================================== 128 129 .. code-block:: c 130 131 struct v4l2_requestbuffers reqbuf; 132 /* Our current format uses 3 planes per bu 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_ 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-st 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 he 159 printf("Not enough buffer memory\\n"); 160 exit(EXIT_FAILURE); 161 } 162 163 buffers = calloc(reqbuf.count, sizeof(*buf 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_PLANE 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 mul 175 * of planes array. */ 176 buffer.length = FMT_NUM_PLANES; 177 buffer.m.planes = planes; 178 179 if (ioctl(fd, VIDIOC_QUERYBUF, &buffer 180 perror("VIDIOC_QUERYBUF"); 181 exit(EXIT_FAILURE); 182 } 183 184 /* Every plane has to be mapped separa 185 for (j = 0; j < FMT_NUM_PLANES; j++) { 186 buffers[i].length[j] = buffer.m.pl 187 188 buffers[i].start[j] = mmap(NULL, b 189 PROT_READ | PROT_WRITE, / 190 MAP_SHARED, / 191 fd, buffer.m.planes[j].m. 192 193 if (MAP_FAILED == buffers[i].start 194 /* If you do not exit here you 195 the buffers and planes mapp 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], buffer 207 208 Conceptually streaming drivers maintain two bu 209 and an outgoing queue. They separate the synch 210 operation locked to a video clock from the app 211 to random disk or network delays and preemptio 212 thereby reducing the probability of data loss. 213 as FIFOs, buffers will be output in the order 214 FIFO, and were captured in the order dequeued 215 216 The driver may require a minimum number of buf 217 to function, apart of this no limit exists on 218 applications can enqueue in advance, or dequeu 219 also enqueue in a different order than buffers 220 the driver can *fill* enqueued *empty* buffers 221 index number of a buffer (struct :c:type:`v4l2 222 ``index``) plays no role here, it only identif 223 224 Initially all mapped buffers are in dequeued s 225 driver. For capturing applications it is custo 226 mapped buffers, then to start capturing and en 227 the application waits until a filled buffer ca 228 re-enqueues the buffer when the data is no lon 229 applications fill and enqueue buffers, when en 230 up the output is started with :ref:`VIDIOC_STR 231 In the write loop, when the application runs o 232 must wait until an empty buffer can be dequeue 233 234 To enqueue and dequeue a buffer applications u 235 :ref:`VIDIOC_QBUF <VIDIOC_QBUF>` and :ref:`VID 236 ioctl. The status of a buffer being mapped, en 237 be determined at any time using the :ref:`VIDI 238 methods exist to suspend execution of the appl 239 buffers can be dequeued. By default :ref:`VID 240 blocks when no buffer is in the outgoing queue 241 flag was given to the :c:func:`open()` functio 242 :ref:`VIDIOC_DQBUF <VIDIOC_QBUF>` returns imme 243 error code when no buffer is available. The :c 244 or :c:func:`poll()` functions are always avail 245 246 To start and stop capturing or output applicat 247 :ref:`VIDIOC_STREAMON <VIDIOC_STREAMON>` and : 248 <VIDIOC_STREAMON>` ioctl. 249 250 .. note:::ref:`VIDIOC_STREAMOFF <VIDIOC_STREAM 251 removes all buffers from both queues as a s 252 no notion of doing anything "now" on a mult 253 application needs to synchronize with anoth 254 the struct ::c:type:`v4l2_buffer` ``timesta 255 or outputted buffers. 256 257 Drivers implementing memory mapping I/O must s 258 :ref:`VIDIOC_REQBUFS <VIDIOC_REQBUFS>`, :ref:` 259 <VIDIOC_QUERYBUF>`, :ref:`VIDIOC_QBUF <VIDIOC_ 260 <VIDIOC_QBUF>`, :ref:`VIDIOC_STREAMON <VIDIOC_ 261 and :ref:`VIDIOC_STREAMOFF <VIDIOC_STREAMON>` 262 <func-mmap>`, :c:func:`munmap()`, :ref:`select 263 <func-select>` and :c:func:`poll()` function. 264 265 [capture example] 266 267 .. [#f1] 268 One could use one file descriptor and set t 269 accordingly when calling :ref:`VIDIOC_QBUF` 270 but it makes the :c:func:`select()` functio 271 like the clean approach of one file descrip 272 Video overlay for example is also a logical 273 is not needed for continuous operation. 274 275 .. [#f2] 276 Random enqueue order permits applications p 277 order (such as video codecs) to return buff 278 probability of data loss. Random fill order 279 buffers on a LIFO-basis, taking advantage o 280 scatter-gather lists and the like. 281 282 .. [#f3] 283 At the driver level :c:func:`select()` and 284 the same, and :c:func:`select()` is too imp 285 The rest should be evident.
Linux® is a registered trademark of Linus Torvalds in the United States and other countries.
TOMOYO® is a registered trademark of NTT DATA CORPORATION.