News Archive (1999-2012) | 2013-current at LinuxGizmos | Current Tech News Portal |    About   

Article: Intro to V4L2

Mar 11, 2009 — by LinuxDevices Staff — from the LinuxDevices Archive — 1191 views

Foreword — This article describes the V4L2 (Video for Linux 2) interface, along with the first steps toward developing a device driver that uses the interface. It is based on Linux 2.6.28, and may not apply to other kernel versions.

The article was contributed by Vladimir Davydov, an engineer with Promwad, an embedded development services company located in Minsk, Belarus. Promwad has used the V4L2 interface in several development projects, Davydov reports. Enjoy . . . !


Practical Application of V4L2 Drivers: Intro to V4L2 (Part 1)
by Vladimir Davydov

Video For Linux (V4L) is an API that provides unified access to various video capturing devices, such as TV tuners, USB web cameras, etc. The first version of this interface was implemented in Linux 2.2, by Alan Cox. In 1999, development began on the second-generation V4L2 interface, which fixed bugs found in V4L, and supported a wider range of devices.

General overview of Video4Linux2 interface (V4L2)

V4L2 drivers are implemented as normal kernel modules that can be loaded by an administrator, or loaded automatically when opening a device file. Drivers use the base “videodev” kernel module, which represents the corresponding kernel interface for working with a video device.

V4L2 API provides access to a device by means of standard Unix character devices.
V4L2 provides the following interfaces:

  • Video capture interface (/dev/video)
  • Video overlay interface (/dev/video)
  • Video output interface (/dev/video)
  • Video output interface (/dev/video)
  • Codec interface (/dev/video)
  • Effect devices interface (/dev/video)
  • Raw vertical blancking interval (VBI) interface (/dev/vbi)
  • Sliced VBI data interface (/dev/vbi)
  • Teletext interface (/dev/vtx)
  • Radio interface (/dev/radio)
  • Radio data system (RDS) interface (/dev/radio)

In this article, we will cover usage of the video capture interface, provided by the /dev/video character device.

Below, you can see a chart of interaction between a user application and a V4L2 driver:


Chart 1: Interaction between a user application and the V4L2 driver

Linux V4L2 userspace programming

In this article we do not cover the issue of V4L2 application in terms of user processes, as it is quite well described in the official specification, available here. It is necessary to note that there is a wide range of free software programs with open source code for playback and recording via V4L2 interface. Here are some of them:

  • MEncoder — free tool for coding, decoding and filtering video, contained in MPlayer package
  • MPlayer — free and open source media player
  • FFmpeg — robust solution for recording, converting, and streaming audio and video in different formats. FFmped contains a set of ready tools and libraries, which can be used for coding/decoding audio and video, and also for multiplexing and demultiplexing in different media containers.
  • xawtv — program for watching TV programs.
  • tvtime — a high-quality TV application for use with video capture cards

Linux V4l2 driver programming

As noted above, V4L2 device drivers use the “videodev” base module. This module exports a set of functions for working with the V4L2 interface. Unfortunately, at the present time, there is no full description of these functions. There is the “Video for Linux Two — Driver Writer's Guide,” dated December 23rd, 1999. This document could be considered outdated, however, due to changes in V4L2's internal interface.

Fortunately, the open model of Linux development provides a great number of ready drivers, which can be used as examples for examining the V4L2 interface, and for developing new drivers for video capturing devices. Source code for these V4L2 drivers is available in kernel's source code tree, in the “drivers/media/video” directory. Most interesting, from this point of view, is the VIVI driver (drivers/media/video/vivi.c).

VIVI – virtual video driver

VIVI is a V4L2 driver module that emulates a real video device. This driver was developed by the team of Video Technology Magazine, and was added into Linux as of the 2.6.17 kernel release.

The main purpose of VIVI development is to design a working sample V4L2 driver, and also a stub driver that simplifies the development of new video drivers. Also, VIVI can be used for debugging user applications that use the V4L2 interface. VIVI code demonstrates the ideal usage of the Linux kernel interface for V4L2 drivers, and it is recommended for developers as an example, when creating new drivers.

Loading the VIVI module:

# modprobe vivi
# ls -l /dev/video*
lrwxrwxrwx 1 root root 6 Feb 14 00:07 /dev/video -> video0
crw-rw---- 1 root video 81, 0 Feb 14 00:07 /dev/video0
#

V4L2 Linux kernel interface

The kernel provides a set of structures and helper functions for convenient V4L2 drivers development.

To use these functions one has to include the following header files:

  • media/v4l2-dev.h> contains declarations of base structures and functions, required for registering V4L2 driver and its work. Most part of implementations of these functions is located in drivers/media/video/v4l2-common.c and drivers/media/video/videodev.c files.
  • media/videobuf-core.h> contains functions for buffering video data, memory management, and PCI DMA. Implementation of these functions is located in drivers/media/video/videobuf-core.c file.
  • media/v4l2-ioctl.h> contains structures and functions required for processing ioctl system call for device's file (/dev/video).

Initializing and registering a V4L2 driver

Some important data structures

To register V4L2 device it is necessary to fill three main structures:
video_device, file_operations, and v4l2_ioctl_ops. Let's look closer at initializing each of these structures, using the example of the VIVI driver:

static const struct file_operations vivi_fops = {
.owner = THIS_MODULE,
.open = vivi_open,
.release = vivi_close,
.read = vivi_read,
.poll = vivi_poll,
.ioctl = video_ioctl2, /* V4L2 ioctl handler */
.compat_ioctl = v4l_compat_ioctl32,
.mmap = vivi_mmap,
.llseek = no_llseek,
};

static const struct v4l2_ioctl_ops vivi_ioctl_ops = {
.vidioc_querycap = vidioc_querycap,
.vidioc_enum_fmt_vid_cap = vidioc_enum_fmt_vid_cap,
.vidioc_g_fmt_vid_cap = vidioc_g_fmt_vid_cap,
.vidioc_try_fmt_vid_cap = vidioc_try_fmt_vid_cap,
.vidioc_s_fmt_vid_cap = vidioc_s_fmt_vid_cap,
.vidioc_reqbufs = vidioc_reqbufs,
.vidioc_querybuf = vidioc_querybuf,
.vidioc_qbuf = vidioc_qbuf,
.vidioc_dqbuf = vidioc_dqbuf,
.vidioc_s_std = vidioc_s_std,
.vidioc_enum_input = vidioc_enum_input,
.vidioc_g_input = vidioc_g_input,
.vidioc_s_input = vidioc_s_input,
.vidioc_queryctrl = vidioc_queryctrl,
.vidioc_g_ctrl = vidioc_g_ctrl,
.vidioc_s_ctrl = vidioc_s_ctrl,
.vidioc_streamon = vidioc_streamon,
.vidioc_streamoff = vidioc_streamoff,
#ifdef CONFIG_VIDEO_V4L1_COMPAT
.vidiocgmbuf = vidiocgmbuf,
#endif
};

static struct video_device vivi_template = {
.name = "vivi",
.fops = &vivi_fops,
.ioctl_ops = &vivi_ioctl_ops,
.minor = -1,
.release = video_device_release,
.tvnorms = V4L2_STD_525_60,
.current_norm = V4L2_STD_NTSC_M,
};

Let's look in more detail at the purposes of some fields of these structures.

The video_device structure is declared in the media/v4l2-dev.h> file. It contains general information about the video device. The fops and ioctl_ops fields point at the corresponding structures file_operations and v4l2_ioctl_ops.

The release field contains a pointer to the function that will be called when the video device is removed from system. In this case, this field points at the standard video_device_release function, which just releases memory allocated for the video_device structure.

The tvnorms field defines a list of supported video standards. The full list of supported standards is defined in the linux/videodev2.h> header file. In our case, V4L2_STD_525_60 represents a bit mask:

#define V4L2_STD_525_60  (V4L2_STD_PAL_M  |
V4L2_STD_PAL_60 |
V4L2_STD_NTSC |
V4L2_STD_NTSC_443)

The current_norm field corresponds to its name, and defines the video standard to be used by default.

The file_operations structure is defined in the linux/fs.h> file, and is an important kernel structure. It contains pointers to functions, each of which implements a corresponding operation, or to NULL, if the operation is not supported. The fields of this structure are quite well described in the book Linux Device Drivers, 3rd Edition (LDD3), which you can download here.

The VIVI driver defines handlers of the main system calls for the device file /dev/video: open, release, read, poll, mmap, ioctl. A specific implementation of these handlers will be considered later in the article.

It is necessary to mention that the video_ioctl2 standard function is used as a handler for the ioctl call. This function performs the initial processing of an ioctl call, analyzing the command's code and calling a corresponding handler using pointers to functions specified in the v4l2_ioctl_ops structure. You can specify your own function for processing ioctl, but in that case, you will have to implement code for command analysis independently. Developers of V4L2 recommend using video_ioctl2, in order to decrease the probabilitiesof errors in driver code.

The v4l2_ioctl_ops structure stores pointers to handlers of V4L2 commands transmitted by means of an ioctl system call. This structure is declared in media/v4l2-ioctl.h> file.

Registering a video device

As mentioned earlier, the kernel uses the video_device structure for describing video device. This structure can be created both statically and dynamically, by using the following function:

struct video_device *video_device_alloc(void);

To use video_device_alloc in your code, you have to include media/v4l2-common.h>.

Then for releasing memory occupied by the structure, make the following call:

void video_device_release(struct video_device *vfd);

A video device is registered by the following function:

int video_register_device(struct video_device *vfd, int type, int nr);

The vfd parameter in the examples above is the pointer to the video device structure that you want to register.

type parameter defines the type of registered device. The following values define device types:

VFL_TYPE_GRABBER — video capturing device
VFL_TYPE_VTX — teletext device
VFL_TYPE_VBI — VBI device
VFL_TYPE_RADIO — radio card

The nr parameter sets the number of the registered device: 0 for /dev/video0, 1 for /dev/video1, etc. If you want to assign the first available number, then specify -1 for this parameter.

To remove a video device from system, you have to call the following function:

void video_unregister_device(struct video_device *vfd);

Registering a video device in VIVI

As in most Linux device drivers, there are mandatory functions for initializing and releasing the module. To understand this process, we recommend reading the LDD3 book.

The VIVI driver allows registering a variable number of video devices. Currently, the maximal number of registered devices is limited by the videodev module, and is 32 devices.

Let's look at modified code from the function for initializing the VIVI driver, to demonstrate registration of a video device.

int ret;
struct video_device *vfd;

vfd = video_device_alloc();
if (!vfd) {
/*Allocation failed*/
}

*vfd = vivi_template;

ret = video_register_device(vfd, VFL_TYPE_GRABBER, -1);
if (ret < 0) {
/*Registration failed*/
video_device_release(vfd);
}

Conclusion

The V4L2 API provides a modern and powerful interface for working with video capturing devices. Excellent documentation on the V4L2 API and the availability of a great number of ready drivers and applications with open source code allow significant reduction of development time. In the next article we will examine structures and helper functions in the V4L interface for buffering.


Useful links

V4L2 home

V4L2 API specification

FFmpeg tools and libraries

Xawtv TV application

Tvtime TV application

Video for Linux Two – Driver Writer's Guide

MPlayer and MEncoder home

The VIVI driver; a great starting point for V4L2 driver writers

Linux Device Drivers, Third Edition


About the author — Vladimir Davydov works as an engineer at Promwad Innovation Company. He has more than seven years experience in network programming and Linux kernel development for multimedia applications. In 2002, he graduated from Belarusian State University of Informatics and Radioelectronics (Minsk, Belarus) with a Bachelor of Science in Computer Science, and main specialization in compute machines, complexes, systems, and networks.


 
This article was originally published on LinuxDevices.com and has been donated to the open source community by QuinStreet Inc. Please visit LinuxToday.com for up-to-date news and articles about Linux and open source.



Comments are closed.