分享

用v4l2和framebuffer实现usb摄像头视频采集并显示

 liluvu 2014-10-10

用v4l2和framebuffer实现usb摄像头图像采集并显示

 

前言

很多天了,看了数不尽的论坛和各网站的帖子后,我把我遇到的问题都解决的差不多了,感觉应该是把摄像头跑起来了,但还是遇到了一些问题,似乎是图像处理方面的,我好像解决不了这个问题了,我好想有个人帮帮我。写这篇文章估计得花3~4小时,我真心希望哪位朋友能明白我的想法,能顺手帮帮我。

 

正文

一,我的思路

我想用一幅图来说明我所做的事情,如图1所示(图中uvcdriver标错了,应该是uvcvideo)。

                                                                                                                          图1

 图1左侧是图像采集,右侧是图像显示。采集的帧速是30 帧/秒。

 

二,v4l2(video for linux two)

驱动摄像头的是uvcdriver,该驱动设计时采用了v4l系列的标准(该标准好像是linuxTV制定的,linuxTV的官网是http:///),我的CentOS6.3(内核是linux-2.6.32.60)采用的是v4l2标准。一开始我编写应用程序的时候什么都不懂,见论坛上帖子怎么讲,我就怎么写,当中很多是参照v4l标准,我当时不知道,直接照抄,出了问题,改用v4l2标准后才解决了问题。v4l2 API的在/usr/include/linux/videodev2.h头文件中,很容易就找到了。

采集图像的实例程序网上很多,但最经典的还是linuxTV官网推出的capture.c,这里给出地址http:///downloads/legacy/video4linux/API/V4L2_API/v4l2spec/capture.c这个程序写的很好,很值得研究。

我就是借鉴的这个程序,然后得到我的摄像头设备的信息,如图2(那个pixel_format应该用十六进制表示的,我没注意,十六进制的话应该是0x56595559,即YUYV的意思)所示。

                                                                 图2

一插上摄像头,uvcvideo就直接把我的摄像头识别了。

v4l2我不想再多写了,基本上只要看了那个经典的capture.c就够了。

 

三,framebuffer

就目前我这水平,我还不想涉及到QT或者别的什么面向对象编程,我想简单一点,慢慢来。于是我直接选择了framebuffer,它的API在usr/include/linux/fb.h头文件中。刚开始用open函数打开/dev/fb0的时候根本就打不开,愣是要把grub设置一下,如图3所示。后面显示的时候要切记切换到命令行模式。

                                                                                                                                      图3

关于那个vga=0x311以及一系列的frambuffer编程我是参照http://bbs./thread-2000076-1-1.html这个人的文章的,这里我复制一下他的一张表到下面,如表1所示。

  1.               4bit        8bit         15bit        16bit        24bit        32bit  
  2.    
  3. 640x400       x           0x300        x            x            x            x  
  4.    
  5. 640x480       x           0x301        0x310        0x311        0x312        x  
  6.    
  7. 800x600       0x302       0x303        0x313        0x314        0x315        x  
  8.    
  9. 1024x768      x           0x305        0x316        0x317        0x318        x  
  10.    
  11. 1280x1024     x           0x307        0x319        0x31A        0x31B        x  
  12.    
  13. 1600x1200     x           0x31C        0x31D        0x31E        0x31F        x  

                                                                                                          表1

 

因为我采集视频的图像时640*480,然后是16bit的BPP,所以我选择了0x311

framebuffer编程很简单,比v4l2简单多了。我截个图来表达我用framebuffer API得到的我的显示屏的信息,如图4所示。

                                                    图4

 四,v4l2+framebuffer

我把v4l和framebuffer集成到一块儿了。因为capture.c图像处理部分没有什么内容,所以,图像处理部分是我自己写的。我的摄像头采集的图像的像素编码是YUYV或者说是YUV422格式,每个像素是16bit。我做的事情就是把YUV422_16转换成RGB565_16,采集的图像尺寸是640*480的,显示屏也是640*480。

对于YUV422_16我想具体一点(因为当初觉得YUV格式很抽象,总是搞不懂)。然后看到一个表好像蛮形象的,我先把表画下来,如表2所示

  1. 像素:Y0U0V0  Y1U1V1  Y2U2V2  Y3U3V3  ...  
  2.   
  3. 采集:Y0U0V0  Y1      Y2U2V2  Y3      ...  
  4.   
  5. 存储:Y0U0Y1V0  Y2U2Y3V2  

表2

Y0是一个字节,U0也是一个字节,V0也是一个字节,都是一个字节。

客观上每个像素是3个字节,但采集的时候却不是3个字节都采集,这样采集:第0个像素(Y0 U0 V0)采集了3个字节(Y0 U0 V0),第1个像素采集了1个字节(Y1),第2个像素采集了3个字节(Y2 U2 V2),第3个像素采集了1个字节(Y3)……第n个像素采集了3个字节(Yn Un Vn),第n+1个像素采集了1个字节(Yn+1)……。这种采集方式叫相邻两像素共用UV(不知道能不能从数学上证明如果每个像素3个字节都采集的话是不是就是冗余)。

怎么存储呢?好像是间隔存储。我记得好像有宏像素的概念,即2个像素占4个字节或者说4个字节的存储单元保存着2个像素的信息。比如Y0U0V1V0共需要一个字(4个字节),这个字的存储单元里保存着第0个像素和第1个像素的信息,第0个像素和第1个像素共享U0和V0。反正在后面的图像处理当中,我是用一个unsigned long *p的指针来处理一个宏像素的。当然了,这张表看不懂没关系,我当初就没看懂。
然后就是RGB了,我感觉RGB还是蛮形象的,尤其是RGB565_16,网上好多人研究这个,这里我就不多说了。

对于YUV和RGB之间的转换,我理解的程度也不深,我怕我的图像处理问题就是出在这个上面。

 

五,v4l2+framebuffer的组合效果

我看到我的摄像头采集出来的视频流了,因为担心YUV和RGB之间的转换时的数值处理出问题,我就只取了Y分量,我听说有黑白图像一说(其实YUV分量都提取的话,效果还是一样)。

1,提取YUV2分量代码如下:

  1. Y0=(*from & 0x000000FF)>>0;         
  2. U0=(*from & 0x0000FF00)>>8;   //colorful  
  3. //U0=128;                           //white and black  
  4. Y1=(*from & 0x00FF0000)>>16;  
  5. V0=(*from & 0xFF000000)>>24;  //colorful  
  6. //V0=128;                           //white and blcak  

注:from是unsigned long型的指针变量,指向YUV2缓存。 

 

2,根据提取到的YUV分量,转换成RGB分量函数:

  1. static  void YUV2RGB(unsigned char Y,unsigned char U,unsigned char V,  
  2.                     unsigned char *R,unsigned char *G,unsigned char *B)                   
  3. {  
  4. /* 
  5.     *R=Y+1.4075*(V-128); 
  6.     *G=Y-0.3455*(U-128)-0.7169*(V-128); 
  7.     *B=Y+1.779*(U-128); 
  8.  
  9.     *R=Y+1.140*V; 
  10.     *G=Y-0.394*U-0.581*V; 
  11.     *B=Y+2.032*U; 
  12. */  
  13.   
  14.     *R=Y+(V-128)+((V-128)*103>>8);  
  15.     *G=Y-((U-128)*88>>8)-((V-128)*183>>8);  
  16.     *B=Y+(U-128)+((U-128)*198>>8);  
  17. }  

 

3,把RGB分量再编码成像素:

  1. *to = (R0&0x1F)<<11 | (G0&0x3F)<<5 |(B0&0x1F)<<0;  
  2. *to |= ((R1&0x1F)<<11 | (G1&0x3F)<<5 |(B1&0x1F)<<0)<<16;  

注:to是unsigned long型指针变量,指向RGB565输出缓存。


 编译好程序后,我用ctrl+alt+F2切换到命令行模式看看效果,我先截图,如图5和图6所示

                                                             图5(我的v4l2+framebuffer)

 

                                                                图6(关掉台灯,我的v4l2+framebuffer)

 

我ctrl+alt+F1切换到图形界面,看看cheese的效果,如图7所示。

                                                                                                     图7(cheese)

 为什么cheese的效果会这么好(显示效果不流畅,但画面很美),为什么我的视频的图像会成为这个样子(显示效果很流畅,但画面很丑),我搞了好长时间都发现不了问题出在哪里。谁能帮帮我吗?

 

六,程序

我的程序就一个bluelover.c文件。

  1. /* 
  2. *  This program can be used and distributed without restrictions. 
  3. */  
  4.  
  5. #include <stdio.h>  
  6. #include <stdlib.h>  
  7. #include <string.h>  
  8. #include <fcntl.h>              /* low-level i/o */  
  9. #include <unistd.h>  
  10. #include <errno.h>  
  11. #include <assert.h>  
  12. #include <sys/stat.h>  
  13. #include <sys/types.h>  
  14. #include <sys/time.h>  
  15. #include <sys/mman.h>  
  16. #include <sys/ioctl.h>  
  17. #include <stdbool.h>  
  18.  
  19. #include <linux/videodev2.h>  
  20. #include <linux/fb.h>  
  21.  
  22. #define CLEAR(x) memset(&(x), 0, sizeof(x))  
  23.   
  24. struct buffer {  
  25.         void   *start;  
  26.         size_t  length;  
  27. };  
  28.   
  29. static char *dev_name1;  
  30. static char *dev_name2;  
  31. static int  fd1 = -1;  
  32. static int  fd2 = -1;  
  33.   
  34. struct buffer          *buffers;  
  35. static unsigned int     n_buffers;  
  36. static char *fb_buffer;  
  37. static unsigned long screensize;  
  38.   
  39. static char *yuv_buffer;  
  40. static char *rgb_buffer;  
  41.   
  42.   
  43. static int              force_format=false;  
  44. static int              frame_count = 1000;  
  45.   
  46. static void errno_exit(const char *s)  
  47. {  
  48.         fprintf(stderr, "%s error %d, %s\n", s, errno, strerror(errno));  
  49.         exit(EXIT_FAILURE);  
  50. }  
  51.   
  52. static int xioctl(int fh, int request, void *arg)  
  53. {  
  54.         int r;  
  55.   
  56.         do {  
  57.                 r = ioctl(fh, request, arg);  
  58.         } while (-1 == r && EINTR == errno);  
  59.   
  60.         return r;  
  61. }  
  62. /* 
  63. static void process_image(const void *p, int size) 
  64.     unsigned short *fb; 
  65.     unsigned short *rgb; 
  66.     unsigned long height = 480; 
  67.     if(size>screensize) 
  68.         size=screensize; 
  69.  
  70.     //move 
  71.     memcpy(yuv_buffer,p,size); 
  72.  
  73.     //proc 
  74.     memcpy(rgb_buffer,yuv_buffer,size); 
  75.  
  76.     //move 
  77.     memcpy(fb_buffer,yuv_buffer,size); 
  78.      
  79.  
  80.     //move 
  81.     rgb=(unsigned short*)rgb_buffer; 
  82.     fb=(unsigned short*)fb_buffer; 
  83.     while(height--) 
  84.     { 
  85.         memcpy(fb,rgb,1280); 
  86.         fb+=640; 
  87.         rgb+=640;    
  88.     } 
  89.  
  90.      
  91.     fflush(stderr); 
  92.     fprintf(stderr, "."); 
  93.     fflush(stdout); 
  94. */  
  95. static  void YUV2RGB(unsigned char Y,unsigned char U,unsigned char V,  
  96.                     unsigned char *R,unsigned char *G,unsigned char *B)  
  97. /*static  void YUV2RGB(int Y,int U,int V, 
  98.                     int *R,int *G,int *B)*/                   
  99. {  
  100. /* 
  101.     *R=Y+1.4075*(V-128); 
  102.     *G=Y-0.3455*(U-128)-0.7169*(V-128); 
  103.     *B=Y+1.779*(U-128); 
  104. */  
  105.   
  106.     *R=Y+(V-128)+((V-128)*103>>8);  
  107.     *G=Y-((U-128)*88>>8)-((V-128)*183>>8);  
  108.     *B=Y+(U-128)+((U-128)*198>>8);  
  109. }  
  110.   
  111. static void process_image(const unsigned long *from, int size)  
  112. {  
  113.     unsigned long *to =(unsigned long*)fb_buffer;  
  114.       
  115.     unsigned char Y0;  
  116.     unsigned char U0;  
  117.     unsigned char Y1;  
  118.     unsigned char V0;  
  119.       
  120.     unsigned char R0;  
  121.     unsigned char G0;  
  122.     unsigned char B0;  
  123.     unsigned char R1;  
  124.     unsigned char G1;  
  125.     unsigned char B1;     
  126.   
  127.     size>>=2;  
  128.     while(size--)  
  129.     {  
  130.         Y0=(*from & 0x000000FF)>>0;         
  131.         U0=128;                         //white and black  
  132.         //U0=(*from & 0x0000FF00)>>8; //colorful  
  133.         Y1=(*from & 0x00FF0000)>>16;        
  134.         V0=128;                         //white and blcak  
  135.         //V0=(*from & 0xFF000000)>>24;    //colorful        
  136.         YUV2RGB(Y0,U0,V0,&R0,&G0,&B0);  
  137.         YUV2RGB(Y1,U0,V0,&R1,&G1,&B1);  
  138.   
  139.         *to = (R0&0x1F)<<11 | (G0&0x3F)<<5 |(B0&0x1F)<<0;  
  140.         *to |= ((R1&0x1F)<<11 | (G1&0x3F)<<5 |(B1&0x1F)<<0)<<16;          
  141.           
  142.         from++;  
  143.         to++;  
  144.     }  
  145. }  
  146.       
  147. static int read_frame(void)  
  148. {  
  149.     struct v4l2_buffer buf;  
  150.   
  151.     CLEAR(buf);  
  152.     buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;  
  153.     buf.memory = V4L2_MEMORY_MMAP;  
  154.     if (-1 == xioctl(fd1, VIDIOC_DQBUF, &buf))  
  155.     {  
  156.         switch (errno)   
  157.         {  
  158.             case EAGAIN:  
  159.                 return 0;  
  160.             case EIO:  
  161.             default:  
  162.                 errno_exit("VIDIOC_DQBUF");  
  163.         }  
  164.     }  
  165.   
  166.     assert(buf.index < n_buffers);  
  167.       
  168.     process_image(buffers[buf.index].start, buf.bytesused);  
  169.   
  170.     if (-1 == xioctl(fd1, VIDIOC_QBUF, &buf))  
  171.         errno_exit("VIDIOC_QBUF");  
  172.   
  173.     return 1;  
  174. }  
  175.   
  176. static void mainloop(void)  
  177. {  
  178.         unsigned int count;  
  179.   
  180.         count = frame_count;  
  181.         while (count-- > 0) {  
  182.                 for (;;) {  
  183.                         fd_set fds;  
  184.                         struct timeval tv;  
  185.                         int r;  
  186.   
  187.                         FD_ZERO(&fds);  
  188.                         FD_SET(fd1, &fds);  
  189.   
  190.                         /* Timeout. */  
  191.                         tv.tv_sec = 2;  
  192.                         tv.tv_usec = 0;  
  193.   
  194.                         r = select(fd1 + 1, &fds, NULL, NULL, &tv);  
  195.   
  196.                         if (-1 == r) {  
  197.                                 if (EINTR == errno)  
  198.                                         continue;  
  199.                                 errno_exit("select");  
  200.                         }  
  201.   
  202.                         if (0 == r) {  
  203.                                 fprintf(stderr, "select timeout\n");  
  204.                                 exit(EXIT_FAILURE);  
  205.                         }  
  206.   
  207.                         if (read_frame())  
  208.                                 break;  
  209.                         /* EAGAIN - continue select loop. */  
  210.                 }  
  211.         }  
  212. }  
  213.   
  214. static void stop_capturing(void)  
  215. {  
  216.     enum v4l2_buf_type type;  
  217.       
  218.     type = V4L2_BUF_TYPE_VIDEO_CAPTURE;  
  219.     if (-1 == xioctl(fd1, VIDIOC_STREAMOFF, &type))  
  220.         errno_exit("VIDIOC_STREAMOFF");  
  221. }  
  222.   
  223. static void start_capturing(void)  
  224. {  
  225.     unsigned int i;  
  226.     enum v4l2_buf_type type;  
  227.     struct v4l2_buffer buf;  
  228.           
  229.     for (i = 0; i < n_buffers; ++i)   
  230.     {         
  231.         CLEAR(buf);  
  232.         buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;  
  233.         buf.memory = V4L2_MEMORY_MMAP;  
  234.         buf.index = i;  
  235.         if (-1 == xioctl(fd1, VIDIOC_QBUF, &buf))  
  236.             errno_exit("VIDIOC_QBUF");  
  237.     }  
  238.       
  239.     type = V4L2_BUF_TYPE_VIDEO_CAPTURE;  
  240.     if (-1 == xioctl(fd1, VIDIOC_STREAMON, &type))  
  241.         errno_exit("VIDIOC_STREAMON");  
  242.   
  243. }  
  244.   
  245. static void uninit_device(void)  
  246. {  
  247.         unsigned int i;  
  248.   
  249.     for (i = 0; i < n_buffers; ++i)  
  250.         if (-1 == munmap(buffers[i].start, buffers[i].length))  
  251.             errno_exit("munmap");  
  252.           
  253.     if(-1 == munmap(fb_buffer,screensize))  
  254.         errno_exit("munmap");  
  255.       
  256.     free(buffers);  
  257.     free(rgb_buffer);  
  258.     free(yuv_buffer);  
  259. }  
  260.   
  261. static void init_mmap(void)  
  262. {  
  263.     struct v4l2_requestbuffers req;  
  264.     struct v4l2_buffer buf;  
  265.   
  266.     //VIDIOC_REQBUFS  
  267.     CLEAR(req);  
  268.     req.count = 4;  
  269.     req.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;  
  270.     req.memory = V4L2_MEMORY_MMAP;  
  271.     if(-1 == xioctl(fd1, VIDIOC_REQBUFS, &req))   
  272.     {  
  273.         if (EINVAL == errno)   
  274.         {  
  275.             fprintf(stderr, "%s does not support ""memory mapping\n", dev_name1);  
  276.             exit(EXIT_FAILURE);  
  277.         }   
  278.         else  
  279.             errno_exit("VIDIOC_REQBUFS");  
  280.     }  
  281.     if(req.count < 2)   
  282.     {  
  283.             fprintf(stderr, "Insufficient buffer memory on %s\n",dev_name1);  
  284.             exit(EXIT_FAILURE);  
  285.     }  
  286.   
  287.     //VIDIOC_QUERYBUF  
  288.     buffers = calloc(req.count, sizeof(*buffers));  
  289.     if (!buffers)   
  290.     {  
  291.             fprintf(stderr, "Out of memory\n");  
  292.             exit(EXIT_FAILURE);  
  293.     }  
  294.     for (n_buffers = 0; n_buffers < req.count; ++n_buffers)   
  295.     {          
  296.         CLEAR(buf);  
  297.         buf.type        = V4L2_BUF_TYPE_VIDEO_CAPTURE;  
  298.         buf.memory      = V4L2_MEMORY_MMAP;  
  299.         buf.index       = n_buffers;  
  300.         if (-1 == xioctl(fd1, VIDIOC_QUERYBUF, &buf))  
  301.             errno_exit("VIDIOC_QUERYBUF");  
  302.         buffers[n_buffers].length = buf.length;  
  303.         buffers[n_buffers].start =mmap(NULL /* start anywhere */,buf.length,  
  304.                                 PROT_READ | PROT_WRITE /* required */,  
  305.                                 MAP_SHARED /* recommended */,  
  306.                                 fd1, buf.m.offset);  
  307.         if (MAP_FAILED == buffers[n_buffers].start)  
  308.         {  
  309.             errno_exit("mmap");  
  310.         }  
  311.     }//now n_buffers is 4  
  312.   
  313.     //fbmmap  
  314.     fb_buffer=(char*)mmap(NULL,screensize,PROT_READ | PROT_WRITE,MAP_SHARED,fd2,0);  
  315.     if(MAP_FAILED == fb_buffer)  
  316.     {  
  317.         errno_exit("mmap");  
  318.     }  
  319.       
  320.     //malloc the yuv_buffer  
  321.     yuv_buffer = (char*)malloc(screensize);  
  322.     if (!yuv_buffer)   
  323.     {  
  324.             fprintf(stderr, "Out of memory\n");  
  325.             exit(EXIT_FAILURE);  
  326.     }  
  327.       
  328.     //malloc the rgb_buffer  
  329.     rgb_buffer = (char*)malloc(screensize);  
  330.     if (!rgb_buffer)   
  331.     {  
  332.             fprintf(stderr, "Out of memory\n");  
  333.             exit(EXIT_FAILURE);  
  334.     }     
  335. }  
  336.   
  337. static void init_device(void)  
  338. {  
  339.     struct v4l2_capability cap;  
  340.     struct v4l2_format fmt;  
  341.     struct fb_fix_screeninfo finfo;  
  342.     struct fb_var_screeninfo vinfo;  
  343.   
  344.     CLEAR(cap);  
  345.     if (-1 == xioctl(fd1, VIDIOC_QUERYCAP, &cap))  
  346.     {  
  347.         if (EINVAL == errno)   
  348.         {  
  349.             fprintf(stderr, "%s is no V4L2 device\n",dev_name1);  
  350.             exit(EXIT_FAILURE);  
  351.         }   
  352.         else   
  353.             errno_exit("VIDIOC_QUERYCAP");  
  354.     }  
  355.     if (!(cap.capabilities & V4L2_CAP_VIDEO_CAPTURE))   
  356.     {  
  357.         fprintf(stderr, "%s is no video capture device\n",dev_name1);  
  358.         exit(EXIT_FAILURE);  
  359.     }  
  360.     if (!(cap.capabilities & V4L2_CAP_STREAMING))   
  361.     {  
  362.         fprintf(stderr, "%s does not support streaming i/o\n",dev_name1);  
  363.         exit(EXIT_FAILURE);  
  364.     }  
  365.   
  366.     CLEAR(fmt);  
  367.     fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;  
  368.     if (force_format)   
  369.     {  
  370.         fmt.fmt.pix.width       = 640;  
  371.         fmt.fmt.pix.height      = 480;  
  372.         fmt.fmt.pix.pixelformat = V4L2_PIX_FMT_YUYV;  
  373.         fmt.fmt.pix.field       = V4L2_FIELD_INTERLACED;  
  374.         if (-1 == xioctl(fd1, VIDIOC_S_FMT, &fmt))  
  375.             errno_exit("VIDIOC_S_FMT");  
  376.     }   
  377.     else  
  378.     {  
  379.         if (-1 == xioctl(fd1, VIDIOC_G_FMT, &fmt))  
  380.             errno_exit("VIDIOC_G_FMT");  
  381.     }  
  382.     fprintf(stdout,"<------------camera infomation------------->\n");  
  383.     fprintf(stdout,"device driver=%s\n",cap.driver);  
  384.     fprintf(stdout,"device name=%s\n",cap.card);  
  385.     fprintf(stdout,"bus_infomation=%s\n",cap.bus_info);  
  386.     fprintf(stdout,"image_width=%d\n",fmt.fmt.pix.width);  
  387.     fprintf(stdout,"image_height=%d\n",fmt.fmt.pix.height);  
  388.     fprintf(stdout,"pixel_format=%d\n",fmt.fmt.pix.pixelformat);  
  389.     fprintf(stdout,"\n");  
  390.   
  391.   
  392.     CLEAR(finfo);  
  393.     if(-1 == xioctl(fd2,FBIOGET_FSCREENINFO,&finfo))  
  394.         errno_exit("FBIOGET_FSCREENINFO");  
  395.   
  396.     CLEAR(vinfo);  
  397.     if(-1 == xioctl(fd2,FBIOGET_VSCREENINFO,&vinfo))  
  398.         errno_exit("FBIOGET_VSCREENINFO");  
  399.     screensize = vinfo.xres*vinfo.yres*vinfo.bits_per_pixel/8;  
  400.   
  401.     fprintf(stdout,"<------------screen infomation------------->\n");  
  402.     fprintf(stdout,"id=%s\n",finfo.id);  
  403.     fprintf(stdout,"x=%d\n",vinfo.xres);  
  404.     fprintf(stdout,"y=%d\n",vinfo.yres);  
  405.     fprintf(stdout,"bpp=%d\n",vinfo.bits_per_pixel);  
  406.     fprintf(stdout,"redoffset=%d,redlength=%d,msb_right=%d\n",  
  407.             vinfo.red.offset,vinfo.red.length,vinfo.red.msb_right);  
  408.     fprintf(stdout,"greenoffset=%d,greenlength=%d,msb_right=%d\n",  
  409.             vinfo.green.offset,vinfo.green.length,vinfo.green.msb_right);  
  410.     fprintf(stdout,"blueoffset=%d,bluelength=%d,msb_right=%d\n",  
  411.             vinfo.blue.offset,vinfo.blue.length,vinfo.blue.msb_right);  
  412.     fprintf(stdout,"screensize=%d\n",screensize);  
  413.       
  414.     init_mmap();  
  415. }  
  416.   
  417. static void close_device(void)  
  418. {  
  419.     if (-1 == close(fd1))  
  420.         errno_exit("close");  
  421.     fd1 = -1;  
  422.       
  423.     if (-1 == close(fd2))  
  424.         errno_exit("close");  
  425.     fd2 = -1;  
  426. }  
  427.   
  428. static void open_device(void)  
  429. {  
  430.   
  431.     fd1 = open(dev_name1, O_RDWR /* required */ | O_NONBLOCK, 0);  
  432.     if (-1 == fd1)   
  433.     {  
  434.         fprintf(stderr, "Cannot open '%s': %d, %s\n",dev_name1, errno, strerror(errno));  
  435.         exit(EXIT_FAILURE);  
  436.     }  
  437.   
  438.     fd2 = open(dev_name2,O_RDWR,0);  
  439.     if(-1 == fd2)  
  440.     {  
  441.         fprintf(stderr, "Cannot open '%s': %d, %s\n",dev_name2, errno, strerror(errno));  
  442.         exit(EXIT_FAILURE);       
  443.     }     
  444. }  
  445.   
  446. int main(int argc, char **argv)  
  447. {  
  448.     dev_name1 = "/dev/video0";  
  449.     dev_name2 = "/dev/fb0";  
  450.   
  451.     open_device();  
  452.     init_device();  
  453.     start_capturing();  
  454.     mainloop();  
  455.     stop_capturing();  
  456.     uninit_device();  
  457.     close_device();  
  458.     fprintf(stderr, "\n");  
  459.     return 0;  
  460. }  


 

 

后记

等解决了这个问题再写吧。

    本站是提供个人知识管理的网络存储空间,所有内容均由用户发布,不代表本站观点。请注意甄别内容中的联系方式、诱导购买等信息,谨防诈骗。如发现有害或侵权内容,请点击一键举报。
    转藏 分享 献花(0

    0条评论

    发表

    请遵守用户 评论公约

    类似文章 更多