1059b1c5bSMauro Carvalho Chehab.. SPDX-License-Identifier: GFDL-1.1-no-invariants-or-later
2407e84cdSMauro Carvalho Chehab.. c:namespace:: V4L
354f38fcaSMauro Carvalho Chehab
454f38fcaSMauro Carvalho Chehab.. _dmabuf:
554f38fcaSMauro Carvalho Chehab
654f38fcaSMauro Carvalho Chehab************************************
754f38fcaSMauro Carvalho ChehabStreaming I/O (DMA buffer importing)
854f38fcaSMauro Carvalho Chehab************************************
954f38fcaSMauro Carvalho Chehab
1054f38fcaSMauro Carvalho ChehabThe DMABUF framework provides a generic method for sharing buffers
1154f38fcaSMauro Carvalho Chehabbetween multiple devices. Device drivers that support DMABUF can export
1254f38fcaSMauro Carvalho Chehaba DMA buffer to userspace as a file descriptor (known as the exporter
1354f38fcaSMauro Carvalho Chehabrole), import a DMA buffer from userspace using a file descriptor
1454f38fcaSMauro Carvalho Chehabpreviously exported for a different or the same device (known as the
1554f38fcaSMauro Carvalho Chehabimporter role), or both. This section describes the DMABUF importer role
1654f38fcaSMauro Carvalho ChehabAPI in V4L2.
1754f38fcaSMauro Carvalho Chehab
1854f38fcaSMauro Carvalho ChehabRefer to :ref:`DMABUF exporting <VIDIOC_EXPBUF>` for details about
1954f38fcaSMauro Carvalho Chehabexporting V4L2 buffers as DMABUF file descriptors.
2054f38fcaSMauro Carvalho Chehab
2154f38fcaSMauro Carvalho ChehabInput and output devices support the streaming I/O method when the
2254f38fcaSMauro Carvalho Chehab``V4L2_CAP_STREAMING`` flag in the ``capabilities`` field of struct
2354f38fcaSMauro Carvalho Chehab:c:type:`v4l2_capability` returned by the
2454f38fcaSMauro Carvalho Chehab:ref:`VIDIOC_QUERYCAP <VIDIOC_QUERYCAP>` ioctl is set. Whether
2554f38fcaSMauro Carvalho Chehabimporting DMA buffers through DMABUF file descriptors is supported is
2654f38fcaSMauro Carvalho Chehabdetermined by calling the :ref:`VIDIOC_REQBUFS <VIDIOC_REQBUFS>`
2754f38fcaSMauro Carvalho Chehabioctl with the memory type set to ``V4L2_MEMORY_DMABUF``.
2854f38fcaSMauro Carvalho Chehab
2954f38fcaSMauro Carvalho ChehabThis I/O method is dedicated to sharing DMA buffers between different
3054f38fcaSMauro Carvalho Chehabdevices, which may be V4L devices or other video-related devices (e.g.
3154f38fcaSMauro Carvalho ChehabDRM). Buffers (planes) are allocated by a driver on behalf of an
3254f38fcaSMauro Carvalho Chehabapplication. Next, these buffers are exported to the application as file
3354f38fcaSMauro Carvalho Chehabdescriptors using an API which is specific for an allocator driver. Only
3454f38fcaSMauro Carvalho Chehabsuch file descriptor are exchanged. The descriptors and meta-information
3554f38fcaSMauro Carvalho Chehabare passed in struct :c:type:`v4l2_buffer` (or in struct
3654f38fcaSMauro Carvalho Chehab:c:type:`v4l2_plane` in the multi-planar API case). The
3754f38fcaSMauro Carvalho Chehabdriver must be switched into DMABUF I/O mode by calling the
3854f38fcaSMauro Carvalho Chehab:ref:`VIDIOC_REQBUFS <VIDIOC_REQBUFS>` with the desired buffer type.
3954f38fcaSMauro Carvalho Chehab
4054f38fcaSMauro Carvalho ChehabExample: Initiating streaming I/O with DMABUF file descriptors
4154f38fcaSMauro Carvalho Chehab==============================================================
4254f38fcaSMauro Carvalho Chehab
4354f38fcaSMauro Carvalho Chehab.. code-block:: c
4454f38fcaSMauro Carvalho Chehab
4554f38fcaSMauro Carvalho Chehab    struct v4l2_requestbuffers reqbuf;
4654f38fcaSMauro Carvalho Chehab
4754f38fcaSMauro Carvalho Chehab    memset(&reqbuf, 0, sizeof (reqbuf));
4854f38fcaSMauro Carvalho Chehab    reqbuf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
4954f38fcaSMauro Carvalho Chehab    reqbuf.memory = V4L2_MEMORY_DMABUF;
5054f38fcaSMauro Carvalho Chehab    reqbuf.count = 1;
5154f38fcaSMauro Carvalho Chehab
5254f38fcaSMauro Carvalho Chehab    if (ioctl(fd, VIDIOC_REQBUFS, &reqbuf) == -1) {
5354f38fcaSMauro Carvalho Chehab	if (errno == EINVAL)
5454f38fcaSMauro Carvalho Chehab	    printf("Video capturing or DMABUF streaming is not supported\\n");
5554f38fcaSMauro Carvalho Chehab	else
5654f38fcaSMauro Carvalho Chehab	    perror("VIDIOC_REQBUFS");
5754f38fcaSMauro Carvalho Chehab
5854f38fcaSMauro Carvalho Chehab	exit(EXIT_FAILURE);
5954f38fcaSMauro Carvalho Chehab    }
6054f38fcaSMauro Carvalho Chehab
6154f38fcaSMauro Carvalho ChehabThe buffer (plane) file descriptor is passed on the fly with the
6254f38fcaSMauro Carvalho Chehab:ref:`VIDIOC_QBUF <VIDIOC_QBUF>` ioctl. In case of multiplanar
6354f38fcaSMauro Carvalho Chehabbuffers, every plane can be associated with a different DMABUF
6454f38fcaSMauro Carvalho Chehabdescriptor. Although buffers are commonly cycled, applications can pass
6554f38fcaSMauro Carvalho Chehaba different DMABUF descriptor at each :ref:`VIDIOC_QBUF <VIDIOC_QBUF>` call.
6654f38fcaSMauro Carvalho Chehab
6754f38fcaSMauro Carvalho ChehabExample: Queueing DMABUF using single plane API
6854f38fcaSMauro Carvalho Chehab===============================================
6954f38fcaSMauro Carvalho Chehab
7054f38fcaSMauro Carvalho Chehab.. code-block:: c
7154f38fcaSMauro Carvalho Chehab
7254f38fcaSMauro Carvalho Chehab    int buffer_queue(int v4lfd, int index, int dmafd)
7354f38fcaSMauro Carvalho Chehab    {
7454f38fcaSMauro Carvalho Chehab	struct v4l2_buffer buf;
7554f38fcaSMauro Carvalho Chehab
7654f38fcaSMauro Carvalho Chehab	memset(&buf, 0, sizeof buf);
7754f38fcaSMauro Carvalho Chehab	buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
7854f38fcaSMauro Carvalho Chehab	buf.memory = V4L2_MEMORY_DMABUF;
7954f38fcaSMauro Carvalho Chehab	buf.index = index;
8054f38fcaSMauro Carvalho Chehab	buf.m.fd = dmafd;
8154f38fcaSMauro Carvalho Chehab
8254f38fcaSMauro Carvalho Chehab	if (ioctl(v4lfd, VIDIOC_QBUF, &buf) == -1) {
8354f38fcaSMauro Carvalho Chehab	    perror("VIDIOC_QBUF");
8454f38fcaSMauro Carvalho Chehab	    return -1;
8554f38fcaSMauro Carvalho Chehab	}
8654f38fcaSMauro Carvalho Chehab
8754f38fcaSMauro Carvalho Chehab	return 0;
8854f38fcaSMauro Carvalho Chehab    }
8954f38fcaSMauro Carvalho Chehab
9054f38fcaSMauro Carvalho ChehabExample 3.6. Queueing DMABUF using multi plane API
9154f38fcaSMauro Carvalho Chehab==================================================
9254f38fcaSMauro Carvalho Chehab
9354f38fcaSMauro Carvalho Chehab.. code-block:: c
9454f38fcaSMauro Carvalho Chehab
9554f38fcaSMauro Carvalho Chehab    int buffer_queue_mp(int v4lfd, int index, int dmafd[], int n_planes)
9654f38fcaSMauro Carvalho Chehab    {
9754f38fcaSMauro Carvalho Chehab	struct v4l2_buffer buf;
9854f38fcaSMauro Carvalho Chehab	struct v4l2_plane planes[VIDEO_MAX_PLANES];
9954f38fcaSMauro Carvalho Chehab	int i;
10054f38fcaSMauro Carvalho Chehab
10154f38fcaSMauro Carvalho Chehab	memset(&buf, 0, sizeof buf);
10254f38fcaSMauro Carvalho Chehab	buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
10354f38fcaSMauro Carvalho Chehab	buf.memory = V4L2_MEMORY_DMABUF;
10454f38fcaSMauro Carvalho Chehab	buf.index = index;
10554f38fcaSMauro Carvalho Chehab	buf.m.planes = planes;
10654f38fcaSMauro Carvalho Chehab	buf.length = n_planes;
10754f38fcaSMauro Carvalho Chehab
10854f38fcaSMauro Carvalho Chehab	memset(&planes, 0, sizeof planes);
10954f38fcaSMauro Carvalho Chehab
11054f38fcaSMauro Carvalho Chehab	for (i = 0; i < n_planes; ++i)
11154f38fcaSMauro Carvalho Chehab	    buf.m.planes[i].m.fd = dmafd[i];
11254f38fcaSMauro Carvalho Chehab
11354f38fcaSMauro Carvalho Chehab	if (ioctl(v4lfd, VIDIOC_QBUF, &buf) == -1) {
11454f38fcaSMauro Carvalho Chehab	    perror("VIDIOC_QBUF");
11554f38fcaSMauro Carvalho Chehab	    return -1;
11654f38fcaSMauro Carvalho Chehab	}
11754f38fcaSMauro Carvalho Chehab
11854f38fcaSMauro Carvalho Chehab	return 0;
11954f38fcaSMauro Carvalho Chehab    }
12054f38fcaSMauro Carvalho Chehab
12154f38fcaSMauro Carvalho ChehabCaptured or displayed buffers are dequeued with the
12254f38fcaSMauro Carvalho Chehab:ref:`VIDIOC_DQBUF <VIDIOC_QBUF>` ioctl. The driver can unlock the
12354f38fcaSMauro Carvalho Chehabbuffer at any time between the completion of the DMA and this ioctl. The
12454f38fcaSMauro Carvalho Chehabmemory is also unlocked when
12554f38fcaSMauro Carvalho Chehab:ref:`VIDIOC_STREAMOFF <VIDIOC_STREAMON>` is called,
12654f38fcaSMauro Carvalho Chehab:ref:`VIDIOC_REQBUFS <VIDIOC_REQBUFS>`, or when the device is closed.
12754f38fcaSMauro Carvalho Chehab
12854f38fcaSMauro Carvalho ChehabFor capturing applications it is customary to enqueue a number of empty
12954f38fcaSMauro Carvalho Chehabbuffers, to start capturing and enter the read loop. Here the
13054f38fcaSMauro Carvalho Chehabapplication waits until a filled buffer can be dequeued, and re-enqueues
13154f38fcaSMauro Carvalho Chehabthe buffer when the data is no longer needed. Output applications fill
13254f38fcaSMauro Carvalho Chehaband enqueue buffers, when enough buffers are stacked up output is
13354f38fcaSMauro Carvalho Chehabstarted. In the write loop, when the application runs out of free
13454f38fcaSMauro Carvalho Chehabbuffers it must wait until an empty buffer can be dequeued and reused.
13554f38fcaSMauro Carvalho ChehabTwo methods exist to suspend execution of the application until one or
13654f38fcaSMauro Carvalho Chehabmore buffers can be dequeued. By default :ref:`VIDIOC_DQBUF
13754f38fcaSMauro Carvalho Chehab<VIDIOC_QBUF>` blocks when no buffer is in the outgoing queue. When the
138407e84cdSMauro Carvalho Chehab``O_NONBLOCK`` flag was given to the :c:func:`open()` function,
13954f38fcaSMauro Carvalho Chehab:ref:`VIDIOC_DQBUF <VIDIOC_QBUF>` returns immediately with an ``EAGAIN``
14054f38fcaSMauro Carvalho Chehaberror code when no buffer is available. The
141407e84cdSMauro Carvalho Chehab:c:func:`select()` and :c:func:`poll()`
14254f38fcaSMauro Carvalho Chehabfunctions are always available.
14354f38fcaSMauro Carvalho Chehab
14454f38fcaSMauro Carvalho ChehabTo start and stop capturing or displaying applications call the
14554f38fcaSMauro Carvalho Chehab:ref:`VIDIOC_STREAMON <VIDIOC_STREAMON>` and
14654f38fcaSMauro Carvalho Chehab:ref:`VIDIOC_STREAMOFF <VIDIOC_STREAMON>` ioctls.
14754f38fcaSMauro Carvalho Chehab
14854f38fcaSMauro Carvalho Chehab.. note::
14954f38fcaSMauro Carvalho Chehab
15054f38fcaSMauro Carvalho Chehab   :ref:`VIDIOC_STREAMOFF <VIDIOC_STREAMON>` removes all buffers from
15154f38fcaSMauro Carvalho Chehab   both queues and unlocks all buffers as a side effect. Since there is no
15254f38fcaSMauro Carvalho Chehab   notion of doing anything "now" on a multitasking system, if an
15354f38fcaSMauro Carvalho Chehab   application needs to synchronize with another event it should examine
15454f38fcaSMauro Carvalho Chehab   the struct :c:type:`v4l2_buffer` ``timestamp`` of captured or
15554f38fcaSMauro Carvalho Chehab   outputted buffers.
15654f38fcaSMauro Carvalho Chehab
15754f38fcaSMauro Carvalho ChehabDrivers implementing DMABUF importing I/O must support the
15854f38fcaSMauro Carvalho Chehab:ref:`VIDIOC_REQBUFS <VIDIOC_REQBUFS>`, :ref:`VIDIOC_QBUF <VIDIOC_QBUF>`,
15954f38fcaSMauro Carvalho Chehab:ref:`VIDIOC_DQBUF <VIDIOC_QBUF>`, :ref:`VIDIOC_STREAMON
16054f38fcaSMauro Carvalho Chehab<VIDIOC_STREAMON>` and :ref:`VIDIOC_STREAMOFF <VIDIOC_STREAMON>` ioctls,
161407e84cdSMauro Carvalho Chehaband the :c:func:`select()` and :c:func:`poll()`
16254f38fcaSMauro Carvalho Chehabfunctions.
163