18c2ecf20Sopenharmony_ci.. SPDX-License-Identifier: GPL-2.0 OR GFDL-1.1-no-invariants-or-later 28c2ecf20Sopenharmony_ci.. c:namespace:: MC 38c2ecf20Sopenharmony_ci 48c2ecf20Sopenharmony_ci.. _media-request-api: 58c2ecf20Sopenharmony_ci 68c2ecf20Sopenharmony_ciRequest API 78c2ecf20Sopenharmony_ci=========== 88c2ecf20Sopenharmony_ci 98c2ecf20Sopenharmony_ciThe Request API has been designed to allow V4L2 to deal with requirements of 108c2ecf20Sopenharmony_cimodern devices (stateless codecs, complex camera pipelines, ...) and APIs 118c2ecf20Sopenharmony_ci(Android Codec v2). One such requirement is the ability for devices belonging to 128c2ecf20Sopenharmony_cithe same pipeline to reconfigure and collaborate closely on a per-frame basis. 138c2ecf20Sopenharmony_ciAnother is support of stateless codecs, which require controls to be applied 148c2ecf20Sopenharmony_cito specific frames (aka 'per-frame controls') in order to be used efficiently. 158c2ecf20Sopenharmony_ci 168c2ecf20Sopenharmony_ciWhile the initial use-case was V4L2, it can be extended to other subsystems 178c2ecf20Sopenharmony_cias well, as long as they use the media controller. 188c2ecf20Sopenharmony_ci 198c2ecf20Sopenharmony_ciSupporting these features without the Request API is not always possible and if 208c2ecf20Sopenharmony_ciit is, it is terribly inefficient: user-space would have to flush all activity 218c2ecf20Sopenharmony_cion the media pipeline, reconfigure it for the next frame, queue the buffers to 228c2ecf20Sopenharmony_cibe processed with that configuration, and wait until they are all available for 238c2ecf20Sopenharmony_cidequeuing before considering the next frame. This defeats the purpose of having 248c2ecf20Sopenharmony_cibuffer queues since in practice only one buffer would be queued at a time. 258c2ecf20Sopenharmony_ci 268c2ecf20Sopenharmony_ciThe Request API allows a specific configuration of the pipeline (media 278c2ecf20Sopenharmony_cicontroller topology + configuration for each media entity) to be associated with 288c2ecf20Sopenharmony_cispecific buffers. This allows user-space to schedule several tasks ("requests") 298c2ecf20Sopenharmony_ciwith different configurations in advance, knowing that the configuration will be 308c2ecf20Sopenharmony_ciapplied when needed to get the expected result. Configuration values at the time 318c2ecf20Sopenharmony_ciof request completion are also available for reading. 328c2ecf20Sopenharmony_ci 338c2ecf20Sopenharmony_ciGeneral Usage 348c2ecf20Sopenharmony_ci------------- 358c2ecf20Sopenharmony_ci 368c2ecf20Sopenharmony_ciThe Request API extends the Media Controller API and cooperates with 378c2ecf20Sopenharmony_cisubsystem-specific APIs to support request usage. At the Media Controller 388c2ecf20Sopenharmony_cilevel, requests are allocated from the supporting Media Controller device 398c2ecf20Sopenharmony_cinode. Their life cycle is then managed through the request file descriptors in 408c2ecf20Sopenharmony_cian opaque way. Configuration data, buffer handles and processing results 418c2ecf20Sopenharmony_cistored in requests are accessed through subsystem-specific APIs extended for 428c2ecf20Sopenharmony_cirequest support, such as V4L2 APIs that take an explicit ``request_fd`` 438c2ecf20Sopenharmony_ciparameter. 448c2ecf20Sopenharmony_ci 458c2ecf20Sopenharmony_ciRequest Allocation 468c2ecf20Sopenharmony_ci------------------ 478c2ecf20Sopenharmony_ci 488c2ecf20Sopenharmony_ciUser-space allocates requests using :ref:`MEDIA_IOC_REQUEST_ALLOC` 498c2ecf20Sopenharmony_cifor the media device node. This returns a file descriptor representing the 508c2ecf20Sopenharmony_cirequest. Typically, several such requests will be allocated. 518c2ecf20Sopenharmony_ci 528c2ecf20Sopenharmony_ciRequest Preparation 538c2ecf20Sopenharmony_ci------------------- 548c2ecf20Sopenharmony_ci 558c2ecf20Sopenharmony_ciStandard V4L2 ioctls can then receive a request file descriptor to express the 568c2ecf20Sopenharmony_cifact that the ioctl is part of said request, and is not to be applied 578c2ecf20Sopenharmony_ciimmediately. See :ref:`MEDIA_IOC_REQUEST_ALLOC` for a list of ioctls that 588c2ecf20Sopenharmony_cisupport this. Configurations set with a ``request_fd`` parameter are stored 598c2ecf20Sopenharmony_ciinstead of being immediately applied, and buffers queued to a request do not 608c2ecf20Sopenharmony_cienter the regular buffer queue until the request itself is queued. 618c2ecf20Sopenharmony_ci 628c2ecf20Sopenharmony_ciRequest Submission 638c2ecf20Sopenharmony_ci------------------ 648c2ecf20Sopenharmony_ci 658c2ecf20Sopenharmony_ciOnce the configuration and buffers of the request are specified, it can be 668c2ecf20Sopenharmony_ciqueued by calling :ref:`MEDIA_REQUEST_IOC_QUEUE` on the request file descriptor. 678c2ecf20Sopenharmony_ciA request must contain at least one buffer, otherwise ``ENOENT`` is returned. 688c2ecf20Sopenharmony_ciA queued request cannot be modified anymore. 698c2ecf20Sopenharmony_ci 708c2ecf20Sopenharmony_ci.. caution:: 718c2ecf20Sopenharmony_ci For :ref:`memory-to-memory devices <mem2mem>` you can use requests only for 728c2ecf20Sopenharmony_ci output buffers, not for capture buffers. Attempting to add a capture buffer 738c2ecf20Sopenharmony_ci to a request will result in an ``EBADR`` error. 748c2ecf20Sopenharmony_ci 758c2ecf20Sopenharmony_ciIf the request contains configurations for multiple entities, individual drivers 768c2ecf20Sopenharmony_cimay synchronize so the requested pipeline's topology is applied before the 778c2ecf20Sopenharmony_cibuffers are processed. Media controller drivers do a best effort implementation 788c2ecf20Sopenharmony_cisince perfect atomicity may not be possible due to hardware limitations. 798c2ecf20Sopenharmony_ci 808c2ecf20Sopenharmony_ci.. caution:: 818c2ecf20Sopenharmony_ci 828c2ecf20Sopenharmony_ci It is not allowed to mix queuing requests with directly queuing buffers: 838c2ecf20Sopenharmony_ci whichever method is used first locks this in place until 848c2ecf20Sopenharmony_ci :ref:`VIDIOC_STREAMOFF <VIDIOC_STREAMON>` is called or the device is 858c2ecf20Sopenharmony_ci :ref:`closed <func-close>`. Attempts to directly queue a buffer when earlier 868c2ecf20Sopenharmony_ci a buffer was queued via a request or vice versa will result in an ``EBUSY`` 878c2ecf20Sopenharmony_ci error. 888c2ecf20Sopenharmony_ci 898c2ecf20Sopenharmony_ciControls can still be set without a request and are applied immediately, 908c2ecf20Sopenharmony_ciregardless of whether a request is in use or not. 918c2ecf20Sopenharmony_ci 928c2ecf20Sopenharmony_ci.. caution:: 938c2ecf20Sopenharmony_ci 948c2ecf20Sopenharmony_ci Setting the same control through a request and also directly can lead to 958c2ecf20Sopenharmony_ci undefined behavior! 968c2ecf20Sopenharmony_ci 978c2ecf20Sopenharmony_ciUser-space can :c:func:`poll()` a request file descriptor in 988c2ecf20Sopenharmony_ciorder to wait until the request completes. A request is considered complete 998c2ecf20Sopenharmony_cionce all its associated buffers are available for dequeuing and all the 1008c2ecf20Sopenharmony_ciassociated controls have been updated with the values at the time of completion. 1018c2ecf20Sopenharmony_ciNote that user-space does not need to wait for the request to complete to 1028c2ecf20Sopenharmony_cidequeue its buffers: buffers that are available halfway through a request can 1038c2ecf20Sopenharmony_cibe dequeued independently of the request's state. 1048c2ecf20Sopenharmony_ci 1058c2ecf20Sopenharmony_ciA completed request contains the state of the device after the request was 1068c2ecf20Sopenharmony_ciexecuted. User-space can query that state by calling 1078c2ecf20Sopenharmony_ci:ref:`ioctl VIDIOC_G_EXT_CTRLS <VIDIOC_G_EXT_CTRLS>` with the request file 1088c2ecf20Sopenharmony_cidescriptor. Calling :ref:`ioctl VIDIOC_G_EXT_CTRLS <VIDIOC_G_EXT_CTRLS>` for a 1098c2ecf20Sopenharmony_cirequest that has been queued but not yet completed will return ``EBUSY`` 1108c2ecf20Sopenharmony_cisince the control values might be changed at any time by the driver while the 1118c2ecf20Sopenharmony_cirequest is in flight. 1128c2ecf20Sopenharmony_ci 1138c2ecf20Sopenharmony_ci.. _media-request-life-time: 1148c2ecf20Sopenharmony_ci 1158c2ecf20Sopenharmony_ciRecycling and Destruction 1168c2ecf20Sopenharmony_ci------------------------- 1178c2ecf20Sopenharmony_ci 1188c2ecf20Sopenharmony_ciFinally, a completed request can either be discarded or be reused. Calling 1198c2ecf20Sopenharmony_ci:c:func:`close()` on a request file descriptor will make 1208c2ecf20Sopenharmony_cithat file descriptor unusable and the request will be freed once it is no 1218c2ecf20Sopenharmony_cilonger in use by the kernel. That is, if the request is queued and then the 1228c2ecf20Sopenharmony_cifile descriptor is closed, then it won't be freed until the driver completed 1238c2ecf20Sopenharmony_cithe request. 1248c2ecf20Sopenharmony_ci 1258c2ecf20Sopenharmony_ciThe :ref:`MEDIA_REQUEST_IOC_REINIT` will clear a request's state and make it 1268c2ecf20Sopenharmony_ciavailable again. No state is retained by this operation: the request is as 1278c2ecf20Sopenharmony_ciif it had just been allocated. 1288c2ecf20Sopenharmony_ci 1298c2ecf20Sopenharmony_ciExample for a Codec Device 1308c2ecf20Sopenharmony_ci-------------------------- 1318c2ecf20Sopenharmony_ci 1328c2ecf20Sopenharmony_ciFor use-cases such as :ref:`codecs <mem2mem>`, the request API can be used 1338c2ecf20Sopenharmony_cito associate specific controls to 1348c2ecf20Sopenharmony_cibe applied by the driver for the OUTPUT buffer, allowing user-space 1358c2ecf20Sopenharmony_cito queue many such buffers in advance. It can also take advantage of requests' 1368c2ecf20Sopenharmony_ciability to capture the state of controls when the request completes to read back 1378c2ecf20Sopenharmony_ciinformation that may be subject to change. 1388c2ecf20Sopenharmony_ci 1398c2ecf20Sopenharmony_ciPut into code, after obtaining a request, user-space can assign controls and one 1408c2ecf20Sopenharmony_ciOUTPUT buffer to it: 1418c2ecf20Sopenharmony_ci 1428c2ecf20Sopenharmony_ci.. code-block:: c 1438c2ecf20Sopenharmony_ci 1448c2ecf20Sopenharmony_ci struct v4l2_buffer buf; 1458c2ecf20Sopenharmony_ci struct v4l2_ext_controls ctrls; 1468c2ecf20Sopenharmony_ci int req_fd; 1478c2ecf20Sopenharmony_ci ... 1488c2ecf20Sopenharmony_ci if (ioctl(media_fd, MEDIA_IOC_REQUEST_ALLOC, &req_fd)) 1498c2ecf20Sopenharmony_ci return errno; 1508c2ecf20Sopenharmony_ci ... 1518c2ecf20Sopenharmony_ci ctrls.which = V4L2_CTRL_WHICH_REQUEST_VAL; 1528c2ecf20Sopenharmony_ci ctrls.request_fd = req_fd; 1538c2ecf20Sopenharmony_ci if (ioctl(codec_fd, VIDIOC_S_EXT_CTRLS, &ctrls)) 1548c2ecf20Sopenharmony_ci return errno; 1558c2ecf20Sopenharmony_ci ... 1568c2ecf20Sopenharmony_ci buf.type = V4L2_BUF_TYPE_VIDEO_OUTPUT; 1578c2ecf20Sopenharmony_ci buf.flags |= V4L2_BUF_FLAG_REQUEST_FD; 1588c2ecf20Sopenharmony_ci buf.request_fd = req_fd; 1598c2ecf20Sopenharmony_ci if (ioctl(codec_fd, VIDIOC_QBUF, &buf)) 1608c2ecf20Sopenharmony_ci return errno; 1618c2ecf20Sopenharmony_ci 1628c2ecf20Sopenharmony_ciNote that it is not allowed to use the Request API for CAPTURE buffers 1638c2ecf20Sopenharmony_cisince there are no per-frame settings to report there. 1648c2ecf20Sopenharmony_ci 1658c2ecf20Sopenharmony_ciOnce the request is fully prepared, it can be queued to the driver: 1668c2ecf20Sopenharmony_ci 1678c2ecf20Sopenharmony_ci.. code-block:: c 1688c2ecf20Sopenharmony_ci 1698c2ecf20Sopenharmony_ci if (ioctl(req_fd, MEDIA_REQUEST_IOC_QUEUE)) 1708c2ecf20Sopenharmony_ci return errno; 1718c2ecf20Sopenharmony_ci 1728c2ecf20Sopenharmony_ciUser-space can then either wait for the request to complete by calling poll() on 1738c2ecf20Sopenharmony_ciits file descriptor, or start dequeuing CAPTURE buffers. Most likely, it will 1748c2ecf20Sopenharmony_ciwant to get CAPTURE buffers as soon as possible and this can be done using a 1758c2ecf20Sopenharmony_ciregular :ref:`VIDIOC_DQBUF <VIDIOC_QBUF>`: 1768c2ecf20Sopenharmony_ci 1778c2ecf20Sopenharmony_ci.. code-block:: c 1788c2ecf20Sopenharmony_ci 1798c2ecf20Sopenharmony_ci struct v4l2_buffer buf; 1808c2ecf20Sopenharmony_ci 1818c2ecf20Sopenharmony_ci memset(&buf, 0, sizeof(buf)); 1828c2ecf20Sopenharmony_ci buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; 1838c2ecf20Sopenharmony_ci if (ioctl(codec_fd, VIDIOC_DQBUF, &buf)) 1848c2ecf20Sopenharmony_ci return errno; 1858c2ecf20Sopenharmony_ci 1868c2ecf20Sopenharmony_ciNote that this example assumes for simplicity that for every OUTPUT buffer 1878c2ecf20Sopenharmony_cithere will be one CAPTURE buffer, but this does not have to be the case. 1888c2ecf20Sopenharmony_ci 1898c2ecf20Sopenharmony_ciWe can then, after ensuring that the request is completed via polling the 1908c2ecf20Sopenharmony_cirequest file descriptor, query control values at the time of its completion via 1918c2ecf20Sopenharmony_cia call to :ref:`VIDIOC_G_EXT_CTRLS <VIDIOC_G_EXT_CTRLS>`. 1928c2ecf20Sopenharmony_ciThis is particularly useful for volatile controls for which we want to 1938c2ecf20Sopenharmony_ciquery values as soon as the capture buffer is produced. 1948c2ecf20Sopenharmony_ci 1958c2ecf20Sopenharmony_ci.. code-block:: c 1968c2ecf20Sopenharmony_ci 1978c2ecf20Sopenharmony_ci struct pollfd pfd = { .events = POLLPRI, .fd = req_fd }; 1988c2ecf20Sopenharmony_ci poll(&pfd, 1, -1); 1998c2ecf20Sopenharmony_ci ... 2008c2ecf20Sopenharmony_ci ctrls.which = V4L2_CTRL_WHICH_REQUEST_VAL; 2018c2ecf20Sopenharmony_ci ctrls.request_fd = req_fd; 2028c2ecf20Sopenharmony_ci if (ioctl(codec_fd, VIDIOC_G_EXT_CTRLS, &ctrls)) 2038c2ecf20Sopenharmony_ci return errno; 2048c2ecf20Sopenharmony_ci 2058c2ecf20Sopenharmony_ciOnce we don't need the request anymore, we can either recycle it for reuse with 2068c2ecf20Sopenharmony_ci:ref:`MEDIA_REQUEST_IOC_REINIT`... 2078c2ecf20Sopenharmony_ci 2088c2ecf20Sopenharmony_ci.. code-block:: c 2098c2ecf20Sopenharmony_ci 2108c2ecf20Sopenharmony_ci if (ioctl(req_fd, MEDIA_REQUEST_IOC_REINIT)) 2118c2ecf20Sopenharmony_ci return errno; 2128c2ecf20Sopenharmony_ci 2138c2ecf20Sopenharmony_ci... or close its file descriptor to completely dispose of it. 2148c2ecf20Sopenharmony_ci 2158c2ecf20Sopenharmony_ci.. code-block:: c 2168c2ecf20Sopenharmony_ci 2178c2ecf20Sopenharmony_ci close(req_fd); 2188c2ecf20Sopenharmony_ci 2198c2ecf20Sopenharmony_ciExample for a Simple Capture Device 2208c2ecf20Sopenharmony_ci----------------------------------- 2218c2ecf20Sopenharmony_ci 2228c2ecf20Sopenharmony_ciWith a simple capture device, requests can be used to specify controls to apply 2238c2ecf20Sopenharmony_cifor a given CAPTURE buffer. 2248c2ecf20Sopenharmony_ci 2258c2ecf20Sopenharmony_ci.. code-block:: c 2268c2ecf20Sopenharmony_ci 2278c2ecf20Sopenharmony_ci struct v4l2_buffer buf; 2288c2ecf20Sopenharmony_ci struct v4l2_ext_controls ctrls; 2298c2ecf20Sopenharmony_ci int req_fd; 2308c2ecf20Sopenharmony_ci ... 2318c2ecf20Sopenharmony_ci if (ioctl(media_fd, MEDIA_IOC_REQUEST_ALLOC, &req_fd)) 2328c2ecf20Sopenharmony_ci return errno; 2338c2ecf20Sopenharmony_ci ... 2348c2ecf20Sopenharmony_ci ctrls.which = V4L2_CTRL_WHICH_REQUEST_VAL; 2358c2ecf20Sopenharmony_ci ctrls.request_fd = req_fd; 2368c2ecf20Sopenharmony_ci if (ioctl(camera_fd, VIDIOC_S_EXT_CTRLS, &ctrls)) 2378c2ecf20Sopenharmony_ci return errno; 2388c2ecf20Sopenharmony_ci ... 2398c2ecf20Sopenharmony_ci buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; 2408c2ecf20Sopenharmony_ci buf.flags |= V4L2_BUF_FLAG_REQUEST_FD; 2418c2ecf20Sopenharmony_ci buf.request_fd = req_fd; 2428c2ecf20Sopenharmony_ci if (ioctl(camera_fd, VIDIOC_QBUF, &buf)) 2438c2ecf20Sopenharmony_ci return errno; 2448c2ecf20Sopenharmony_ci 2458c2ecf20Sopenharmony_ciOnce the request is fully prepared, it can be queued to the driver: 2468c2ecf20Sopenharmony_ci 2478c2ecf20Sopenharmony_ci.. code-block:: c 2488c2ecf20Sopenharmony_ci 2498c2ecf20Sopenharmony_ci if (ioctl(req_fd, MEDIA_REQUEST_IOC_QUEUE)) 2508c2ecf20Sopenharmony_ci return errno; 2518c2ecf20Sopenharmony_ci 2528c2ecf20Sopenharmony_ciUser-space can then dequeue buffers, wait for the request completion, query 2538c2ecf20Sopenharmony_cicontrols and recycle the request as in the M2M example above. 254