android摄像头(camera)之 v4l2的c测试代码

书史足自悦,安用勤与劬。这篇文章主要讲述android摄像头(camera)之 v4l2的c测试代码相关的知识,希望能为你提供帮助。
转自:https://blog.csdn.net/ldswfun/article/details/8745577
在移植android hal的过程中,移植的首要任务是要确保驱动完好,camera是属于字符设备,但是对于其测试代码的编写就不像一般的驱动那么简单啦,因为camera的测试代码一定是要用v4l2 api,所以接下来就是介绍我们写camera的测试代码的流程。
1,打开设备
 
[c]  view plain  copy  

  1.      
  2. static  int  open_device(char  *dev_name)   
  3. {   
  4.         assert(dev_name);    
  5.    
  6.         int  fd  =  -1;    
  7.    
  8.         fd  =  open(dev_name  ,  O_RDWR);    
  9.         if(  -1  ==  fd  )   
  10.         {   
  11.                 MYLOGD("open  %s  fail:  %s ",  dev_name,  strerror  (errno));    
  12.                 exit(EXIT_FAILURE);    
  13.         }   
  14.            
  15.         MYLOGD("the  fd  of  %s  is  %d  ",  dev_name,  fd);    
  16.         return  fd;    
  17.            
  18. }         
 
 
2,初始化camera,设置camera输出图像的格式
 
[c]  view plain  copy  
  1.   static  int  init_cam_device(int  dev_fd)   
  2. {   
  3.         int  ret  =  -1;    
  4.         int  input_index;    
  5.    
  6.         //ret  =  fimc_v4l2_querycap(dev_fd);    
  7.         //assert(ret  ==  0);    
  8.         //获取到输入源通道   
  9.         input_index  =  cam_v4l2_enuminput(dev_fd);          
  10.         assert(input_index  ==  0);    
  11.            
  12.         ret  =  cam_v4l2_s_input(dev_fd,  input_index);    
  13.         assert(ret  ==  0);    
  14.    
  15.         MYLOGD("VIDIOC_S_FMT  start...  dev_fd  =  %d ",  dev_fd);    
  16.    
  17.         ret  =  cam_v4l2_s_format(dev_fd,  IMAGE_HEIGHT,  IMAGE_WIDTH,  V4L2_PIX_FMT_YUYV);    
  18.         assert(ret  ==  0);    
  19.    
  20.         ret  =  cam_v4l2_g_fmt(dev_fd);    
  21.         assert(ret  ==  0);    
  22.                    
  23.         init_cam_mmap(dev_fd);    
  24.            
  25.         return  1;          
  26.            
  27. }   
 
 

4,向内核申请buffer,并将buffer映射mmap到引用空间
struct buffer
{
    void *start; //mmap后的地址;
    size_t length//大小;
}user_buffers[4];   //用于记录将内核buffer映射mmap到用户空间的地址和大小
//申请4个buffer
cam_v4l2_reqbuf(dev_fd, 4);
//查询申请到的buffer信息,比如每个buffer的其实位置和大小
cam_v4l2_querybuf(dev_fd, & buf, buf_index);
//将buffer映射到用户空间
user_buffers[buf_index].length = buf.length;
          user_buffers[buf_index].start = mmap(NULL   buf.length,
        PROT_READ | PROT_WRITE /* required */ ,
        MAP_SHARED /* recommended */ ,
        dev_fd, buf.m.offset);
 
注释    :   NULL:  /* start anywhere */
buf.length:  buffer在内核的地址
                          buf.m.offset:内核中的buffer大小
5,将所有的buffer全部放到循环工作队列中,集中管理
for (i = 0; i < max_buffers; ++i)
{
cam_v4l2_qbuf(dev_fd, i);
}
6,开始获取图像:
ioctl(dev_fd, VIDIOC_STREAMON, & type);
7,通过select来监控camera数据是否准备好
  FD_ZERO (& rd_set);
FD_SET (dev_fd, & rd_set);
ret = select(maxfd + 1, & rd_set, NULL, NULL, NULL);
 
if(FD_ISSET(dev_fd, & rd_set))//如果camera准备好,就可以去读数据了
read_frame(dev_fd)
8,read_frame(dev_fd)的实现:
//select仅仅是知道有数据可以读了,但是在多个buffer中,
//不知道是哪个buffer准备好了,所以将准备好的buffer出队列,从而知道buffer的编号
int index = cam_v4l2_dqbuf(dev_fd);
//将buffer中的yuv420数据转换成rgb565,
//因为lcd是没办法显示yuv的,所以需要将yuv转换成rgb565
yuyv_to_rgb(src_address, data_buf);
//将转换好的rgb565数据方到framebuffer中去显示
show_rgb565_img(data_buf, LCD_WIDTH, LCD_HEIGHT);
这个过程仅仅是将一个流程写下来了,每个函数都是封装了一次,没办法一一去写出来,
所以我会将源代码文件上传,给大家去下载。包含Android.mk
可以到这个链接下载:
http://download.csdn.net/detail/ldswfun/5208766
 
【android摄像头(camera)之 v4l2的c测试代码】同时附上一些图片让大家去理解这个过程
android摄像头(camera)之 v4l2的c测试代码

文章图片

 

    推荐阅读