Hey folks,
Well, I'm at least getting wavy lines in my window which somewhat
resemble the camera image, depending on various COL/ROW settings. But
I'm still not there.
Some questions:
1. Are the bt878 frame grabbers? My ioctls are saying no. But I'm
wondering if it's a matter of something else.
2. If I set the ROWS and COLS to anything but 300 x 200 or 400 x 200, I
get a garbled image.
3. Image is ONLY B&W.
4. How do I set things like PAL, NTSC, etc?? I tried using the
VIDIOCSTUNER ioctl but got an error ... assuming my card has no tuner
(Osprey 100).
Anyone have some comments on the following code? I found most of it on
the web, don't ask me where at this point as I've been searching
everywhere.
Quick compile:
cc -c grab.c `gtk-config --cflags`
cc grab.o -o grab `gtk-config --libs`
Thanks,
DT
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
#include <glib.h>
#include <string.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <time.h>
#include <sys/ioctl.h>
#include <sys/mman.h>
#include <fcntl.h>
#include <signal.h>
#include <linux/types.h>
#include <linux/videodev.h>
#include <errno.h>
#include <time.h>
#include <gtk/gtk.h>
#define COLS 300
#define ROWS 200
int on_darea_expose (GtkWidget*);
void display(GtkWidget*, GtkWidget*);
int cam,size,i,frame,q,st;
struct video_capability cap;
struct video_picture pic;
struct video_window win;
struct video_capture vicap;
struct video_channel vidcan;
struct video_mbuf vidbuf;
struct video_buffer buffer;
struct video_mmap mapbuf;
struct video_tuner vidtun;
guchar *bigbuf;
guchar *buf;
int gray[3];
time_t t, t2;
ssize_t st;
GtkWidget *window, *darea;
int main (int argc, char *argv[])
{
//-------------------------------------------------------------------
/* OPEN VIDEO DEVICE */
//-------------------------------------------------------------------
cam = open("/dev/video", O_RDWR );
if (cam<0){printf("ERROR: THERE IS NO CAMERA CONECTED\n");
exit(-1);}
//--------------------------------------------------------------------
/* VIDEO CAPABILITIES*/
//---------------------------------------------------------------------
if (-1==ioctl(cam,VIDIOCGCAP,&cap)){perror("ioctl VIDIOCGCAP");
exit(-1);}
printf("------------------------------------\n");
printf("------------------------------------\n");
printf("name hola-> %s\n", cap.name);
printf("type -> %d\n", cap.type);
printf("channels -> %d\n", cap.channels);
printf("audios -> %d\n", cap.audios );
printf("maxwidth -> %d\n", cap.maxwidth );
printf("maxheight -> %d\n", cap.maxheight);
printf("minwidth -> %d\n", cap.minwidth );
printf("minheight -> %d\n", cap.minheight );
printf("------------------------------------\n");
//-----------------------------------------------------------------------
/* SET VIDEO CHANNEL */
//-----------------------------------------------------------------------
vidcan.channel = 3;
vidcan.tuners = 0;
vidcan.type = VIDEO_TYPE_TV;
if (-1== ioctl(cam, VIDIOCSCHAN,&vidcan)) {
perror ("ioctl VIDIOCSCHAN");
exit (-1);
}
//-----------------------------------------------------------------------
/* CAPTURE WINDOW */
//-----------------------------------------------------------------------
win.x = 0;
win.y = 0;
win.width = COLS;
win.height = ROWS;
win.clipcount = 0;
win.chromakey = 0;
win.flags = 0; /* VIDEO_CLIPMAP_SIZE; */
if (-1== ioctl(cam, VIDIOCSWIN,&win)){perror ("ioctl VIDIOCSWIN");
exit (-1);}
//---------------------------------------------------------------------
/* IMAGE PROPERTIES*/
//---------------------------------------------------------------------
pic.depth = 24;
pic.palette = VIDEO_PALETTE_RGB24;
pic.brightness = 32000;
pic.contrast = 32000;
pic.whiteness = 32000;
pic.colour = 32000;
pic.hue = 32000;
if (-1==ioctl( cam, VIDIOCSPICT, &pic )){perror("ioctl VIDIOCSPICT");
exit(-1);}
ioctl( cam, VIDIOCGPICT, &pic );
printf("------------------------------------\n");
printf("brightness -> %d \n", pic.brightness/256 );
printf("hue -> %d\n", pic.hue/256);
printf("colour -> %d\n", pic.colour/256 );
printf("contrast -> %d \n", pic.contrast/256 );
printf("whiteness -> %d\n", pic.whiteness/256 );
printf("depth -> %d\n", pic.depth );
printf("palette -> %d \n", pic.palette );
printf("------------------------------------\n");
//-----------------------------------------------------------------------
/* MAPPING BUFFER */
//------------------------------------------------------------------------
if (-1==ioctl(cam,VIDIOCGMBUF,&vidbuf)){perror("ioctl VIDIOCGMBUF");
exit(-1);}
printf("------------------------------------\n");
printf("size -> %d\n",vidbuf.size);
printf("frames -> %d\n",vidbuf.frames);
printf("offsets -> %d\n",vidbuf.offsets);
printf("------------------------------------\n");
bigbuf = (char *)mmap(0,vidbuf.size, PROT_READ, MAP_SHARED, cam, 0);
mapbuf.width = COLS;
mapbuf.height = ROWS;
mapbuf.format = VIDEO_PALETTE_RGB24;
//-------------------------------------------------------------------------
/* CREATE DISPLAY WINDOWS AND IMAGE AREA */
//------------------------------------------------------------------------
gtk_init (&argc, &argv);
gdk_init (&argc, &argv);
gdk_rgb_init();
window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
darea = gtk_drawing_area_new();
//----------------------------------------------------------------------
/* SET BUFFERS*/
//----------------------------------------------------------------------
for(frame=0; frame<vidbuf.frames;frame++){ // turn on both of the buffers
mapbuf.frame = frame; // to start capture process.
if (ioctl(cam,VIDIOCMCAPTURE, &mapbuf)<0){ // Now they can store images.
perror("VIDIOCMCAPTURE");
exit(-1);}
}
frame = 0;
q=1;
time(&t);
//---------------------------------------------------------------------
/* CAPTURING*/
//---------------------------------------------------------------------
while (1){
i = -1;
while(i<0){
i= ioctl(cam,VIDIOCSYNC, &frame); // Wait until the actual buffer
if(i < 0 && errno == EINTR) continue; // is full. When it happends
if (i < 0) { // it start to capture to
perror ("VIDIOCSYNC"); // the other buffer.
exit(-1);
}
break;
}
q++;
buf = bigbuf + vidbuf.offsets[frame];
mapbuf.frame = frame;
display(window,darea);
if (ioctl(cam,VIDIOCMCAPTURE, &mapbuf)<0) {
perror("VIDIOCMCAPTURE");
exit(-1);
}
frame++;
if (frame>=vidbuf.frames) frame=0;
if (q==20){
time(&t2);
fprintf (stderr,"Time: initial: %d \nfinal: %d\nelapsed: %d \n", (time_t)t, (time_t)t2, (time_t)t2-t);
}
}
}
//------------------------------------------------------------------------
/* DISPLAY IMAGES */
//------------------------------------------------------------------------
void display(GtkWidget *window, GtkWidget *darea)
{
gint x, y;
static first = 1;
if (first)
{
gtk_container_add (GTK_CONTAINER (window), darea);
gtk_signal_connect (GTK_OBJECT (darea), "expose-event",
GTK_SIGNAL_FUNC (on_darea_expose), NULL);
first = 0;
}
gtk_drawing_area_size (GTK_DRAWING_AREA (darea), COLS, ROWS);
gtk_widget_show_all (window);
gtk_main();
}
int on_darea_expose (GtkWidget *widget)
{
gdk_draw_rgb_image (widget->window, widget->style->fg_gc[GTK_STATE_NORMAL],
0, 0, COLS, ROWS,GDK_RGB_DITHER_NONE, buf, COLS*3);
gtk_main_quit();
}