​​三 Android Camer2 Pipeline总结... 5​​

​​3.1 Pipeline架构... 5​​

​​3.2 关键组件... 6​​

​​四 Android Camer2 相机开发流程总结... 8​​

​​4.1 开发流程综述... 8​​

​​4.2 Camera2消息流转... 8​​

​​4.3 开关相机流程及API调用... 9​​

​​4.4 SurfaceView与TextView.. 11​​

​​五 BasicCaptureDemo设计优化... 13​​

​​5.1 优化目标... 13​​

​​5.2 优化效果展示... 13​​

​​5.3 界面布局调整... 18​​

​​5.4 APP主入口... 19​​

​​5.5 主流程设计... 19​​

​​5.5 AutoFitTextureView设计... 20​​

​​5.6 Camera2BasicFragment设计... 20​​

​​六 Android LogCat采集日志... 22​​

​​6.1 Log API及等级... 22​​

​​6.2 LogCat打开方式... 22​​

​​6.3 LogCat使用... 23​​

​​6.4 LogCat常用命令汇总... 24​​

​​七 Android HAL总结... 25​​

​​7.1 HAL结构... 25​​

​​7.2 HAL Android引入HAL. 25​​

​​八 Android Camera架构总结... 27​​

​​8.1 概述... 27​​

​​8.2 层次解析... 27​​

​​8.3 Android Camera Request概念解析... 28​​

​​8.4 Android Camera Request流程... 28​​

​​8.5 request在HAL的处理方式... 29​​

三 Android Camer2 Pipeline总结

3.1 Pipeline架构

从 Android 5.0 开始,Google 引入了一套全新的相机框架 Camera2(android.hardware.camera2)并且废弃了旧的相机框架 Camera1(android.hardware.Camera), Camera2 的出现给相机应用程序带来了巨大的变革,因为它的目的是为了给应用层提供更多的相机控制权限,从而构建出更高质量的相机应用程序。Android设备和Camera设备是通过管道pipeline的概念将两者进行串联的,pipeline即一套camera处理流程,可抽象为一个CaptureRequestSession,在一个CaptureRequestSession过程中由Android系统发送CaptureRequest,Camera返回元数据MetaData进行来回交互,预览和拍照等数据的传递是通过Surface进行,其架构如下所示:

正在上传…重新上传取消

处理流程总结如下:

  1. 应用程序构建一个包含capture具体属性集的请求CaptureRequest,并将用于保存拍照结果数据的内存区域Surface加入到CaptureRequest中;
  2. CaptureRequest会在capture会话CameraCaptureSession中被加入拍照设备CameraDevice的请求队列Pending Request Queue中,等待Camera处理;
  3. In-Flight Capture Queue是Camera的工作队列,当此队列空闲时,Android系统就会将拍照请求加入其中,等待capture执行;
  4. capture完成后,其处理结果会以回调函数形式在CameraCaptureSession通知到应用程序处理,拍照数据会根据配置输出到Surface或ImageReader。

3.2 关键组件

  1. Capture

相机的所有操作和参数配置最终都是服务于图像捕获,因此Camera2 中相机所有操作和参数配置都被抽象成Capture(捕获),其更像是一个相机类,可配置参数,完成拍照,调节曝光补偿,对焦等行为。Capture 从执行方式上可总结如下模式:

模式

英文术语

含义描述

单次模式

One-shot

只执行一次的 Capture 操作,例如设置闪光灯模式、对焦模式和拍一张照片等,多个一次性模式的 Capture 会进入队列按顺序执行。

多次模式

Burst

连续多次执行指定的 Capture 操作,在此模式执行期间不允许插入其他任何 Capture 操作,例如连续拍摄 100 张照片,在拍摄这 100 张照片期间任何新的 Capture 请求都会排队等待,直到拍完 100 张照片。多组多次模式的 Capture 会进入队列按顺序执行。

重复模式

Repeating

不断重复执行指定的 Capture 操作,但当有其他模式的 Capture 提交时会暂停该模式,转而执行其他被模式的 Capture,当其他模式的 Capture 执行完毕后又会自动恢复继续执行该模式的 Capture。

  1. CameraManager

CameraManager是一个用于检测、连接和描述相机设备的系统服务,负责管理所有的CameraDevice相机设备。可以通过调用Context.getSystemService(java.lang.String)方法来获取一个CameraManager的实例,其关键功能:

  1. 将相机信息封装到 CameraCharacteristics 中,并提获取 CameraCharacteristics 实例的方式;
  2. 根据指定的相机 ID 连接相机设备;
  3. 提供将闪光灯设置成手电筒模式的快捷方式。
  4. CameraCharacteristics

CameraCharacteristics 是描述相机设备的属性类,包含大量的相机信息,其继承了CameraMetadata 类。CameraCharacteristic常用属性包括如下所示:

属性

英文术语

曝光补偿

Exposure compensation

自动曝光/自动对焦/自动白平衡模式

AE / AF / AWB mode

自动曝光/自动白平衡锁

AE / AWB lock

自动对焦触发器

AF trigger

拍摄前自动曝光触发器

Precapture AE trigger

测量区域

Metering regions

闪光灯触发器

Flash trigger

曝光时间

Exposure time

感光度

ISO Sensitivity

帧间隔

Frame duration

镜头对焦距离

Lens focus distance

色彩校正矩阵

Color correction matrix

JPEG 元数据

JPEG metadata

色调映射曲线

Tonemap curve

裁剪区域

Crop region

目标 FPS 范围

Target FPS range

拍摄意图

Capture intent

硬件视频防抖

Video stabilization

  1. CameraDevice

CameraDevice 代表当前连接的相机设备,相当于pipeline的终端,它的职责有以下四个:

  1. 根据指定的参数创建CameraCaptureSession;
  2. 根据指定的模板创建CaptureRequest;
  3. 关闭相机设备;
  4. 监听相机设备的状态,例如断开连接、开启成功和开启失败等。

CameraDevice 的功能则十分的单一,就是只负责建立相机连接的事务,而更加细化的相机操作则交给CameraCaptureSession。

  1. CameraCaptureSession

CameraCaptureSession 实际上就是配置了目标 Surface 的 Pipeline 实例,一个 CameraDevice 一次只能开启一个 CameraCaptureSession,绝大部分的相机操作都是通过向 CameraCaptureSession 提交一个 Capture 请求实现的,例如拍照、连拍、设置闪光灯模式、触摸对焦、显示预览画面等。

  1. Surface

Surface 是一块用于填充图像数据的内存空间,例如APP可以使用 SurfaceView 的 Surface 接收每一帧预览数据用于显示预览画面,也可以使用 ImageReader 的 Surface 接收 JPEG 或 YUV 数据。每一个 Surface 都可以有自己的尺寸和数据格式,应用程序从 CameraCharacteristics 获取某一个数据格式支持的尺寸列表。

  1. CaptureRequest

CaptureRequest 是向 CameraCaptureSession 提交 Capture 请求时的信息载体,其内部包括了本次 Capture 的参数配置和接收图像数据的 Surface。CaptureRequest 可以配置的信息非常多,包括图像格式、图像分辨率、传感器控制、闪光灯控制、3A 控制等等,可以说绝大部分的相机参数都是通过 CaptureRequest 配置的。

注意:每一个 CaptureRequest 表示一帧画面的操作,这表示可以精确控制每一帧的 Capture 操作。

  1. CaptureResult

CaptureResult 是每一次 Capture 操作的结果,里面包括了很多状态信息,包括闪光灯状态、对焦状态、时间戳等等。例如应用程序可以在拍照完成的时候,通过 CaptureResult 获取本次拍照时的对焦状态和时间戳信息等。

注意: CaptureResult 并不包含任何图像数据。

四 Android Camer2 相机开发流程总结

4.1 开发流程综述

1.检测并访问相机资源:检查手机是否存在相机资源,如果存在则请求访问相机资源。

2.创建预览界面:创建继承自SurfaceView并实现SurfaceHolder接口的拍摄预览类。有了拍摄预览类,即可创建一个布局文件,将预览画面与设计好的用户界面控件融合在一起,实时显示相机的预览图像。

3.设置拍照监听器:给用户界面控件绑定监听器,使其能响应用户操作, 开始拍照过程。

4.拍照并保存文件:将拍摄获得的图像转换成位图文件,最终输出保存成各种常用格式的图片。

5.释放相机资源:相机是一个共享资源,当相机使用完毕后,必须正确地将其释放,以免其它程序访问使用时发生冲突。

4.2 Camera2消息流转

正在上传…重新上传取消

  1. 由SystemService创建CameraManager;
  2. 整个camera2由CameraManager来进行统一管理;
  3. CameraManager通过CameraDevice、CameraCharacteristic和CameraCaptureSession对Camera进行操作;
  4. CameraDevice和CameraCaptureSession都有回调函数完成相关操作,包括相机打开,capture过程处理,capture完成处理等。
  5. Android设备发送CameraCaptureRequest给Camera,而Camera处理完后发送元数据CameraMetaData给Android设备。

4.3 开关相机流程及API调用

1. 创建相机项目

使用Android Studio创建Blank Activity的android项目

2. 注册相关权限

使用相API 之前,必须在 AndroidManifest.xml 注册相机权限 android.permission.CAMERA,此外如果APP有保存照片的需求,则读写 SD 卡的权限也是必要的,常用权限如下所示:

<uses-permission android:name="android.permission.CAMERA" />

<uses-feature android:name="android.hardware.camera" />

<uses-feature android:name="android.hardware.camera.autofocus" />

<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>

<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/>

Android6.0 以上的系统需要APP在运行的时候进行动态权限申请,因此可设计checkPermissions在相机打开时检查相关权限:

List<String> requiredPermissions = Arrays.asList(Manifest.permission.CAMERA, Manifest.permission.WRITE_EXTERNAL_STORAGE);

private void checkPermissions() {

    List<String> unGrantedPermissions = new ArrayList<>();

    for (String permission : requiredPermissions) {

        if (PackageManager.PERMISSION_GRANTED != checkSelfPermission(permission)) {

            unGrantedPermissions.add(permission);

        }

    }

    if (unGrantedPermissions.size() != 0) {

        requestPermissions(unGrantedPermissions.toArray(new String[unGrantedPermissions.size()]), 0);

}

  1. 获取 CameraManager 实例

CameraManager是一个负责查询和建立相机连接的系统服务,可以说 CameraManager是Camera2使用流程的起点,所以APP要通过 getSystemService() 获取 CameraManager 实例,如下所示:

CameraManager cameraManager = (CameraManager)getSystemService(Context.CAMERA_SERVICE);

  1. 获取相机 ID 列表

使用的API 是CameraManager.getCameraIdList(),它会返回一个包含所有可用相机ID的字符串数组,如下所示:

try {

    String[] cameraLis= cameraManager.getCameraIdList();

} catch (CameraAccessException e) {

    e.printStackTrace();

}

  1. 根据相机 ID 获取 CameraCharacteristics

CameraCharacteristics 是相机属性的信息库,通过它APP可以获取所有相机信息,涉及的 API 是CameraManager.getCameraCharacteristics(),它会根据你指定的相机 ID 返回对应的相机信息,如下所示:

String[] cameraIdList;

try {

    cameraIdList= cameraManager.getCameraIdList();

    CameraCharacteristics characteristics;

    for (String cameraId :cameraIdList) {

        characteristics = cameraManager.getCameraCharacteristics(cameraId);

        int facing = characteristics.get(CameraCharacteristics.LENS_FACING);

        int level = characteristics.get(CameraCharacteristics.INFO_SUPPORTED_HARDWARE_LEVEL);

        Log.e(TAG, "facing = " + facing + ", level = " + level);

    }

} catch (CameraAccessException e) {

    e.printStackTrace();

}

  1. 开启相机

开启相机调用CameraManager.openCamera(),该方法要求我们传递两个参数,相机 ID和监听相机状态的回调函数 CameraStateCallback。当相机被成功开启的时候会通过回调函数CameraStateCallback.onOpened() 方法回调一个 CameraDevice 实例,否则的话会通过 CameraStateCallback.onError() 方法回调一个 CameraDevice 实例和一个错误码,其API用例如下所示:

private String getBackCameraId(CameraManager cameraManager) {

   try {

        String[] cameraIdList = cameraManager.getCameraIdList();

        CameraCharacteristics characteristics;

        for (String cameraId : cameraIdList) {

            characteristics = cameraManager.getCameraCharacteristics(cameraId);

            int facing = characteristics.get(CameraCharacteristics.LENS_FACING);

            if (CameraCharacteristics.LENS_FACING_BACK == facing) {

                return cameraId;

            }

        }

    } catch (CameraAccessException e) {

        e.printStackTrace();

    }

    return null;

}

private void openCamera(CameraManager cameraManager, String cameraId) {

    if (checkSelfPermission(Manifest.permission.CAMERA) != PackageManager.PERMISSION_GRANTED) {

        return;

    }

    try {

        cameraManager.openCamera(cameraId, callback, null);

    } catch (CameraAccessException e) {

        e.printStackTrace();

    }

}

private CameraDevice.StateCallback callback = new CameraDevice.StateCallback() {

    @Override

    public void onOpened(@NonNull CameraDevice camera) {

        Toast.makeText(MainActivity.this, "相机已开启", Toast.LENGTH_LONG).show();

    }

    @Override

    public void onDisconnected(@NonNull CameraDevice camera) {

    }

    @Override

    public void onError(@NonNull CameraDevice camera, int error) {

        camera.close();

    }

};

  1. 关闭相机

关闭相机至关重要,其API是CameraDevice.close(),当相机被完全关闭的时候会通过 CameraStateCallback.onCllosed() 方法通知APP已经被关闭。关闭相机除了上述onError外还应该在 onPause() 的时候关闭相机,因为此时Activity已经不是用户关注的焦点,通常需要关闭相机,其API调用如下:

@Override

protected void onPause() {

    super.onPause();

    if (cameraDevice != null) {

        cameraDevice.close();

    }

}

4.4 SurfaceView与TextView

1.区别

(1)SurfaceView是一个有自己Surface的View。界面渲染可以放在单独线程而不是主线程中。它更像是一个Window,自身不能做变形和动画。

(2)TextureView同样也有自己的Surface。但是它只能在拥有硬件加速层的Window中绘制,它更像是一个普通View,可以做变形和动画。

2.应用场景

正在上传…重新上传取消

五 BasicCaptureDemo设计优化

5.1 优化目标

1.UI界面优化,包括定制APP图片,拍照显示界面等;

2.实现连续多张照片拍摄,之前demo出现拍照连续拍照崩溃现象;

3.合理适配预览比例,为了避免照片失真(照片被拉长或者压扁),需要保证预览的长宽比例、照片的长宽比例和相机输出格式的长宽比例三者保持一致,之前demo没有做该功能;

4.矫正图像数据方向,Android设备的屏幕方向,与摄像头的原始方向并不一致,需要做方向转换。一般而言,当Android设备横着放时,与摄像头的方向是一致的,之前demo没有做该功能;

5.代码结构优化与调整,参考google camera2程序对原代码结构做调整与优化。

5.2 优化效果展示

1.APP UI

正在上传…重新上传取消

2.拍照界面

正在上传…重新上传取消

3.拍照效果

(1)竖屏拍照

正在上传…重新上传取消

(2)横屏拍照

正在上传…重新上传取消

(3)拍照结果存盘

正在上传…重新上传取消

5.3 界面布局调整

1.activity_main.xml使用FrameLayout;

2. FrameLayout内嵌RelativeLayout;

3. RelativeLayout内嵌AutoFitTextureView和FrameLayout,AutoFitTextureView用于相机预览数据;

4. FrameLayout内嵌Button和ImageButton,Button用于拍照按钮,ImageButton是提升按钮。

效果如下所示:

正在上传…重新上传取消

5.4 APP主入口

MainActivity在onCreate方法中装载UI框架

正在上传…重新上传取消

5.5 主流程设计

MainActivity在onCreate方法中装载UI框

正在上传…重新上传取消

整个代码流程用一个activity承载一个fragment,所有的代码都写在fragment里面,重写了fragment的生命周期函数:

1.onCreateView:加载fragment的布局文件;

2.onViewCreated:实例化布局控件;

3.onActivityCreated:在SD卡的目录下建立jpg文件等待待将拍到的照片写进去;

4.onResume:开始照相机线程,执行一些逻辑判断;

5.onPause:关闭照相机,停止照相机线程。

5.5 AutoFitTextureView设计

public class AutoFitTextureView extends TextureView {

         // 设置预览的宽度和高度

    // width:预览宽度

    // height:预览高度

public void setAspectRatio(int width, int height);

// 根据预览尺寸调节TextView的尺寸

// 预览尺寸的高宽比和TextView的高宽比一致

 @Override

 protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec);

}

AutoFitTextureView是保存预览数据,核心方法是onMeasure,即它可根据预览尺寸动态调整TextView的尺寸,使得预览尺寸高/宽比与TextView尺寸高/宽比一致。

5.6 Camera2BasicFragment设计

Camera2BasicFragment利用camer2 pipeline将capture过程组合在一起,使用mState

public class Camera2BasicFragment extends Fragment implements View.OnClickListener, ActivityCompat.OnRequestPermissionsResultCallback  {

         …

}

1.主流程:

(1)由于camera是共享资源,使用信号量作为锁机制,对多个activity的onPause事件进行加锁处理;

(2)使用全局状态state表示capture状态,根据CaptureResult状态进行相应的动作,包括拍照,预拍照;

2.关键属性和方法

(1)TextureView.SurfaceTextureListener mSurfaceTextureListener

TextView回调函数,当TextView可用时,打开Camera,当预览尺寸发生变化,重新调整TextView尺寸

(2)CameraDevice.StateCallback mStateCallback

当CameraDevice打开时,该回调函数中可获取相机及相机状态。在onOpen方法中获取相机和创建预览会话,在onError中关闭相机,如下所示:

正在上传…重新上传取消

(3)ImageReader.OnImageAvailableListener mOnImageAvailableListener

ImageReader回调函数,当ImageReader获取相机拍照数据,即在onImageAvailable方法中,让后台线程保存图片数据,如下所示:

正在上传…重新上传取消

(4)CameraCaptureSession.CaptureCallback mCaptureCallback

CameraCaptureSession回调函数,提供onCaptureProgressed用于capture处理和onCaptureCompleted用于capture善后处理,如下所示:

正在上传…重新上传取消

prorcess类似状态机处理,它根据capture状态mState进行状态切换

附源码:

正在上传…重新上传取消

六 Android LogCat采集日志

6.1 Log API及等级

Android Log定义在android.util.Log,常用的方法及等级如下:

1.Log.v:v代表Verbose日志的详细信息,对应的log等级为VERVOSE。采用该等级的log,任何消息都会输出;

2.Log.d:这里的d表示调试,对应的log等级为DEBUG。采用该等级的log,除了VERBOSE级别的log外,其余4个等级的log都会被输出。

3.Log.i:i代表information,为信息日志,对应的log等级为INFO。采用该等级的log,不会输出VERBOSE和DEBUG信息,只会输出其余3个等级的信息。

4.Log.w:w代表warning警告信息,一般用于系统提示开发者需要优化android代码等场景,对应的等级为WARN。该级别log,只会输出WARN和ERROR的信息。

5.Log.e:e代表error错误信息,一般用于输出异常和报错信息。该级别的log,只会输出该级别信息。一般Android系统在输出crash等致命信息的时候,都会采用该级别的log。

6.2 LogCat打开方式

1.方法一:使用Android Studio的LogCat

正在上传…重新上传取消

2.方法二:使用cmd命令行

正在上传…重新上传取消

3.方法三:使用android studio的Terminal

正在上传…重新上传取消

6.3 LogCat使用

1.代码

(1)导入包:

import android.util.Log;

(2)定义TAG

private static final String TAG = "Camera5BasicFragment";

(3)按级别打印日志

Log.e(TAG, "OPENCAMERA");

2.使用Logcat过滤日志

(1)方法1:使用android studio日志过滤功能

正在上传…重新上传取消

如图所示,新建过滤器,然后启动设备调试后可输出日志信息。

(2)方法2:在cmd或者android studio终端输入命令

logcat -v time *:E>d:\11.txt

以上命令将错误日志重定向到11.txt文件,打开文件可查看日志信息,如下所示:

正在上传…重新上传取消

6.4 LogCat常用命令汇总

1.格式1:打印默认日志数据

adb logcat

2.格式2:需要打印日志详细时间的简单数据

adb logcat -v time

3.格式3:需要打印级别为Error的信息

adb logcat *:E

4.格式4:需要打印时间和级别是Error的信息

adb logcat -v time *:E

5.格式5:将日志保存到固定的位置,比如D:\log.txt

adb logcat -v time >D:\log.txt

七 Android HAL总结

7.1 HAL结构

硬件抽象层HAL(HardWare Abstraction Layer)在 Linux和Windows有着不同的实现方式,Windows下的HAL位于操作系统的最底层,它直接操作物理硬件设备,使用抽象接口来隔离不同硬件的具体实现,为上层的操作系统和设备驱动程序提供一个统一接口,起到对硬件抽象作用。这样更换硬件时,编写硬件的驱动只要实现符合HAL定义的标准接口就可以顺利进行硬件更换,而对上层的应用没有影响。Linux下的HAL与Windows不同,HAL层并不位于操作系统的最底层直接操作硬件,而是在操作系统内核层和驱动程序之上,是一个运行在User Space(用户空间)的服务程序。

正在上传…重新上传取消

如上图所示,HAL位于操作系统和驱动程序之上,运行在用户空间中的服务程序。其目的是为上层的应用提供一个统一的查询硬件设备的接口。有了HAL接口,就可以将硬件开发和上层的应用开发分离开,上层的应用开发不必关系具体实现是什么硬件,同样地,如果硬件厂家需要改变硬件设备,只需要按照HAL接口的规范和标准提供对应的硬件驱动,而不必更改应用,HAL层并不提供对硬件的实际操作,对硬件的实际操作仍然由具体的驱动程序来完成。

7.2 HAL Android引入HAL

  1. 引入原因

Linux HAL能够屏蔽底层硬件差异,为应用层提供访问硬件统一接口,除此之外,Android引入HAL另一个重要的原因就是为了保障在Android 平台基于Linux开发的硬件驱动和应用程序不必遵循GPL(General Public License)许可而保持封闭,保证硬件厂家的利益。

  1. Android中HAL的运行机制

Android源码中已经实现了一部分的HAL,包括Wi-Fi、GPS、RIL、Sensor等。老式的HAL结构,采用直接调用so动态链接库方式,新式HAL结构,采用Stub代理方式调用,如下所示:

正在上传…重新上传取消

在老式的HAL结构中,应用通过so动态链接库调用而达到对硬件驱动的访问。在so动态链接库中,实现了对驱动的访问逻辑处理。新式HAL结构采用Stub的代理模式,Stub虽然仍是以*.so的形式存在,但是HAL已经将动态链接库的具体实现隐藏了起来。Stub向HAL提供operations方法,Runtime通过对Stub提供的so获取它的operations方法,并告知Runtime的callback方法。这样,Runtime和Stub都有对方调用的方法,一个应用的请求通过Runtime调用Stub的operations方法,而Stub响应operations方法并完成后,再调用Runtime的callback方法进行返回。

  1. 源码目录

(1)/hardware/libhardware_legacy/:旧的架构、采取链接库模块的方式;

(2)/hardware/libhardware:HAL stub;

(3)/hardware/ril:无线电抽象层

除此之外是硬件厂商相关的hal目录。

  1. 调用过程

(1)概述:android frameworks中JNI调用hardware.c中定义的hw_get_module函数来获取硬件模块,然后调用硬件模块中的方法,硬件模块中的方法直接调用内核接口完成相关功能。

(2)hw_get_module函数原型:

int hw_get_module(const char *id, const struct hw_module_t **module);

参数id为模块标识,定义在/hardware/libhardware/include/hardware录下的硬件模块头文件中

参数module是硬件模块地址,定义在/hardware/libhardware/include/hardware/hardware.h中

八 Android Camera架构总结

8.1 概述

正在上传…重新上传取消

Android Camera整体框架主要包括三个进程:app进程、camera server进程、hal进程(provider进程)。进程之间的通信都是通过IPC binder实现,其中app和camera server通信使用 AIDL(Android Interface Definition Language) ,camera server和hal(provider进程)通信使用HIDL(HAL interface definition language) 。

8.2 层次解析

1. Application framework

这一层是用于给APP提供访问hardware的Camera API2,通过IPC binder来访问camera service。有两个主要的类:

(1)CameraManager:一个独一无二地用于检测、连接和描述相机设备的系统服务,负责管理所有的CameraDevice相机设备。通过ICameraService调用到CameraService。

(2)CameraDevice:单个相机的抽象表示,通过ICameraDeviceUser调用到CameraDeviceClient。

2. Native framework:代码路径位于:frameworks/av/camera/。提供了ICameraService、ICameraDeviceUser、ICameraDeviceCallbacks、ICameraServiceListener等aidl接口的实现。

(1) ICameraService 是相机服务的接口。用于请求连接、添加监听等。

(2) ICameraDeviceUser 是已打开的特定相机设备的接口。应用框架可通过它访问具体设备。

(3) ICameraServiceListener 和 ICameraDeviceCallbacks 分别是从 CameraService 和 CameraDevice 到应用框架的回调。

3.HAL

Google的HAL定义了可以让Camera Service访问的标准接口。有关这些接口的具体实现则交由硬件厂商,代码路径:/hardware/interfaces/camera。

8.3 Android Camera Request概念解析

1. request特征

应用框架是通过向camera子系统发送request来获取其想要的result,其特征如下:

(1)一个request可以对应一系列的result;

(2)request应当包含所有必要的配置信息,存放于metadata中。如:分辨率和像素格式;sensor、镜头、闪光等的控制信息;3A 操作模式;RAW 到 YUV 处理控件;以及统计信息的生成等;

(3)request需要携带对应的surface(也就是框架里面的stream),用于接收返回的图像;

(4)多个request可以同时处于in-flight状态,并且submit request是non-blocking方式的。也就是说,上一个request没有处理完,也可以submit新的request。但队列中request的处理总是按照FIFO的形式;

(5)snapshot的request的preview的request拥有更高的优先级。

8.4 Android Camera Request流程

正在上传…重新上传取消

1.open 流程(黑色箭头线条)

(1)CameraManager注册AvailabilityCallback回调,用于接收相机设备的可用性状态变更的通知。

(2)CameraManager通过调用getCameraIdList()获取到当前可用的camera id,通过getCameraCharacteristcs()函数获取到指定相机设备的特性。

(3)CameraManager调用openCamera()打开指定相机设备,并返回一个CameraDevice对象,后续通过该CameraDevice对象操控具体的相机设备。

(4)使用CameraDevice对象的createCaptureSession()创建一个session,数据请求(预览、拍照等)都是通过session进行。在创建session时,需要提供Surface作为参数,用于接收返回的图像。

2.configure stream流程(蓝色箭头线条)

(1)申请Surface,如上图的OUTPUT STREAMS DESTINATIONS框,用于在创建session时作为参数,接收session返回的图像。

(2)创建session后,surface会被配置成框架的stream。在框架中,stream定义了图像的size及format。

(3)每个request都需要携带target surface用于指定返回的图像是归属到哪个被configure的stream的。

3.request处理流程(橙色箭头线条)

(1)CameraDevice对象通过createCaptureRequest()来创建request,每个reqeust都需要有surface和settings(settings就是metadata,request包含的所有配置信息都是放在metadata中的)。

(2)使用session的capture()、captureBurst()、setStreamingRequest()、setStreamingBurst()等api可以将request发送到框架。

(3)预览的request,通过setStreamingRequest()、setStreamingBurst()发送,仅调用一次。将request set到repeating request list里面。只要pending request queue里面没有request,就将repeating list里面的request copy到pending queue里面。

(4)拍照的request,通过capture()、captureBurst()发送,每次需要拍照都会调用。每次触发,都会直接将request入到pending request queue里面,所以拍照的request比预览的request的优先级更高。

(5)in-progress queue代表当前正在处理的request的queue,每处理完一个,都会从pending queue里面拿出来一个新的request放到这里。

4.数据返回流程(紫色箭头线条)

硬件层面返回的数据会放到result里面返回,会通过session的capture callback回调响应。

8.5 request在HAL的处理方式

1.流程总结

(1)framework发送异步的request到hal;

(2)hal必须顺序处理request,对于每一个request都要返回timestamp(shutter,也就是帧的生成时间)、metadata、image buffers;

(3)对于request引用的每一类steam,必须按FIFO的方式返回result。比如:对于预览的stream,result id 9必须要先于result id 10返回。但是拍照的stream,当前可以只返回到result id 7,因为拍照和预览用的stream不一样;

(4)hal需要的信息都通过request携带的metadata接收,hal需要返回的信息都通过result携带的metadata返回。

2.流程分析:

正在上传…重新上传取消

1.request处理流程(黑色箭头线条)

(1)framework异步地submit request到hal,hal依次处理,并返回result;

(2)每个被submit到hal的request都必须携带stream。stream分为input stream和output stream:input stream对应的buffer是已有图像数据的buffer,hal对这些buffer进行reprocess;output stream对应的buffer是empty buffer,hal将生成的图像数据填充的这些buffer里面。

2.input stream处理流程(图像的INPUT STREAM 1)

(1)request携带input stream及input buffer到hal;

(2)hal进行reprocess,然后新的图像数据重新填充到buffer里面,返回到framework。

3.output stream处理流程(图像的OUTPUT STREAM 1…N)

(1)request携带output stream及output buffer到hal;

(2)hal经过一系列模块的的处理,将图像数据写到buffer中,返回到frameowork。