Android 复习学习使用

camera2 简单总结

2022-09-26  本文已影响0人  梧叶已秋声

写在开头:本文为学习 camera2 过程中的知识点归纳总结。

1. camera2 相机体系结构

https://blog.csdn.net/u012596975/article/details/107136568

https://blog.csdn.net/u012596975/article/details/107138177
对于Camera Api v2的实现,是通过Camera Framework来完成的,而该层也有着一次不小的演变,刚开始Framework层并不是直接通过AIDL接口与Camera Service进行通信,而是通过一个JNI层来完成从Java到Native的转换,而Native部分作为客户端,保持对Service的通信。这种设计,很显然会比较臃肿,并且代码难以维护,所以之后由于AIDL接口的提出,谷歌直接将其加入到相机框架中,用于保持Framework与Service的通信,进而摈弃了JNI层,进一步减少了不必要的层级结构,保持了整个体系简洁性。

更多可参考 深入理解Android相机体系结构 系列。

2. camera1和camera2的使用简单对比

先回顾一下,camera1和camera2的简单使用。
这两篇camera1和camera2的预览demo,十分简洁,功能单一,可供对比。
Android Camera1最简单的预览框显示
Android Camera2最简单的预览框显示

下面这两张思维导图,较为详细得说明了camera的使用流程和API。这不是本篇的重点。


https://www.jianshu.com/p/f63f296a920b https://www.jianshu.com/p/f63f296a920b

camera1 的 open 简单代码流程可参考这篇:
Android Camera open 从上到下代码流程
camera2 的 open 简单代码流程可参考这篇:
Android CameraManager open 从上到下代码流程

如果需要更详细的demo,可参考官方的 demo:cameraview

camera1和camera2 的调用流程对比,可参考这张图。可以看到,API V2是没有通过JNI的api的,这里是直接调用的service。


https://source.android.google.cn/docs/core/camera

https://blog.csdn.net/u012596975/article/details/107137110

谷歌在Andorid 5.0(API Level 21)便重新对Camera进行了设计,摒弃了Camera Api v1的设计逻辑,提出了一个全新的API – camera2,引入了Session以及Request概念,将控制逻辑统一成一个视图,因此在使用上更加复杂,同时也支持了更多特性,比如逐帧控制曝光、感光度以及支持Raw格式的输出等。并且由于对控制逻辑的高度抽象化,使得该接口具有很高的灵活性,可以通过简单的操作实现30fps的全高清连拍的功能,总得来说,该接口极大地提高了对于相机框架的控制能力,同时也进一步大幅度提升了其整体性能。
camera2的应用层与framework层之间的流程如下:


https://blog.csdn.net/u012596975/article/details/107137110

简单来说就是,引入了Session以及Request,使用更加复杂,功能多,更加灵活了。

注意,虽然新增了camera2的api,camera1的代码依然在android源码中。分析的时候要注意。
frameworks/base/core/java/android/hardware/camera2/这个目录下的是camera2的framework层代码。

Camera整体架构简述


https://blog.csdn.net/TaylorPotter/article/details/105387109

忽略掉驱动层,就是这张图。


https://source.android.google.cn/docs/core/camera

了解完Android Camera工作大体流程后,来看看部分细节。

2. 源码简单分析

本篇源码分析,不会涉及驱动层及以下(最多一点点)。另由于MTK和高通camera,还有android原生的,在camera这块差异很大,流程分析查找资料的时候要注意下。

Android Camera工作大体流程:


https://blog.csdn.net/TaylorPotter/article/details/105387109

出处: https://blog.csdn.net/TaylorPotter/article/details/105387109
绿色框中是应用开发者需要做的操作,蓝色为AOSP提供的API,黄色为Native Framework Service,紫色为HAL层Service.
描述一下步骤:

简单图如下:


https://blog.csdn.net/TaylorPotter/article/details/105387109

https://blog.csdn.net/TaylorPotter/article/details/105387109
通过AIDL binder调用向Framework层的CameraServer进程下指令,从CameraServer进程中取的数据.
基本过程都如下:

着重看看以下几点

2.1 CameraService和CameraProvider服务启动

层级架构概览


https://blog.csdn.net/weixin_41678668/article/details/88620265

总体逻辑顺序计
(1) CameraProvider进程启动、注册
(2) CameraServer进程启动、注册、初始化
(3) CameraServer初始化过程中通过HIDL通信获取CameraProvider,并对 CameraProvider进行初始化

CameraService和CameraProvider初始化


https://blog.csdn.net/qq_16775897/article/details/81240600

CameraServer初始化


https://blog.csdn.net/TaylorPotter/article/details/105387109

具体代码流程可参考:
Android 8.1 Camera2架构解析(1) CameraService和CameraProvider服务启动流程
[Android O] Camera 服务启动流程简析

2.2 open

可直接参考这篇:

camera framework open流程
有道笔记上排版更好。
camera2 open流程

最后来张时序图加深下印象。


https://blog.csdn.net/TaylorPotter/article/details/105387109

2.3 configure

以下代码出自这篇Android Camera2最简单的预览框显示

/**
     * 打开相机,预览是在回调里面执行的。
     */
    private void openCamera() {
        try {
            // 4.权限检查
            if (ContextCompat.checkSelfPermission(this, Manifest.permission.CAMERA)
                    != PackageManager.PERMISSION_GRANTED) {
                requestCameraPermission();
                return;
            }

            // 5.真正打开相机
            Log.i(TAG, "openCamera");
            mCameraManager.openCamera(mCameraId, mStateCallback, null);
        } catch (CameraAccessException e) {
            Log.e(TAG, "openCamera error = " + e.getMessage());
        }

     /**
     * 相机状态监听对象
     */
    private final CameraDevice.StateCallback mStateCallback = new CameraDevice.StateCallback() {
        @Override
        public void onOpened(CameraDevice camera) {
            Log.i(TAG, "StateCallback! onOpened");
            mCameraDevice = camera; // 打开成功,保存代表相机的CameraDevice实例
            SurfaceTexture surfaceTexture = mTextureView.getSurfaceTexture();
            surfaceTexture.setDefaultBufferSize(mTextureView.getWidth(), mTextureView.getHeight());
            Surface surface = new Surface(surfaceTexture);
            ArrayList<Surface> previewList = new ArrayList<>();
            previewList.add(surface);
            try {
                // 6.将TextureView的surface传递给CameraDevice
                mCameraDevice.createCaptureSession(previewList, new CameraCaptureSession.StateCallback() {
                    @Override
                    public void onConfigured(@NonNull CameraCaptureSession session) {
                        try {
                            CaptureRequest.Builder builder = mCameraDevice.createCaptureRequest(CameraDevice.TEMPLATE_PREVIEW);
                            builder.addTarget(surface); // 必须设置才能正常预览
                            CaptureRequest captureRequest = builder.build();

                            // 7.CameraCaptureSession与CaptureRequest绑定(这是最后一步,已可显示相机预览)
                            session.setRepeatingRequest(captureRequest, mSessionCaptureCallback, null);
                        } catch (CameraAccessException e) {
                            Log.e(TAG, "createCaptureRequest error = " + e.getMessage());
                        }
                    }

                    @Override
                    public void onConfigureFailed(@NonNull CameraCaptureSession session) {
                        Log.e(TAG, "onConfigureFailed");
                    }
                }, null);
            } catch (CameraAccessException e) {
                Log.e(TAG, "createCaptureSession error = " + e.getMessage());
            }
        }


应用层在openCamera之后,会调用createCaptureSession。


image.png

createCaptureSession之后的流程可参考这篇:
camera framework configure流程分析

涉及到的主要类:
http://androidxref.com/9.0.0_r3/xref/frameworks/base/core/java/android/hardware/camera2/impl/CameraDeviceImpl.java#632

http://aosp.opersys.com/xref/android-9.0.0_r61/xref/frameworks/av/services/camera/libcameraservice/common/Camera2ClientBase.cpp

http://aosp.opersys.com/xref/android-9.0.0_r61/xref/frameworks/av/services/camera/libcameraservice/device3/Camera3Device.cpp

出处:https://blog.csdn.net/haodada1226/article/details/121719939

总结一下:

① configure为app传入的surface配置相应的stream,然后将gbp、streamid、surfaceid进行绑定,以便于发送request请求的时候去获取;
② 告诉hal层,需要从camera中获取什么样格式的buffer

简单版时序图


https://www.jianshu.com/p/26d4b781a14d

复杂版时序图


https://blog.csdn.net/TaylorPotter/article/details/105387109

2.4 request

在 Android Camera2最简单的预览框显示 这篇文的代码中可以看到,
调用createCaptureRequest之后通过build创建CaptureRequest,然后session.setRepeatingRequest,然后就可以预览了。

https://blog.csdn.net/TaylorPotter/article/details/105387109

然后接下来的流程可直接参考这篇:
camera framework request流程

涉及到的主要类如下:
http://aosp.opersys.com/xref/android-9.0.0_r61/xref/frameworks/base/core/java/android/hardware/camera2/impl/CameraCaptureSessionImpl.java#121

http://aosp.opersys.com/xref/android-9.0.0_r61/xref/frameworks/base/core/java/android/hardware/camera2/impl/CameraDeviceImpl.java#submitCaptureRequest

http://aosp.opersys.com/xref/android-9.0.0_r61/xref/frameworks/av/services/camera/libcameraservice/api2/CameraDeviceClient.cpp

http://aosp.opersys.com/xref/android-9.0.0_r61/xref/frameworks/av/services/camera/libcameraservice/device3/Camera3Device.cpp

http://aosp.opersys.com/xref/android-9.0.0_r61/xref/hardware/interfaces/camera/device/3.4/default/ExternalCameraDeviceSession.cpp#400

出处: https://blog.csdn.net/haodada1226/article/details/121848769

这里总结一下:

configure的时候为每个surface创建相应的Camera3OutputStream,然后将相应的信息保存起来(注意CameraDeviceClient中的mStreamMap、mConfiguredOutputs以及Camera3Device中的mOutputStreams等),然后告诉hal层需要配置什么格式、分辨率等的流。request中会将上述的surfaces和outputStreams填充进request请求中,然后在Camera3Device中起一个thread,一直向hal层发送request请求。

最后来张时序图


https://blog.csdn.net/TaylorPotter/article/details/105387109

3.camera中的BufferQueue

https://www.jianshu.com/p/05a8d6f5b4df
BufferQueue可以理解为一个生产者-消费者”模型,对GraphicBuffer管理的一种机制。
需注意的是,可以将BufferQueue当作是一个算法结构,并不是只有Surfaceflinger会使用到,其他进程只要有GraphicBuffer的消费地方都会使用到。

BufferQueue结构


https://www.jianshu.com/p/05a8d6f5b4df
https://www.jianshu.com/p/05a8d6f5b4df

https://www.jianshu.com/p/05a8d6f5b4df
图形生产者(如相机,View绘制等)先向BufferQueue申请GraphicBuffer,填充完GraphicBuffer后,将GraphicBuffer移交给BufferQueue,BufferQueue会通知图形消费者(如Surfaceflinger,ImageReader,GLConsumer等)
相机中preview使用到的TextureView中的成员SurfaceTexture就是个自带BufferQueue的组件。

https://www.jianshu.com/p/05a8d6f5b4df

框架流程汇总


https://www.jianshu.com/p/26d4b781a14d

参考链接:
深入理解Android相机体系结构之二
深入理解Android相机体系结构之三
深入理解Android相机体系结构之十

官方文档

Android Camera简单整理(一)-Camera Android架构(基于Q)
Android Camera简单整理(三)-Mtk Camera MtkCam3架构学习

[Android O] Camera 服务启动流程简析

CameraService启动流程
Android 8.1 Camera2架构解析(1) CameraService和CameraProvider服务启动流程
Camera service服务启动流程

BufferQueue详解 原理
Android-Fk:BufferQueue学习整理
Android Camera2 Framwork+Hal+Surface整体数据流程

Android Camera 打开预览流程分析(三)-- Camera 连接到CameraService 过程分析
camera framework configure流程分析
Camera2 API -- OutputConfiguration
camera framework configure流程分析

上一篇下一篇

猜你喜欢

热点阅读