|
大家看下我写的实现streamio方式捕获视频桢的程序。
大家互相交流下经验。
有没有谁做过overlay和capture同时进行的程序呀?
希望可以抛砖引玉。
- #include <stdio.h>
- #include <errno.h>
- #include <sys/ioctl.h>
- #include <sys/stat.h>
- #include <fcntl.h>
- #include <linux/types.h>
- #include <unistd.h>
- #include <stdlib.h>
- #include <sys/mman.h>
- #include <sys/poll.h>
- #include <linux/videodev.h>
- #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<reqbuf.count;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<reqbuf.count;i++)
- munmap (buffers[i].start,buffers[i].length);
- //close the device file and return
- close(fd);
- return 0;
- }
- }
- }
复制代码 |
|