Video4Linux2 part 7: Controls

來源:互聯網
上載者:User

With the completion of part 6
of
this series
, we now know how to set up a video device and transfer
frames back and forth. It is a well known fact, however, that users can
be
hard to please; not content with being able to see video from their
camera
device, they immediately start asking if they can play with parameters
like
brightness, contrast, and more. These adjustments could be done in the
video application, and sometimes they are, but there are advantages to
doing them in the hardware itself when the hardware has that capability.
A
brightness adjustment, for example, might lose dynamic range if done
after
the fact, but a hardware-based adjustment may retain the full range that
the sensor is capable of delivering. Hardware-based adjustments,
obviously, will also be easier on the host processor.

Current hardware typically has a wide range of parameters which can be
adjusted on the fly. Just how those parameters work varies widely from
one
device to the next, though. An adjustment as simple as "brightness"
could
involve a straightforward register setting, or it could require a rather
more complex change to an obscure transformation matrix. It would be
nice
to hide as much of this detail from the application as possible, but
there
are limits to how much hiding can be done. An overly abstract interface
might make it impossible to use the hardware's controls to their fullest
potential.

The V4L2 control interface tries to simplify things as much as possible
while allowing full use of the hardware. It starts by defining a set of
standard control names; these include V4L2_CID_BRIGHTNESS
,
V4L2_CID_CONTRAST
, V4L2_CID_SATURATION
, and many more.
There are boolean controls for features like white balance, horizontal
and vertical mirroring, etc. See the V4L2 API spec

for
a full list of predefined control ID values.
There is also a provision for driver-specific
controls, but those, clearly, will generally only be usable by
special-purpose applications. Private controls start at
V4L2_CID_PRIVATE_BASE
and go up from there.

In typical fashion, the V4L2 API provides a mechanism by which an
application can enumerate the available controls. To that end, they
will
make ioctl()
calls which end up in a V4L2 driver via the
vidioc_queryctrl()
callback:

 

    int (*vidioc_queryctrl)(struct file *file, void *private_data,
struct v4l2_queryctrl *qc);

The driver will normally fill in the structure qc
with
information
about the control of interest, or return EINVAL
if that control
is
not supported. This structure has a number of fields:

 

    struct v4l2_queryctrl
{
__u32 id;
enum v4l2_ctrl_type type;
__u8 name[32];
__s32 minimum;
__s32 maximum;
__s32 step;
__s32 default_value;
__u32 flags;
__u32 reserved[2];
};

The control being queried will be passed in via id
. As a
special
case, the application can supply a control ID with the
V4L2_CTRL_FLAG_NEXT_CTRL
bit set; when this happens, the driver
should return information about the next supported control ID higher
than
the one given by the application. In any case, id
should be
set
to the ID of the control actually being described.

All of the other fields are set by the driver to describe the selected
control. The data type of the control is given in type
; it can
be
V4L2_CTRL_TYPE_INTEGER
,
V4L2_CTRL_TYPE_BOOLEAN
,
V4L2_CTRL_TYPE_MENU
(for a set of fixed choices), or
V4L2_CTRL_TYPE_BUTTON
(for a control which performs some action
when set and which ignores any given value). name
describes
the control; it
could be used in the interface presented to the user by the application.
For integer controls (only), minimum
and maximum

describe
the range of values implemented by the control, and step
gives
the
granularity of that range. default_value
is exactly what it
sounds like - though it is only applicable to integer, boolean, and menu
controls. Drivers should set control values to their default at
initialization time only; like other device parameters, they should
persist
across open()
and close()
calls. As a result,
default_value
may well not be the current value of the control.

Inevitably, there is a set of flags which further describe a control.
V4L2_CTRL_FLAG_DISABLED
means that the control is disabled; the
application should ignore it. V4L2_CTRL_FLAG_GRABBED
means
that
the control, temporarily, cannot be changed, perhaps because another
application has taken it over. V4L2_CTRL_FLAG_READ_ONLY
marks
controls which can be queried, but which cannot be changed.
V4L2_CTRL_FLAG_UPDATE
means that adjusting this control may
affect
the values of other controls. V4L2_CTRL_FLAG_INACTIVE
marks a
control which is not relevant to the current device configuration. And
V4L2_CTRL_FLAG_SLIDER
is a hint that applications should
represent
the control with a slider-like interface.

Applications might just query a few controls which have been
specifically
programmed in, or they may want to enumerate the entire set. In the
latter
case, they will start at V4L2_CID_BASE
and step through
V4L2_CID_LASTP1
, perhaps using the
V4L2_CTRL_FLAG_NEXT_CTRL
flag in the process. For controls of
the
menu variety (type V4L2_CTRL_TYPE_MENU
), applications will
probably want to enumerate the possible values as well. The relevant
callback is:

 

    int (*vidioc_querymenu)(struct file *file, void *private_data,
struct v4l2_querymenu *qm);

The v4l2_querymenu
structure looks like:

 

    struct v4l2_querymenu
{
__u32id;
__u32index;
__u8name[32];
__u32reserved;
};

On input, id
is the ID value for the menu control of interest,
and
index
is the index value for a specific menu value. Index
values
start at zero and go up to the maximum
value returned from
vidioc_queryctrl()
. The driver will fill in the name

of
the menu item; the reserved
field should be set to zero.

Once the application knows about the available controls, it will likely
set
about querying and changing their values. The structure used in this
case
is relatively simple:

 

    struct v4l2_control
{
__u32 id;
__s32 value;
};

To query a specific control, an application will set id
to the
ID
of the control and make a call which ends up in the driver as:

 

    int (*vidioc_g_ctrl)(struct file *file, void *private_data,
struct v4l2_control *ctrl);

The driver should set value
to the current setting of the
control. Of course, it should also be sure that it knows about this
specific control and return EINVAL
if the application attempts
to
query a nonexistent control. Attempts to query button controls should
also
return EINVAL
.

A request to change a control ends up in:

 

    int (*vidioc_s_ctrl)(struct file *file, void *private_data,
struct v4l2_control *ctrl);

The driver should verify the id
and make sure that value
falls within the allowed range. If all is well, the new value should be
set in the hardware.

Finally, it is worth noting that there is a separate extended controls
interface
supported with V4L2. This API is meant for relatively
complex controls; in practice, its main use is for MPEG encoding and
decoding parameters. Extended controls can be grouped into classes, and
64-bit integer values are supported. The interface is similar to the
regular control interface; see the API specification for details.

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.