Video devices typically support one or more different video
standards or variations of standards. Each video input and output may
support another set of standards. This set is reported by the
std
field of struct v4l2_input and
struct v4l2_output returned by the VIDIOC_ENUMINPUT
and
VIDIOC_ENUMOUTPUT
ioctl, respectively.
V4L2 defines one bit for each analog video standard
currently in use worldwide, and sets aside bits for driver defined
standards, e. g. hybrid standards to watch NTSC video tapes on PAL TVs
and vice versa. Applications can use the predefined bits to select a
particular standard, although presenting the user a menu of supported
standards is preferred. To enumerate and query the attributes of the
supported standards applications use the VIDIOC_ENUMSTD
ioctl.
Many of the defined standards are actually just variations of a few major standards. The hardware may in fact not distinguish between them, or do so internal and switch automatically. Therefore enumerated standards also contain sets of one or more standard bits.
Assume a hypothetic tuner capable of demodulating B/PAL, G/PAL and I/PAL signals. The first enumerated standard is a set of B and G/PAL, switched automatically depending on the selected radio frequency in UHF or VHF band. Enumeration gives a "PAL-B/G" or "PAL-I" choice. Similar a Composite input may collapse standards, enumerating "PAL-B/G/H/I", "NTSC-M" and "SECAM-D/K".[1]
To query and select the standard used by the current video
input or output applications call the VIDIOC_G_STD
and
VIDIOC_S_STD
ioctl, respectively. The received
standard can be sensed with the VIDIOC_QUERYSTD
ioctl. Note parameter of all these ioctls is a pointer to a v4l2_std_id type (a standard set), not an index into the standard enumeration.[2] Drivers must implement all video standard ioctls
when the device has one or more video inputs or outputs.
Special rules apply to USB cameras where the notion of video standards makes little sense. More generally any capture device, output devices accordingly, which is
incapable of capturing fields or frames at the nominal rate of the video standard, or
where timestamps refer to the instant the field or frame was received by the driver, not the capture time, or
where sequence numbers refer to the frames received by the driver, not the captured frames.
std
field of struct v4l2_input and struct v4l2_output
to zero, the VIDIOC_G_STD
,
VIDIOC_S_STD
,
VIDIOC_QUERYSTD
and
VIDIOC_ENUMSTD
ioctls shall return the
EINVAL error code.[3]Example 1-5. Information about the current video standard
v4l2_std_id std_id; struct v4l2_standard standard; if (-1 == ioctl (fd,VIDIOC_G_STD
, &std_id)) { /* Note when VIDIOC_ENUMSTD always returns EINVAL this is no video device or it falls under the USB exception, and VIDIOC_G_STD returning EINVAL is no error. */ perror ("VIDIOC_G_STD"); exit (EXIT_FAILURE); } memset (&standard, 0, sizeof (standard)); standard.index = 0; while (0 == ioctl (fd,VIDIOC_ENUMSTD
, &standard)) { if (standard.id & std_id) { printf ("Current video standard: %s\n", standard.name); exit (EXIT_SUCCESS); } standard.index++; } /* EINVAL indicates the end of the enumeration, which cannot be empty unless this device falls under the USB exception. */ if (errno == EINVAL || standard.index == 0) { perror ("VIDIOC_ENUMSTD"); exit (EXIT_FAILURE); }
Example 1-6. Listing the video standards supported by the current input
struct v4l2_input input; struct v4l2_standard standard; memset (&input, 0, sizeof (input)); if (-1 == ioctl (fd,VIDIOC_G_INPUT
, &input.index)) { perror ("VIDIOC_G_INPUT"); exit (EXIT_FAILURE); } if (-1 == ioctl (fd,VIDIOC_ENUMINPUT
, &input)) { perror ("VIDIOC_ENUM_INPUT"); exit (EXIT_FAILURE); } printf ("Current input %s supports:\n", input.name); memset (&standard, 0, sizeof (standard)); standard.index = 0; while (0 == ioctl (fd,VIDIOC_ENUMSTD
, &standard)) { if (standard.id & input.std) printf ("%s\n", standard.name); standard.index++; } /* EINVAL indicates the end of the enumeration, which cannot be empty unless this device falls under the USB exception. */ if (errno != EINVAL || standard.index == 0) { perror ("VIDIOC_ENUMSTD"); exit (EXIT_FAILURE); }
Example 1-7. Selecting a new video standard
struct v4l2_input input; v4l2_std_id std_id; memset (&input, 0, sizeof (input)); if (-1 == ioctl (fd,VIDIOC_G_INPUT
, &input.index)) { perror ("VIDIOC_G_INPUT"); exit (EXIT_FAILURE); } if (-1 == ioctl (fd,VIDIOC_ENUMINPUT
, &input)) { perror ("VIDIOC_ENUM_INPUT"); exit (EXIT_FAILURE); } if (0 == (input.std & V4L2_STD_PAL_BG)) { fprintf (stderr, "Oops. B/G PAL is not supported.\n"); exit (EXIT_FAILURE); } /* Note this is also supposed to work when only B or G/PAL is supported. */ std_id = V4L2_STD_PAL_BG; if (-1 == ioctl (fd,VIDIOC_S_STD
, &std_id)) { perror ("VIDIOC_S_STD"); exit (EXIT_FAILURE); }
[1] | Some users are already confused by technical terms PAL, NTSC and SECAM. There is no point asking them to distinguish between B, G, D, or K when the software or hardware can do that automatically. |
[2] | An alternative to the current scheme is to use pointers
to indices as arguments of Indices are consistent with the rest of the API
and identify the standard unambiguously. In the present scheme of
things an enumerated standard is looked up by v4l2_std_id. Now the
standards supported by the inputs of a device can overlap. Just
assume the tuner and composite input in the example above both
exist on a device. An enumeration of "PAL-B/G", "PAL-H/I" suggests
a choice which does not exist. We cannot merge or omit sets, because
applications would be unable to find the standards reported by
So in summary, the lookup itself is unavoidable. The difference is only whether the lookup is necessary to find an enumerated standard or to switch to a standard by v4l2_std_id. |
[3] | See Section 3.5 for a rationale. Probably even USB cameras follow some well known video standard. It might have been better to explicitly indicate elsewhere if a device cannot live up to normal expectations, instead of this exception. |