Camera3研读前沿:
当初在研读Camera1.0相关的内容时,主要围绕着CameraClient、CameraHardwareInterface等方面进行工作的开展,无论是数据流还是控制流看起来都很简单、明了,一系列的流程化操作使得整个框架学起来特别的容易。因为没有Camera2.0相关的基础,所以这次直接看3.0相关的源码时,显得十分的吃紧,再加上底层高通HAL3.0实现的过程也是相当的复杂,都给整个研读过程带来了很多的困难。可以说,自身目前对Camera3.0框架的熟悉度也大概只有70%左右,希望通过总结来进一步梳理他的工作原理与整个框架,并进一步熟悉与加深理解。
1.Camera3下的整体架构图。
整个CameraService建立起一个可用操作底层Camera device大致需要经过Camera2Client、Camera3Device以及HAL层的camera3_device_t三个部分。
从上图中可以发现Camera3架构看上去明显比camera1来的复杂,但他更加的模块化。对比起Android4.2.2 Camer系统架构图(HAL和回调处理)一文中描述的单顺序执行流程,Camera3将更多的工作集中在了Framework去完成,将更多的控制权掌握在自己的手里,从而与HAL的交互的数据信息更少,也进一步减轻了一些在旧版本中HAL层所需要做的事情。
2. Camera2Client的建立与初始化过程
在建立好Camera2Client后会进行initialize操作,完成各个处理模块的创建:
- ....
- StreamingProcessor = new StreamingProcessor(this);
- threadName = String8::format("C2-%d-StreamProc",
- mCameraId);
- mStreamingProcessor->run(threadName.string());
-
- mFrameProcessor = new FrameProcessor(mDevice, this);
- threadName = String8::format("C2-%d-FrameProc",
- mCameraId);
- mFrameProcessor->run(threadName.string());
-
- mCaptureSequencer = new CaptureSequencer(this);
- threadName = String8::format("C2-%d-CaptureSeq",
- mCameraId);
- mCaptureSequencer->run(threadName.string());
-
- mJpegProcessor = new JpegProcessor(this, mCaptureSequencer);
- threadName = String8::format("C2-%d-JpegProc",
- mCameraId);
- mJpegProcessor->run(threadName.string());
- ...
- mCallbackProcessor = new CallbackProcessor(this);
- threadName = String8::format("C2-%d-CallbkProc",
- mCameraId);
- mCallbackProcessor->run(threadName.string());
依次分别创建了:
StreamingProcessor并启动一个他所属的thread,该模块主要负责处理previews与record两种视频流的处理,用于从hal层获取原始的视频数据
FrameProcessor并启动一个thread,该模块专门用于处理回调回来的每一帧的3A等信息,即每一帧视频除去原始视频数据外,还应该有其他附加的数据信息,如3A值。
CaptureSequencer并启动一个thread,该模块需要和其他模块配合使用,主要用于向APP层告知capture到的picture。
JpegProcessor并启动一个thread,该模块和streamprocessor类似,他启动一个拍照流,一般用于从HAL层获取jpeg编码后的图像照片数据。
此外ZslProcessor模块称之为0秒快拍,其本质是直接从原始的Preview流中获取预存着的最近的几帧,直接编码后返回给APP,而不需要再经过take picture去请求获取jpeg数据。0秒快拍技术得意于当下处理器CSI2 MIPI性能的提升以及Sensor支持全像素高帧率的实时输出。一般手机拍照在按下快门后都会有一定的延时,是因为需要切换底层Camera以及ISP等的工作模式,并重新设置参数以及重新对焦等等,都需要花一定时间后才抓取一帧用于编码为jpeg图像。
以上5个模块整合在一起基本上实现了Camera应用开发所需的基本业务功能。
3. 预览Preview下的控制流
研读Camera具体的业务处理功能,一般从视频实时预览Preview入手。一般熟悉Camera架构的人,可以从一个app端的一个api一直连续打通到底层hal的一个控制命令。大致可以如下图所示:
对于preview部分到CameraService的控制流可以参考博文Android4.2.2的preview的数据流和控制流以及最终的预览显示,本文将直接从Camera2Client::startPreview() 作为入口来分析整个Framework层中Preview相关的数据流。
- status_t Camera2Client::startPreview() {
- ATRACE_CALL();
- ALOGV("%s: E", __FUNCTION__);
- Mutex::Autolock icl(mBinderSerializationLock);
- status_t res;
- if ( (res = checkPid(__FUNCTION__) ) != OK) return res;
- SharedParameters::Lock l(mParameters);
- return startPreviewL(l.mParameters, false);
- }
startPreview通过startPreviewL提取参数后真正的开始执行Preview相关的控制流。该函数看上去内容虽然较多,但基本采用了同一种处理方式:
- status_t Camera2Client::startPreviewL(Parameters ¶ms, bool restart) {
- ATRACE_CALL();
- status_t res;
- ......
- int lastPreviewStreamId = mStreamingProcessor->getPreviewStreamId();
-
- res = mStreamingProcessor->updatePreviewStream(params);
- .....
- int lastJpegStreamId = mJpegProcessor->getStreamId();
- res = updateProcessorStream(mJpegProcessor, params);
- .....
- res = mCallbackProcessor->updateStream(params);
- if (res != OK) {
- ALOGE("%s: Camera %d: Unable to update callback stream: %s (%d)",
- __FUNCTION__, mCameraId, strerror(-res), res);
- return res;
- }
- outputStreams.push(getCallbackStreamId());
- ......
- outputStreams.push(getPreviewStreamId());
- ......
- if (!params.recordingHint) {
- if (!restart) {
- res = mStreamingProcessor->updatePreviewRequest(params);
- if (res != OK) {
- ALOGE("%s: Camera %d: Can't set up preview request: "
- "%s (%d)", __FUNCTION__, mCameraId,
- strerror(-res), res);
- return res;
- }
- }
- res = mStreamingProcessor->startStream(StreamingProcessor::PREVIEW,
- outputStreams);
- } else {
- if (!restart) {
- res = mStreamingProcessor->updateRecordingRequest(params);
- if (res != OK) {
- ALOGE("%s: Camera %d: Can't set up preview request with "
- "record hint: %s (%d)", __FUNCTION__, mCameraId,
- strerror(-res), res);
- return res;
- }
- }
- res = mStreamingProcessor->startStream(StreamingProcessor::RECORD,
- outputStreams);
- }
- ......
- }
(1). mStreamingProcessor->updatePreviewStream()
由预览与录像处理模块更新一个预览流,其实现过程如下:
- status_t StreamingProcessor::updatePreviewStream(const Parameters ¶ms) {
- ATRACE_CALL();
- Mutex::Autolock m(mMutex);
-
- status_t res;
- sp<CameraDeviceBase> device = mDevice.promote();
- if (device == 0) {
- ALOGE("%s: Camera %d: Device does not exist", __FUNCTION__, mId);
- return INVALID_OPERATION;
- }
-
- if (mPreviewStreamId != NO_STREAM) {
-
- uint32_t currentWidth, currentHeight;
- res = device->getStreamInfo(mPreviewStreamId,
- ¤tWidth, ¤tHeight, 0);
- if (res != OK) {
- ALOGE("%s: Camera %d: Error querying preview stream info: %2