← Documents Documentation/userspace-api/media/mediactl/request-api.rst GitHub 원문 ↗

Linux 6.18.37 · Userspace API / Media / Media Controller

Media Request API

Frame별 configuration과 buffer를 request로 결합해 여러 작업을 미리 queue하고 완료 상태를 읽습니다.

Source pathDocumentation/userspace-api/media/mediactl/request-api.rst
Source versionLinux v6.18.37
TranslationDUJINLABS 전문 번역 + 해설

요약·해설과 원문, 전문 번역을 서로 분리했습니다. API 이름, symbol, source path는 원문 표기를 사용합니다.

1. 요약·해설

원문의 핵심 논리와 kernel programming 관점의 보충 설명입니다. 아래의 전문 번역과는 별도로 작성했습니다.

요약·해설

request-api.rst:1-253

Request fd는 buffer와 control을 같은 frame 작업으로 묶는 opaque handle입니다. Queue 방식 혼용, M2M CAPTURE 사용과 실행 중 control 조회에는 명시된 오류가 발생하며, 완료 후 reinit 또는 close로 정리합니다.

2. 영어 원문 전체

번역 기준이 된 Linux v6.18.37 원문입니다. 줄 번호는 이 버전의 파일 좌표입니다.

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

3. 한국어 전문 번역

영어 원문의 문단 순서와 의미를 유지한 전체 번역입니다. 코드, 함수명, symbol과 URL은 원문 표기를 유지합니다.

설계 목적과 per-frame configuration

1-32

Request API는 stateless codec, 복잡한 camera pipeline, Android Codec v2 같은 현대 장치와 API의 요구 사항을 V4L2가 처리하도록 설계되었습니다.

같은 pipeline에 속한 여러 장치가 frame마다 재구성되고 긴밀히 협력해야 하며, stateless codec은 특정 frame에 control을 적용하는 per-frame control이 필요합니다. 최초 사용 사례는 V4L2지만 Media Controller를 사용하는 다른 subsystem으로도 확장할 수 있습니다.

Request API가 없으면 매 frame마다 pipeline 활동을 모두 비우고 다음 frame용으로 재설정한 뒤 buffer를 queue하고 전부 dequeue 가능해질 때까지 기다려야 합니다. 실제로 한 번에 buffer 하나만 queue하는 셈이라 buffer queue의 이점을 잃습니다.

Request는 특정 pipeline configuration, 즉 Media Controller topology와 각 media entity의 설정을 특정 buffer와 결합합니다. Userspace는 서로 다른 설정을 가진 여러 task를 미리 schedule하고, 필요한 시점에 정확한 설정이 적용되도록 할 수 있습니다. 완료 시점의 configuration value도 읽을 수 있습니다.

Per-frame request scheduling
Frame별 entity control과 pipeline configuration 준비각 configuration을 대응하는 buffer와 request로 결합서로 다른 request 여러 개를 미리 queueDriver가 처리 시점에 해당 request의 설정 적용완료된 request에서 결과 buffer와 completion-time control 조회

여러 frame의 설정과 buffer를 미리 묶어 pipeline에 제출합니다.

.. SPDX-License-Identifier: GPL-2.0 OR GFDL-1.1-no-invariants-or-later
.. c:namespace:: MC

.. _media-request-api:

Request API
===========

The Request API has been designed to allow V4L2 to deal with requirements of
modern devices (stateless codecs, complex camera pipelines, ...) and APIs
(Android Codec v2). One such requirement is the ability for devices belonging to
the same pipeline to reconfigure and collaborate closely on a per-frame basis.
Another is support of stateless codecs, which require controls to be applied
to specific frames (aka 'per-frame controls') in order to be used efficiently.

While the initial use-case was V4L2, it can be extended to other subsystems
as well, as long as they use the media controller.

Supporting these features without the Request API is not always possible and if
it is, it is terribly inefficient: user-space would have to flush all activity
on the media pipeline, reconfigure it for the next frame, queue the buffers to
be processed with that configuration, and wait until they are all available for
dequeuing before considering the next frame. This defeats the purpose of having
buffer queues since in practice only one buffer would be queued at a time.

The Request API allows a specific configuration of the pipeline (media
controller topology + configuration for each media entity) to be associated with
specific buffers. This allows user-space to schedule several tasks ("requests")
with different configurations in advance, knowing that the configuration will be
applied when needed to get the expected result. Configuration values at the time
of request completion are also available for reading.

일반 사용, 할당과 준비

33-61

Request API는 Media Controller API를 확장하고 subsystem별 API와 협력합니다. Media Controller device node에서 request를 할당한 뒤 opaque한 request fd로 수명 주기를 관리합니다.

Request에 저장된 configuration data, buffer handle과 처리 결과는 request 지원이 추가된 subsystem별 API로 접근합니다. V4L2에서는 명시적인 `request_fd` parameter를 받는 ioctl이 그 역할을 합니다.

Userspace는 media device node에 `MEDIA_IOC_REQUEST_ALLOC`을 호출해 request fd를 받습니다. Pipeline을 채워 운용하려면 보통 여러 request를 할당합니다.

지원되는 표준 V4L2 ioctl에 request fd를 전달하면 명령을 즉시 적용하지 않고 해당 request의 일부로 저장합니다. Request에 queue한 buffer도 request 자체가 queue될 때까지 일반 buffer queue에 들어가지 않습니다.

Request 준비 단계
항목설명
MEDIA_IOC_REQUEST_ALLOCMedia device node에서 opaque request fd 할당
ioctl + request_fdConfiguration을 즉시 적용하지 않고 request에 저장
VIDIOC_QBUF + request_fdBuffer를 request에 연결하고 일반 queue 진입을 보류
여러 request서로 다른 frame configuration을 pipeline에 미리 준비

즉시 적용되는 일반 호출과 request에 저장되는 호출을 구분합니다.

General Usage
-------------

The Request API extends the Media Controller API and cooperates with
subsystem-specific APIs to support request usage. At the Media Controller
level, requests are allocated from the supporting Media Controller device
node. Their life cycle is then managed through the request file descriptors in
an opaque way. Configuration data, buffer handles and processing results
stored in requests are accessed through subsystem-specific APIs extended for
request support, such as V4L2 APIs that take an explicit ``request_fd``
parameter.

Request Allocation
------------------

User-space allocates requests using :ref:`MEDIA_IOC_REQUEST_ALLOC`
for the media device node. This returns a file descriptor representing the
request. Typically, several such requests will be allocated.

Request Preparation
-------------------

Standard V4L2 ioctls can then receive a request file descriptor to express the
fact that the ioctl is part of said request, and is not to be applied
immediately. See :ref:`MEDIA_IOC_REQUEST_ALLOC` for a list of ioctls that
support this. Configurations set with a ``request_fd`` parameter are stored
instead of being immediately applied, and buffers queued to a request do not
enter the regular buffer queue until the request itself is queued.

제출 제약과 동기화

62-96

Configuration과 buffer를 모두 지정하면 request fd에 `MEDIA_REQUEST_IOC_QUEUE`를 호출합니다. Request에는 buffer가 하나 이상 있어야 하며 없으면 `ENOENT`입니다. Queue된 request는 더 이상 수정할 수 없습니다.

Memory-to-memory device에서는 request를 OUTPUT buffer에만 사용할 수 있고 CAPTURE buffer에는 사용할 수 없습니다. Capture buffer를 request에 추가하면 `EBADR`입니다.

여러 entity의 configuration을 포함한 request에서는 driver들이 buffer 처리 전에 요청된 pipeline topology를 적용하도록 동기화할 수 있습니다. Hardware 한계 때문에 완전한 atomicity가 불가능할 수 있어 Media Controller driver는 best effort로 구현합니다.

Request queue와 direct buffer queue는 섞을 수 없습니다. 먼저 사용한 방식은 `VIDIOC_STREAMOFF`를 호출하거나 device를 닫을 때까지 고정되며, 반대 방식을 시도하면 `EBUSY`입니다.

Request 없이 설정한 control은 request 사용 여부와 관계없이 즉시 적용됩니다. 같은 control을 request를 통해서도 설정하고 직접 설정하기도 하면 동작이 정의되지 않습니다.

Request 제출 주의 조건
항목설명
최소 bufferRequest당 buffer 1개 이상, 없으면 ENOENT
Queue 후 수정Queue된 request는 수정 불가
M2M buffer 방향Request는 OUTPUT만 허용, CAPTURE 추가 시 EBADR
Queue 방식Request queue와 direct queue 혼용 시 EBUSY
Control 경로같은 control을 request와 direct 방식으로 함께 설정하면 undefined behavior
Atomicity여러 entity 동기화는 hardware 한계 안에서 best effort

Queue 전에 위반 여부를 확인해야 하는 규칙입니다.

Request Submission
------------------

Once the configuration and buffers of the request are specified, it can be
queued by calling :ref:`MEDIA_REQUEST_IOC_QUEUE` on the request file descriptor.
A request must contain at least one buffer, otherwise ``ENOENT`` is returned.
A queued request cannot be modified anymore.

.. caution::
   For :ref:`memory-to-memory devices <mem2mem>` you can use requests only for
   output buffers, not for capture buffers. Attempting to add a capture buffer
   to a request will result in an ``EBADR`` error.

If the request contains configurations for multiple entities, individual drivers
may synchronize so the requested pipeline's topology is applied before the
buffers are processed. Media controller drivers do a best effort implementation
since perfect atomicity may not be possible due to hardware limitations.

.. caution::

   It is not allowed to mix queuing requests with directly queuing buffers:
   whichever method is used first locks this in place until
   :ref:`VIDIOC_STREAMOFF <VIDIOC_STREAMON>` is called or the device is
   :ref:`closed <func-close>`. Attempts to directly queue a buffer when earlier
   a buffer was queued via a request or vice versa will result in an ``EBUSY``
   error.

Controls can still be set without a request and are applied immediately,
regardless of whether a request is in use or not.

.. caution::

   Setting the same control through a request and also directly can lead to
   undefined behavior!

완료 판정, 결과 조회와 수명

97-128

Userspace는 request fd를 `poll()`해 완료를 기다릴 수 있습니다. 연관된 모든 buffer가 dequeue 가능하고 모든 control이 완료 시점 값으로 갱신되면 request가 완료된 것으로 간주합니다.

Request 전체가 완료되기 전이라도 중간에 사용 가능해진 buffer는 독립적으로 dequeue할 수 있습니다. Buffer 반환과 request completion은 같은 시점일 필요가 없습니다.

완료된 request에는 실행 후 device state가 들어 있습니다. `request_fd`와 함께 `VIDIOC_G_EXT_CTRLS`를 호출해 그 상태를 읽습니다. 아직 실행 중인 request는 driver가 control value를 바꿀 수 있으므로 조회하면 `EBUSY`입니다.

완료된 request는 버리거나 재사용할 수 있습니다. Request fd를 `close()`하면 그 fd는 즉시 사용할 수 없지만 kernel이 request 사용을 마칠 때까지 object는 해제되지 않습니다. Queue 직후 닫았다면 driver 완료 뒤 해제됩니다.

`MEDIA_REQUEST_IOC_REINIT`은 상태를 전부 지워 방금 할당한 것과 같은 request로 만듭니다. 이전 상태는 하나도 유지되지 않습니다.

Request 완료와 정리
Queue된 request 처리 시작먼저 준비된 buffer는 request 완료 전에도 dequeue 가능모든 buffer와 control update가 끝나면 POLLPRI completionVIDIOC_G_EXT_CTRLS로 완료 시점 control 조회MEDIA_REQUEST_IOC_REINIT으로 완전 초기화해 재사용또는 close하고 kernel 내부 사용 종료 후 object 해제

Buffer 반환, control snapshot, object lifetime을 구분합니다.

User-space can :c:func:`poll()` a request file descriptor in
order to wait until the request completes. A request is considered complete
once all its associated buffers are available for dequeuing and all the
associated controls have been updated with the values at the time of completion.
Note that user-space does not need to wait for the request to complete to
dequeue its buffers: buffers that are available halfway through a request can
be dequeued independently of the request's state.

A completed request contains the state of the device after the request was
executed. User-space can query that state by calling
:ref:`ioctl VIDIOC_G_EXT_CTRLS <VIDIOC_G_EXT_CTRLS>` with the request file
descriptor. Calling :ref:`ioctl VIDIOC_G_EXT_CTRLS <VIDIOC_G_EXT_CTRLS>` for a
request that has been queued but not yet completed will return ``EBUSY``
since the control values might be changed at any time by the driver while the
request is in flight.

.. _media-request-life-time:

Recycling and Destruction
-------------------------

Finally, a completed request can either be discarded or be reused. Calling
:c:func:`close()` on a request file descriptor will make
that file descriptor unusable and the request will be freed once it is no
longer in use by the kernel. That is, if the request is queued and then the
file descriptor is closed, then it won't be freed until the driver completed
the request.

The :ref:`MEDIA_REQUEST_IOC_REINIT` will clear a request's state and make it
available again. No state is retained by this operation: the request is as
if it had just been allocated.

Codec device 예제

129-218

Memory-to-memory codec에서는 OUTPUT buffer에 적용할 특정 control을 request로 결합해 여러 OUTPUT buffer를 미리 queue할 수 있습니다. 완료 시점의 volatile control도 request에서 읽을 수 있습니다.

먼저 request를 할당하고 `V4L2_CTRL_WHICH_REQUEST_VAL`과 `request_fd`로 control을 저장한 뒤, OUTPUT buffer에 `V4L2_BUF_FLAG_REQUEST_FD`와 같은 fd를 설정해 queue합니다.

struct v4l2_buffer buf;
struct v4l2_ext_controls ctrls;
int req_fd;
...
if (ioctl(media_fd, MEDIA_IOC_REQUEST_ALLOC, &req_fd))
    return errno;
...
ctrls.which = V4L2_CTRL_WHICH_REQUEST_VAL;
ctrls.request_fd = req_fd;
if (ioctl(codec_fd, VIDIOC_S_EXT_CTRLS, &ctrls))
    return errno;
...
buf.type = V4L2_BUF_TYPE_VIDEO_OUTPUT;
buf.flags |= V4L2_BUF_FLAG_REQUEST_FD;
buf.request_fd = req_fd;
if (ioctl(codec_fd, VIDIOC_QBUF, &buf))
    return errno;

M2M에서는 CAPTURE buffer에 report할 per-frame setting이 없으므로 Request API를 CAPTURE buffer에 사용할 수 없습니다.

준비가 끝나면 request fd에 `MEDIA_REQUEST_IOC_QUEUE`를 호출합니다. 이후 poll로 전체 완료를 기다리거나 일반 `VIDIOC_DQBUF`로 준비된 CAPTURE buffer부터 받을 수 있습니다.

if (ioctl(req_fd, MEDIA_REQUEST_IOC_QUEUE))
    return errno;

struct v4l2_buffer buf;
memset(&buf, 0, sizeof(buf));
buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
if (ioctl(codec_fd, VIDIOC_DQBUF, &buf))
    return errno;

예제는 OUTPUT buffer 하나마다 CAPTURE buffer 하나가 나온다고 단순화하지만 실제 codec은 이 비율을 보장하지 않습니다.

Request fd에서 `POLLPRI`를 기다린 뒤 `VIDIOC_G_EXT_CTRLS`에 `V4L2_CTRL_WHICH_REQUEST_VAL`과 request fd를 전달하면 완료 시점 control을 읽습니다. Capture buffer 생성 직후 volatile control을 확인할 때 유용합니다.

struct pollfd pfd = { .events = POLLPRI, .fd = req_fd };
poll(&pfd, 1, -1);
...
ctrls.which = V4L2_CTRL_WHICH_REQUEST_VAL;
ctrls.request_fd = req_fd;
if (ioctl(codec_fd, VIDIOC_G_EXT_CTRLS, &ctrls))
    return errno;

마지막에는 `MEDIA_REQUEST_IOC_REINIT`으로 재사용하거나 `close(req_fd)`로 폐기합니다.

if (ioctl(req_fd, MEDIA_REQUEST_IOC_REINIT))
    return errno;

close(req_fd);
Codec request 예제
Request 할당Per-frame control과 OUTPUT buffer를 같은 request_fd에 연결Request queueCAPTURE buffer가 준비되는 대로 VIDIOC_DQBUFPOLLPRI로 request completion 확인Completion-time control 조회 후 reinit 또는 close

OUTPUT request와 독립적인 CAPTURE dequeue 흐름입니다.

Example for a Codec Device
--------------------------

For use-cases such as :ref:`codecs <mem2mem>`, the request API can be used
to associate specific controls to
be applied by the driver for the OUTPUT buffer, allowing user-space
to queue many such buffers in advance. It can also take advantage of requests'
ability to capture the state of controls when the request completes to read back
information that may be subject to change.

Put into code, after obtaining a request, user-space can assign controls and one
OUTPUT buffer to it:

.. code-block:: c

	struct v4l2_buffer buf;
	struct v4l2_ext_controls ctrls;
	int req_fd;
	...
	if (ioctl(media_fd, MEDIA_IOC_REQUEST_ALLOC, &req_fd))
		return errno;
	...
	ctrls.which = V4L2_CTRL_WHICH_REQUEST_VAL;
	ctrls.request_fd = req_fd;
	if (ioctl(codec_fd, VIDIOC_S_EXT_CTRLS, &ctrls))
		return errno;
	...
	buf.type = V4L2_BUF_TYPE_VIDEO_OUTPUT;
	buf.flags |= V4L2_BUF_FLAG_REQUEST_FD;
	buf.request_fd = req_fd;
	if (ioctl(codec_fd, VIDIOC_QBUF, &buf))
		return errno;

Note that it is not allowed to use the Request API for CAPTURE buffers
since there are no per-frame settings to report there.

Once the request is fully prepared, it can be queued to the driver:

.. code-block:: c

	if (ioctl(req_fd, MEDIA_REQUEST_IOC_QUEUE))
		return errno;

User-space can then either wait for the request to complete by calling poll() on
its file descriptor, or start dequeuing CAPTURE buffers. Most likely, it will
want to get CAPTURE buffers as soon as possible and this can be done using a
regular :ref:`VIDIOC_DQBUF <VIDIOC_QBUF>`:

.. code-block:: c

	struct v4l2_buffer buf;

	memset(&buf, 0, sizeof(buf));
	buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
	if (ioctl(codec_fd, VIDIOC_DQBUF, &buf))
		return errno;

Note that this example assumes for simplicity that for every OUTPUT buffer
there will be one CAPTURE buffer, but this does not have to be the case.

We can then, after ensuring that the request is completed via polling the
request file descriptor, query control values at the time of its completion via
a call to :ref:`VIDIOC_G_EXT_CTRLS <VIDIOC_G_EXT_CTRLS>`.
This is particularly useful for volatile controls for which we want to
query values as soon as the capture buffer is produced.

.. code-block:: c

	struct pollfd pfd = { .events = POLLPRI, .fd = req_fd };
	poll(&pfd, 1, -1);
	...
	ctrls.which = V4L2_CTRL_WHICH_REQUEST_VAL;
	ctrls.request_fd = req_fd;
	if (ioctl(codec_fd, VIDIOC_G_EXT_CTRLS, &ctrls))
		return errno;

Once we don't need the request anymore, we can either recycle it for reuse with
:ref:`MEDIA_REQUEST_IOC_REINIT`...

.. code-block:: c

	if (ioctl(req_fd, MEDIA_REQUEST_IOC_REINIT))
		return errno;

... or close its file descriptor to completely dispose of it.

.. code-block:: c

	close(req_fd);

Simple capture device 예제

219-253

Simple capture device에서는 특정 CAPTURE buffer에 적용할 control을 request로 지정할 수 있습니다. 이는 M2M codec의 CAPTURE 제한과 다르며 device 유형을 구분해야 합니다.

Request를 할당하고 `VIDIOC_S_EXT_CTRLS`로 control을 저장한 뒤 CAPTURE buffer에 `V4L2_BUF_FLAG_REQUEST_FD`와 request fd를 넣어 queue합니다.

struct v4l2_buffer buf;
struct v4l2_ext_controls ctrls;
int req_fd;
...
if (ioctl(media_fd, MEDIA_IOC_REQUEST_ALLOC, &req_fd))
    return errno;
...
ctrls.which = V4L2_CTRL_WHICH_REQUEST_VAL;
ctrls.request_fd = req_fd;
if (ioctl(camera_fd, VIDIOC_S_EXT_CTRLS, &ctrls))
    return errno;
...
buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
buf.flags |= V4L2_BUF_FLAG_REQUEST_FD;
buf.request_fd = req_fd;
if (ioctl(camera_fd, VIDIOC_QBUF, &buf))
    return errno;

완전히 준비된 request를 `MEDIA_REQUEST_IOC_QUEUE`로 제출합니다. 이후 buffer dequeue, 완료 대기, control 조회와 request 재사용은 M2M 예제와 같습니다.

if (ioctl(req_fd, MEDIA_REQUEST_IOC_QUEUE))
    return errno;
Example for a Simple Capture Device
-----------------------------------

With a simple capture device, requests can be used to specify controls to apply
for a given CAPTURE buffer.

.. code-block:: c

	struct v4l2_buffer buf;
	struct v4l2_ext_controls ctrls;
	int req_fd;
	...
	if (ioctl(media_fd, MEDIA_IOC_REQUEST_ALLOC, &req_fd))
		return errno;
	...
	ctrls.which = V4L2_CTRL_WHICH_REQUEST_VAL;
	ctrls.request_fd = req_fd;
	if (ioctl(camera_fd, VIDIOC_S_EXT_CTRLS, &ctrls))
		return errno;
	...
	buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
	buf.flags |= V4L2_BUF_FLAG_REQUEST_FD;
	buf.request_fd = req_fd;
	if (ioctl(camera_fd, VIDIOC_QBUF, &buf))
		return errno;

Once the request is fully prepared, it can be queued to the driver:

.. code-block:: c

	if (ioctl(req_fd, MEDIA_REQUEST_IOC_QUEUE))
		return errno;

User-space can then dequeue buffers, wait for the request completion, query
controls and recycle the request as in the M2M example above.