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:
|
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
- The video capture card is represented by /dev/video0.
fd = open("/dev/video0", O_RDONLY)
- Get information on the capability of the video device.
struct video_capability cap
ioctl(fd, VIDIOCGCAP, &cap)
- 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)
- 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)
- 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)
- 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 */
- 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
*/
- 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
- Capture a frame from the camera
ioctl(fd, VIDIOCMCAPTURE, &v_map)
- Wait for end of frame
ioctl(fd, VIDIOCSYNC, &v_map)
- 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.
|