Starting with API version 0.20 we are planning on making some changes to the V4L2 kernel driver API specification which will not be backward compatible with 0.19 and earlier. The purpose is to simplify the API, while at the same time make it more extensible, and follow common Linux driver API conventions.
The changes to existing applications and drivers should be simple to
make. For the convenience of those who are maintaining V4L2 drivers and
applications, I have written this document to summarize these changes and
how to modify your code.
1. All ioctl() commands that took an integer argument before, will
now take a pointer to an integer. Where it makes sense, the driver
will return the actual value used in the integer pointed to by the argument.
This is a common convention, and also makes certain things easier in libv4l2
and other system code when the parameter to ioctl() is always a pointer.
The ioctl commands affected are:
VIDIOC_PREVIEW
VIDIOC_STREAMON VIDIOC_STREAMOFF VIDIOC_S_FREQ VIDIOC_S_INPUT VIDIOC_S_OUTPUT VIDIOC_S_EFFECT |
For example, where before you might have had code like:
err = ioctl(fd, VIDIOC_XXX, V4L2_XXX); |
that becomes
int a = V4L2_XXX;
err = ioctl(fd, VIDIOC_XXX, &a); |
2. All the different set-format ioctl() commands are swept into a single set-format command whose parameter consists of an integer value indicating the type of format, followed by the format data. The same for the get-format commands, of course. This will simplify the API by eliminating several ioctl codes and also make it possible to add additional kinds of data streams, or driver-private kinds of streams without having to add more set-format ioctls.
The parameter to VIDIOC_S_FMT is as follows. The first field is a V4L2_BUF_TYPE_*
value that indicates which stream the set-format is for, and implicitly,
what type of format data. After that is a union of the different format
structures. More can be added later without breaking backward compatibility.
Nonstandard driver-private formats can be used by casting raw_data.
struct v4l2_format
{ __u32 type; union { struct v4l2_pix_format pix; struct v4l2_vbi_format vbi; ...and so on... __u8 raw_data[200]; } fmt; }; |
For a get-format, the application fills in the type field, and the driver fills in the rest.
What was before the image format structure, struct v4l2_format, becomes struct v4l2_pix_format.
These ioctls become obsolete:
VIDIOC_S_INFMT
VIDIOC_G_INFMT VIDIOC_S_OUTFMT VIDIOC_G_OUTFMT VIDIOC_S_VBIFMT VIDIOC_G_VBIFMT |
3. Similar to #2, VIDIOC_G/S_PARM and VIDIOC_G/S_OUTPARM are merged,
along with the corresponding 'get' functions. A type field will indicate
which stream the parameters are for, set to a V4L2_BUF_TYPE_* value.
struct v4l2_streamparm
{ __u32 type; union { struct v4l2_captureparm capture; struct v4l2_outputparm output; __u8 raw_data[200]; } parm; }; |
These ioctls become obsolete:
VIDIOC_G_OUTPARM
VIDIOC_S_OUTPARM |
4. The way controls are enumerated is simplified. Simultaneously, two new control flags are introduced and the existing flag is dropped. Also, the catname field is dropped in favor of a group name.
To enumerate controls call VIDIOC_QUERYCTRL with successive id's starting from V4L2_CID_BASE or V4L2_CID_PRIVATE_BASE and stop when the driver returns the EINVAL error code. Controls that are not supported on the hardware are marked with the V4L2_CTRL_FLAG_DISABLED flag. Additionally, controls that are temporarily unavailable, or that can only be controlled from another file descriptor are marked with the V4L2_CTRL_FLAG_GRABBED flag. Usually, a control that is GRABBED, but not DISABLED can be read, but changed.
The group name indicates a possibly narrower classification than
the category. In other words, there may be multiple groups within
a category. Controls within a group would typically be drawn within a group
box. Controls in different categories might have a greater separation,
or even be in separate windows.
5. The v4l2_buffer timestamp field is changed to a 64-bit integer, and holds the time of the frame based on the system time, in 1 nanosecond units. Additionally, timestamps will be in absolute system time, not starting from zero at the beginning of a stream as it is now.
The data type name for timestamps is stamp_t, defined as a signed 64-bit integer.
Output devices should not send a buffer out until the time in the timestamp field has arrived.
I would like to follow SGI's lead, and adopt a multimedia timestamping system like their UST (Unadjusted System Time). See http://reality.sgi.com/cpirazzi_engr/lg/time/intro.html. UST uses timestamps that are 64-bit signed integers (not struct timeval's) and given in nanosecond units. The UST clock starts at zero when the system is booted and runs continuously and uniformly. It takes a little over 292 years for UST to overflow. There is no way to set the UST clock. The regular Linux time-of-day clock can be changed periodically, which would cause errors if it were being used for timestamping a multimedia stream.
A real UST style clock will require some support in the kernel that
is not there yet. But in anticipation, I will change the timestamp field
to a 64-bit integer, and I will change the v4l2_masterclock_gettime() function
(used only by drivers) to return a 64-bit integer.
6. The sequence field is added to the v4l2_buffer structure.
The sequence field indicates which frame this is in the sequence-- 0, 1,
2, 3, 4, etc. Set by capturing devices. Ignored by output devices. If a
capture driver drops a frame, the sequence number of that frame is skipped.
A break in the sequence will indicate to the application which frame was
dropped.