xref: /OK3568_Linux_fs/kernel/Documentation/userspace-api/media/mediactl/request-api.rst (revision 4882a59341e53eb6f0b4789bf948001014eff981)
1*4882a593Smuzhiyun.. SPDX-License-Identifier: GPL-2.0 OR GFDL-1.1-no-invariants-or-later
2*4882a593Smuzhiyun.. c:namespace:: MC
3*4882a593Smuzhiyun
4*4882a593Smuzhiyun.. _media-request-api:
5*4882a593Smuzhiyun
6*4882a593SmuzhiyunRequest API
7*4882a593Smuzhiyun===========
8*4882a593Smuzhiyun
9*4882a593SmuzhiyunThe Request API has been designed to allow V4L2 to deal with requirements of
10*4882a593Smuzhiyunmodern devices (stateless codecs, complex camera pipelines, ...) and APIs
11*4882a593Smuzhiyun(Android Codec v2). One such requirement is the ability for devices belonging to
12*4882a593Smuzhiyunthe same pipeline to reconfigure and collaborate closely on a per-frame basis.
13*4882a593SmuzhiyunAnother is support of stateless codecs, which require controls to be applied
14*4882a593Smuzhiyunto specific frames (aka 'per-frame controls') in order to be used efficiently.
15*4882a593Smuzhiyun
16*4882a593SmuzhiyunWhile the initial use-case was V4L2, it can be extended to other subsystems
17*4882a593Smuzhiyunas well, as long as they use the media controller.
18*4882a593Smuzhiyun
19*4882a593SmuzhiyunSupporting these features without the Request API is not always possible and if
20*4882a593Smuzhiyunit is, it is terribly inefficient: user-space would have to flush all activity
21*4882a593Smuzhiyunon the media pipeline, reconfigure it for the next frame, queue the buffers to
22*4882a593Smuzhiyunbe processed with that configuration, and wait until they are all available for
23*4882a593Smuzhiyundequeuing before considering the next frame. This defeats the purpose of having
24*4882a593Smuzhiyunbuffer queues since in practice only one buffer would be queued at a time.
25*4882a593Smuzhiyun
26*4882a593SmuzhiyunThe Request API allows a specific configuration of the pipeline (media
27*4882a593Smuzhiyuncontroller topology + configuration for each media entity) to be associated with
28*4882a593Smuzhiyunspecific buffers. This allows user-space to schedule several tasks ("requests")
29*4882a593Smuzhiyunwith different configurations in advance, knowing that the configuration will be
30*4882a593Smuzhiyunapplied when needed to get the expected result. Configuration values at the time
31*4882a593Smuzhiyunof request completion are also available for reading.
32*4882a593Smuzhiyun
33*4882a593SmuzhiyunGeneral Usage
34*4882a593Smuzhiyun-------------
35*4882a593Smuzhiyun
36*4882a593SmuzhiyunThe Request API extends the Media Controller API and cooperates with
37*4882a593Smuzhiyunsubsystem-specific APIs to support request usage. At the Media Controller
38*4882a593Smuzhiyunlevel, requests are allocated from the supporting Media Controller device
39*4882a593Smuzhiyunnode. Their life cycle is then managed through the request file descriptors in
40*4882a593Smuzhiyunan opaque way. Configuration data, buffer handles and processing results
41*4882a593Smuzhiyunstored in requests are accessed through subsystem-specific APIs extended for
42*4882a593Smuzhiyunrequest support, such as V4L2 APIs that take an explicit ``request_fd``
43*4882a593Smuzhiyunparameter.
44*4882a593Smuzhiyun
45*4882a593SmuzhiyunRequest Allocation
46*4882a593Smuzhiyun------------------
47*4882a593Smuzhiyun
48*4882a593SmuzhiyunUser-space allocates requests using :ref:`MEDIA_IOC_REQUEST_ALLOC`
49*4882a593Smuzhiyunfor the media device node. This returns a file descriptor representing the
50*4882a593Smuzhiyunrequest. Typically, several such requests will be allocated.
51*4882a593Smuzhiyun
52*4882a593SmuzhiyunRequest Preparation
53*4882a593Smuzhiyun-------------------
54*4882a593Smuzhiyun
55*4882a593SmuzhiyunStandard V4L2 ioctls can then receive a request file descriptor to express the
56*4882a593Smuzhiyunfact that the ioctl is part of said request, and is not to be applied
57*4882a593Smuzhiyunimmediately. See :ref:`MEDIA_IOC_REQUEST_ALLOC` for a list of ioctls that
58*4882a593Smuzhiyunsupport this. Configurations set with a ``request_fd`` parameter are stored
59*4882a593Smuzhiyuninstead of being immediately applied, and buffers queued to a request do not
60*4882a593Smuzhiyunenter the regular buffer queue until the request itself is queued.
61*4882a593Smuzhiyun
62*4882a593SmuzhiyunRequest Submission
63*4882a593Smuzhiyun------------------
64*4882a593Smuzhiyun
65*4882a593SmuzhiyunOnce the configuration and buffers of the request are specified, it can be
66*4882a593Smuzhiyunqueued by calling :ref:`MEDIA_REQUEST_IOC_QUEUE` on the request file descriptor.
67*4882a593SmuzhiyunA request must contain at least one buffer, otherwise ``ENOENT`` is returned.
68*4882a593SmuzhiyunA queued request cannot be modified anymore.
69*4882a593Smuzhiyun
70*4882a593Smuzhiyun.. caution::
71*4882a593Smuzhiyun   For :ref:`memory-to-memory devices <mem2mem>` you can use requests only for
72*4882a593Smuzhiyun   output buffers, not for capture buffers. Attempting to add a capture buffer
73*4882a593Smuzhiyun   to a request will result in an ``EBADR`` error.
74*4882a593Smuzhiyun
75*4882a593SmuzhiyunIf the request contains configurations for multiple entities, individual drivers
76*4882a593Smuzhiyunmay synchronize so the requested pipeline's topology is applied before the
77*4882a593Smuzhiyunbuffers are processed. Media controller drivers do a best effort implementation
78*4882a593Smuzhiyunsince perfect atomicity may not be possible due to hardware limitations.
79*4882a593Smuzhiyun
80*4882a593Smuzhiyun.. caution::
81*4882a593Smuzhiyun
82*4882a593Smuzhiyun   It is not allowed to mix queuing requests with directly queuing buffers:
83*4882a593Smuzhiyun   whichever method is used first locks this in place until
84*4882a593Smuzhiyun   :ref:`VIDIOC_STREAMOFF <VIDIOC_STREAMON>` is called or the device is
85*4882a593Smuzhiyun   :ref:`closed <func-close>`. Attempts to directly queue a buffer when earlier
86*4882a593Smuzhiyun   a buffer was queued via a request or vice versa will result in an ``EBUSY``
87*4882a593Smuzhiyun   error.
88*4882a593Smuzhiyun
89*4882a593SmuzhiyunControls can still be set without a request and are applied immediately,
90*4882a593Smuzhiyunregardless of whether a request is in use or not.
91*4882a593Smuzhiyun
92*4882a593Smuzhiyun.. caution::
93*4882a593Smuzhiyun
94*4882a593Smuzhiyun   Setting the same control through a request and also directly can lead to
95*4882a593Smuzhiyun   undefined behavior!
96*4882a593Smuzhiyun
97*4882a593SmuzhiyunUser-space can :c:func:`poll()` a request file descriptor in
98*4882a593Smuzhiyunorder to wait until the request completes. A request is considered complete
99*4882a593Smuzhiyunonce all its associated buffers are available for dequeuing and all the
100*4882a593Smuzhiyunassociated controls have been updated with the values at the time of completion.
101*4882a593SmuzhiyunNote that user-space does not need to wait for the request to complete to
102*4882a593Smuzhiyundequeue its buffers: buffers that are available halfway through a request can
103*4882a593Smuzhiyunbe dequeued independently of the request's state.
104*4882a593Smuzhiyun
105*4882a593SmuzhiyunA completed request contains the state of the device after the request was
106*4882a593Smuzhiyunexecuted. User-space can query that state by calling
107*4882a593Smuzhiyun:ref:`ioctl VIDIOC_G_EXT_CTRLS <VIDIOC_G_EXT_CTRLS>` with the request file
108*4882a593Smuzhiyundescriptor. Calling :ref:`ioctl VIDIOC_G_EXT_CTRLS <VIDIOC_G_EXT_CTRLS>` for a
109*4882a593Smuzhiyunrequest that has been queued but not yet completed will return ``EBUSY``
110*4882a593Smuzhiyunsince the control values might be changed at any time by the driver while the
111*4882a593Smuzhiyunrequest is in flight.
112*4882a593Smuzhiyun
113*4882a593Smuzhiyun.. _media-request-life-time:
114*4882a593Smuzhiyun
115*4882a593SmuzhiyunRecycling and Destruction
116*4882a593Smuzhiyun-------------------------
117*4882a593Smuzhiyun
118*4882a593SmuzhiyunFinally, a completed request can either be discarded or be reused. Calling
119*4882a593Smuzhiyun:c:func:`close()` on a request file descriptor will make
120*4882a593Smuzhiyunthat file descriptor unusable and the request will be freed once it is no
121*4882a593Smuzhiyunlonger in use by the kernel. That is, if the request is queued and then the
122*4882a593Smuzhiyunfile descriptor is closed, then it won't be freed until the driver completed
123*4882a593Smuzhiyunthe request.
124*4882a593Smuzhiyun
125*4882a593SmuzhiyunThe :ref:`MEDIA_REQUEST_IOC_REINIT` will clear a request's state and make it
126*4882a593Smuzhiyunavailable again. No state is retained by this operation: the request is as
127*4882a593Smuzhiyunif it had just been allocated.
128*4882a593Smuzhiyun
129*4882a593SmuzhiyunExample for a Codec Device
130*4882a593Smuzhiyun--------------------------
131*4882a593Smuzhiyun
132*4882a593SmuzhiyunFor use-cases such as :ref:`codecs <mem2mem>`, the request API can be used
133*4882a593Smuzhiyunto associate specific controls to
134*4882a593Smuzhiyunbe applied by the driver for the OUTPUT buffer, allowing user-space
135*4882a593Smuzhiyunto queue many such buffers in advance. It can also take advantage of requests'
136*4882a593Smuzhiyunability to capture the state of controls when the request completes to read back
137*4882a593Smuzhiyuninformation that may be subject to change.
138*4882a593Smuzhiyun
139*4882a593SmuzhiyunPut into code, after obtaining a request, user-space can assign controls and one
140*4882a593SmuzhiyunOUTPUT buffer to it:
141*4882a593Smuzhiyun
142*4882a593Smuzhiyun.. code-block:: c
143*4882a593Smuzhiyun
144*4882a593Smuzhiyun	struct v4l2_buffer buf;
145*4882a593Smuzhiyun	struct v4l2_ext_controls ctrls;
146*4882a593Smuzhiyun	int req_fd;
147*4882a593Smuzhiyun	...
148*4882a593Smuzhiyun	if (ioctl(media_fd, MEDIA_IOC_REQUEST_ALLOC, &req_fd))
149*4882a593Smuzhiyun		return errno;
150*4882a593Smuzhiyun	...
151*4882a593Smuzhiyun	ctrls.which = V4L2_CTRL_WHICH_REQUEST_VAL;
152*4882a593Smuzhiyun	ctrls.request_fd = req_fd;
153*4882a593Smuzhiyun	if (ioctl(codec_fd, VIDIOC_S_EXT_CTRLS, &ctrls))
154*4882a593Smuzhiyun		return errno;
155*4882a593Smuzhiyun	...
156*4882a593Smuzhiyun	buf.type = V4L2_BUF_TYPE_VIDEO_OUTPUT;
157*4882a593Smuzhiyun	buf.flags |= V4L2_BUF_FLAG_REQUEST_FD;
158*4882a593Smuzhiyun	buf.request_fd = req_fd;
159*4882a593Smuzhiyun	if (ioctl(codec_fd, VIDIOC_QBUF, &buf))
160*4882a593Smuzhiyun		return errno;
161*4882a593Smuzhiyun
162*4882a593SmuzhiyunNote that it is not allowed to use the Request API for CAPTURE buffers
163*4882a593Smuzhiyunsince there are no per-frame settings to report there.
164*4882a593Smuzhiyun
165*4882a593SmuzhiyunOnce the request is fully prepared, it can be queued to the driver:
166*4882a593Smuzhiyun
167*4882a593Smuzhiyun.. code-block:: c
168*4882a593Smuzhiyun
169*4882a593Smuzhiyun	if (ioctl(req_fd, MEDIA_REQUEST_IOC_QUEUE))
170*4882a593Smuzhiyun		return errno;
171*4882a593Smuzhiyun
172*4882a593SmuzhiyunUser-space can then either wait for the request to complete by calling poll() on
173*4882a593Smuzhiyunits file descriptor, or start dequeuing CAPTURE buffers. Most likely, it will
174*4882a593Smuzhiyunwant to get CAPTURE buffers as soon as possible and this can be done using a
175*4882a593Smuzhiyunregular :ref:`VIDIOC_DQBUF <VIDIOC_QBUF>`:
176*4882a593Smuzhiyun
177*4882a593Smuzhiyun.. code-block:: c
178*4882a593Smuzhiyun
179*4882a593Smuzhiyun	struct v4l2_buffer buf;
180*4882a593Smuzhiyun
181*4882a593Smuzhiyun	memset(&buf, 0, sizeof(buf));
182*4882a593Smuzhiyun	buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
183*4882a593Smuzhiyun	if (ioctl(codec_fd, VIDIOC_DQBUF, &buf))
184*4882a593Smuzhiyun		return errno;
185*4882a593Smuzhiyun
186*4882a593SmuzhiyunNote that this example assumes for simplicity that for every OUTPUT buffer
187*4882a593Smuzhiyunthere will be one CAPTURE buffer, but this does not have to be the case.
188*4882a593Smuzhiyun
189*4882a593SmuzhiyunWe can then, after ensuring that the request is completed via polling the
190*4882a593Smuzhiyunrequest file descriptor, query control values at the time of its completion via
191*4882a593Smuzhiyuna call to :ref:`VIDIOC_G_EXT_CTRLS <VIDIOC_G_EXT_CTRLS>`.
192*4882a593SmuzhiyunThis is particularly useful for volatile controls for which we want to
193*4882a593Smuzhiyunquery values as soon as the capture buffer is produced.
194*4882a593Smuzhiyun
195*4882a593Smuzhiyun.. code-block:: c
196*4882a593Smuzhiyun
197*4882a593Smuzhiyun	struct pollfd pfd = { .events = POLLPRI, .fd = req_fd };
198*4882a593Smuzhiyun	poll(&pfd, 1, -1);
199*4882a593Smuzhiyun	...
200*4882a593Smuzhiyun	ctrls.which = V4L2_CTRL_WHICH_REQUEST_VAL;
201*4882a593Smuzhiyun	ctrls.request_fd = req_fd;
202*4882a593Smuzhiyun	if (ioctl(codec_fd, VIDIOC_G_EXT_CTRLS, &ctrls))
203*4882a593Smuzhiyun		return errno;
204*4882a593Smuzhiyun
205*4882a593SmuzhiyunOnce we don't need the request anymore, we can either recycle it for reuse with
206*4882a593Smuzhiyun:ref:`MEDIA_REQUEST_IOC_REINIT`...
207*4882a593Smuzhiyun
208*4882a593Smuzhiyun.. code-block:: c
209*4882a593Smuzhiyun
210*4882a593Smuzhiyun	if (ioctl(req_fd, MEDIA_REQUEST_IOC_REINIT))
211*4882a593Smuzhiyun		return errno;
212*4882a593Smuzhiyun
213*4882a593Smuzhiyun... or close its file descriptor to completely dispose of it.
214*4882a593Smuzhiyun
215*4882a593Smuzhiyun.. code-block:: c
216*4882a593Smuzhiyun
217*4882a593Smuzhiyun	close(req_fd);
218*4882a593Smuzhiyun
219*4882a593SmuzhiyunExample for a Simple Capture Device
220*4882a593Smuzhiyun-----------------------------------
221*4882a593Smuzhiyun
222*4882a593SmuzhiyunWith a simple capture device, requests can be used to specify controls to apply
223*4882a593Smuzhiyunfor a given CAPTURE buffer.
224*4882a593Smuzhiyun
225*4882a593Smuzhiyun.. code-block:: c
226*4882a593Smuzhiyun
227*4882a593Smuzhiyun	struct v4l2_buffer buf;
228*4882a593Smuzhiyun	struct v4l2_ext_controls ctrls;
229*4882a593Smuzhiyun	int req_fd;
230*4882a593Smuzhiyun	...
231*4882a593Smuzhiyun	if (ioctl(media_fd, MEDIA_IOC_REQUEST_ALLOC, &req_fd))
232*4882a593Smuzhiyun		return errno;
233*4882a593Smuzhiyun	...
234*4882a593Smuzhiyun	ctrls.which = V4L2_CTRL_WHICH_REQUEST_VAL;
235*4882a593Smuzhiyun	ctrls.request_fd = req_fd;
236*4882a593Smuzhiyun	if (ioctl(camera_fd, VIDIOC_S_EXT_CTRLS, &ctrls))
237*4882a593Smuzhiyun		return errno;
238*4882a593Smuzhiyun	...
239*4882a593Smuzhiyun	buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
240*4882a593Smuzhiyun	buf.flags |= V4L2_BUF_FLAG_REQUEST_FD;
241*4882a593Smuzhiyun	buf.request_fd = req_fd;
242*4882a593Smuzhiyun	if (ioctl(camera_fd, VIDIOC_QBUF, &buf))
243*4882a593Smuzhiyun		return errno;
244*4882a593Smuzhiyun
245*4882a593SmuzhiyunOnce the request is fully prepared, it can be queued to the driver:
246*4882a593Smuzhiyun
247*4882a593Smuzhiyun.. code-block:: c
248*4882a593Smuzhiyun
249*4882a593Smuzhiyun	if (ioctl(req_fd, MEDIA_REQUEST_IOC_QUEUE))
250*4882a593Smuzhiyun		return errno;
251*4882a593Smuzhiyun
252*4882a593SmuzhiyunUser-space can then dequeue buffers, wait for the request completion, query
253*4882a593Smuzhiyuncontrols and recycle the request as in the M2M example above.
254