// Telerobotics Senior Project
// (c) 2000 Bradley University ECE
// -------------------------------
// Frame grabber - prints JPEG data to stdout
// Adapted from:
// vcat.c from V4L2 Sample Apps by Bill Dirks
// vctrl.c from V4L2 Sample Apps originally by Erik Walthinsen
// example.c from jpeg6-b library by IJG
// Required software packages:
// -- Video for Linux Two
// -- Winnov Videum V4L2 driver, or other driver for other card.
// -- libjpeg-6b
#include <sys/time.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/ioctl.h>
#include <fcntl.h>
#include <unistd.h>
#include <stdlib.h>
#include <stdio.h>
#include <sys/mman.h>
#include <errno.h>
/* These are needed to use the Videum driver */
#include <linux/fs.h>
#include <linux/kernel.h>
#include <linux/videodev.h> /* Video for Linux Two */
// JPEG library includes
#include "jpeglib.h"
#include <setjmp.h>
int main(int argc, char *argv[])
{
char *device = NULL;
int vid = -1;
int err;
int i;
int n;
struct v4l2_capability cap;
struct v4l2_format fmt;
int bgr = 0;
int rgb = 0;
int rgbswap = 0;
char *data;
char t;
char *jpgfile;
FILE *outfile;
struct jpeg_compress_struct cinfo;
struct jpeg_error_mgr jerr;
JSAMPROW row_pointer[1];
int row_stride;
int quality;
int input;
device = "/dev/video";
quality = 50;
input = atoi(argv[1]);
while(vid < 0)
{
vid = open(device, O_RDONLY);
}
ioctl(vid, VIDIOC_S_INPUT, &input); // set input
err = ioctl(vid, VIDIOC_QUERYCAP, &cap);
if (err)
{
fprintf(stderr, "QUERYCAP returned error %d\n", errno);
return 1;
}
if (cap.type != V4L2_TYPE_CAPTURE)
{
fprintf(stderr, "Device %s is not a video capture device.\n",
device);
return 1;
}
if (!(cap.flags & V4L2_FLAG_READ))
{
fprintf(stderr, "Device %s doesn't support read().\n", device);
return 1;
}
fmt.type = V4L2_BUF_TYPE_CAPTURE;
err = ioctl(vid, VIDIOC_G_FMT, &fmt);
if (err)
{
fprintf(stderr, "1.G_FMT returned error %d\n", errno);
return 1;
}
fmt.fmt.pix.width=320;
fmt.fmt.pix.height=240;
fmt.fmt.pix.depth=24;
fmt.fmt.pix.pixelformat=V4L2_PIX_FMT_BGR24;
err = ioctl(vid, VIDIOC_S_FMT, &fmt);
if (err)
{
fprintf(stderr, "S_FMT returned error %d\n", errno);
return 1;
}
err = ioctl(vid, VIDIOC_G_FMT, &fmt);
if (err)
{
fprintf(stderr, "2.G_FMT returned error %d\n", errno);
return 1;
}
data = malloc(fmt.fmt.pix.sizeimage);
if (data == NULL)
{
fprintf(stderr, "malloc(%d) failed\n", fmt.fmt.pix.sizeimage);
return 1;
}
// some sorta delay here, to stabilize image
// sleep(1);
n = read(vid, data, fmt.fmt.pix.sizeimage);
if (n < 0)
{
fprintf(stderr, "read() returned error %d\n", errno);
return 1;
}
// Dirty hack - reads extra frame because the first might not look perty
// Figure out why the first frame is so ugly sometimes.
n = read(vid, data, fmt.fmt.pix.sizeimage);
if (n < 0)
{
fprintf(stderr, "read() returned error %d\n", errno);
return 1;
}
n = read(vid, data, fmt.fmt.pix.sizeimage);
if (n < 0)
{
fprintf(stderr, "read() returned error %d\n", errno);
return 1;
}
n = read(vid, data, fmt.fmt.pix.sizeimage);
if (n < 0)
{
fprintf(stderr, "read() returned error %d\n", errno);
return 1;
}
n = read(vid, data, fmt.fmt.pix.sizeimage);
if (n < 0)
{
fprintf(stderr, "read() returned error %d\n", errno);
return 1;
}
close(vid);
// Videum driver only supports BGR, so we have to
// invert to RGB for use by the JPEG compressor
for (i = 0; i < n; i += 3)
{
t = data[i];
data[i] = data[i + 2];
data[i + 2] = t;
}
// if (n)
// fwrite(data, (size_t)n, 1, stdout);
// print_settings(vid);
cinfo.err = jpeg_std_error(&jerr);
jpeg_create_compress(&cinfo);
jpeg_stdio_dest(&cinfo, stdout);
cinfo.image_width = 320;
cinfo.image_height = 240;
cinfo.input_components = 3;
cinfo.in_color_space = JCS_RGB;
jpeg_set_defaults(&cinfo);
jpeg_set_quality(&cinfo, quality, TRUE);
jpeg_start_compress(&cinfo, TRUE);
row_stride = 320 * 3;
while (cinfo.next_scanline < cinfo.image_height)
{
row_pointer[0] = & data[cinfo.next_scanline * row_stride];
(void) jpeg_write_scanlines(&cinfo, row_pointer, 1);
}
jpeg_finish_compress(&cinfo);
jpeg_destroy_compress(&cinfo);
return 0;
}
syntax highlighted by Code2HTML, v. 0.8.11