一,V4L2驱动申请buffer

视频应用可以通过两种方式从V4L2驱动申请buffer

1. V4L2_MEMORY_USERPTR方式, 顾名思义是用户空间指针的意思,应用层负责分配需要的内存空间,然后以指针的形式传递给V4L2驱动层,V4L2驱动会把capture的内容保存到指针所指的空间

一般来说,应用层需要确保这个内存空间物理上是连续的(IPU处理单元的需求),在android系统可以通过PMEM驱动来分配大块的连续物理内存。应用层在不需要的时候要负责释放申请的PMEM内存。

2. V4L2_MEMORY_MMAP方式,内存映射模式,应用调用VIDIOC_REQBUFS ioctl分配设备buffers,参数标识需要的数目和类型。这个ioctl也可以用来改变buffers的数据以及释放分配的内存,当然

这个内存空间一般也是连续的。在应用空间能够访问这些物理地址之前,必须调用mmap函数把这些物理空间映射为用户虚拟地址空间。

  虚拟地址空间是通过munmap函数释放的; 而物理内存的释放是通过VIDIOC_REQBUFS来实现的(设置参数buf count为(0)),物理内存的释放是实现特定的,mx51 v4l2是在关闭设备时进行释放

的。所以二者都是申请连续的物理内存,只是申请和释放的方式不同

2.V4L2_MEMORY_USERPTR,qualcomm在android 4.1后使用ion方式分配内存,原来是使用pmem分配内存,先从hal层申请内存空间,然后给camera驱动用的。

二,camera的测试代码流程

1,打开设备

static int open_device(char *dev_name)

{

assert(dev_name);

int fd = -1;

fd = open(dev_name , O_RDWR);

if( -1 == fd ) {

MYLOGD("open %s fail: %s\n", dev_name, strerror (errno));

exit(EXIT_FAILURE);

}

MYLOGD("the fd of %s is %d ", dev_name, fd);

return fd;

}

2,初始化camera,设置camera输出图像的格式

static
int init_cam_device(int dev_fd)

{

int
ret = -1;

int
input_index;

//ret
= fimc_v4l2_querycap(dev_fd);

//assert(ret
== 0);

//获取到输入源通道

input_index
= cam_v4l2_enuminput(dev_fd);

assert(input_index
== 0);

ret
= cam_v4l2_s_input(dev_fd, input_index);

assert(ret
== 0);

MYLOGD("VIDIOC_S_FMT
start... dev_fd = %d\n", dev_fd);

ret
= cam_v4l2_s_format(dev_fd, IMAGE_HEIGHT, IMAGE_WIDTH,

V4L2_PIX_FMT_YUYV);

assert(ret
== 0);

ret
= cam_v4l2_g_fmt(dev_fd);

assert(ret
== 0);

init_cam_mmap(dev_fd);

return
1;

}

三,向内核申请buffer,并将buffer映射mmap到引用空间

1)数据结构

  struct
buffer{

     void *start; //mmap后的地址;

     size_t length//大小;
  }user_buffers[4];
//用于记录将内核buffer映射mmap到用户空间的地址和大小

2)申请4个buffer

  camera_v4l2_reqbuf(dev_fd,
4);

3)查询申请到的buffer信息,比如每个buffer的其实位置和大小

  camera_v4l2_querybuf(dev_fd,
&buf, buf_index);

4)将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)
  {
    camera_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 = camera_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);

四,高通buffer管理使用代码流程

一,HAL->kernel 分配buffer
mm_stream_request_buf->//Mm_camera_stream.c (8953_dual_camera\src\hardware\qcom\camera\qcamera2\stack\mm-camera-interface\src)    
    ioctl(my_obj->fd, VIDIOC_REQBUFS, &bufreq);//向kernel发送IOCTL命令,请求分配buffer
{=================kernel===================<
        v4l_reqbufs->//V4l2-ioctl.c (8953_dual_camera\src\kernel\msm-3.18\drivers\media\v4l2-core)    
                                    //ops->vidioc_reqbufs(file, fh, p)
            camera_v4l2_reqbufs->//Camera.c (camera)    
                vb2_reqbufs->//Videobuf2-core.c (\8953_dual_camera\src\kernel\msm-3.18\drivers\media\v4l2-core)    
                    __reqbufs->//
                        __vb2_queue_alloc->
                            __vb2_buf_mem_alloc->//分配video buffer
                                                                     //最后通过mmap函数将buffer映射到用户空间
 =================kernel===================>
}
二,HAL->kernel 读取一帧数据
mm_stream_read_msm_frame->//Mm_camera_stream.c (8953_dual_camera\src\hardware\qcom\camera\qcamera2\stack\mm-camera-interface\src)    
    ioctl(my_obj->fd, VIDIOC_DQBUF, &vb);//向kernel发送IOCTL命令,向kernel读取一帧数据
                                                                             //kernel流程同【一】
 
三,HAL->kernel 向kernel buffer释放一个buffer,使kernel可以填充新的视频数据
mm_stream_qbuf->//Mm_camera_stream.c (8953_dual_camera\src\hardware\qcom\camera\qcamera2\stack\mm-camera-interface\src)    
     ioctl(my_obj->fd, VIDIOC_QBUF, &buffer);//向kernel发送IOCTL命令,向kernel释放buffer,让kernel可以填充新的视频数据
                                                                                     //kernel流程同【一】

android摄像头(camera)之buffer管理的更多相关文章

  1. android摄像头(camera)之 v4l2的c测试代码【转】

    转自:https://blog.csdn.net/ldswfun/article/details/8745577 在移植android hal的过程中,移植的首要任务是要确保驱动完好,camera是属 ...

  2. Android中直播视频技术探究之---采集摄像头Camera视频源数据进行推流(采用金山云SDK)

    一.前言 在之前已经详细介绍了Android中的一种视频数据源:Camera,不了解的同学可以点击进入:Android中Camera使用详解 ,在这篇文章中我们介绍了如何采集摄像头的每一帧数据,然后进 ...

  3. Android中直播视频技术探究之---摄像头Camera视频源数据采集解析

    一.前言 在视频直播中一般都是两种视频数据源,一个是摄像头数据,一个是录制桌面数据,而一般来说美女妹子直播都是来自于摄像头数据,游戏直播都是录制桌面数据的,那么今天就来看看第一个数据源数据采集分析,A ...

  4. 介绍 Android 的 Camera 框架

    总体介绍 Android Camera 框架从整体上看是一个 client/service 的架构,有两个进程:一个是 client 进 程,可以看成是 AP 端,主要包括 JAVA 代码与一些 na ...

  5. Android 开发 Camera类的拍照与录像

    前言 在开发Android应用的时候,如果需要调用摄像头拍照或者录像,除了通过Intent调用系统现有相机应用进行拍照录像之外,还可以通过直接调用Camera硬件去去获取摄像头进行拍照录像的操作.本篇 ...

  6. 【Android】Camera 使用浅析

    Camera的简单使用浅析 由于最近工作上用到android.hardware.Camera这个类,于是简单的学习了一些基本用法. 首先注意:Camera这个类在API21以后就不推荐使用了,官方提供 ...

  7. android中Camera setDisplayOrientation使用

    在写相机相关应用的时候遇到捕获的画面方向和手机的方向不一致的问题,比如手机是竖着拿的,但是画面是横的,这是由于摄像头默认捕获的画面byte[]是根据横向来的,而你的应用是竖向的,解决办法是调用setD ...

  8. Android之Camera控制拍照

    package com.android.xiong.cameratest; import java.io.File; import java.io.FileOutputStream; import j ...

  9. Android摄像头:只拍摄SurfaceView预览界面特定区域内容(矩形框)---完整(原理:底层SurfaceView+上层绘制ImageView)

    Android摄像头:只拍摄SurfaceView预览界面特定区域内容(矩形框)---完整实现(原理:底层SurfaceView+上层绘制ImageView) 分类: Android开发 Androi ...

随机推荐

  1. 【小白的CFD之旅】01 引子

    小白的CFD之旅 写在前面 CFD是计算流体力学的英文简称,是计算机辅助工程(CAE)的主要分支,目前广泛应用与科学研究.工程设计中.这是一门综合了数学.计算机及流体力学的综合学科,涉及到众多的专业理 ...

  2. CSS3使用AnimationEnd为同一个元素添加多个动画效果

    <!DOCTYPE HTML> <html> <head> <meta charset="utf-8"> <meta name ...

  3. 冲刺阶段 day 9

    项目进展 昨天终于完成了教师部分的内容,今天我们又重新开始对之前系部设置不能实现的内容进行了编写,之前缺少删除和查询也做了补充,在与数据库的连接上也做了修改和更新. 存在问题 由于是之前遇到困难没做完 ...

  4. Button未设type属性时在非IE6/7中具有submit特性

    代码如下 <!DOCTYPE html> <html> <head> <title>Button在Form中具有submit的特性</title& ...

  5. discuz插件开发新手入门 超详细

    作为一个新手,目前也是刚刚玩转discuz的插件功能,好东西不敢独享,就拿出来大家一起分享入门的过程.现在网上很多关于discuz的插件教程都是很简单的教程,原因可能是这个东西是商业化的东西,本着分享 ...

  6. [原创] zabbix学习之旅一:源码安装

    zabbix是一个基于WEB界面的提供分布式系统监视以及网络监视功能的企业级的开源解决方案.zabbix能监视各种网络参数,保证服务器系统的安全运营:并提供灵活的通知机制以让系统管理员快速定位/解决存 ...

  7. android 下载instagram动态中图片的demo

    最近迷上了刷instagram,里面的很多照片都特别喜欢,于是就想分享到朋友圈或者微博,奈何墙外不知墙内苦啊.于是只能想办法将它们保存到本地,既可以做壁纸也能分享给别人. 我发现每条ins的动态在ap ...

  8. 七天学会 SALT STACK 自动化运维 (1)

    七天学会 SALT STACK 自动化运维 (1) 简单理解 SALTSTACK 安装与配置 基本的使用方法 结束语 引用资源 简单理解 SALT STACK 笔者是初次接触 自动化运维 这一技术领域 ...

  9. android webview点击返回键返回上一级activity

    android webview点击返回键返回上一个activity @Override public boolean onKeyDown(int keyCode, KeyEvent event) { ...

  10. ES6 Promise 用法讲解

    Promise是一个构造函数,自己身上有all.reject.resolve这几个眼熟的方法,原型上有then.catch等同样很眼熟的方法. 那就new一个 var p = new Promise( ...