系列文章
- [Android P] CameraAPI1 转 HAL3 预览流程(一) — 背景概述
- [Android P] CameraAPI1 转 HAL3 预览流程(二) — startPreview
- [Android P] CameraAPI1 转 HAL3 预览流程(三) — setPreviewCallbackFlag
- [Android P] CameraAPI1 转 HAL3 预览流程(四) — Preview Data
总览
三方应用调用 Camera API1 的 startPreview
接口时, Framework 部分的时序图如下,其中注意几个点:
- API1 转 HAL3 的主要逻辑都在 Camera2Client 中,只有在底层 HAL3 的情况下调用 API1 会走到这(在
openCamera
时会有相关的实例化逻辑); - Camera3Device 相当于 HAL3 架构下 Framework 层中与 HAL 层进行对接的实例,这部分不区分 API1 还是 API2;
startPreview
只打开一路 Stream,对应上 StreamingProcessor。其流程中对应 configureStream 这一动作的逻辑是在 startStream 调用期间完成的。
主要涉及到的类及其对应的代码地址分别是:
- Camera2Client:
/frameworks/av/services/camera/libcameraservice/api1/Camera2Client.cpp
- StreamingProcessor:
/frameworks/av/services/camera/libcameraservice/api1/client2/StreamingProcessor.cpp
- Camera3Device && Camera3Device::RequestThread:
/frameworks/av/services/camera/libcameraservice/device3/Camera3Device.cpp
接下来我会照着上面的时序图,结合具体代码进行更深入一些的解释。
代码分析
下面这部分我只会写我关注到的部分,没有完整覆盖所有的调用逻辑以及相应细节,建议有空时自己走一遍这个流程,印象、理解会深刻许多。
根据时序图来看,可以分成三个重点部分来看:
- Camera2Client 中的
startPreview
; - StreamingProcessor 中的
updatePreviewStream
; - Camera3Device 中的
setStreamingRequest
;
在进行分析前,有必要提及一下,preview stream 和 preview callback stream 是两路不同的 stream。其中 preview 这一路主要是由 StreamingProcessor 来创建管理的,preview callback 则主要对应 CallbackProcessor。
startPreview 相关内容
首先需要提一下,APP 调用 Camera API1 的接口 startPreview
后,会先到 JNI 部分会调用到 android_hardware_Camera_startPreview
,然后才会到 Camera2Client 这边的 startPreview
。
Camera2Client::startPreview
这个函数应该不用多说:
- 主要就是去调用
startPreviewL
; - 传入的第一个参数是 API1 风格的参数 Parameters;
- 注意第二个参数是 restart 标志,这里设置为 false。
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);
}
Camera2Client::startPreviewL
到这个函数就要注意了,内容比较多,我省略部分语句,挑一些重点(时序图中体现到的逻辑)来讲。
NOTE:省略的部分我会加一句注释 “N Lines are omitted here” 代替。
下面来看一下这里面的流程:
- 第 5 行,先把 state 设置为 STOPPED;
- 第 6 行,从 StreamingProcessor 实例中获取 preview stream 的 ID,由于是第一次打开预览,这里返回的是 NO_STREAM;
- 第 8 行,执行 StreamingProcessor 实例的
updatePreviewStream
方法,这个方法后续单独拿出来分析,这里主要作用是创建 preview 这一路 stream,对应地会生成 streamID; - 第 20~22 行,注意这里 previewCallbackFlags 一般是需要 preview callback stream 时候才会设置,而首次打开预览时候这里的 callbacksEnabled 最终值会是 false;
- 第 26~31 行中,一般走的是 else 分支里面的
deleteStream
; - 第 33 行,这里把从 StreamingProcessor 创建的 preview stream 加入到 outputStreams 中,这是一个 int 型的 vector,相当于当前 output stream 的 ID 列表;
- 第 38~46 行,最开始时说过,传入的参数 restart 为 false,所以会先执行一次
updatePreviewRequest
,这个函数主要是把 API1 风格的参数 Parameters 转换成 API2 风格的参数 Metadata; - 第 47 行,这里调用了
startStream
,这里面的逻辑会更复杂一些,后面会详细分析,需要注意的是这里会对接到 configureStreams 流程,与 HAL 存在交互; - 第 53 行,预览启动完毕,将 state 设置为 PREVIEW。
status_t Camera2Client::startPreviewL(Parameters ¶ms, bool restart) {
// NOTE: N Lines are omitted here
params.state = Parameters::STOPPED;
int lastPreviewStreamId = mStreamingProcessor->getPreviewStreamId();
res = mStreamingProcessor->updatePreviewStream(params);
if (res != OK) {
ALOGE("%s: Camera %d: Unable to update preview stream: %s (%d)",
__FUNCTION__, mCameraId, strerror(-res), res);
return res;
}
bool previewStreamChanged = mStreamingProcessor->getPreviewStreamId() != lastPreviewStreamId;
// NOTE: N Lines are omitted here
Vector<int32_t> outputStreams;
bool callbacksEnabled = (params.previewCallbackFlags &
CAMERA_FRAME_CALLBACK_FLAG_ENABLE_MASK) ||
params.previewCallbackSurface;
// NOTE: N Lines are omitted here
if (params.useZeroShutterLag() &&
getRecordingStreamId() == NO_STREAM) {
// NOTE: N Lines are omitted here
} else {
mZslProcessor->deleteStream();
}
outputStreams.push(getPreviewStreamId());
// NOTE: N Lines are omitted here
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 {
// NOTE: N Lines are omitted here
}
params.state = Parameters::PREVIEW;
return OK;
}
updatePreviewStream 相关内容
这一部分主要作用是创建 preview 这一路 stream。
StreamingProcessor::updataPreviewStream
关于这段代码:
- 第 5~15 行,由于当前还没有 preview stream,所以需要调用
createStream
方法去创建一个 OuputStream,需要注意这里的 device 对应的是 Camera3Device 的实例; - 第 17 行,创建 Stream 完毕后,要给它设置一下 Transform 的信息,这个函数就不深究了。
status_t StreamingProcessor::updatePreviewStream(const Parameters ¶ms) {
// NOTE: N Lines are omitted here
if (mPreviewStreamId == NO_STREAM) {
res = device->createStream(mPreviewWindow,
params.previewWidth, params.previewHeight,
CAMERA2_HAL_PIXEL_FORMAT_OPAQUE, HAL_DATASPACE_UNKNOWN,
CAMERA3_STREAM_ROTATION_0, &mPreviewStreamId, String8());
if (res != OK) {
ALOGE("%s: Camera %d: Unable to create preview stream: %s (%d)",
__FUNCTION__, mId, strerror(-res), res);
return res;
}
}
res = device->setStreamTransform(mPreviewStreamId,
params.previewTransform);
if (res != OK) {
ALOGE("%s: Camera %d: Unable to set preview stream transform: "
"%s (%d)", __FUNCTION__, mId, strerror(-res), res);
return res;
}
return OK;
}
Camera3Device::createStream
注意这里有两个 createStream
:
- 第 1~19 行,这个
createStream
是首先调用到的,它会调用真正实现创建 stream 的createStream
函数; - 第 31~54 行,这里面走的是 STATUS_UNCONFIGURED 的分支,即直接跳出 switch 逻辑;
- 第 61~78 行,这里走的是 HAL_PIXEL_FORMAT_RAW_OPAQUE 分支的部分,主要是第 69~71 行创建了 Camera3OutputStream 实例;
- 第 82、84 行,对新创建的 stream 进行一些基本配置,主要关于 StatusTracker 和 BufferManager,这部分就不继续深入了;
- 第 86 行,此处把新创建的 stream 加入到 Camera3Device 的成员变量 mOutputStreams 中,它是一个 Set,其中 streamID 和 stream 实例一一对应;
- 第 93 行,这里设置 Camera3Device 的成员变量 mNeedCon