Introduction

V4L, Video4Linux, is an API that allows control of a video capture card on linux machines. A card-specific driver controls a video capture card and offers a semi-standard interface to the system. V4L is an implementation that uses this interface to add additional features, and in turn, provides an API of its own. V4L provides a uniform API for a variety of capture cards which can be TV cards, Radio cards, or cards used just to capture images from a camera. If V4L and the driver for the capture card are installed on a machine, then application developers can use V4L's API without knowing much about the actual card or it's driver.

Some helpful websites for V4L are:


Goal of this document

The main purpose of this document is to help people who are trying to analyze images. To analyze images, pixel values must be available for each pixel in the frame. This documentation explains how to grab an image from a camera and how to construct a Plain PPM file that contains pixel values in decimal format.


V4L API

The V4L API consists of the open, read, ioctl, and close system calls. A lot of commands exists for the ioctl system call, which is why the API is complex to understand. The right set of ioctl functions to call in a V4L program depends on the type of the application.

V4L Usage for a Specific Application

The documentation given below is applicable to a system with the following attributes.

  • The videodev module, which is the implementation of V4L, is installed and operational.
  • A camera serves as an input to the video capture card and the camera is compatible with the video capture card. For example, a camera producing an analog signal requires a capture card accepting analog input.
  • A driver for the video capture card used is installed and operational.


Usage

  1. The video capture card is represented by /dev/video0. fd = open("/dev/video0", O_RDONLY)
  2. Get information on the capability of the video device. struct video_capability cap ioctl(fd, VIDIOCGCAP, &cap)
  3. Use channel 1 for capturing from a camera. Set features for channel number 1. struct video_channel chan chan.channel = 1 /* Get the current settings */ ioctl(fd, VIDIOCGCHAN, &chan) /* The next line sets no tuners and no audio for the channel */ chan.flags = 0 /* The next line sets input type to be of type camera */ chan.type = VIDEO_TYPE_CAMERA /* NTSC is an American standard. Some European countries use PAL */ chan.norm = VIDEO_MODE_NTSC /* Set the new settings */ ioctl(fd, VIDIOCSCHAN, &chan)
  4. Set the properties of the image window where the image will be captured. struct video_windown win ioctl(fd, VIDIOCGWIN, &win) win.x = win.y = win.chromakey = 0 win.width = 640 win.height = 480 win.flags = 0 ioctl(fd, VIDIOCSWIN, &win)
  5. Set the properties of the image to be captured struct video_picture pic ioctl(fd, VIDIOCGPICT, &pic) pic.depth = 24 /* use 24 for color or 8 for b&w */ pic.palette = VIDEO_PALETTE_RGB24 pic.brightness = pic.hue = pic.colour = pic.contrast = pic.whiteness = 32767 ioctl(fd, VIDIOCSPICT, &pic)
  6. Determine size of card memory to map to user space struct video_mbuf m_buf ioctl(fd, VIDIOCGMBUF, &m_buf) /* For simple image grabbing, do not consider the frames and * offsets field of m_buf */
  7. Map video capture card memory to user space memory void *map map = mmap(0, m_buf.size, PROT_READ, MAP_SHARED, fd, 0) /* PROT_READ specifies that the memory mapped will only be read from. * MAP_SHARED specifies that a change to the video memory will change * the user space memory * A good description of mmap() is available at * http://www.opengroup.org/onlinepubs/7908799/xsh/mmap.html */
  8. Set the capture parameters for the mapped area struct video_mmap v_map v_map.frame = 0 v_map.width = 640 v_map.height = 480 v_map.format = VIDEO_PALETTE_RGB24
  9. Capture a frame from the camera ioctl(fd, VIDIOCMCAPTURE, &v_map)
  10. Wait for end of frame ioctl(fd, VIDIOCSYNC, &v_map)
  11. Output a Plain PPM file containing RGB values. /* Values in user space memory are in BGR format. * Consult the man page for PPM to output the correct format. * Values for each of the 640 * 480 pixels are outputted in * decimal format. For each pixel value, a red value, a green * value, and a blue value is printed in decimal separated by * whitespace. No line can have more than 70 characters. * Whitespace exists between sample values of a pixel and * between samples of two adjacent pixels. The format of a Plain PPM * file has to be exactly as specified in the man page. Note the * difference between a PPM file and a Plain PPM file. * Initially the driver for this particular application stores the * pixels in BGR format. The values are printed in RGB format. */ // Sample printing of RGB values of a PPM file p = map; printf("P3\n%d %d\n255", img_w, img_h); for(i = 0; i < img_h; i++) { for(j = 0; j < img_w; j++) { if( (3*j%15) == 0 ) printf("\n"); printf("%d %d %d ", *(p+2), *(p+1), *p); p = p + 3; } printf("\n"); } When the application program is run, redirect the output to a file with an .ppm extension. Then use the /usr/bin/pnmtojpeg utility to produce a jpeg file. The output from this utility should also be directed to a file. Then the file can viewed by a JPEG file viewer. The last step of converting to a JPEG file is only necessary to check that the correct PPM file was generated. The raw RGB values in the PPM file are the important values to be used for processing the image.


Ankur Mahajan
November 6, 2002