← Documents Documentation/userspace-api/media/v4l/extended-controls.rst GitHub 원문 ↗

Linux 6.18.37 · Userspace API / Media / V4L

Extended Controls API

여러 V4L2 control의 원자적 처리, compound type, 열거와 GUI 구성을 설명합니다.

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

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

1. 요약·해설

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

요약·해설

extended-controls.rst:1-173

Extended Control API는 같은 class의 여러 값을 한 번에 다루고 64-bit·pointer·compound type을 전달하며, 표준화된 ID 순회로 driver별 구현 부분집합을 발견하게 합니다.

2. 영어 원문 전체

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

원문 전체 펼치기
1 .. SPDX-License-Identifier: GFDL-1.1-no-invariants-or-later
2
3 .. _extended-controls:
4
5 *********************
6 Extended Controls API
7 *********************
8
9
10 Introduction
11 ============
12
13 The control mechanism as originally designed was meant to be used for
14 user settings (brightness, saturation, etc). However, it turned out to
15 be a very useful model for implementing more complicated driver APIs
16 where each driver implements only a subset of a larger API.
17
18 The MPEG encoding API was the driving force behind designing and
19 implementing this extended control mechanism: the MPEG standard is quite
20 large and the currently supported hardware MPEG encoders each only
21 implement a subset of this standard. Further more, many parameters
22 relating to how the video is encoded into an MPEG stream are specific to
23 the MPEG encoding chip since the MPEG standard only defines the format
24 of the resulting MPEG stream, not how the video is actually encoded into
25 that format.
26
27 Unfortunately, the original control API lacked some features needed for
28 these new uses and so it was extended into the (not terribly originally
29 named) extended control API.
30
31 Even though the MPEG encoding API was the first effort to use the
32 Extended Control API, nowadays there are also other classes of Extended
33 Controls, such as Camera Controls and FM Transmitter Controls. The
34 Extended Controls API as well as all Extended Controls classes are
35 described in the following text.
36
37
38 The Extended Control API
39 ========================
40
41 Three new ioctls are available:
42 :ref:`VIDIOC_G_EXT_CTRLS <VIDIOC_G_EXT_CTRLS>`,
43 :ref:`VIDIOC_S_EXT_CTRLS <VIDIOC_G_EXT_CTRLS>` and
44 :ref:`VIDIOC_TRY_EXT_CTRLS <VIDIOC_G_EXT_CTRLS>`. These ioctls act
45 on arrays of controls (as opposed to the
46 :ref:`VIDIOC_G_CTRL <VIDIOC_G_CTRL>` and
47 :ref:`VIDIOC_S_CTRL <VIDIOC_G_CTRL>` ioctls that act on a single
48 control). This is needed since it is often required to atomically change
49 several controls at once.
50
51 Each of the new ioctls expects a pointer to a struct
52 :c:type:`v4l2_ext_controls`. This structure
53 contains a pointer to the control array, a count of the number of
54 controls in that array and a control class. Control classes are used to
55 group similar controls into a single class. For example, control class
56 ``V4L2_CTRL_CLASS_USER`` contains all user controls (i. e. all controls
57 that can also be set using the old :ref:`VIDIOC_S_CTRL <VIDIOC_G_CTRL>`
58 ioctl). Control class ``V4L2_CTRL_CLASS_CODEC`` contains controls
59 relating to codecs.
60
61 All controls in the control array must belong to the specified control
62 class. An error is returned if this is not the case.
63
64 It is also possible to use an empty control array (``count`` == 0) to check
65 whether the specified control class is supported.
66
67 The control array is a struct
68 :c:type:`v4l2_ext_control` array. The
69 struct :c:type:`v4l2_ext_control` is very similar to
70 struct :c:type:`v4l2_control`, except for the fact that
71 it also allows for 64-bit values and pointers to be passed.
72
73 Since the struct :c:type:`v4l2_ext_control` supports
74 pointers it is now also possible to have controls with compound types
75 such as N-dimensional arrays and/or structures. You need to specify the
76 ``V4L2_CTRL_FLAG_NEXT_COMPOUND`` when enumerating controls to actually
77 be able to see such compound controls. In other words, these controls
78 with compound types should only be used programmatically.
79
80 Since such compound controls need to expose more information about
81 themselves than is possible with :ref:`VIDIOC_QUERYCTRL <VIDIOC_QUERYCTRL>`
82 the :ref:`VIDIOC_QUERY_EXT_CTRL <VIDIOC_QUERYCTRL>` ioctl was added. In
83 particular, this ioctl gives the dimensions of the N-dimensional array if
84 this control consists of more than one element.
85
86 .. note::
87
88 #. It is important to realize that due to the flexibility of controls it is
89 necessary to check whether the control you want to set actually is
90 supported in the driver and what the valid range of values is. So use
91 :ref:`VIDIOC_QUERYCTRL` to check this.
92
93 #. It is possible that some of the menu indices in a control of
94 type ``V4L2_CTRL_TYPE_MENU`` may not be supported (``VIDIOC_QUERYMENU``
95 will return an error). A good example is the list of supported MPEG
96 audio bitrates. Some drivers only support one or two bitrates, others
97 support a wider range.
98
99 All controls use machine endianness.
100
101
102 Enumerating Extended Controls
103 =============================
104
105 The recommended way to enumerate over the extended controls is by using
106 :ref:`VIDIOC_QUERYCTRL` in combination with the
107 ``V4L2_CTRL_FLAG_NEXT_CTRL`` flag:
108
109
110 .. code-block:: c
111
112 struct v4l2_queryctrl qctrl;
113
114 qctrl.id = V4L2_CTRL_FLAG_NEXT_CTRL;
115 while (0 == ioctl (fd, VIDIOC_QUERYCTRL, &qctrl)) {
116 /* ... */
117 qctrl.id |= V4L2_CTRL_FLAG_NEXT_CTRL;
118 }
119
120 The initial control ID is set to 0 ORed with the
121 ``V4L2_CTRL_FLAG_NEXT_CTRL`` flag. The ``VIDIOC_QUERYCTRL`` ioctl will
122 return the first control with a higher ID than the specified one. When
123 no such controls are found an error is returned.
124
125 If you want to get all controls within a specific control class, then
126 you can set the initial ``qctrl.id`` value to the control class and add
127 an extra check to break out of the loop when a control of another
128 control class is found:
129
130
131 .. code-block:: c
132
133 qctrl.id = V4L2_CTRL_CLASS_CODEC | V4L2_CTRL_FLAG_NEXT_CTRL;
134 while (0 == ioctl(fd, VIDIOC_QUERYCTRL, &qctrl)) {
135 if (V4L2_CTRL_ID2CLASS(qctrl.id) != V4L2_CTRL_CLASS_CODEC)
136 break;
137 /* ... */
138 qctrl.id |= V4L2_CTRL_FLAG_NEXT_CTRL;
139 }
140
141 The 32-bit ``qctrl.id`` value is subdivided into three bit ranges: the
142 top 4 bits are reserved for flags (e. g. ``V4L2_CTRL_FLAG_NEXT_CTRL``)
143 and are not actually part of the ID. The remaining 28 bits form the
144 control ID, of which the most significant 12 bits define the control
145 class and the least significant 16 bits identify the control within the
146 control class. It is guaranteed that these last 16 bits are always
147 non-zero for controls. The range of 0x1000 and up are reserved for
148 driver-specific controls. The macro ``V4L2_CTRL_ID2CLASS(id)`` returns
149 the control class ID based on a control ID.
150
151 If the driver does not support extended controls, then
152 ``VIDIOC_QUERYCTRL`` will fail when used in combination with
153 ``V4L2_CTRL_FLAG_NEXT_CTRL``. In that case the old method of enumerating
154 control should be used (see :ref:`enum_all_controls`). But if it is
155 supported, then it is guaranteed to enumerate over all controls,
156 including driver-private controls.
157
158
159 Creating Control Panels
160 =======================
161
162 It is possible to create control panels for a graphical user interface
163 where the user can select the various controls. Basically you will have
164 to iterate over all controls using the method described above. Each
165 control class starts with a control of type
166 ``V4L2_CTRL_TYPE_CTRL_CLASS``. ``VIDIOC_QUERYCTRL`` will return the name
167 of this control class which can be used as the title of a tab page
168 within a control panel.
169
170 The flags field of struct :ref:`v4l2_queryctrl <v4l2-queryctrl>` also
171 contains hints on the behavior of the control. See the
172 :ref:`VIDIOC_QUERYCTRL` documentation for more
173 details.
174

3. 한국어 전문 번역

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

확장 제어가 필요한 이유

1-37

초기 V4L2 control mechanism은 brightness나 saturation 같은 사용자 설정을 위해 설계됐습니다. 그러나 큰 API 가운데 각 드라이버가 일부만 구현하는 복잡한 기능에도 이 모델이 유용하다는 점이 드러났습니다.

Extended Control API의 직접적인 계기는 MPEG encoding API였습니다. MPEG 표준은 크고 hardware encoder마다 구현하는 부분집합이 다릅니다. 또한 표준은 결과 stream의 형식만 정의하므로 실제 encoding 방법에 관한 많은 parameter는 MPEG chip별로 달라집니다. 기존 control API에 부족한 기능을 보충해 extended control mechanism이 만들어졌습니다.

처음에는 MPEG encoding을 대상으로 했지만 현재는 Camera Controls, FM Transmitter Controls 등 여러 class가 같은 API를 사용합니다.

제어 모델의 확장
Brightness·saturation 단일 제어MPEG hardware별 기능 부분집합여러 값을 함께 전달할 필요64-bit·pointer·compound type 지원Camera·FM 등 여러 control class로 확장

단일 사용자 설정 모델이 복합 드라이버 API의 공통 전달 방식으로 확장됐습니다.

.. SPDX-License-Identifier: GFDL-1.1-no-invariants-or-later

.. _extended-controls:

*********************
Extended Controls API
*********************


Introduction
============

The control mechanism as originally designed was meant to be used for
user settings (brightness, saturation, etc). However, it turned out to
be a very useful model for implementing more complicated driver APIs
where each driver implements only a subset of a larger API.

The MPEG encoding API was the driving force behind designing and
implementing this extended control mechanism: the MPEG standard is quite
large and the currently supported hardware MPEG encoders each only
implement a subset of this standard. Further more, many parameters
relating to how the video is encoded into an MPEG stream are specific to
the MPEG encoding chip since the MPEG standard only defines the format
of the resulting MPEG stream, not how the video is actually encoded into
that format.

Unfortunately, the original control API lacked some features needed for
these new uses and so it was extended into the (not terribly originally
named) extended control API.

Even though the MPEG encoding API was the first effort to use the
Extended Control API, nowadays there are also other classes of Extended
Controls, such as Camera Controls and FM Transmitter Controls. The
Extended Controls API as well as all Extended Controls classes are
described in the following text.

제어 배열과 compound type

38-101

`VIDIOC_G_EXT_CTRLS`, `VIDIOC_S_EXT_CTRLS`, `VIDIOC_TRY_EXT_CTRLS`는 하나의 control만 다루는 `VIDIOC_G_CTRL`과 `VIDIOC_S_CTRL`과 달리 control 배열에 작동합니다. 여러 control을 원자적으로 바꿔야 하는 경우를 지원하기 위한 설계입니다.

세 ioctl은 `v4l2_ext_controls` 포인터를 받습니다. 이 구조체는 control 배열 포인터, 배열 원소 수와 control class를 포함합니다. `V4L2_CTRL_CLASS_USER`는 구형 `VIDIOC_S_CTRL`로도 설정할 수 있는 user control을, `V4L2_CTRL_CLASS_CODEC`은 codec 관련 control을 묶습니다. 배열의 모든 control은 지정한 한 class에 속해야 하며 그렇지 않으면 오류입니다.

`count == 0`인 빈 배열을 전달하면 지정한 control class의 지원 여부만 검사할 수 있습니다. 배열 원소 `v4l2_ext_control`은 `v4l2_control`과 비슷하지만 64-bit 값과 pointer도 전달할 수 있습니다.

Pointer 지원 덕분에 N-dimensional array와 structure 같은 compound control을 정의할 수 있습니다. 열거할 때 `V4L2_CTRL_FLAG_NEXT_COMPOUND`를 지정해야 compound control이 보이며, 이런 control은 program 방식으로만 사용하는 것이 적절합니다. `VIDIOC_QUERY_EXT_CTRL`은 기존 `VIDIOC_QUERYCTRL`보다 많은 정보를 노출하고 여러 원소를 가진 N-dimensional array의 차원도 제공합니다.

Extended control 구조
항목설명
`v4l2_ext_controls.controls`Control 배열을 가리키는 pointer입니다.
`v4l2_ext_controls.count`배열 원소 수이며 0이면 class 지원 여부를 검사합니다.
Control class배열의 모든 원소가 속해야 하는 하나의 class입니다.
`v4l2_ext_control`일반 값 외에 64-bit 값과 pointer를 전달합니다.
`V4L2_CTRL_FLAG_NEXT_COMPOUND`Compound type control도 열거하도록 요청합니다.
`VIDIOC_QUERY_EXT_CTRL`Compound control의 원소 수와 N-dimensional array 차원을 조회합니다.

배열 전체와 개별 원소의 역할을 구분합니다.

Control의 유연성 때문에 application은 `VIDIOC_QUERYCTRL`로 드라이버가 해당 control을 지원하는지와 유효 범위를 반드시 확인해야 합니다. `V4L2_CTRL_TYPE_MENU`에는 지원하지 않는 index가 있을 수 있고 이때 `VIDIOC_QUERYMENU`는 오류를 반환합니다. 모든 control 값은 machine endianness를 사용합니다.

The Extended Control API
========================

Three new ioctls are available:
:ref:`VIDIOC_G_EXT_CTRLS <VIDIOC_G_EXT_CTRLS>`,
:ref:`VIDIOC_S_EXT_CTRLS <VIDIOC_G_EXT_CTRLS>` and
:ref:`VIDIOC_TRY_EXT_CTRLS <VIDIOC_G_EXT_CTRLS>`. These ioctls act
on arrays of controls (as opposed to the
:ref:`VIDIOC_G_CTRL <VIDIOC_G_CTRL>` and
:ref:`VIDIOC_S_CTRL <VIDIOC_G_CTRL>` ioctls that act on a single
control). This is needed since it is often required to atomically change
several controls at once.

Each of the new ioctls expects a pointer to a struct
:c:type:`v4l2_ext_controls`. This structure
contains a pointer to the control array, a count of the number of
controls in that array and a control class. Control classes are used to
group similar controls into a single class. For example, control class
``V4L2_CTRL_CLASS_USER`` contains all user controls (i. e. all controls
that can also be set using the old :ref:`VIDIOC_S_CTRL <VIDIOC_G_CTRL>`
ioctl). Control class ``V4L2_CTRL_CLASS_CODEC`` contains controls
relating to codecs.

All controls in the control array must belong to the specified control
class. An error is returned if this is not the case.

It is also possible to use an empty control array (``count`` == 0) to check
whether the specified control class is supported.

The control array is a struct
:c:type:`v4l2_ext_control` array. The
struct :c:type:`v4l2_ext_control` is very similar to
struct :c:type:`v4l2_control`, except for the fact that
it also allows for 64-bit values and pointers to be passed.

Since the struct :c:type:`v4l2_ext_control` supports
pointers it is now also possible to have controls with compound types
such as N-dimensional arrays and/or structures. You need to specify the
``V4L2_CTRL_FLAG_NEXT_COMPOUND`` when enumerating controls to actually
be able to see such compound controls. In other words, these controls
with compound types should only be used programmatically.

Since such compound controls need to expose more information about
themselves than is possible with :ref:`VIDIOC_QUERYCTRL <VIDIOC_QUERYCTRL>`
the :ref:`VIDIOC_QUERY_EXT_CTRL <VIDIOC_QUERYCTRL>` ioctl was added. In
particular, this ioctl gives the dimensions of the N-dimensional array if
this control consists of more than one element.

.. note::

   #. It is important to realize that due to the flexibility of controls it is
      necessary to check whether the control you want to set actually is
      supported in the driver and what the valid range of values is. So use
      :ref:`VIDIOC_QUERYCTRL` to check this.

   #. It is possible that some of the menu indices in a control of
      type ``V4L2_CTRL_TYPE_MENU`` may not be supported (``VIDIOC_QUERYMENU``
      will return an error). A good example is the list of supported MPEG
      audio bitrates. Some drivers only support one or two bitrates, others
      support a wider range.

All controls use machine endianness.

열거와 control panel 구성

102-173

권장 열거 방식은 `VIDIOC_QUERYCTRL`과 `V4L2_CTRL_FLAG_NEXT_CTRL`을 함께 사용하는 것입니다. 최초 ID를 flag만 설정한 값으로 두면 ioctl이 그보다 큰 첫 control ID를 반환합니다. 매 반복에서 반환된 ID에 flag를 다시 OR하고, 더 큰 ID가 없으면 오류로 반복이 끝납니다.

특정 class만 열거하려면 초기 ID를 class와 `NEXT_CTRL` flag의 OR로 두고, `V4L2_CTRL_ID2CLASS(qctrl.id)`가 원하는 class와 달라지는 순간 반복을 종료합니다. 원문의 두 C 예제는 전체 열거와 codec class 한정 열거를 각각 보여 줍니다.

32-bit control ID 배치
항목설명
상위 4 bit`V4L2_CTRL_FLAG_NEXT_CTRL` 같은 flag이며 실제 ID에는 포함되지 않습니다.
나머지 28 bitControl ID 전체입니다.
그중 상위 12 bitControl class를 식별합니다.
그중 하위 16 bitClass 안의 control을 식별하며 항상 0이 아닙니다.
`0x1000` 이상Driver-specific control을 위해 예약된 범위입니다.

Flag와 class, class 내부 control 번호가 하나의 ID에 들어갑니다.

Driver가 extended control을 지원하지 않으면 `NEXT_CTRL`과 함께 쓴 `VIDIOC_QUERYCTRL`이 실패하므로 구형 전체 열거 방법으로 돌아가야 합니다. 지원한다면 driver-private control까지 모두 열거된다는 것이 보장됩니다.

GUI control panel은 같은 방식으로 모든 control을 순회해 만들 수 있습니다. 각 class는 `V4L2_CTRL_TYPE_CTRL_CLASS` type의 control로 시작하고, `VIDIOC_QUERYCTRL`이 반환한 class 이름을 tab 제목으로 쓸 수 있습니다. `v4l2_queryctrl.flags`에는 control 동작 방식에 관한 hint도 들어 있습니다.

Enumerating Extended Controls
=============================

The recommended way to enumerate over the extended controls is by using
:ref:`VIDIOC_QUERYCTRL` in combination with the
``V4L2_CTRL_FLAG_NEXT_CTRL`` flag:


.. code-block:: c

    struct v4l2_queryctrl qctrl;

    qctrl.id = V4L2_CTRL_FLAG_NEXT_CTRL;
    while (0 == ioctl (fd, VIDIOC_QUERYCTRL, &qctrl)) {
	/* ... */
	qctrl.id |= V4L2_CTRL_FLAG_NEXT_CTRL;
    }

The initial control ID is set to 0 ORed with the
``V4L2_CTRL_FLAG_NEXT_CTRL`` flag. The ``VIDIOC_QUERYCTRL`` ioctl will
return the first control with a higher ID than the specified one. When
no such controls are found an error is returned.

If you want to get all controls within a specific control class, then
you can set the initial ``qctrl.id`` value to the control class and add
an extra check to break out of the loop when a control of another
control class is found:


.. code-block:: c

    qctrl.id = V4L2_CTRL_CLASS_CODEC | V4L2_CTRL_FLAG_NEXT_CTRL;
    while (0 == ioctl(fd, VIDIOC_QUERYCTRL, &qctrl)) {
	if (V4L2_CTRL_ID2CLASS(qctrl.id) != V4L2_CTRL_CLASS_CODEC)
	    break;
	/* ... */
	qctrl.id |= V4L2_CTRL_FLAG_NEXT_CTRL;
    }

The 32-bit ``qctrl.id`` value is subdivided into three bit ranges: the
top 4 bits are reserved for flags (e. g. ``V4L2_CTRL_FLAG_NEXT_CTRL``)
and are not actually part of the ID. The remaining 28 bits form the
control ID, of which the most significant 12 bits define the control
class and the least significant 16 bits identify the control within the
control class. It is guaranteed that these last 16 bits are always
non-zero for controls. The range of 0x1000 and up are reserved for
driver-specific controls. The macro ``V4L2_CTRL_ID2CLASS(id)`` returns
the control class ID based on a control ID.

If the driver does not support extended controls, then
``VIDIOC_QUERYCTRL`` will fail when used in combination with
``V4L2_CTRL_FLAG_NEXT_CTRL``. In that case the old method of enumerating
control should be used (see :ref:`enum_all_controls`). But if it is
supported, then it is guaranteed to enumerate over all controls,
including driver-private controls.


Creating Control Panels
=======================

It is possible to create control panels for a graphical user interface
where the user can select the various controls. Basically you will have
to iterate over all controls using the method described above. Each
control class starts with a control of type
``V4L2_CTRL_TYPE_CTRL_CLASS``. ``VIDIOC_QUERYCTRL`` will return the name
of this control class which can be used as the title of a tab page
within a control panel.

The flags field of struct :ref:`v4l2_queryctrl <v4l2-queryctrl>` also
contains hints on the behavior of the control. See the
:ref:`VIDIOC_QUERYCTRL` documentation for more
details.