Ben Bridgwater wrote: > You shouldn't need videodevX, or the new i2c stack, probably not bttv > 0.8 either! > > Just as an overview: > > There are two video API's for Linux, V4L and V4L2. V4L is supported by > the kernel, and is what the bttv driver uses. V4L2 needs the videodevX > packages, and uses the bttv2 or bttv 0.8.x driver. > > There are four(!) bttv drivers for Bt8x8 based cards: the one in the > kernel (V4L), Gerd's 0.7.x one (V4L), Gerd's 0.8.x one (V4L/V4L2) and > Justin's bttv2 (V4L2). The difference between the kernel driver and the > 0.7.x one is that the 0.7.x one is generally more up to date and better > maintained - but the kernel one roughly keeps up with it. The 0.8.x > driver may fix some problems in 0.7.x (which works perfectly for me), > but is newer and more experimental. > > The only time when you need to patch your kernel with the new i2c stack > is if you want to use the 0.7.x driver with the 2.2 kernel. > > Unless you have a specific reason to want V4L2, I'd suggest you start > using the V4L API and the 2.4 kernel bttv driver, or the 0.7.x driver - > you shouldn't need anything else. > > >From your description I'd guess your real problem is that there's just > something a bit wrong with your capture code - can you post your actual > capture loop code? Ok. that cleared up my overview. Thanks. in fact I have downloaded all bttr drivers but I could not find the "the thin red line". I have attached my code.
#include <stdio.h> #include <unistd.h> #include <fcntl.h> #include <sys/ioctl.h> #include <sys/mman.h> #include <time.h> #include <linux/videodev.h> #include <stdlib.h> #include <string.h> #include <pthread.h> #include "piclib.h" #ifdef DEBUG #include <asm/timex.h> unsigned int tmp[2]; #define MSG(string, args...) printf("piclib : " string, ##args) int debug = 1; #else #define MSG(string, args...) int debug = 0; #endif static void *video_thread(void *arg); static int xioctl(int fd,int cmd, void *arg); typedef struct pic_data { pthread_mutex_t mutex; pthread_cond_t cond; unsigned char *frame_ptr; int wont_pic; } pic_data_struct; static pic_data_struct pic_data = { PTHREAD_MUTEX_INITIALIZER, PTHREAD_COND_INITIALIZER, NULL,0}; #define RUN 1 #define STOP 0 static struct { int fd; int run; pthread_t thread_ID; int height,width; unsigned char *pic_ptr; struct video_capability vidcap; struct video_buffer vidfbuf; struct video_mbuf vidmbuf; struct video_picture vidpict; struct video_channel vidchan; struct video_mmap vidmmap; } vid_data; /* * basic funktions * open, close get_pic and free_pic *----------------------------------*/ int open_video(int width, int height) { int fd; vid_data.run = RUN; /* * open device */ vid_data.fd = open("/dev/video0",O_RDWR); MSG(" fd %d\n",vid_data.fd); fd = vid_data.fd; if(fd < 0) { vid_data.run = STOP; perror("open"); MSG("error in open\n"); } /* init height, width */ if( width==0 || height==0 ) { vid_data.height = 480; vid_data.width = 640; } else { vid_data.height = height; vid_data.width = width; } /* get and set cap and frame structure */ xioctl(fd,VIDIOCGCAP,&vid_data.vidcap); xioctl(fd,VIDIOCGFBUF,&vid_data.vidfbuf); xioctl(fd,VIDIOCGMBUF,&vid_data.vidmbuf); /* set palette and depth. */ xioctl(fd,VIDIOCGPICT,&vid_data.vidpict); vid_data.vidpict.palette = VIDEO_PALETTE_GREY; vid_data.vidpict.depth = 8; xioctl(fd,VIDIOCSPICT,&vid_data.vidpict); /* set channel and type */ vid_data.vidchan.channel = 1; vid_data.vidchan.type = VIDEO_TYPE_CAMERA; xioctl(fd,VIDIOCSCHAN,&vid_data.vidchan); xioctl(fd,VIDIOCGCHAN,&vid_data.vidchan); /* starting up thread */ pthread_create(&vid_data.thread_ID, NULL, video_thread, (void *) fd); return 0; } pic_struct *get_pic(void) { struct timespec timeout; int status; pic_struct *pic_struct_ptr; timeout.tv_sec = time (NULL) + 2; timeout.tv_nsec = 0; if(vid_data.run == STOP) return NULL; pthread_mutex_lock(&pic_data.mutex); /* lock mutex */ status = pthread_cond_timedwait(&pic_data.cond,&pic_data.mutex,&timeout); if(status != 0) { MSG("pthread_cond_timedwait timed out get_pic\n"); return NULL; } /* MSG("allocate mem and copy form adr %p\n",pic_data.frame_ptr); */ pic_struct_ptr = malloc(sizeof(pic_struct)); pic_struct_ptr->pic_ptr = malloc(vid_data.width*vid_data.height); pic_struct_ptr->width = vid_data.width; pic_struct_ptr->height = vid_data.height; memcpy(pic_struct_ptr->pic_ptr, pic_data.frame_ptr,vid_data.width*vid_data.height); status = pthread_cond_broadcast(&pic_data.cond); pthread_mutex_unlock(&pic_data.mutex); return pic_struct_ptr; } void free_pic(pic_struct *pic) { free(pic->pic_ptr); free(pic); } void close_video(void) { vid_data.run = STOP; pthread_join(vid_data.thread_ID,NULL); close(vid_data.fd); } void *video_thread(void *arg) { int fd =vid_data.fd; int res; unsigned char *frame[2]; #ifdef DEBUG int count=0; double tmp[2]={0,0}; double val; #endif /* * init structs */ vid_data.vidmmap.frame = 0; vid_data.vidmmap.height = vid_data.height; vid_data.vidmmap.width = vid_data.width; vid_data.vidmmap.format = VIDEO_PALETTE_GREY; frame[0] = (unsigned char *) mmap(0,vid_data.height*vid_data.width, PROT_READ|PROT_WRITE, MAP_SHARED, fd ,vid_data.vidmbuf.offsets[0]); frame[1] = (unsigned char *) mmap(0,vid_data.height*vid_data.width, PROT_READ|PROT_WRITE, MAP_SHARED, fd ,vid_data.vidmbuf.offsets[1]); /* starting first picture */ xioctl(fd,VIDIOCMCAPTURE, &vid_data.vidmmap); vid_data.vidmmap.frame++; vid_data.vidmmap.frame &= 0x1; while(vid_data.run == RUN) { /* starting other image */ MSG("start\n"); xioctl(fd,VIDIOCMCAPTURE, &vid_data.vidmmap); vid_data.vidmmap.frame++; vid_data.vidmmap.frame &= 0x1; /* wait read picture */ MSG("before\n"); xioctl(fd,VIDIOCSYNC,&vid_data.vidmmap.frame); /* got a picture, and signal */ res = pthread_mutex_lock(&pic_data.mutex); if(res != 0) { vid_data.run = STOP; MSG("error in mutex"); } pic_data.frame_ptr = frame[ vid_data.vidmmap.frame ]; res = pthread_cond_broadcast(&pic_data.cond); #ifdef DEBUG if(count++ != 100) { count = 0; tmp[0] = get_cycles()/400.0; val = (tmp[0] > tmp[1]) ? (tmp[0] - tmp[1]) : ((tmp[1] - tmp[0]) + 1e6); tmp[1] = tmp[0]; val /= 1e6; /* printf("BROADCAST frame %d time %f\n",vid_data.vidmmap.frame,val); */ } #endif if(res != 0) { vid_data.run = STOP; MSG("error in cond"); } res = pthread_mutex_unlock(&pic_data.mutex); } return (void *) 0; } /* * smart system calling for debug *-------------------------------*/ static int xioctl(int fd,int cmd, void *arg) { int res; struct video_capability *a; struct video_buffer *b; struct video_mbuf *c; struct video_picture *d; struct video_channel *e; struct video_mmap *f; int *g; res = ioctl(fd,cmd,arg); if(res == 0 && !debug) { return res; } else { switch(cmd) { case VIDIOCGCAP: a = arg; if(res < 0) perror("VIDIOCGCAP"); printf(" name %s, type 0x%x, chan %d, maxwidth %d, maxheight %d, minwidth %d, minheight %d\n", a->name,a->type, a->channels, a->maxwidth, a->maxheight, a->minwidth, a->minheight); /* VID_TYPE_TELETEXT 4 Does NOT teletext */ /* VID_TYPE_CHROMAKEY 16 Does NOT Overlay by chromakey */ break; case VIDIOCGFBUF: case VIDIOCSFBUF: b = arg; if(res < 0) perror("VIDIOCGFBUF"); printf("base %p, height %d, width %d, depth %d, bytes line %d\n", b->base,b->height, b->width, b->depth, b->bytesperline); break; case VIDIOCGMBUF: c = arg; if(res < 0) perror("VIDIOCGCAP"); printf("size %x, frames %d, offsets 1= %x 2= %x\n", c->size,c->frames,c->offsets[0],c->offsets[1]); break; case VIDIOCGPICT: case VIDIOCSPICT: d = arg; if(res < 0) perror("VIDIOCGCAP"); printf("brightness %x, hue %x, colour %x, contrast %x, whiteness %x, depth %x, palette %x\n", d->brightness, d->hue, d->colour, d->contrast, d->whiteness, d->depth, d->palette); break; case VIDIOCGCHAN: case VIDIOCSCHAN: e = arg; if(res < 0) perror("VIDIOCGCAP"); printf("channel %d, name %s, tuners %d, flags %x, type %x, norm %d\n", e->channel, e->name, e->tuners, e->flags, e->type, e->norm); break; case VIDIOCMCAPTURE: f = arg; if(res < 0) perror("VIDIOCMCAPTURE"); break; case VIDIOCSYNC: g = arg; if(res < 0) perror("VIDIOCSYNC"); break; } } return res; } /* * other priactical funktions. * funktions added 1/6-01 *------------------------------*/ int pic2file( pic_struct *pic, char *name) { FILE *file_ptr; int height = pic->height, width = pic->width; char *buf; const char extension[] = ".pgm"; char *tmp_name; tmp_name = malloc(strlen(name) + strlen(extension)); tmp_name = strcpy(tmp_name,name); tmp_name = strcat(tmp_name,extension); buf = pic->pic_ptr; if(buf == NULL) return -1; file_ptr = fopen(tmp_name,"wb"); /* picture saved in pgm format se man pgm*/ fprintf(file_ptr,"P5\n%d %d\n255\n",width,height); fwrite(buf,1,width*height,file_ptr); fclose(file_ptr); free(tmp_name); return 0; }
/* * billedbehandlings funktioner * * lavet af Anders Gnistrup * dato 29-05-01, email agn@xxxxxxx *------------------------------------*/ typedef struct pic { int height; int width; unsigned char *pic_ptr; /* pointer to picture */ } pic_struct; int open_video(int,int); void close_video(void); pic_struct *get_pic(void); void free_pic(pic_struct *); int pic2file( pic_struct *,char *);
#include <fcntl.h> #include <stdio.h> #include <linux/videodev.h> #include "piclib.h" #include <stdlib.h> #ifdef DEBUG #define MSG(string, args...) printf("test_vid : " string, ##args) #else #define MSG(string, args...) #endif #define NR_PICT 10 int main(void) { int i; char name[] = "pic0"; pic_struct *pic[NR_PICT]; open_video(0,0); /* for(i=0;i<NR_PICT;i++) { pic[i] = get_pic(); } */ close_video(); for(i=0;i<NR_PICT;i++) { name[3]='0'+ i; pic2file(pic[i],name); free_pic(pic[i]); } return 0; }
CC = gcc DFLAGS = -DDEBUG CFLAGS = -O2 -Wall LINK = -lpthread OBJS = piclib.o test_vid.o all: test test: $(OBJS) $(CC) $(OBJS) -o test $(LINK) clean: rm -f *.o test *.ppm .c.o: $(CC) $(DFLAGS) $(CFLAGS) -c $<