android摄像头(camera)之buffer管理
一,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管理的更多相关文章
- android摄像头(camera)之 v4l2的c测试代码【转】
转自:https://blog.csdn.net/ldswfun/article/details/8745577 在移植android hal的过程中,移植的首要任务是要确保驱动完好,camera是属 ...
- Android中直播视频技术探究之---采集摄像头Camera视频源数据进行推流(采用金山云SDK)
一.前言 在之前已经详细介绍了Android中的一种视频数据源:Camera,不了解的同学可以点击进入:Android中Camera使用详解 ,在这篇文章中我们介绍了如何采集摄像头的每一帧数据,然后进 ...
- Android中直播视频技术探究之---摄像头Camera视频源数据采集解析
一.前言 在视频直播中一般都是两种视频数据源,一个是摄像头数据,一个是录制桌面数据,而一般来说美女妹子直播都是来自于摄像头数据,游戏直播都是录制桌面数据的,那么今天就来看看第一个数据源数据采集分析,A ...
- 介绍 Android 的 Camera 框架
总体介绍 Android Camera 框架从整体上看是一个 client/service 的架构,有两个进程:一个是 client 进 程,可以看成是 AP 端,主要包括 JAVA 代码与一些 na ...
- Android 开发 Camera类的拍照与录像
前言 在开发Android应用的时候,如果需要调用摄像头拍照或者录像,除了通过Intent调用系统现有相机应用进行拍照录像之外,还可以通过直接调用Camera硬件去去获取摄像头进行拍照录像的操作.本篇 ...
- 【Android】Camera 使用浅析
Camera的简单使用浅析 由于最近工作上用到android.hardware.Camera这个类,于是简单的学习了一些基本用法. 首先注意:Camera这个类在API21以后就不推荐使用了,官方提供 ...
- android中Camera setDisplayOrientation使用
在写相机相关应用的时候遇到捕获的画面方向和手机的方向不一致的问题,比如手机是竖着拿的,但是画面是横的,这是由于摄像头默认捕获的画面byte[]是根据横向来的,而你的应用是竖向的,解决办法是调用setD ...
- Android之Camera控制拍照
package com.android.xiong.cameratest; import java.io.File; import java.io.FileOutputStream; import j ...
- Android摄像头:只拍摄SurfaceView预览界面特定区域内容(矩形框)---完整(原理:底层SurfaceView+上层绘制ImageView)
Android摄像头:只拍摄SurfaceView预览界面特定区域内容(矩形框)---完整实现(原理:底层SurfaceView+上层绘制ImageView) 分类: Android开发 Androi ...
随机推荐
- Spring Boot 揭秘与实战(六) 消息队列篇 - RabbitMQ
文章目录 1. 什么是 RabitMQ 2. Spring Boot 整合 RabbitMQ 3. 实战演练4. 源代码 3.1. 一个简单的实战开始 3.1.1. Configuration 3.1 ...
- JAVA小程序-----买衣服
import java.util.Scanner; //引用扫描器 public class TestDemo1 { public static void main(String [] args){ ...
- 内置变量WEBGL
gl_FragCoord是片元着色器中的只读变量,它保存了片元相对窗口的坐标位置:x, y, z, 1/w.这个值是顶点处理产生片元后固定功能内插图元的结果.组件z是用于表示片元深度的深度值. gl_ ...
- Java 构造器Constructor 继承
Java默认构造方法 构造方法作用:初始化所定义的类的对象和属性. 构造方法没有返回类型. 2 继承中的构造器 子类是不继承父类的构造器(构造方法或者构造函数)的,它只是调用(隐式或显式). 如果父类 ...
- pytorch实现rnn并且对mnist进行分类
1.RNN简介 rnn,相比很多人都已经听腻,但是真正用代码操练起来,其中还是有很多细节值得琢磨. 虽然大家都在说,我还是要强调一次,rnn实际上是处理的是序列问题,与之形成对比的是cnn,cnn不能 ...
- Unity跳转场景进度条制作教程(异步加载)
Unity跳转场景进度条制作 本文提供全流程,中文翻译. Chinar 坚持将简单的生活方式,带给世人!(拥有更好的阅读体验 -- 高分辨率用户请根据需求调整网页缩放比例) Chinar -- 心分享 ...
- annotation注释简单介绍
元数据的作用 如果要对于元数据的作用进行分类,目前还没有明确的定义,不过我们可以根据它所起的作用,大致可分为三类: l 编写文档:通过代码里标识的元数据生成文档. l ...
- apache 和 php 整合、apache配制虚拟机
如何 把apache 和 php 整合起来 ? (关闭防火墙或在防火墙内添加80端口,关闭selinux) 修改:apache的配制文件:/usr/local/apache2.4/conf/h ...
- 更换JDK版本时的问题:Error: could not open `C:\Java\jre7\lib\amd64\jvm.cfg'
1.先把oracle自带的weblogic给卸载了,然后打开eclipse,发现报错了:Error: could not open `C:\Java\jre7\lib\amd64\jvm.cfg' J ...
- C++学习(二十)(C语言部分)之 函数1
函数 printf 输出的函数 scanf 输入的函数函数是什么 怎么写 是一组一起执行一个任务的语句 一个程序的基本组成单位是函数 只需要知道函数名字和括号里面要填的内容 就可以调用函数 1.如果代 ...