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