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 [EMAIL PROTECTED]
*------------------------------------*/
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 $<