Chinaunix首页 | 论坛 | 博客
  • 博客访问: 1157010
  • 博文数量: 309
  • 博客积分: 6093
  • 博客等级: 准将
  • 技术积分: 3038
  • 用 户 组: 普通用户
  • 注册时间: 2008-02-03 17:14
个人简介

linux学习记录

文章分类

全部博文(309)

文章存档

2014年(2)

2012年(37)

2011年(41)

2010年(87)

2009年(54)

2008年(88)

分类:

2010-08-04 14:14:58

大家看下我写的实现streamio方式捕获视频桢的程序。
大家互相交流下经验。
有没有谁做过overlay和capture同时进行的程序呀?
希望可以抛砖引玉。
代码:

#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;
              }
        }
}

 原文地址
阅读(797) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~