Part1: Camera1(Android的傻瓜机)
- Camera1 的开发中,打开相机,设置参数的过程是同步的,就跟用户实际使用camera的操作步骤一样。但是如果有耗时情况发生时,会导致整个调用线程等待;
- 开发者如果想要个性化设置camera效果,无法手动设置调整参数,需要依靠第三方算法对于回调的数据进行处理(NV21)。而且不同手机的回调数据效果都是不一样的,采用第三方算法调整,通常效果不好;
- 开发者所能获取的Camera状态信息有限;
camera1 的开发过程比较简单,对于常规视频采集,如果只要一般的预览功能,是没问题的,然而如果想要挖掘Camera更多的功能,camera1无法满足,于是有了camera2.
Part2: Camera2(Android的单反)
- Camera2 的开发中,camera的生命周期都是异步的,即发送请求,等待回调的client-service模式;
- 系统: Android L+;
- 这里的关键回调主要是三个:
(1)CameraDevice.StateCallback ///比如线程A发送打开相机请求, 线程B中收到相机状态回调,线程B中与cameraDevice建立会话,设置参数,数据回调处理;
(2)CameraCaptureSession.StateCallback ///与CameraDevice建立会话后,收到的会话状态回调;
(3)ImageReader.OnImageAvailableListener // 开发者可以直接获取并且操作的数据回调;
- 通过跟相机建立的会话,可以更加精细的调整Camera参数:比如ISO感光度,曝光时间,曝光补偿……;
- 如果开发者想要更多自己的定制,也可以直接使用回调数据(YUV488);
- MultiCamera的支持;
Multi-Camera 的支持:
- 系统:Android P+;
- 目前支持的multi-camera的设备: Pixel 3, mate20 系列;
- Multi-Camera 新功能:
(1)更好的光学变焦:之前的方式通常使用数码变焦或者是单个摄像头的光学变焦来达到变焦的效果, 通过多摄像头的变焦方式,无论远景还是近景,都可以采到更好质量的数据。
(2)景深计算:通过多摄像头的景深不同,可以得到每一帧图片中不同物体的景深,从而更好的区分前景或者后景。应用范围:背景虚化,背景替换,现实增强。
(3)更广的视角:更广的视角带来鱼眼镜头的畸变效果,畸变矫正功能。
CaptureRequest.DISTORTION_CORRECTION_MODE
(4)人脸识别功能:跟畸变效果一样,自带人脸识别功能。应用范围:人脸裁剪,人脸特效。
CaptureResult.STATISTICS_FACE_DETECT_MODE
(5)多路流同时采集:场景包括(单摄像头输出多流,多摄像头输出多流)
normalOutputConfigImageReader.setPhysicalCameraId(normalLensId)
wideOutputConfigImageReader.setPhysicalCameraId(wideAngleId)
params.previewBuilder?.addTarget(normalSurface)
params.previewBuilder?.addTarget(wideSurface)
- 带来的问题:更耗内存,更耗电
- 趋势:单个手机中,支持更多的摄像头
Camera2 虽然给开发者带来了相机的更多可玩性,然而android的碎片化,导致很多设备的兼容性问题频繁发生。尤其国内的手机厂商,对camera2 的支持程度各不相同,
所以Camera2的开发难度更多的是在兼容性,于是有了CameraX。
Part3: CameraX(Android的个性化相机)
- 系统:Android L+
- Jetpack 内的一套Camera开发支持库。
- 特点:
- 更简单易用的API,更少的代码量,使开发者更专注业务的个性化实现。比如:对采集到图片做分析处理。
- 更好的兼容性,减少不同设备适配烦恼:包括宽高比、屏幕方向、旋转、预览大小和高分辨率图片大小。
- 数据分析: 开发者依然可以对数据进行个性化处理。
- 第三方Camera特效拓展:对于一些手机厂商特定实现的camera特效,开发者也可以使用。
- Code Sample 1(CameraX的常规使用)
(1)CameraX 创建UseCaseConfig; //已经提前实现好各种UseCase(preview,ImageCapture,ImageAnalysis...)对应不同的UseCaseConfig, 开发者重要专注自己的业务。
(2)创建对应UseCase
(3)CameraX bindToLifecycle(LifeCycleOwner, UseCases) //CameraX 会观察生命周期以确定何时打开相机、何时创建拍摄会话以及何时停止和关闭。
(4)CameraX unbind(UseCase)
6. Code Sample 2(CameraX的特效拓展)
Part4: 开发二三事
Rotation:Camera1 和 Camera2 上来的数据角度是不一样;Camera2的某些设备,前置摄像头的sensor orientation是不一致的。一般前置270,后置90。
- 相机角度获取:
Camera1:CameraInfo.orientation
Camera2:CameraCharacteristics.SENSOR_ORIENTATION - 手机角度:
通过传感器获取:
(SensorManager) context.getSystemService(Context.SENSOR_SERVICE);
- APP角度获取:
通过WindowManager:
WindowManager wm = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE);
Coordinate system:Camera1 和 Camera2的坐标系不一样,所以在View坐标和相机坐标系转换的时候是不一样的。
Camera1的坐标系:
Camera2的坐标系:
Render:
YUV数据的纹理映射:
- glGenTextures(...);///create glTexture id
- glBindTextures(...); //bind texture into Gl context
- glTexParameterf(...);//filter param set when Texture Maping
- glTexImage2D(...); // load YUV data
- GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, 0) //unBinde Texture
离屏渲染:
- glGenFramebuffers(...);
- glBindFramebuffer(...);
- glFramebufferTexture2D(...); //bind frame buffer with Texture
- glDrawArrays(...); //draw texture data into frame buffer
- glReadPixels(...); //get frame buffer data for snapshot.
- glBindFramebuffer(...);// unbind texture
GLSL:
- glCreateShader(...);
- glShaderSource(...);//bind Vertex/Segment program with Vertex/Segment object
- glCompileShader(...);
- glCreateProgram(...);
- glAttachShader(...);///attach Vertex/Segment object with Shader program
- glLinkProgram(...);
- glUseProgram(...); //draw
总结:
Camera的数据输出格式:
|
ByteBuffer |
Texture |
FPS |
Resolution |
Camera1 |
NV21 |
Support |
30 |
1080P |
Camera2 |
I420 |
Support |
30 |
1080P |
对于Texture的数据采集,直接在GPU中创建Texture Object并拿到Texture id,Camera 的采集数据直接交给texture object 进行离屏渲染。
对于Byte Buffer的数据采集,需要将YUV数据加载到纹理object,再进行离屏渲染。
两种比较起来,直接用Texture 数据进行采集,可以省去cpu往GPU的数据拷贝过程,更高效。
Part5:Camera Next Plane:
添加自己的CameraX功能
Reference :
https://developer.android.com/training/camerax/architecture;
https://source.android.com/devices/camera/multi-camera;
https://developer.android.com/guide/topics/media/camera
https://github.com/google/basicbokeh
https://github.com/IvenFu/Android-MultiCamera
https://medium.com/androiddevelopers/getting-the-most-from-the-new-multi-camera-api-5155fb3d77d9