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