Commit | Line | Data |
---|---|---|
5377d91f MH |
1 | .. -*- coding: utf-8; mode: rst -*- |
2 | ||
3 | .. _dmabuf: | |
4 | ||
5 | ************************************ | |
6 | Streaming I/O (DMA buffer importing) | |
7 | ************************************ | |
8 | ||
9 | The DMABUF framework provides a generic method for sharing buffers | |
10 | between multiple devices. Device drivers that support DMABUF can export | |
11 | a DMA buffer to userspace as a file descriptor (known as the exporter | |
12 | role), import a DMA buffer from userspace using a file descriptor | |
13 | previously exported for a different or the same device (known as the | |
14 | importer role), or both. This section describes the DMABUF importer role | |
15 | API in V4L2. | |
16 | ||
17 | Refer to :ref:`DMABUF exporting <vidioc-expbuf>` for details about | |
18 | exporting V4L2 buffers as DMABUF file descriptors. | |
19 | ||
20 | Input and output devices support the streaming I/O method when the | |
21 | ``V4L2_CAP_STREAMING`` flag in the ``capabilities`` field of struct | |
22 | :ref:`v4l2_capability <v4l2-capability>` returned by the | |
23 | :ref:`VIDIOC_QUERYCAP <vidioc-querycap>` ioctl is set. Whether | |
24 | importing DMA buffers through DMABUF file descriptors is supported is | |
25 | determined by calling the :ref:`VIDIOC_REQBUFS <vidioc-reqbufs>` | |
26 | ioctl with the memory type set to ``V4L2_MEMORY_DMABUF``. | |
27 | ||
28 | This I/O method is dedicated to sharing DMA buffers between different | |
29 | devices, which may be V4L devices or other video-related devices (e.g. | |
30 | DRM). Buffers (planes) are allocated by a driver on behalf of an | |
31 | application. Next, these buffers are exported to the application as file | |
32 | descriptors using an API which is specific for an allocator driver. Only | |
33 | such file descriptor are exchanged. The descriptors and meta-information | |
34 | are passed in struct :ref:`v4l2_buffer <v4l2-buffer>` (or in struct | |
35 | :ref:`v4l2_plane <v4l2-plane>` in the multi-planar API case). The | |
36 | driver must be switched into DMABUF I/O mode by calling the | |
37 | :ref:`VIDIOC_REQBUFS <vidioc-reqbufs>` with the desired buffer type. | |
38 | ||
39 | ||
40 | .. code-block:: c | |
41 | ||
42 | struct v4l2_requestbuffers reqbuf; | |
43 | ||
44 | memset(&reqbuf, 0, sizeof (reqbuf)); | |
45 | reqbuf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; | |
46 | reqbuf.memory = V4L2_MEMORY_DMABUF; | |
47 | reqbuf.count = 1; | |
48 | ||
49 | if (ioctl(fd, VIDIOC_REQBUFS, &reqbuf) == -1) { | |
50 | if (errno == EINVAL) | |
51 | printf("Video capturing or DMABUF streaming is not supported\\n"); | |
52 | else | |
53 | perror("VIDIOC_REQBUFS"); | |
54 | ||
55 | exit(EXIT_FAILURE); | |
56 | } | |
57 | ||
58 | The buffer (plane) file descriptor is passed on the fly with the | |
59 | :ref:`VIDIOC_QBUF <vidioc-qbuf>` ioctl. In case of multiplanar | |
60 | buffers, every plane can be associated with a different DMABUF | |
61 | descriptor. Although buffers are commonly cycled, applications can pass | |
62 | a different DMABUF descriptor at each ``VIDIOC_QBUF`` call. | |
63 | ||
64 | ||
65 | .. code-block:: c | |
66 | ||
67 | int buffer_queue(int v4lfd, int index, int dmafd) | |
68 | { | |
69 | struct v4l2_buffer buf; | |
70 | ||
71 | memset(&buf, 0, sizeof buf); | |
72 | buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; | |
73 | buf.memory = V4L2_MEMORY_DMABUF; | |
74 | buf.index = index; | |
75 | buf.m.fd = dmafd; | |
76 | ||
77 | if (ioctl(v4lfd, VIDIOC_QBUF, &buf) == -1) { | |
78 | perror("VIDIOC_QBUF"); | |
79 | return -1; | |
80 | } | |
81 | ||
82 | return 0; | |
83 | } | |
84 | ||
85 | ||
86 | .. code-block:: c | |
87 | ||
88 | int buffer_queue_mp(int v4lfd, int index, int dmafd[], int n_planes) | |
89 | { | |
90 | struct v4l2_buffer buf; | |
91 | struct v4l2_plane planes[VIDEO_MAX_PLANES]; | |
92 | int i; | |
93 | ||
94 | memset(&buf, 0, sizeof buf); | |
95 | buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE; | |
96 | buf.memory = V4L2_MEMORY_DMABUF; | |
97 | buf.index = index; | |
98 | buf.m.planes = planes; | |
99 | buf.length = n_planes; | |
100 | ||
101 | memset(&planes, 0, sizeof planes); | |
102 | ||
103 | for (i = 0; i < n_planes; ++i) | |
104 | buf.m.planes[i].m.fd = dmafd[i]; | |
105 | ||
106 | if (ioctl(v4lfd, VIDIOC_QBUF, &buf) == -1) { | |
107 | perror("VIDIOC_QBUF"); | |
108 | return -1; | |
109 | } | |
110 | ||
111 | return 0; | |
112 | } | |
113 | ||
114 | Captured or displayed buffers are dequeued with the | |
115 | :ref:`VIDIOC_DQBUF <vidioc-qbuf>` ioctl. The driver can unlock the | |
116 | buffer at any time between the completion of the DMA and this ioctl. The | |
117 | memory is also unlocked when | |
118 | :ref:`VIDIOC_STREAMOFF <vidioc-streamon>` is called, | |
119 | :ref:`VIDIOC_REQBUFS <vidioc-reqbufs>`, or when the device is closed. | |
120 | ||
121 | For capturing applications it is customary to enqueue a number of empty | |
122 | buffers, to start capturing and enter the read loop. Here the | |
123 | application waits until a filled buffer can be dequeued, and re-enqueues | |
124 | the buffer when the data is no longer needed. Output applications fill | |
125 | and enqueue buffers, when enough buffers are stacked up output is | |
126 | started. In the write loop, when the application runs out of free | |
127 | buffers it must wait until an empty buffer can be dequeued and reused. | |
128 | Two methods exist to suspend execution of the application until one or | |
129 | more buffers can be dequeued. By default ``VIDIOC_DQBUF`` blocks when no | |
130 | buffer is in the outgoing queue. When the ``O_NONBLOCK`` flag was given | |
131 | to the :ref:`open() <func-open>` function, ``VIDIOC_DQBUF`` returns | |
132 | immediately with an EAGAIN error code when no buffer is available. The | |
133 | :ref:`select() <func-select>` and :ref:`poll() <func-poll>` | |
134 | functions are always available. | |
135 | ||
136 | To start and stop capturing or displaying applications call the | |
137 | :ref:`VIDIOC_STREAMON <vidioc-streamon>` and | |
138 | :ref:`VIDIOC_STREAMOFF <vidioc-streamon>` ioctls. Note that | |
139 | ``VIDIOC_STREAMOFF`` removes all buffers from both queues and unlocks | |
140 | all buffers as a side effect. Since there is no notion of doing anything | |
141 | "now" on a multitasking system, if an application needs to synchronize | |
142 | with another event it should examine the struct | |
143 | :ref:`v4l2_buffer <v4l2-buffer>` ``timestamp`` of captured or | |
144 | outputted buffers. | |
145 | ||
146 | Drivers implementing DMABUF importing I/O must support the | |
147 | ``VIDIOC_REQBUFS``, ``VIDIOC_QBUF``, ``VIDIOC_DQBUF``, | |
148 | ``VIDIOC_STREAMON`` and ``VIDIOC_STREAMOFF`` ioctls, and the | |
149 | :c:func:`select()` and :c:func:`poll()` functions. | |
150 | ||
151 | ||
152 | .. ------------------------------------------------------------------------------ | |
153 | .. This file was automatically converted from DocBook-XML with the dbxml | |
154 | .. library (https://github.com/return42/sphkerneldoc). The origin XML comes | |
155 | .. from the linux kernel, refer to: | |
156 | .. | |
157 | .. * https://github.com/torvalds/linux/tree/master/Documentation/DocBook | |
158 | .. ------------------------------------------------------------------------------ |