request-api.rst 9.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253
  1. .. SPDX-License-Identifier: GPL-2.0 OR GFDL-1.1-no-invariants-or-later
  2. .. c:namespace:: MC
  3. .. _media-request-api:
  4. Request API
  5. ===========
  6. The Request API has been designed to allow V4L2 to deal with requirements of
  7. modern devices (stateless codecs, complex camera pipelines, ...) and APIs
  8. (Android Codec v2). One such requirement is the ability for devices belonging to
  9. the same pipeline to reconfigure and collaborate closely on a per-frame basis.
  10. Another is support of stateless codecs, which require controls to be applied
  11. to specific frames (aka 'per-frame controls') in order to be used efficiently.
  12. While the initial use-case was V4L2, it can be extended to other subsystems
  13. as well, as long as they use the media controller.
  14. Supporting these features without the Request API is not always possible and if
  15. it is, it is terribly inefficient: user-space would have to flush all activity
  16. on the media pipeline, reconfigure it for the next frame, queue the buffers to
  17. be processed with that configuration, and wait until they are all available for
  18. dequeuing before considering the next frame. This defeats the purpose of having
  19. buffer queues since in practice only one buffer would be queued at a time.
  20. The Request API allows a specific configuration of the pipeline (media
  21. controller topology + configuration for each media entity) to be associated with
  22. specific buffers. This allows user-space to schedule several tasks ("requests")
  23. with different configurations in advance, knowing that the configuration will be
  24. applied when needed to get the expected result. Configuration values at the time
  25. of request completion are also available for reading.
  26. General Usage
  27. -------------
  28. The Request API extends the Media Controller API and cooperates with
  29. subsystem-specific APIs to support request usage. At the Media Controller
  30. level, requests are allocated from the supporting Media Controller device
  31. node. Their life cycle is then managed through the request file descriptors in
  32. an opaque way. Configuration data, buffer handles and processing results
  33. stored in requests are accessed through subsystem-specific APIs extended for
  34. request support, such as V4L2 APIs that take an explicit ``request_fd``
  35. parameter.
  36. Request Allocation
  37. ------------------
  38. User-space allocates requests using :ref:`MEDIA_IOC_REQUEST_ALLOC`
  39. for the media device node. This returns a file descriptor representing the
  40. request. Typically, several such requests will be allocated.
  41. Request Preparation
  42. -------------------
  43. Standard V4L2 ioctls can then receive a request file descriptor to express the
  44. fact that the ioctl is part of said request, and is not to be applied
  45. immediately. See :ref:`MEDIA_IOC_REQUEST_ALLOC` for a list of ioctls that
  46. support this. Configurations set with a ``request_fd`` parameter are stored
  47. instead of being immediately applied, and buffers queued to a request do not
  48. enter the regular buffer queue until the request itself is queued.
  49. Request Submission
  50. ------------------
  51. Once the configuration and buffers of the request are specified, it can be
  52. queued by calling :ref:`MEDIA_REQUEST_IOC_QUEUE` on the request file descriptor.
  53. A request must contain at least one buffer, otherwise ``ENOENT`` is returned.
  54. A queued request cannot be modified anymore.
  55. .. caution::
  56. For :ref:`memory-to-memory devices <mem2mem>` you can use requests only for
  57. output buffers, not for capture buffers. Attempting to add a capture buffer
  58. to a request will result in an ``EBADR`` error.
  59. If the request contains configurations for multiple entities, individual drivers
  60. may synchronize so the requested pipeline's topology is applied before the
  61. buffers are processed. Media controller drivers do a best effort implementation
  62. since perfect atomicity may not be possible due to hardware limitations.
  63. .. caution::
  64. It is not allowed to mix queuing requests with directly queuing buffers:
  65. whichever method is used first locks this in place until
  66. :ref:`VIDIOC_STREAMOFF <VIDIOC_STREAMON>` is called or the device is
  67. :ref:`closed <func-close>`. Attempts to directly queue a buffer when earlier
  68. a buffer was queued via a request or vice versa will result in an ``EBUSY``
  69. error.
  70. Controls can still be set without a request and are applied immediately,
  71. regardless of whether a request is in use or not.
  72. .. caution::
  73. Setting the same control through a request and also directly can lead to
  74. undefined behavior!
  75. User-space can :c:func:`poll()` a request file descriptor in
  76. order to wait until the request completes. A request is considered complete
  77. once all its associated buffers are available for dequeuing and all the
  78. associated controls have been updated with the values at the time of completion.
  79. Note that user-space does not need to wait for the request to complete to
  80. dequeue its buffers: buffers that are available halfway through a request can
  81. be dequeued independently of the request's state.
  82. A completed request contains the state of the device after the request was
  83. executed. User-space can query that state by calling
  84. :ref:`ioctl VIDIOC_G_EXT_CTRLS <VIDIOC_G_EXT_CTRLS>` with the request file
  85. descriptor. Calling :ref:`ioctl VIDIOC_G_EXT_CTRLS <VIDIOC_G_EXT_CTRLS>` for a
  86. request that has been queued but not yet completed will return ``EBUSY``
  87. since the control values might be changed at any time by the driver while the
  88. request is in flight.
  89. .. _media-request-life-time:
  90. Recycling and Destruction
  91. -------------------------
  92. Finally, a completed request can either be discarded or be reused. Calling
  93. :c:func:`close()` on a request file descriptor will make
  94. that file descriptor unusable and the request will be freed once it is no
  95. longer in use by the kernel. That is, if the request is queued and then the
  96. file descriptor is closed, then it won't be freed until the driver completed
  97. the request.
  98. The :ref:`MEDIA_REQUEST_IOC_REINIT` will clear a request's state and make it
  99. available again. No state is retained by this operation: the request is as
  100. if it had just been allocated.
  101. Example for a Codec Device
  102. --------------------------
  103. For use-cases such as :ref:`codecs <mem2mem>`, the request API can be used
  104. to associate specific controls to
  105. be applied by the driver for the OUTPUT buffer, allowing user-space
  106. to queue many such buffers in advance. It can also take advantage of requests'
  107. ability to capture the state of controls when the request completes to read back
  108. information that may be subject to change.
  109. Put into code, after obtaining a request, user-space can assign controls and one
  110. OUTPUT buffer to it:
  111. .. code-block:: c
  112. struct v4l2_buffer buf;
  113. struct v4l2_ext_controls ctrls;
  114. int req_fd;
  115. ...
  116. if (ioctl(media_fd, MEDIA_IOC_REQUEST_ALLOC, &req_fd))
  117. return errno;
  118. ...
  119. ctrls.which = V4L2_CTRL_WHICH_REQUEST_VAL;
  120. ctrls.request_fd = req_fd;
  121. if (ioctl(codec_fd, VIDIOC_S_EXT_CTRLS, &ctrls))
  122. return errno;
  123. ...
  124. buf.type = V4L2_BUF_TYPE_VIDEO_OUTPUT;
  125. buf.flags |= V4L2_BUF_FLAG_REQUEST_FD;
  126. buf.request_fd = req_fd;
  127. if (ioctl(codec_fd, VIDIOC_QBUF, &buf))
  128. return errno;
  129. Note that it is not allowed to use the Request API for CAPTURE buffers
  130. since there are no per-frame settings to report there.
  131. Once the request is fully prepared, it can be queued to the driver:
  132. .. code-block:: c
  133. if (ioctl(req_fd, MEDIA_REQUEST_IOC_QUEUE))
  134. return errno;
  135. User-space can then either wait for the request to complete by calling poll() on
  136. its file descriptor, or start dequeuing CAPTURE buffers. Most likely, it will
  137. want to get CAPTURE buffers as soon as possible and this can be done using a
  138. regular :ref:`VIDIOC_DQBUF <VIDIOC_QBUF>`:
  139. .. code-block:: c
  140. struct v4l2_buffer buf;
  141. memset(&buf, 0, sizeof(buf));
  142. buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
  143. if (ioctl(codec_fd, VIDIOC_DQBUF, &buf))
  144. return errno;
  145. Note that this example assumes for simplicity that for every OUTPUT buffer
  146. there will be one CAPTURE buffer, but this does not have to be the case.
  147. We can then, after ensuring that the request is completed via polling the
  148. request file descriptor, query control values at the time of its completion via
  149. a call to :ref:`VIDIOC_G_EXT_CTRLS <VIDIOC_G_EXT_CTRLS>`.
  150. This is particularly useful for volatile controls for which we want to
  151. query values as soon as the capture buffer is produced.
  152. .. code-block:: c
  153. struct pollfd pfd = { .events = POLLPRI, .fd = req_fd };
  154. poll(&pfd, 1, -1);
  155. ...
  156. ctrls.which = V4L2_CTRL_WHICH_REQUEST_VAL;
  157. ctrls.request_fd = req_fd;
  158. if (ioctl(codec_fd, VIDIOC_G_EXT_CTRLS, &ctrls))
  159. return errno;
  160. Once we don't need the request anymore, we can either recycle it for reuse with
  161. :ref:`MEDIA_REQUEST_IOC_REINIT`...
  162. .. code-block:: c
  163. if (ioctl(req_fd, MEDIA_REQUEST_IOC_REINIT))
  164. return errno;
  165. ... or close its file descriptor to completely dispose of it.
  166. .. code-block:: c
  167. close(req_fd);
  168. Example for a Simple Capture Device
  169. -----------------------------------
  170. With a simple capture device, requests can be used to specify controls to apply
  171. for a given CAPTURE buffer.
  172. .. code-block:: c
  173. struct v4l2_buffer buf;
  174. struct v4l2_ext_controls ctrls;
  175. int req_fd;
  176. ...
  177. if (ioctl(media_fd, MEDIA_IOC_REQUEST_ALLOC, &req_fd))
  178. return errno;
  179. ...
  180. ctrls.which = V4L2_CTRL_WHICH_REQUEST_VAL;
  181. ctrls.request_fd = req_fd;
  182. if (ioctl(camera_fd, VIDIOC_S_EXT_CTRLS, &ctrls))
  183. return errno;
  184. ...
  185. buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
  186. buf.flags |= V4L2_BUF_FLAG_REQUEST_FD;
  187. buf.request_fd = req_fd;
  188. if (ioctl(camera_fd, VIDIOC_QBUF, &buf))
  189. return errno;
  190. Once the request is fully prepared, it can be queued to the driver:
  191. .. code-block:: c
  192. if (ioctl(req_fd, MEDIA_REQUEST_IOC_QUEUE))
  193. return errno;
  194. User-space can then dequeue buffers, wait for the request completion, query
  195. controls and recycle the request as in the M2M example above.