Chinaunix首页 | 论坛 | 博客
  • 博客访问: 115137
  • 博文数量: 29
  • 博客积分: 826
  • 博客等级: 上士
  • 技术积分: 390
  • 用 户 组: 普通用户
  • 注册时间: 2012-06-11 08:30
文章分类
文章存档

2012年(29)

我的朋友

分类: LINUX

2012-06-29 10:41:54

#include  
#include  
#include  
#include  
#include  
#include  
#include  
#include  
#include  
#include  
#include  
#include  
#include  
#include  
#include  
#include  
 
#define CLEAR(x) memset(&(x),0,sizeof(x)) 
 
//定义一个缓存结构体 
struct buffer 

  void* start;     //空指针 
  size_t length;   //长度大小 
}; 
 
#define CAPTURE_FILE "/home/denggs/capture/hp.yuv" 
 
static char* dev_name = NULL;   //设备名 
static int fd = -1;              //文件序列 
static struct buffer* buffers = NULL;    //缓存对象 
static unsigned int n_buffers = 0;   //缓存数   
 
static void read_frame(FILE *fp)   //读取数据帧,用的都是mmap 

    struct v4l2_buffer buf; 
   int i; 
    buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; 
    buf.memory = V4L2_MEMORY_MMAP; 
    if(ioctl(fd,VIDIOC_DQBUF,&buf)==-1)  //把数据从缓存队列取出  
    {
     perror("error 1\n");
     exit(0);
    }
    printf("6\n");
    i=fwrite(buffers[buf.index].start,buf.length,1,fp);
    printf("**%d**\n",buf.length);
    printf("7\n");
   if(ioctl(fd,VIDIOC_QBUF,&buf)==-1)    //把数据放回缓存队列 
    {
     perror("error 2\n");
     exit(0); 
    }

 
static void mainloop(void) 

    unsigned int count; 
   count=10; 
   FILE *fp = fopen(CAPTURE_FILE, "w+"); 
    if (fp<0)  
    { 
        printf("open frame data file failed\n"); 
        exit(EXIT_FAILURE); 
    } 
   while(count-- > 0) 
   { 
    read_frame(fp);   
   } 
   fclose(fp); 
    printf("Capture one frame saved in %s\n", CAPTURE_FILE); 

 
static void stop_capturing(void)  //停止捕获帧 

   enum v4l2_buf_type type; 
   type = V4L2_BUF_TYPE_VIDEO_CAPTURE; 
 
   if(-1 == ioctl(fd,VIDIOC_STREAMOFF,&type))  //关闭视频流 
   {
    perror("close error\n");
    exit(0); 
   } 
   printf("\nStreamOff success!\n"); 

 
static void start_capturing(void)   //开始捕获帧 

    unsigned int i; 
    enum v4l2_buf_type type; 
 
   for(i = 0;i < n_buffers;i++) 
   { 
     struct v4l2_buffer buf; 
    CLEAR(buf); 
   
    buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; 
    buf.memory = V4L2_MEMORY_MMAP; 
    buf.index = i; 
  
    if(ioctl(fd,VIDIOC_QBUF,&buf)==-1)   //把数据从缓存读出来
    {
      perror("VIDIOC_QBUF,error\n");
      exit(0); 
    } 
   } 
 
    type = V4L2_BUF_TYPE_VIDEO_CAPTURE; 
 
   if(ioctl(fd,VIDIOC_STREAMON,&type)==-1)   //开始视屏 显示函数
   { 
    perror("error VIDIOC_STREAMON\n");
    exit(0);
   } 
   else printf("StreamOn success!\n"); 

 
static void uninit_device(void)   //释放存储空间 

   unsigned int i; 
 
   for(i =0;i < n_buffers;i++) 
   { 
      if(munmap(buffers[i].start,buffers[i].length)==-1) 
     {
      perror("error munmap\n");
      exit(0);
     } 
   } 
 
   free(buffers); 
 
static void init_device(void)  //初始化设备 

   struct v4l2_capability cap; 
   struct v4l2_format fmt; 
   unsigned int min; 
 
   if(ioctl(fd,VIDIOC_QUERYCAP,&cap)==-1)  //数据内存转化内存地址
   { 
       if(EINVAL == errno) 
      { 
        perror("no V4L2");   
      exit(0); 
       } 
       else  
       {
        perror("error 3 \n");
        exit(0); 
       } 
   } 
   if((cap.capabilities & V4L2_CAP_VIDEO_CAPTURE)==0) 
   { 
         perror("no capture\n"); 
          exit(0); 
   } 
 
   if(!(cap.capabilities & V4L2_CAP_STREAMING)) 
   { 
       perror("no format\n"); 
       exit(0);
   } 
////////////////////////////////////////// 
  struct v4l2_fmtdesc fmtdesc;
  fmtdesc.pixelformat=V4L2_PIX_FMT_MPEG;
  ioctl(fd,VIDIOC_S_FMT,&fmtdesc);
  
    CLEAR(fmt);       //设置帧格式 
    fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; 
    fmt.fmt.pix.width=352; 
    fmt.fmt.pix.height=288;  //v4l2_std_id stdid
    fmt.fmt.pix.pixelformat=V4L2_PIX_FMT_YUYV; 
    fmt.fmt.pix.field=V4L2_FIELD_INTERLACED; 
   //buf.length = fmt.fmt.pix.bytesperline * fmt.fmt.pix.height;
   if(ioctl(fd,VIDIOC_S_FMT,&fmt)==-1)       //设置驱动捕获视屏的格式
   {
    perror("error VIDIOC_S_FMT\n");
    exit(0); 
   }
   printf("Set frame format successful!\n"); 
   struct v4l2_requestbuffers req; 
   CLEAR(req); 
 
   req.count = 4; 
   req.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; 
   req.memory = V4L2_MEMORY_MMAP; 
 
   if(-1 == ioctl(fd,VIDIOC_REQBUFS,&req))   //分配内存 
   { 
      if(EINVAL == errno) 
     { 
       perror("not support mmap\n");
       exit(0); 
     } 
     else
     {
      perror("not VIDIOC_REQBUFS");
      exit(0);
     } 
   } 
 
  //分配缓存 
   
    buffers=(buffer *)calloc(req.count,sizeof(*buffers));
    if(buffers==NULL) 
    { 
      perror("out of buffer\n");
      exit(0); 
    } 
    for(n_buffers = 0;n_buffers < req.count;n_buffers++) 
    { 
       struct v4l2_buffer buf;
    CLEAR(buf);
     buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; 
     buf.memory =V4L2_MEMORY_MMAP; 
     buf.index = n_buffers; 
 
     if(-1 == ioctl(fd,VIDIOC_QUERYBUF,&buf))    //把分配的数据转换成物理地址
     {
      perror("error VIDIOC_QUERYBUF\n");
      exit(0); 
     } 
     buffers[n_buffers].length =buf.length;   //设置映射方式为mmap 
     buffers[n_buffers].start = mmap(NULL,buf.length,PROT_READ|PROT_WRITE,MAP_SHARED,fd,buf.m.offset);
     if(MAP_FAILED == buffers[n_buffers].start) 
     {
      perror("error mmap\n");
      exit(0); 
     } 
   }

 
static void close_device(void)   //关闭设备 

   if(close(fd)==-1) 
   {
     perror("close \n");
     exit(0);
   }
   fd = -1; 
   printf("Close the device successful!\n"); 

 
static void open_device(void)    //打开设备 

   if((fd = open(dev_name,O_RDWR,0))==-1) 
   {
    perror("error open_device\n");
    exit(0); 
   }
   printf("success open_device\n"); 

 
int main(int argc,char* argv[]) 

   char bb[]="/dev/video0";
   dev_name=bb;
   open_device();
   init_device(); 
   start_capturing(); 
   mainloop();
   stop_capturing(); 
   uninit_device();
   close_device();   
   return 0; 
阅读(3005) | 评论(1) | 转发(0) |
0

上一篇:avi文件格式

下一篇:jpeg转bmp

给主人留下些什么吧!~~

行潇1152012-10-28 11:34:09

请问,为什么要在static void mainloop(void)  
函数中加 count =10, while(count-- > 0)  
这一句,不加是不是不会报段错误!