xref: /OK3568_Linux_fs/kernel/Documentation/userspace-api/media/v4l/mmap.rst (revision 4882a59341e53eb6f0b4789bf948001014eff981)
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