分类: LINUX
2009-03-13 13:31:44
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#define FILENAME "/dev/video"
#define IOCTL(fd, req, addr ) ((-1==ioctl(fd,req,addr))?(perror(#req),exit(EXIT_FAILURE)):0)
int main(void) {
int fd;
struct v4l2_capability cap;
v4l2_std_id std;
struct v4l2_format format;
struct v4l2_requestbuffers reqbuf;
struct {
void * start;
size_t length;
} * buffers;
struct v4l2_buffer buffer;
unsigned int i,x,y,index;
unsigned char *data,*ptr;
FILE *pgm ;
//open device file
fd = open(FILENAME,O_RDWR);
//query the device's ability
IOCTL(fd, VIDIOC_QUERYCAP, &cap);
//if device can support capture and streamio
if ( (cap.capabilities & V4L2_CAP_VIDEO_CAPTURE)&&(cap.capabilities & V4L2_CAP_STREAMING)) {
//set the current input is composite 1
index = 1;
IOCTL(fd,VIDIOC_S_INPUT,&index);
//query the current video std whether PAL
IOCTL(fd,VIDIOC_G_STD,&std);
//if the current video std is PAL
if ( std & V4L2_STD_PAL) {
//negotiate the image format
format.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
IOCTL(fd,VIDIOC_G_FMT,&format);
//printf("the current pixelformat is %x \n",format.fmt.pix.pixelformat);
format.fmt.pix.width = 384;
format.fmt.pix.height = 288;
format.fmt.pix.pixelformat = V4L2_PIX_FMT_BGR24;
format.fmt.pix.field = V4L2_FIELD_TOP;
format.fmt.pix.bytesperline = 384*3;
format.fmt.pix.sizeimage = 384*288*3;
format.fmt.pix.colorspace =V4L2_COLORSPACE_SRGB;//SMPTE170M;
format.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
IOCTL(fd,VIDIOC_S_FMT,&format);
printf("change the current pixelformat is %c%c%c%c\n",(format.fmt.pix.pixelformat & 0x000000FF) ,((format.fmt.pix.pixelformat & 0x0000FF00)>>8),
((format.fmt.pix.pixelformat & 0x00FF0000)>>16), ((format.fmt.pix.pixelformat & 0xFF000000)>>24) );
// negotiate the request buffer
reqbuf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
reqbuf.memory = V4L2_MEMORY_MMAP;
reqbuf.count = 2;
//init the device memory
IOCTL(fd,VIDIOC_REQBUFS,&reqbuf );
//if init fails
if (reqbuf.count < 2) {
printf ("Not enough buffer memory\n");
exit (EXIT_FAILURE);
}
buffers = calloc (reqbuf.count,sizeof(*buffers));//later clean the buffers can use
// assert(buffers != NULL);
//map the device memory to application memory
for (i=0;i
buffer.type = reqbuf.type;
buffer.index =i ;
//query the status of one buffer
IOCTL(fd,VIDIOC_QUERYBUF,&buffer);
buffers[i].length = buffer.length;
buffers[i].start = mmap (NULL,buffer.length,
PROT_READ | PROT_WRITE,
MAP_SHARED,
fd,buffer.m.offset);
if (buffers[i].start == MAP_FAILED) {
perror ("mmap");
exit(EXIT_FAILURE);
}
}
//begian streaming
IOCTL(fd,VIDIOC_STREAMON,&reqbuf.type);
//put one frame into the device incoming queue
buffer.type = reqbuf.type;
buffer.index = 0;
// IOCTL( fd, VIDIOC_QUERYBUF, &buffer );
//put another frame into the device incoming queue
IOCTL(fd,VIDIOC_QBUF,&buffer);
buffer.type =reqbuf.type;
buffer.index =1 ;
// IOCTL(fd,VIDIOC_QUERYBUF,&buffer);
IOCTL(fd,VIDIOC_QBUF,&buffer);
//get one frame out of the incoming queue and save as a pgm file
buffer.type = reqbuf.type;
buffer.index = 0;
IOCTL( fd, VIDIOC_DQBUF, &buffer );
data = buffers[0].start;
pgm = fopen( "framea.pgm", "w" );
fprintf( pgm, "P2\n%d %d 255\n",
format.fmt.pix.width, format.fmt.pix.height );
ptr = data;
for( y = 0; y < format.fmt.pix.height; y++ ) {
for( x = 0; x < format.fmt.pix.width; x++ ) {
fprintf( pgm, "%03d ",
(ptr[ 0] + ptr[1] + ptr[2] ) / 3 );
ptr += 3;
}
fprintf( pgm, "\n" );
}
fclose( pgm );
//get another frame out of the incoming queue and save as a pgm file
buffer.type = reqbuf.type;
buffer.index = 1;
IOCTL( fd, VIDIOC_DQBUF, &buffer );
data = buffers[1].start;
pgm = fopen( "frameb.pgm", "w" );
fprintf( pgm, "P2\n%d %d 255\n",
format.fmt.pix.width, format.fmt.pix.height );
ptr = data;
for( y = 0; y < format.fmt.pix.height; y++ ) {
for( x = 0; x < format.fmt.pix.width; x++ ) {
fprintf( pgm, "%03d ",
(ptr[ 0] + ptr[1] + ptr[2] ) / 3 );
ptr += 3;
}
fprintf( pgm, "\n" );
}
fclose( pgm );
//stop the stream
IOCTL( fd, VIDIOC_STREAMOFF, &reqbuf.type );
//clean the allocated buffers
for (i=0;i munmap (buffers[i].start,buffers[i].length);
//close the device file and return
close(fd);
return 0;
}
}
}