xref: /openbmc/linux/Documentation/userspace-api/media/mediactl/request-api.rst (revision cbecf716ca618fd44feda6bd9a64a8179d031fc5)
184d33341SMauro Carvalho Chehab.. SPDX-License-Identifier: GPL-2.0 OR GFDL-1.1-no-invariants-or-later
2*937e6805SMauro Carvalho Chehab.. c:namespace:: MC
354f38fcaSMauro Carvalho Chehab
454f38fcaSMauro Carvalho Chehab.. _media-request-api:
554f38fcaSMauro Carvalho Chehab
654f38fcaSMauro Carvalho ChehabRequest API
754f38fcaSMauro Carvalho Chehab===========
854f38fcaSMauro Carvalho Chehab
954f38fcaSMauro Carvalho ChehabThe Request API has been designed to allow V4L2 to deal with requirements of
1054f38fcaSMauro Carvalho Chehabmodern devices (stateless codecs, complex camera pipelines, ...) and APIs
1154f38fcaSMauro Carvalho Chehab(Android Codec v2). One such requirement is the ability for devices belonging to
1254f38fcaSMauro Carvalho Chehabthe same pipeline to reconfigure and collaborate closely on a per-frame basis.
1354f38fcaSMauro Carvalho ChehabAnother is support of stateless codecs, which require controls to be applied
1454f38fcaSMauro Carvalho Chehabto specific frames (aka 'per-frame controls') in order to be used efficiently.
1554f38fcaSMauro Carvalho Chehab
1654f38fcaSMauro Carvalho ChehabWhile the initial use-case was V4L2, it can be extended to other subsystems
1754f38fcaSMauro Carvalho Chehabas well, as long as they use the media controller.
1854f38fcaSMauro Carvalho Chehab
1954f38fcaSMauro Carvalho ChehabSupporting these features without the Request API is not always possible and if
2054f38fcaSMauro Carvalho Chehabit is, it is terribly inefficient: user-space would have to flush all activity
2154f38fcaSMauro Carvalho Chehabon the media pipeline, reconfigure it for the next frame, queue the buffers to
2254f38fcaSMauro Carvalho Chehabbe processed with that configuration, and wait until they are all available for
2354f38fcaSMauro Carvalho Chehabdequeuing before considering the next frame. This defeats the purpose of having
2454f38fcaSMauro Carvalho Chehabbuffer queues since in practice only one buffer would be queued at a time.
2554f38fcaSMauro Carvalho Chehab
2654f38fcaSMauro Carvalho ChehabThe Request API allows a specific configuration of the pipeline (media
2754f38fcaSMauro Carvalho Chehabcontroller topology + configuration for each media entity) to be associated with
2854f38fcaSMauro Carvalho Chehabspecific buffers. This allows user-space to schedule several tasks ("requests")
2954f38fcaSMauro Carvalho Chehabwith different configurations in advance, knowing that the configuration will be
3054f38fcaSMauro Carvalho Chehabapplied when needed to get the expected result. Configuration values at the time
3154f38fcaSMauro Carvalho Chehabof request completion are also available for reading.
3254f38fcaSMauro Carvalho Chehab
3354f38fcaSMauro Carvalho ChehabGeneral Usage
3454f38fcaSMauro Carvalho Chehab-------------
3554f38fcaSMauro Carvalho Chehab
3654f38fcaSMauro Carvalho ChehabThe Request API extends the Media Controller API and cooperates with
3754f38fcaSMauro Carvalho Chehabsubsystem-specific APIs to support request usage. At the Media Controller
3854f38fcaSMauro Carvalho Chehablevel, requests are allocated from the supporting Media Controller device
3954f38fcaSMauro Carvalho Chehabnode. Their life cycle is then managed through the request file descriptors in
4054f38fcaSMauro Carvalho Chehaban opaque way. Configuration data, buffer handles and processing results
4154f38fcaSMauro Carvalho Chehabstored in requests are accessed through subsystem-specific APIs extended for
4254f38fcaSMauro Carvalho Chehabrequest support, such as V4L2 APIs that take an explicit ``request_fd``
4354f38fcaSMauro Carvalho Chehabparameter.
4454f38fcaSMauro Carvalho Chehab
4554f38fcaSMauro Carvalho ChehabRequest Allocation
4654f38fcaSMauro Carvalho Chehab------------------
4754f38fcaSMauro Carvalho Chehab
4854f38fcaSMauro Carvalho ChehabUser-space allocates requests using :ref:`MEDIA_IOC_REQUEST_ALLOC`
4954f38fcaSMauro Carvalho Chehabfor the media device node. This returns a file descriptor representing the
5054f38fcaSMauro Carvalho Chehabrequest. Typically, several such requests will be allocated.
5154f38fcaSMauro Carvalho Chehab
5254f38fcaSMauro Carvalho ChehabRequest Preparation
5354f38fcaSMauro Carvalho Chehab-------------------
5454f38fcaSMauro Carvalho Chehab
5554f38fcaSMauro Carvalho ChehabStandard V4L2 ioctls can then receive a request file descriptor to express the
5654f38fcaSMauro Carvalho Chehabfact that the ioctl is part of said request, and is not to be applied
5754f38fcaSMauro Carvalho Chehabimmediately. See :ref:`MEDIA_IOC_REQUEST_ALLOC` for a list of ioctls that
5854f38fcaSMauro Carvalho Chehabsupport this. Configurations set with a ``request_fd`` parameter are stored
5954f38fcaSMauro Carvalho Chehabinstead of being immediately applied, and buffers queued to a request do not
6054f38fcaSMauro Carvalho Chehabenter the regular buffer queue until the request itself is queued.
6154f38fcaSMauro Carvalho Chehab
6254f38fcaSMauro Carvalho ChehabRequest Submission
6354f38fcaSMauro Carvalho Chehab------------------
6454f38fcaSMauro Carvalho Chehab
6554f38fcaSMauro Carvalho ChehabOnce the configuration and buffers of the request are specified, it can be
6654f38fcaSMauro Carvalho Chehabqueued by calling :ref:`MEDIA_REQUEST_IOC_QUEUE` on the request file descriptor.
6754f38fcaSMauro Carvalho ChehabA request must contain at least one buffer, otherwise ``ENOENT`` is returned.
6854f38fcaSMauro Carvalho ChehabA queued request cannot be modified anymore.
6954f38fcaSMauro Carvalho Chehab
7054f38fcaSMauro Carvalho Chehab.. caution::
7154f38fcaSMauro Carvalho Chehab   For :ref:`memory-to-memory devices <mem2mem>` you can use requests only for
7254f38fcaSMauro Carvalho Chehab   output buffers, not for capture buffers. Attempting to add a capture buffer
7354f38fcaSMauro Carvalho Chehab   to a request will result in an ``EBADR`` error.
7454f38fcaSMauro Carvalho Chehab
7554f38fcaSMauro Carvalho ChehabIf the request contains configurations for multiple entities, individual drivers
7654f38fcaSMauro Carvalho Chehabmay synchronize so the requested pipeline's topology is applied before the
7754f38fcaSMauro Carvalho Chehabbuffers are processed. Media controller drivers do a best effort implementation
7854f38fcaSMauro Carvalho Chehabsince perfect atomicity may not be possible due to hardware limitations.
7954f38fcaSMauro Carvalho Chehab
8054f38fcaSMauro Carvalho Chehab.. caution::
8154f38fcaSMauro Carvalho Chehab
8254f38fcaSMauro Carvalho Chehab   It is not allowed to mix queuing requests with directly queuing buffers:
8354f38fcaSMauro Carvalho Chehab   whichever method is used first locks this in place until
8454f38fcaSMauro Carvalho Chehab   :ref:`VIDIOC_STREAMOFF <VIDIOC_STREAMON>` is called or the device is
8554f38fcaSMauro Carvalho Chehab   :ref:`closed <func-close>`. Attempts to directly queue a buffer when earlier
8654f38fcaSMauro Carvalho Chehab   a buffer was queued via a request or vice versa will result in an ``EBUSY``
8754f38fcaSMauro Carvalho Chehab   error.
8854f38fcaSMauro Carvalho Chehab
8954f38fcaSMauro Carvalho ChehabControls can still be set without a request and are applied immediately,
9054f38fcaSMauro Carvalho Chehabregardless of whether a request is in use or not.
9154f38fcaSMauro Carvalho Chehab
9254f38fcaSMauro Carvalho Chehab.. caution::
9354f38fcaSMauro Carvalho Chehab
9454f38fcaSMauro Carvalho Chehab   Setting the same control through a request and also directly can lead to
9554f38fcaSMauro Carvalho Chehab   undefined behavior!
9654f38fcaSMauro Carvalho Chehab
97*937e6805SMauro Carvalho ChehabUser-space can :c:func:`poll()` a request file descriptor in
9854f38fcaSMauro Carvalho Chehaborder to wait until the request completes. A request is considered complete
9954f38fcaSMauro Carvalho Chehabonce all its associated buffers are available for dequeuing and all the
10054f38fcaSMauro Carvalho Chehabassociated controls have been updated with the values at the time of completion.
10154f38fcaSMauro Carvalho ChehabNote that user-space does not need to wait for the request to complete to
10254f38fcaSMauro Carvalho Chehabdequeue its buffers: buffers that are available halfway through a request can
10354f38fcaSMauro Carvalho Chehabbe dequeued independently of the request's state.
10454f38fcaSMauro Carvalho Chehab
10554f38fcaSMauro Carvalho ChehabA completed request contains the state of the device after the request was
10654f38fcaSMauro Carvalho Chehabexecuted. User-space can query that state by calling
10754f38fcaSMauro Carvalho Chehab:ref:`ioctl VIDIOC_G_EXT_CTRLS <VIDIOC_G_EXT_CTRLS>` with the request file
10854f38fcaSMauro Carvalho Chehabdescriptor. Calling :ref:`ioctl VIDIOC_G_EXT_CTRLS <VIDIOC_G_EXT_CTRLS>` for a
10954f38fcaSMauro Carvalho Chehabrequest that has been queued but not yet completed will return ``EBUSY``
11054f38fcaSMauro Carvalho Chehabsince the control values might be changed at any time by the driver while the
11154f38fcaSMauro Carvalho Chehabrequest is in flight.
11254f38fcaSMauro Carvalho Chehab
11354f38fcaSMauro Carvalho Chehab.. _media-request-life-time:
11454f38fcaSMauro Carvalho Chehab
11554f38fcaSMauro Carvalho ChehabRecycling and Destruction
11654f38fcaSMauro Carvalho Chehab-------------------------
11754f38fcaSMauro Carvalho Chehab
11854f38fcaSMauro Carvalho ChehabFinally, a completed request can either be discarded or be reused. Calling
119*937e6805SMauro Carvalho Chehab:c:func:`close()` on a request file descriptor will make
12054f38fcaSMauro Carvalho Chehabthat file descriptor unusable and the request will be freed once it is no
12154f38fcaSMauro Carvalho Chehablonger in use by the kernel. That is, if the request is queued and then the
12254f38fcaSMauro Carvalho Chehabfile descriptor is closed, then it won't be freed until the driver completed
12354f38fcaSMauro Carvalho Chehabthe request.
12454f38fcaSMauro Carvalho Chehab
12554f38fcaSMauro Carvalho ChehabThe :ref:`MEDIA_REQUEST_IOC_REINIT` will clear a request's state and make it
12654f38fcaSMauro Carvalho Chehabavailable again. No state is retained by this operation: the request is as
12754f38fcaSMauro Carvalho Chehabif it had just been allocated.
12854f38fcaSMauro Carvalho Chehab
12954f38fcaSMauro Carvalho ChehabExample for a Codec Device
13054f38fcaSMauro Carvalho Chehab--------------------------
13154f38fcaSMauro Carvalho Chehab
13254f38fcaSMauro Carvalho ChehabFor use-cases such as :ref:`codecs <mem2mem>`, the request API can be used
13354f38fcaSMauro Carvalho Chehabto associate specific controls to
13454f38fcaSMauro Carvalho Chehabbe applied by the driver for the OUTPUT buffer, allowing user-space
13554f38fcaSMauro Carvalho Chehabto queue many such buffers in advance. It can also take advantage of requests'
13654f38fcaSMauro Carvalho Chehabability to capture the state of controls when the request completes to read back
13754f38fcaSMauro Carvalho Chehabinformation that may be subject to change.
13854f38fcaSMauro Carvalho Chehab
13954f38fcaSMauro Carvalho ChehabPut into code, after obtaining a request, user-space can assign controls and one
14054f38fcaSMauro Carvalho ChehabOUTPUT buffer to it:
14154f38fcaSMauro Carvalho Chehab
14254f38fcaSMauro Carvalho Chehab.. code-block:: c
14354f38fcaSMauro Carvalho Chehab
14454f38fcaSMauro Carvalho Chehab	struct v4l2_buffer buf;
14554f38fcaSMauro Carvalho Chehab	struct v4l2_ext_controls ctrls;
14654f38fcaSMauro Carvalho Chehab	int req_fd;
14754f38fcaSMauro Carvalho Chehab	...
14854f38fcaSMauro Carvalho Chehab	if (ioctl(media_fd, MEDIA_IOC_REQUEST_ALLOC, &req_fd))
14954f38fcaSMauro Carvalho Chehab		return errno;
15054f38fcaSMauro Carvalho Chehab	...
15154f38fcaSMauro Carvalho Chehab	ctrls.which = V4L2_CTRL_WHICH_REQUEST_VAL;
15254f38fcaSMauro Carvalho Chehab	ctrls.request_fd = req_fd;
15354f38fcaSMauro Carvalho Chehab	if (ioctl(codec_fd, VIDIOC_S_EXT_CTRLS, &ctrls))
15454f38fcaSMauro Carvalho Chehab		return errno;
15554f38fcaSMauro Carvalho Chehab	...
15654f38fcaSMauro Carvalho Chehab	buf.type = V4L2_BUF_TYPE_VIDEO_OUTPUT;
15754f38fcaSMauro Carvalho Chehab	buf.flags |= V4L2_BUF_FLAG_REQUEST_FD;
15854f38fcaSMauro Carvalho Chehab	buf.request_fd = req_fd;
15954f38fcaSMauro Carvalho Chehab	if (ioctl(codec_fd, VIDIOC_QBUF, &buf))
16054f38fcaSMauro Carvalho Chehab		return errno;
16154f38fcaSMauro Carvalho Chehab
16254f38fcaSMauro Carvalho ChehabNote that it is not allowed to use the Request API for CAPTURE buffers
16354f38fcaSMauro Carvalho Chehabsince there are no per-frame settings to report there.
16454f38fcaSMauro Carvalho Chehab
16554f38fcaSMauro Carvalho ChehabOnce the request is fully prepared, it can be queued to the driver:
16654f38fcaSMauro Carvalho Chehab
16754f38fcaSMauro Carvalho Chehab.. code-block:: c
16854f38fcaSMauro Carvalho Chehab
16954f38fcaSMauro Carvalho Chehab	if (ioctl(req_fd, MEDIA_REQUEST_IOC_QUEUE))
17054f38fcaSMauro Carvalho Chehab		return errno;
17154f38fcaSMauro Carvalho Chehab
17254f38fcaSMauro Carvalho ChehabUser-space can then either wait for the request to complete by calling poll() on
17354f38fcaSMauro Carvalho Chehabits file descriptor, or start dequeuing CAPTURE buffers. Most likely, it will
17454f38fcaSMauro Carvalho Chehabwant to get CAPTURE buffers as soon as possible and this can be done using a
17554f38fcaSMauro Carvalho Chehabregular :ref:`VIDIOC_DQBUF <VIDIOC_QBUF>`:
17654f38fcaSMauro Carvalho Chehab
17754f38fcaSMauro Carvalho Chehab.. code-block:: c
17854f38fcaSMauro Carvalho Chehab
17954f38fcaSMauro Carvalho Chehab	struct v4l2_buffer buf;
18054f38fcaSMauro Carvalho Chehab
18154f38fcaSMauro Carvalho Chehab	memset(&buf, 0, sizeof(buf));
18254f38fcaSMauro Carvalho Chehab	buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
18354f38fcaSMauro Carvalho Chehab	if (ioctl(codec_fd, VIDIOC_DQBUF, &buf))
18454f38fcaSMauro Carvalho Chehab		return errno;
18554f38fcaSMauro Carvalho Chehab
18654f38fcaSMauro Carvalho ChehabNote that this example assumes for simplicity that for every OUTPUT buffer
18754f38fcaSMauro Carvalho Chehabthere will be one CAPTURE buffer, but this does not have to be the case.
18854f38fcaSMauro Carvalho Chehab
18954f38fcaSMauro Carvalho ChehabWe can then, after ensuring that the request is completed via polling the
19054f38fcaSMauro Carvalho Chehabrequest file descriptor, query control values at the time of its completion via
19154f38fcaSMauro Carvalho Chehaba call to :ref:`VIDIOC_G_EXT_CTRLS <VIDIOC_G_EXT_CTRLS>`.
19254f38fcaSMauro Carvalho ChehabThis is particularly useful for volatile controls for which we want to
19354f38fcaSMauro Carvalho Chehabquery values as soon as the capture buffer is produced.
19454f38fcaSMauro Carvalho Chehab
19554f38fcaSMauro Carvalho Chehab.. code-block:: c
19654f38fcaSMauro Carvalho Chehab
19754f38fcaSMauro Carvalho Chehab	struct pollfd pfd = { .events = POLLPRI, .fd = req_fd };
19854f38fcaSMauro Carvalho Chehab	poll(&pfd, 1, -1);
19954f38fcaSMauro Carvalho Chehab	...
20054f38fcaSMauro Carvalho Chehab	ctrls.which = V4L2_CTRL_WHICH_REQUEST_VAL;
20154f38fcaSMauro Carvalho Chehab	ctrls.request_fd = req_fd;
20254f38fcaSMauro Carvalho Chehab	if (ioctl(codec_fd, VIDIOC_G_EXT_CTRLS, &ctrls))
20354f38fcaSMauro Carvalho Chehab		return errno;
20454f38fcaSMauro Carvalho Chehab
20554f38fcaSMauro Carvalho ChehabOnce we don't need the request anymore, we can either recycle it for reuse with
20654f38fcaSMauro Carvalho Chehab:ref:`MEDIA_REQUEST_IOC_REINIT`...
20754f38fcaSMauro Carvalho Chehab
20854f38fcaSMauro Carvalho Chehab.. code-block:: c
20954f38fcaSMauro Carvalho Chehab
21054f38fcaSMauro Carvalho Chehab	if (ioctl(req_fd, MEDIA_REQUEST_IOC_REINIT))
21154f38fcaSMauro Carvalho Chehab		return errno;
21254f38fcaSMauro Carvalho Chehab
21354f38fcaSMauro Carvalho Chehab... or close its file descriptor to completely dispose of it.
21454f38fcaSMauro Carvalho Chehab
21554f38fcaSMauro Carvalho Chehab.. code-block:: c
21654f38fcaSMauro Carvalho Chehab
21754f38fcaSMauro Carvalho Chehab	close(req_fd);
21854f38fcaSMauro Carvalho Chehab
21954f38fcaSMauro Carvalho ChehabExample for a Simple Capture Device
22054f38fcaSMauro Carvalho Chehab-----------------------------------
22154f38fcaSMauro Carvalho Chehab
22254f38fcaSMauro Carvalho ChehabWith a simple capture device, requests can be used to specify controls to apply
22354f38fcaSMauro Carvalho Chehabfor a given CAPTURE buffer.
22454f38fcaSMauro Carvalho Chehab
22554f38fcaSMauro Carvalho Chehab.. code-block:: c
22654f38fcaSMauro Carvalho Chehab
22754f38fcaSMauro Carvalho Chehab	struct v4l2_buffer buf;
22854f38fcaSMauro Carvalho Chehab	struct v4l2_ext_controls ctrls;
22954f38fcaSMauro Carvalho Chehab	int req_fd;
23054f38fcaSMauro Carvalho Chehab	...
23154f38fcaSMauro Carvalho Chehab	if (ioctl(media_fd, MEDIA_IOC_REQUEST_ALLOC, &req_fd))
23254f38fcaSMauro Carvalho Chehab		return errno;
23354f38fcaSMauro Carvalho Chehab	...
23454f38fcaSMauro Carvalho Chehab	ctrls.which = V4L2_CTRL_WHICH_REQUEST_VAL;
23554f38fcaSMauro Carvalho Chehab	ctrls.request_fd = req_fd;
23654f38fcaSMauro Carvalho Chehab	if (ioctl(camera_fd, VIDIOC_S_EXT_CTRLS, &ctrls))
23754f38fcaSMauro Carvalho Chehab		return errno;
23854f38fcaSMauro Carvalho Chehab	...
23954f38fcaSMauro Carvalho Chehab	buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
24054f38fcaSMauro Carvalho Chehab	buf.flags |= V4L2_BUF_FLAG_REQUEST_FD;
24154f38fcaSMauro Carvalho Chehab	buf.request_fd = req_fd;
24254f38fcaSMauro Carvalho Chehab	if (ioctl(camera_fd, VIDIOC_QBUF, &buf))
24354f38fcaSMauro Carvalho Chehab		return errno;
24454f38fcaSMauro Carvalho Chehab
24554f38fcaSMauro Carvalho ChehabOnce the request is fully prepared, it can be queued to the driver:
24654f38fcaSMauro Carvalho Chehab
24754f38fcaSMauro Carvalho Chehab.. code-block:: c
24854f38fcaSMauro Carvalho Chehab
24954f38fcaSMauro Carvalho Chehab	if (ioctl(req_fd, MEDIA_REQUEST_IOC_QUEUE))
25054f38fcaSMauro Carvalho Chehab		return errno;
25154f38fcaSMauro Carvalho Chehab
25254f38fcaSMauro Carvalho ChehabUser-space can then dequeue buffers, wait for the request completion, query
25354f38fcaSMauro Carvalho Chehabcontrols and recycle the request as in the M2M example above.
254