1*4882a593Smuzhiyun.. SPDX-License-Identifier: GFDL-1.1-no-invariants-or-later 2*4882a593Smuzhiyun.. c:namespace:: V4L 3*4882a593Smuzhiyun 4*4882a593Smuzhiyun.. _mmap: 5*4882a593Smuzhiyun 6*4882a593Smuzhiyun****************************** 7*4882a593SmuzhiyunStreaming I/O (Memory Mapping) 8*4882a593Smuzhiyun****************************** 9*4882a593Smuzhiyun 10*4882a593SmuzhiyunInput and output devices support this I/O method when the 11*4882a593Smuzhiyun``V4L2_CAP_STREAMING`` flag in the ``capabilities`` field of struct 12*4882a593Smuzhiyun:c:type:`v4l2_capability` returned by the 13*4882a593Smuzhiyun:ref:`VIDIOC_QUERYCAP` ioctl is set. There are two 14*4882a593Smuzhiyunstreaming methods, to determine if the memory mapping flavor is 15*4882a593Smuzhiyunsupported applications must call the :ref:`VIDIOC_REQBUFS` ioctl 16*4882a593Smuzhiyunwith the memory type set to ``V4L2_MEMORY_MMAP``. 17*4882a593Smuzhiyun 18*4882a593SmuzhiyunStreaming is an I/O method where only pointers to buffers are exchanged 19*4882a593Smuzhiyunbetween application and driver, the data itself is not copied. Memory 20*4882a593Smuzhiyunmapping is primarily intended to map buffers in device memory into the 21*4882a593Smuzhiyunapplication's address space. Device memory can be for example the video 22*4882a593Smuzhiyunmemory on a graphics card with a video capture add-on. However, being 23*4882a593Smuzhiyunthe most efficient I/O method available for a long time, many other 24*4882a593Smuzhiyundrivers support streaming as well, allocating buffers in DMA-able main 25*4882a593Smuzhiyunmemory. 26*4882a593Smuzhiyun 27*4882a593SmuzhiyunA driver can support many sets of buffers. Each set is identified by a 28*4882a593Smuzhiyununique buffer type value. The sets are independent and each set can hold 29*4882a593Smuzhiyuna different type of data. To access different sets at the same time 30*4882a593Smuzhiyundifferent file descriptors must be used. [#f1]_ 31*4882a593Smuzhiyun 32*4882a593SmuzhiyunTo allocate device buffers applications call the 33*4882a593Smuzhiyun:ref:`VIDIOC_REQBUFS` ioctl with the desired number 34*4882a593Smuzhiyunof buffers and buffer type, for example ``V4L2_BUF_TYPE_VIDEO_CAPTURE``. 35*4882a593SmuzhiyunThis ioctl can also be used to change the number of buffers or to free 36*4882a593Smuzhiyunthe allocated memory, provided none of the buffers are still mapped. 37*4882a593Smuzhiyun 38*4882a593SmuzhiyunBefore applications can access the buffers they must map them into their 39*4882a593Smuzhiyunaddress space with the :c:func:`mmap()` function. The 40*4882a593Smuzhiyunlocation of the buffers in device memory can be determined with the 41*4882a593Smuzhiyun:ref:`VIDIOC_QUERYBUF` ioctl. In the single-planar 42*4882a593SmuzhiyunAPI case, the ``m.offset`` and ``length`` returned in a struct 43*4882a593Smuzhiyun:c:type:`v4l2_buffer` are passed as sixth and second 44*4882a593Smuzhiyunparameter to the :c:func:`mmap()` function. When using the 45*4882a593Smuzhiyunmulti-planar API, struct :c:type:`v4l2_buffer` contains an 46*4882a593Smuzhiyunarray of struct :c:type:`v4l2_plane` structures, each 47*4882a593Smuzhiyuncontaining its own ``m.offset`` and ``length``. When using the 48*4882a593Smuzhiyunmulti-planar API, every plane of every buffer has to be mapped 49*4882a593Smuzhiyunseparately, so the number of calls to :c:func:`mmap()` should 50*4882a593Smuzhiyunbe equal to number of buffers times number of planes in each buffer. The 51*4882a593Smuzhiyunoffset and length values must not be modified. Remember, the buffers are 52*4882a593Smuzhiyunallocated in physical memory, as opposed to virtual memory, which can be 53*4882a593Smuzhiyunswapped out to disk. Applications should free the buffers as soon as 54*4882a593Smuzhiyunpossible with the :c:func:`munmap()` function. 55*4882a593Smuzhiyun 56*4882a593SmuzhiyunExample: Mapping buffers in the single-planar API 57*4882a593Smuzhiyun================================================= 58*4882a593Smuzhiyun 59*4882a593Smuzhiyun.. code-block:: c 60*4882a593Smuzhiyun 61*4882a593Smuzhiyun struct v4l2_requestbuffers reqbuf; 62*4882a593Smuzhiyun struct { 63*4882a593Smuzhiyun void *start; 64*4882a593Smuzhiyun size_t length; 65*4882a593Smuzhiyun } *buffers; 66*4882a593Smuzhiyun unsigned int i; 67*4882a593Smuzhiyun 68*4882a593Smuzhiyun memset(&reqbuf, 0, sizeof(reqbuf)); 69*4882a593Smuzhiyun reqbuf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; 70*4882a593Smuzhiyun reqbuf.memory = V4L2_MEMORY_MMAP; 71*4882a593Smuzhiyun reqbuf.count = 20; 72*4882a593Smuzhiyun 73*4882a593Smuzhiyun if (-1 == ioctl (fd, VIDIOC_REQBUFS, &reqbuf)) { 74*4882a593Smuzhiyun if (errno == EINVAL) 75*4882a593Smuzhiyun printf("Video capturing or mmap-streaming is not supported\\n"); 76*4882a593Smuzhiyun else 77*4882a593Smuzhiyun perror("VIDIOC_REQBUFS"); 78*4882a593Smuzhiyun 79*4882a593Smuzhiyun exit(EXIT_FAILURE); 80*4882a593Smuzhiyun } 81*4882a593Smuzhiyun 82*4882a593Smuzhiyun /* We want at least five buffers. */ 83*4882a593Smuzhiyun 84*4882a593Smuzhiyun if (reqbuf.count < 5) { 85*4882a593Smuzhiyun /* You may need to free the buffers here. */ 86*4882a593Smuzhiyun printf("Not enough buffer memory\\n"); 87*4882a593Smuzhiyun exit(EXIT_FAILURE); 88*4882a593Smuzhiyun } 89*4882a593Smuzhiyun 90*4882a593Smuzhiyun buffers = calloc(reqbuf.count, sizeof(*buffers)); 91*4882a593Smuzhiyun assert(buffers != NULL); 92*4882a593Smuzhiyun 93*4882a593Smuzhiyun for (i = 0; i < reqbuf.count; i++) { 94*4882a593Smuzhiyun struct v4l2_buffer buffer; 95*4882a593Smuzhiyun 96*4882a593Smuzhiyun memset(&buffer, 0, sizeof(buffer)); 97*4882a593Smuzhiyun buffer.type = reqbuf.type; 98*4882a593Smuzhiyun buffer.memory = V4L2_MEMORY_MMAP; 99*4882a593Smuzhiyun buffer.index = i; 100*4882a593Smuzhiyun 101*4882a593Smuzhiyun if (-1 == ioctl (fd, VIDIOC_QUERYBUF, &buffer)) { 102*4882a593Smuzhiyun perror("VIDIOC_QUERYBUF"); 103*4882a593Smuzhiyun exit(EXIT_FAILURE); 104*4882a593Smuzhiyun } 105*4882a593Smuzhiyun 106*4882a593Smuzhiyun buffers[i].length = buffer.length; /* remember for munmap() */ 107*4882a593Smuzhiyun 108*4882a593Smuzhiyun buffers[i].start = mmap(NULL, buffer.length, 109*4882a593Smuzhiyun PROT_READ | PROT_WRITE, /* recommended */ 110*4882a593Smuzhiyun MAP_SHARED, /* recommended */ 111*4882a593Smuzhiyun fd, buffer.m.offset); 112*4882a593Smuzhiyun 113*4882a593Smuzhiyun if (MAP_FAILED == buffers[i].start) { 114*4882a593Smuzhiyun /* If you do not exit here you should unmap() and free() 115*4882a593Smuzhiyun the buffers mapped so far. */ 116*4882a593Smuzhiyun perror("mmap"); 117*4882a593Smuzhiyun exit(EXIT_FAILURE); 118*4882a593Smuzhiyun } 119*4882a593Smuzhiyun } 120*4882a593Smuzhiyun 121*4882a593Smuzhiyun /* Cleanup. */ 122*4882a593Smuzhiyun 123*4882a593Smuzhiyun for (i = 0; i < reqbuf.count; i++) 124*4882a593Smuzhiyun munmap(buffers[i].start, buffers[i].length); 125*4882a593Smuzhiyun 126*4882a593SmuzhiyunExample: Mapping buffers in the multi-planar API 127*4882a593Smuzhiyun================================================ 128*4882a593Smuzhiyun 129*4882a593Smuzhiyun.. code-block:: c 130*4882a593Smuzhiyun 131*4882a593Smuzhiyun struct v4l2_requestbuffers reqbuf; 132*4882a593Smuzhiyun /* Our current format uses 3 planes per buffer */ 133*4882a593Smuzhiyun #define FMT_NUM_PLANES = 3 134*4882a593Smuzhiyun 135*4882a593Smuzhiyun struct { 136*4882a593Smuzhiyun void *start[FMT_NUM_PLANES]; 137*4882a593Smuzhiyun size_t length[FMT_NUM_PLANES]; 138*4882a593Smuzhiyun } *buffers; 139*4882a593Smuzhiyun unsigned int i, j; 140*4882a593Smuzhiyun 141*4882a593Smuzhiyun memset(&reqbuf, 0, sizeof(reqbuf)); 142*4882a593Smuzhiyun reqbuf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE; 143*4882a593Smuzhiyun reqbuf.memory = V4L2_MEMORY_MMAP; 144*4882a593Smuzhiyun reqbuf.count = 20; 145*4882a593Smuzhiyun 146*4882a593Smuzhiyun if (ioctl(fd, VIDIOC_REQBUFS, &reqbuf) < 0) { 147*4882a593Smuzhiyun if (errno == EINVAL) 148*4882a593Smuzhiyun printf("Video capturing or mmap-streaming is not supported\\n"); 149*4882a593Smuzhiyun else 150*4882a593Smuzhiyun perror("VIDIOC_REQBUFS"); 151*4882a593Smuzhiyun 152*4882a593Smuzhiyun exit(EXIT_FAILURE); 153*4882a593Smuzhiyun } 154*4882a593Smuzhiyun 155*4882a593Smuzhiyun /* We want at least five buffers. */ 156*4882a593Smuzhiyun 157*4882a593Smuzhiyun if (reqbuf.count < 5) { 158*4882a593Smuzhiyun /* You may need to free the buffers here. */ 159*4882a593Smuzhiyun printf("Not enough buffer memory\\n"); 160*4882a593Smuzhiyun exit(EXIT_FAILURE); 161*4882a593Smuzhiyun } 162*4882a593Smuzhiyun 163*4882a593Smuzhiyun buffers = calloc(reqbuf.count, sizeof(*buffers)); 164*4882a593Smuzhiyun assert(buffers != NULL); 165*4882a593Smuzhiyun 166*4882a593Smuzhiyun for (i = 0; i < reqbuf.count; i++) { 167*4882a593Smuzhiyun struct v4l2_buffer buffer; 168*4882a593Smuzhiyun struct v4l2_plane planes[FMT_NUM_PLANES]; 169*4882a593Smuzhiyun 170*4882a593Smuzhiyun memset(&buffer, 0, sizeof(buffer)); 171*4882a593Smuzhiyun buffer.type = reqbuf.type; 172*4882a593Smuzhiyun buffer.memory = V4L2_MEMORY_MMAP; 173*4882a593Smuzhiyun buffer.index = i; 174*4882a593Smuzhiyun /* length in struct v4l2_buffer in multi-planar API stores the size 175*4882a593Smuzhiyun * of planes array. */ 176*4882a593Smuzhiyun buffer.length = FMT_NUM_PLANES; 177*4882a593Smuzhiyun buffer.m.planes = planes; 178*4882a593Smuzhiyun 179*4882a593Smuzhiyun if (ioctl(fd, VIDIOC_QUERYBUF, &buffer) < 0) { 180*4882a593Smuzhiyun perror("VIDIOC_QUERYBUF"); 181*4882a593Smuzhiyun exit(EXIT_FAILURE); 182*4882a593Smuzhiyun } 183*4882a593Smuzhiyun 184*4882a593Smuzhiyun /* Every plane has to be mapped separately */ 185*4882a593Smuzhiyun for (j = 0; j < FMT_NUM_PLANES; j++) { 186*4882a593Smuzhiyun buffers[i].length[j] = buffer.m.planes[j].length; /* remember for munmap() */ 187*4882a593Smuzhiyun 188*4882a593Smuzhiyun buffers[i].start[j] = mmap(NULL, buffer.m.planes[j].length, 189*4882a593Smuzhiyun PROT_READ | PROT_WRITE, /* recommended */ 190*4882a593Smuzhiyun MAP_SHARED, /* recommended */ 191*4882a593Smuzhiyun fd, buffer.m.planes[j].m.offset); 192*4882a593Smuzhiyun 193*4882a593Smuzhiyun if (MAP_FAILED == buffers[i].start[j]) { 194*4882a593Smuzhiyun /* If you do not exit here you should unmap() and free() 195*4882a593Smuzhiyun the buffers and planes mapped so far. */ 196*4882a593Smuzhiyun perror("mmap"); 197*4882a593Smuzhiyun exit(EXIT_FAILURE); 198*4882a593Smuzhiyun } 199*4882a593Smuzhiyun } 200*4882a593Smuzhiyun } 201*4882a593Smuzhiyun 202*4882a593Smuzhiyun /* Cleanup. */ 203*4882a593Smuzhiyun 204*4882a593Smuzhiyun for (i = 0; i < reqbuf.count; i++) 205*4882a593Smuzhiyun for (j = 0; j < FMT_NUM_PLANES; j++) 206*4882a593Smuzhiyun munmap(buffers[i].start[j], buffers[i].length[j]); 207*4882a593Smuzhiyun 208*4882a593SmuzhiyunConceptually streaming drivers maintain two buffer queues, an incoming 209*4882a593Smuzhiyunand an outgoing queue. They separate the synchronous capture or output 210*4882a593Smuzhiyunoperation locked to a video clock from the application which is subject 211*4882a593Smuzhiyunto random disk or network delays and preemption by other processes, 212*4882a593Smuzhiyunthereby reducing the probability of data loss. The queues are organized 213*4882a593Smuzhiyunas FIFOs, buffers will be output in the order enqueued in the incoming 214*4882a593SmuzhiyunFIFO, and were captured in the order dequeued from the outgoing FIFO. 215*4882a593Smuzhiyun 216*4882a593SmuzhiyunThe driver may require a minimum number of buffers enqueued at all times 217*4882a593Smuzhiyunto function, apart of this no limit exists on the number of buffers 218*4882a593Smuzhiyunapplications can enqueue in advance, or dequeue and process. They can 219*4882a593Smuzhiyunalso enqueue in a different order than buffers have been dequeued, and 220*4882a593Smuzhiyunthe driver can *fill* enqueued *empty* buffers in any order. [#f2]_ The 221*4882a593Smuzhiyunindex number of a buffer (struct :c:type:`v4l2_buffer` 222*4882a593Smuzhiyun``index``) plays no role here, it only identifies the buffer. 223*4882a593Smuzhiyun 224*4882a593SmuzhiyunInitially all mapped buffers are in dequeued state, inaccessible by the 225*4882a593Smuzhiyundriver. For capturing applications it is customary to first enqueue all 226*4882a593Smuzhiyunmapped buffers, then to start capturing and enter the read loop. Here 227*4882a593Smuzhiyunthe application waits until a filled buffer can be dequeued, and 228*4882a593Smuzhiyunre-enqueues the buffer when the data is no longer needed. Output 229*4882a593Smuzhiyunapplications fill and enqueue buffers, when enough buffers are stacked 230*4882a593Smuzhiyunup the output is started with :ref:`VIDIOC_STREAMON <VIDIOC_STREAMON>`. 231*4882a593SmuzhiyunIn the write loop, when the application runs out of free buffers, it 232*4882a593Smuzhiyunmust wait until an empty buffer can be dequeued and reused. 233*4882a593Smuzhiyun 234*4882a593SmuzhiyunTo enqueue and dequeue a buffer applications use the 235*4882a593Smuzhiyun:ref:`VIVIOC_QBUF <VIDIOC_QBUF>` and :ref:`VIDIOC_DQBUF <VIDIOC_QBUF>` 236*4882a593Smuzhiyunioctl. The status of a buffer being mapped, enqueued, full or empty can 237*4882a593Smuzhiyunbe determined at any time using the :ref:`VIDIOC_QUERYBUF` ioctl. Two 238*4882a593Smuzhiyunmethods exist to suspend execution of the application until one or more 239*4882a593Smuzhiyunbuffers can be dequeued. By default :ref:`VIDIOC_DQBUF <VIDIOC_QBUF>` 240*4882a593Smuzhiyunblocks when no buffer is in the outgoing queue. When the ``O_NONBLOCK`` 241*4882a593Smuzhiyunflag was given to the :c:func:`open()` function, 242*4882a593Smuzhiyun:ref:`VIDIOC_DQBUF <VIDIOC_QBUF>` returns immediately with an ``EAGAIN`` 243*4882a593Smuzhiyunerror code when no buffer is available. The :c:func:`select()` 244*4882a593Smuzhiyunor :c:func:`poll()` functions are always available. 245*4882a593Smuzhiyun 246*4882a593SmuzhiyunTo start and stop capturing or output applications call the 247*4882a593Smuzhiyun:ref:`VIDIOC_STREAMON <VIDIOC_STREAMON>` and :ref:`VIDIOC_STREAMOFF 248*4882a593Smuzhiyun<VIDIOC_STREAMON>` ioctl. 249*4882a593Smuzhiyun 250*4882a593Smuzhiyun.. note:::ref:`VIDIOC_STREAMOFF <VIDIOC_STREAMON>` 251*4882a593Smuzhiyun removes all buffers from both queues as a side effect. Since there is 252*4882a593Smuzhiyun no notion of doing anything "now" on a multitasking system, if an 253*4882a593Smuzhiyun application needs to synchronize with another event it should examine 254*4882a593Smuzhiyun the struct ::c:type:`v4l2_buffer` ``timestamp`` of captured 255*4882a593Smuzhiyun or outputted buffers. 256*4882a593Smuzhiyun 257*4882a593SmuzhiyunDrivers implementing memory mapping I/O must support the 258*4882a593Smuzhiyun:ref:`VIDIOC_REQBUFS <VIDIOC_REQBUFS>`, :ref:`VIDIOC_QUERYBUF 259*4882a593Smuzhiyun<VIDIOC_QUERYBUF>`, :ref:`VIDIOC_QBUF <VIDIOC_QBUF>`, :ref:`VIDIOC_DQBUF 260*4882a593Smuzhiyun<VIDIOC_QBUF>`, :ref:`VIDIOC_STREAMON <VIDIOC_STREAMON>` 261*4882a593Smuzhiyunand :ref:`VIDIOC_STREAMOFF <VIDIOC_STREAMON>` ioctls, the :ref:`mmap() 262*4882a593Smuzhiyun<func-mmap>`, :c:func:`munmap()`, :ref:`select() 263*4882a593Smuzhiyun<func-select>` and :c:func:`poll()` function. [#f3]_ 264*4882a593Smuzhiyun 265*4882a593Smuzhiyun[capture example] 266*4882a593Smuzhiyun 267*4882a593Smuzhiyun.. [#f1] 268*4882a593Smuzhiyun One could use one file descriptor and set the buffer type field 269*4882a593Smuzhiyun accordingly when calling :ref:`VIDIOC_QBUF` etc., 270*4882a593Smuzhiyun but it makes the :c:func:`select()` function ambiguous. We also 271*4882a593Smuzhiyun like the clean approach of one file descriptor per logical stream. 272*4882a593Smuzhiyun Video overlay for example is also a logical stream, although the CPU 273*4882a593Smuzhiyun is not needed for continuous operation. 274*4882a593Smuzhiyun 275*4882a593Smuzhiyun.. [#f2] 276*4882a593Smuzhiyun Random enqueue order permits applications processing images out of 277*4882a593Smuzhiyun order (such as video codecs) to return buffers earlier, reducing the 278*4882a593Smuzhiyun probability of data loss. Random fill order allows drivers to reuse 279*4882a593Smuzhiyun buffers on a LIFO-basis, taking advantage of caches holding 280*4882a593Smuzhiyun scatter-gather lists and the like. 281*4882a593Smuzhiyun 282*4882a593Smuzhiyun.. [#f3] 283*4882a593Smuzhiyun At the driver level :c:func:`select()` and :c:func:`poll()` are 284*4882a593Smuzhiyun the same, and :c:func:`select()` is too important to be optional. 285*4882a593Smuzhiyun The rest should be evident. 286