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(); }