总览
注意一下,虽然题目主要写的是 setPreviewCallbackFlag,但实际上这对于 Camera 应用,它的动作是调用 API1 的 setPreviewCallbackWithBuffer 和 addCallbackBuffer,这样会把 Preview Callback 的 Buffer 模式设置为手动模式(由 APP 主动带 Callback Buffer 下来,底层数据回来后会被 Copy 到这块 APP Buffer 中)。
本篇文章对这一部分进行的时序分析,有几个前提条件:
APP 先调用了 startPreview;
紧随其后的是调用 addCallbackBuffer 带下 Buffer;
然后调用了 setPreviewCallbackWithBuffer,该接口设置 manualMode 为 true,标志 APP 自主带下 Callback Buffer;
第三点会触发第一次 setPreviewCallbackFlag(0x05)。
需要注意的几个点:
由于 Callback 是单独的一路 stream,所以这里相当于是要打开第二路 stream,会触发 re-configure 机制;
configureStream 的逻辑是在 CallbackProcessor 中 updateStream 期间触发的,注意这里的时机区别于 startPreview 的 startStream。
主要涉及到的类及其对应的代码地址分别是:
Camera-JNI:/frameworks/base/core/jni/android_hardware_Camera.cpp
Camera2Client:/frameworks/av/services/camera/libcameraservice/api1/Camera2Client.cpp
StreamingProcessor:/frameworks/av/services/camera/libcameraservice/api1/client2/StreamingProcessor.cpp
CallbackProcessor:/frameworks/av/services/camera/libcameraservice/api1/client2/CallbackProcessor.cpp
Camera3Device:/frameworks/av/services/camera/libcameraservice/device3/Camera3Device.cpp
接下来我会照着上面的时序图,结合具体代码进行更深入一些的解释。
代码分析
根据时序图来看,可以分成三个部分来看:
Camera2Client 中的 setPreviewCallbackFlag;
CallBackProcessor 中的 updateStream;
StreamingProcessor 中的 startStream;
setPreviewCallbackFlag 相关内容
需要注意的是:
从时序上看,通常 APP 会先调用到 addCallbackBuffer,这会使得 JNI 这边有至少一个 Callback Buffer 存在;
setPreviewCallbackWithBuffer 会调用到 setHasPreviewCallback 这一 native 方法,传下去的 manualBuffer 参数值是 true。
————————————————
所以接下来从 JNI 部分开始看起。
Camera-JNI::addCallbackBuffer
这个函数主要关注第 8~23 行:
第 10 行,把 APP 送下来的 Buffer 放到向量中,此时 size 增加;
第 18 行,由于此时 mManualBufferMode 处于初始的 false 状态,所以该分支就此结束。
void JNICameraContext::addCallbackBuffer(
JNIEnv *env, jbyteArray cbb, int msgType)
{
ALOGV("addCallbackBuffer: 0x%x", msgType);
if (cbb != NULL) {
Mutex::Autolock _l(mLock);
switch (msgType) {
case CAMERA_MSG_PREVIEW_FRAME: {
jbyteArray callbackBuffer = (jbyteArray)env->NewGlobalRef(cbb);
mCallbackBuffers.push(callbackBuffer);
ALOGV("Adding callback buffer to queue, %zu total",
mCallbackBuffers.size());
// We want to make sure the camera knows we're ready for the
// next frame. This may have come unset had we not had a
// callbackbuffer ready for it last time.
if (mManualBufferMode && !mManualCameraCallbackSet) {
mCamera->setPreviewCallbackFlags(CAMERA_FRAME_CALLBACK_FLAG_CAMERA);
mManualCameraCallbackSet = true;
}
break;
}
case CAMERA_MSG_RAW_IMAGE: {
jbyteArray callbackBuffer = (jbyteArray)env->NewGlobalRef(cbb);
mRawImageCallbackBuffers.push(callbackBuffer);
break;
}
default: {
jniThrowException(env,
"java/lang/IllegalArgumentException",
"Unsupported message type");
return;
}
}
} else {
ALOGE("Null byte array!");
}
}
Camera-JNI::setHasPreviewCallback
这个函数主要因调用 setPreviewCallbackWithBuffer 接口而触发,该接口可以在 Camera.java 看到,这里不多做解释。
它主要是继续调用 JNI 里的 setCallbackMode 函数(第 13 行),注意 manualBuffer 这一参数值为 true。
static void android_hardware_Camera_setHasPreviewCallback(JNIEnv *env, jobject thiz, jboolean installed, jboolean manualBuffer)
{
ALOGV("setHasPreviewCallback: installed:%d, manualBuffer:%d", (int)installed, (int)manualBuffer);
// Important: Only install preview_callback if the Java code has called
// setPreviewCallback() with a non-null value, otherwise we'd pay to memcpy
// each preview frame for nothing.
JNICameraContext* context;
sp<Camera> camera = get_native_camera(env, thiz, &context);
if (camera == 0) return;
// setCallbackMode will take care of setting the context flags and calling
// camera->setPreviewCallbackFlags within a mutex for us.
context->setCallbackMode(env, installed, manualBuffer);
}
Camera-JNI::setCallbackMode
关于这个函数需要注意的:
第 4 行,mManualBufferMode 被设置为 true;
第 17~21 行,由于之前调用了 addCallbackBuffer,此时 mCallbackBuffers 非空,于是会调用到 setPreviewCallbackFlags,注意传入的参数是 CAMERA_FRAME_CALLBACK_FLAG_CAMERA,可以查到这个宏定义对应的数值是 0x05;
注意下第 20 行,把 mManualCameraCallbackSet 设置为 true;
void JNICameraContext::setCallbackMode(JNIEnv *env, bool installed, bool manualMode)
{
Mutex::Autolock _l(mLock);
mManualBufferMode = manualMode;
mManualCameraCallbackSet = false;
// In order to limit the over usage of binder threads, all non-manual buffer
// callbacks use CAMERA_FRAME_CALLBACK_FLAG_BARCODE_SCANNER mode now.
//
// Continuous callbacks will have the callback re-registered from handleMessage.
// Manual buffer mode will operate as fast as possible, relying on the finite supply
// of buffers for throttling.
if (!installed) {
mCamera->setPreviewCallbackFlags(CAMERA_FRAME_CALLBACK_FLAG_NOOP);
clearCallbackBuffers_l(env, &mCallbackBuffers);
} else if (mManualBufferMode) {
if (!mCallbackBuffers.isEmpty()) {
mCamera->setPreviewCallbackFlags(CAMERA_FRAME_CALLBACK_FLAG_CAMERA);
mManualCameraCallbackSet = true;
}
} else {
mCamera->setPreviewCallbackFlags(CAMERA_FRAME_CALLBACK_FLAG_BARCODE_SCANNER);
clearCallbackBuffers_l(env, &mCallbackBuffers);
}
}
Camera2Client::setPreviewCallbackFlag
看到这你可能会奇怪,前面调用的是 setPreviewCallbackFlags,怎么这里就到了 setPreviewCallbackFlag(缺了一个字母 s)。这里是因为我省略了 Camera.cpp 的内容,有兴趣可以去看看。
回到正题,这个函数只是个入口,主要是第 9 行进入正题。
void Camera2Client::setPreviewCallbackFlag(int flag) {
ATRACE_CALL();
ALOGV("%s: Camera %d: Flag 0x%x", __FUNCTION__, mCameraId, flag);
Mutex::Autolock icl(mBinderSerializationLock);
if ( checkPid(__FUNCTION__) != OK) return;
SharedParameters::Lock l(mParameters);
setPreviewCallbackFlagL(l.mParameters, flag);
}
Camera2Client::setPreviewCallbackFlagL
该函数主要逻辑如下:
第 4~17 行,由于前面已经 startPreview 过,此处 state 为 PREVIEW 状态(即走第 7 行的分支,直接离开 switch);
第 21 行,之前的 previewCallbackFlags 还是默认的 0x00,此处 flag 带下来 0x05 这个值,于是走入这个分支;
第 25 行,更新 previewCallbackFlags 值为 0x05;
第 28 行,再次进入 startPreviewL 流程,注意这次 restart 参数值是 true。
void Camera2Client::setPreviewCallbackFlagL(Parameters ¶ms, int flag) {
status_t res = OK;
switch(params.state) {
case Parameters::STOPPED:
case Parameters::WAITING_FOR_PREVIEW_WINDOW:
case Parameters::PREVIEW:
case Parameters::STILL_CAPTURE:
// OK
break;
default:
if (flag & CAMERA_FRAME_CALLBACK_FLAG_ENABLE_MASK) {
ALOGE("%s: Camera %d: Can't use preview callbacks "
"in state %d", __FUNCTION__, mCameraId, params.state);
return;
}
}
// NOTE: N Lines are omitted here
if (params.previewCallbackFlags != (uint32_t)flag) {
// NOTE: N Lines are omitted here
params.previewCallbackFlags = flag;
if (params.state == Parameters::PREVIEW) {
res = startPreviewL(params, true);
if (res != OK) {
ALOGE("%s: Camera %d: Unable to refresh request in state %s",
__FUNCTION__, mCameraId,
Parameters::getStateName(params.state));
}
}
}
}
Camera2Client::startPreviewL
该函数主要逻辑如下:
第 4 行,将 state 设置为 STOPPED;
第 5~14 行,由于已经 startPreview 过, 这里能拿到当前 preview stream 的 ID,相关逻辑需要关注的信息不多,就不深入去看了;
第 19 行,由于 params.previewCallbackFlags 是 0x05,这里的 callbacksEnabled 被设置为 true;
第 26 行,调用到 CallbackProcessor 的 updateStream,此处就是后续关注的重点了,由于需要新的这一路 callback stream,此处会有相关的创建新 stream 的逻辑,包括触发 re-config 动作;
第 32 行,callback stream 准备好后,加入到 output buffer 集合中;
第 44 行,将 preview stream 加入到 output buffer 集合中;
第 58 行,这次的 startStream 就不会触发 configureStream 的动作了,需要注意的是它会调用到 setRepeatingRequests;
第 65 行,将 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;
if (callbacksEnabled) {
// NOTE: N Lines are omitted here
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());
} else if (previewStreamChanged && mCallbackProcessor->getStreamId() != NO_STREAM) {
// 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
}
// NOTE: N Lines are omitted here
params.state = Parameters::PREVIEW;
return OK;
}
updateStream 相关内容
这里主要就是更新一个 callback stream,触发 re-config 动作。
CallbackProcessor::updateStream
此处逻辑如下:
第 4~14 行,创建 BufferQueue,并进行相应的配置。这里面需要注意一下 Consumer 这个类,它与后续接收 callback buffer,触发 onFrameAvailable 回调密切相关,但由于此处关系略复杂,就不深入去分析了,有兴趣可以自己看看;
第 22 行,由于当前无 callback stream,所以需要新创建一个。
status_t CallbackProcessor::updateStream(const Parameters ¶ms) {
// NOTE: N Lines are omitted here
if (!mCallbackToApp && mCallbackConsumer == 0) {
// Create CPU buffer queue endpoint, since app hasn't given us one
// Make it async to avoid disconnect deadlocks
sp<IGraphicBufferProducer> producer;
sp<IGraphicBufferConsumer> consumer;
BufferQueue::createBufferQueue(&producer, &consumer);
mCallbackConsumer = new CpuConsumer(consumer, kCallbackHeapCount);
mCallbackConsumer->setFrameAvailableListener(this);
mCallbackConsumer->setName(String8("Camera2-CallbackConsumer"));
mCallbackWindow = new Surface(producer);
}
// NOTE: N Lines are omitted here
if (mCallbackStreamId == NO_STREAM) {
ALOGV("Creating callback stream: %d x %d, format 0x%x, API format 0x%x",
params.previewWidth, params.previewHeight,
callbackFormat, params.previewFormat);
res = device->createStream(mCallbackWindow,
params.previewWidth, params.previewHeight, callbackFormat,
HAL_DATASPACE_V0_JFIF, CAMERA3_STREAM_ROTATION_0, &mCallbackStreamId,
String8());
if (res != OK) {
ALOGE("%s: Camera %d: Can't create output stream for callbacks: "
"%s (%d)", __FUNCTION__, mId,
strerror(-res), res);
return res;
}
}
return OK;
}
Camera3Device::createStream
实际上 createStream
有两个,这里只看最后执行的那一个:
第 8 行,注意 wasActive 初始值是 false;
第 21~29 行,当前 mStatus 是 STATUS_ACTIVE,在第 23 行会把 RequestThread 暂停,等待到 STATUS_CONFIGURED,至于为什么会有这样的转变,与 StatusTracker 有关,有兴趣可以再深入看看,这里先忽略该细节。第 28 行将 wasActive 改为 true;
第 49 行,创建用于 preview callback 的 stream;
第 54~64 行,根据 consumer 个数将 callback stream 中的各 Surface ID 找出来,通过参数 surfaceIds 返回;
第 70 行,将 callback stream 加入到 Camera3Device 的成员 mOutputStreams 中,这是一个 StreamSet,这里需要注意的是,要和 Camera3Device::CaptureRequest 类的成员 mOutputStreams 区别开来,不是同一个东西;
第 80~90 行,由于 wasActive 为 true,走入该 if 分支中,并在第 83 行调用了 configureStreamsLocked,这里面就会触发 re-config 情况。注意第 89 行的函数会把 Pause 住的 RequestThread 重新开起来。
status_t Camera3Device::createStream(const std::vector<sp<Surface>>& consumers,
bool hasDeferredConsumer, uint32_t width, uint32_t height, int format,
android_dataspace dataSpace, camera3_stream_rotation_t rotation, int *id,
const String8& physicalCameraId,
std::vector<int> *surfaceIds, int streamSetId, bool isShared, uint64_t consumerUsage) {
// NOTE: N Lines are omitted here
bool wasActive = false;
switch (mStatus) {
case STATUS_ERROR:
CLOGE("Device has encountered a serious error");
return INVALID_OPERATION;
case STATUS_UNINITIALIZED:
CLOGE("Device not initialized");
return INVALID_OPERATION;
case STATUS_UNCONFIGURED:
case STATUS_CONFIGURED:
// OK
break;
case STATUS_ACTIVE:
ALOGV("%s: Stopping activity to reconfigure streams", __FUNCTION__);
res = internalPauseAndWaitLocked(maxExpectedDuration);
if (res != OK) {
SET_ERR_L("Can't pause captures to reconfigure streams!");
return res;
}
wasActive = true;
break;
default:
SET_ERR_L("Unexpected status: %d", mStatus);
return INVALID_OPERATION;
}
assert(mStatus != STATUS_ACTIVE);
sp<Camera3OutputStream> newStream;
// NOTE: N Lines are omitted here
if (format == HAL_PIXEL_FORMAT_BLOB) {
// NOTE: N Lines are omitted here
} else if (format == HAL_PIXEL_FORMAT_RAW_OPAQUE) {
// NOTE: N Lines are omitted here
} else if (isShared) {
// NOTE: N Lines are omitted here
} else if (consumers.size() == 0 && hasDeferredConsumer) {
// NOTE: N Lines are omitted here
} else {
newStream = new Camera3OutputStream(mNextStreamId, consumers[0],
width, height, format, dataSpace, rotation,
mTimestampOffset, physicalCameraId, streamSetId);
}
size_t consumerCount = consumers.size();
for (size_t i = 0; i < consumerCount; i++) {
int id = newStream->getSurfaceId(consumers[i]);
if (id < 0) {
SET_ERR_L("Invalid surface id");
return BAD_VALUE;
}
if (surfaceIds != nullptr) {
surfaceIds->push_back(id);
}
}
newStream->setStatusTracker(mStatusTracker);
newStream->setBufferManager(mBufferManager);
res = mOutputStreams.add(mNextStreamId, newStream);
if (res < 0) {
SET_ERR_L("Can't add new stream to set: %s (%d)", strerror(-res), res);
return res;
}
*id = mNextStreamId++;
mNeedConfig = true;
// Continue captures if active at start
if (wasActive) {
ALOGV("%s: Restarting activity to reconfigure streams", __FUNCTION__);
// Reuse current operating mode and session parameters for new stream config
res = configureStreamsLocked(mOperatingMode, mSessionParams);
if (res != OK) {
CLOGE("Can't reconfigure device for new stream %d: %s (%d)",
mNextStreamId, strerror(-res), res);
return res;
}
internalResumeLocked();
}
ALOGV("Camera %s: Created new stream", mId.string());
return OK;
}
Camera3Device::configureStreamsLocked
此处逻辑如下:
第 6 行,这里要注意了,mStatus 在前面 createStream 的流程中已经被改成 STATUS_CONFIGURED 了,所以此处不会被 return,如果还是 STATUS_ACTIVE 的话这里就触发 return,就不会继续 config 了;
第 13 行,createStream 里面有设置 mNeedConfig 为 true,所以此处不会触发 return;
第 20 行,先停掉 PrepareThread 的 Loop;
第 24~50 行,主要是对每个 output stream 执行 startConfiguration 的动作;
第 58 行,通过 Camera3Device::HalInterface 实例,透过 HIDL 启动 HAL 层的 configureStreams 流程;
第 63~75 行,对应第 4 点,这里是执行 finishConfiguration 动作;
第 85 行,mNeedConfig 设置为 false;
第 87 行,这里会再次设置 mStatus 为 STATUS_CONFIGURED;
第 95 行,继续 PrepareThread 的 Loop。
status_t Camera3Device::configureStreamsLocked(int operatingMode,
const CameraMetadata& sessionParams, bool notifyRequestThread) {
ATRACE_CALL();
status_t res;
if (mStatus != STATUS_UNCONFIGURED && mStatus != STATUS_CONFIGURED) {
CLOGE("Not idle");
return INVALID_OPERATION;
}
// NOTE: N Lines are omitted here
if (!mNeedConfig) {
ALOGV("%s: Skipping config, no stream changes", __FUNCTION__);
return OK;
}
// NOTE: N Lines are omitted here
mPreparerThread->pause();
// NOTE: N Lines are omitted here
for (size_t i = 0; i < mOutputStreams.size(); i++) {
// Don't configure bidi streams twice, nor add them twice to the list
if (mOutputStreams[i].get() ==
static_cast<Camera3StreamInterface*>(mInputStream.get())) {
config.num_streams--;
continue;
}
camera3_stream_t *outputStream;
outputStream = mOutputStreams.editValueAt(i)->startConfiguration();
if (outputStream == NULL) {
CLOGE("Can't start output stream configuration");
cancelStreamsConfigurationLocked();
return INVALID_OPERATION;
}
streams.add(outputStream);
if (outputStream->format == HAL_PIXEL_FORMAT_BLOB &&
outputStream->data_space == HAL_DATASPACE_V0_JFIF) {
size_t k = i + ((mInputStream != nullptr) ? 1 : 0); // Input stream if present should
// always occupy the initial entry.
bufferSizes[k] = static_cast<uint32_t>(
getJpegBufferSize(outputStream->width, outputStream->height));
}
}
config.streams = streams.editArray();
// Do the HAL configuration; will potentially touch stream
// max_buffers, usage, priv fields.
const camera_metadata_t *sessionBuffer = sessionParams.getAndLock();
res = mInterface->configureStreams(sessionBuffer, &config, bufferSizes);
sessionParams.unlock(sessionBuffer);
// NOTE: N Lines are omitted here
for (size_t i = 0; i < mOutputStreams.size(); i++) {
sp<Camera3OutputStreamInterface> outputStream =
mOutputStreams.editValueAt(i);
if (outputStream->isConfiguring() && !outputStream->isConsumerConfigurationDeferred()) {
res = outputStream->finishConfiguration();
if (res != OK) {
CLOGE("Can't finish configuring output stream %d: %s (%d)",
outputStream->getId(), strerror(-res), res);
cancelStreamsConfigurationLocked();
return BAD_VALUE;
}
}
}
// Request thread needs to know to avoid using repeat-last-settings protocol
// across configure_streams() calls
if (notifyRequestThread) {
mRequestThread->configurationComplete(mIsConstrainedHighSpeedConfiguration, sessionParams);
}
// NOTE: N Lines are omitted here
mNeedConfig = false;
internalUpdateStatusLocked((mDummyStreamId == NO_STREAM) ?
STATUS_CONFIGURED : STATUS_UNCONFIGURED);
ALOGV("%s: Camera %s: Stream configuration complete", __FUNCTION__, mId.string());
// tear down the deleted streams after configure streams.
mDeletedStreams.clear();
auto rc = mPreparerThread->resume();
if (rc != OK) {
SET_ERR_L("%s: Camera %s: Preparer thread failed to resume!", __FUNCTION__, mId.string());
return rc;
}
return OK;
}
startStream 相关内容
这部分与 startPreview 流程比较重复,不过由于某些变量值不同,需要执行的逻辑少了许多。
StreamingProcessor::startStream
此处逻辑如下:
第 5~6 行,这里拿到的是 mPreviewRequest;
第 8~10 行,更新 Request Metadata 里的 output stream 参数,注意这里传入的 ouputStreams 的个数,会影响到 RequestThread 在 prepareHalRequest 时所准备的 buffer 个数;
第 14 行,将当前 request 更新到 Streaming 流程。
status_t StreamingProcessor::startStream(StreamType type,
const Vector<int32_t> &outputStreams) {
// NOTE: N Lines are omitted here
CameraMetadata &request = (type == PREVIEW) ?
mPreviewRequest : mRecordingRequest;
res = request.update(
ANDROID_REQUEST_OUTPUT_STREAMS,
outputStreams);
// NOTE: N Lines are omitted here
res = device->setStreamingRequest(request);
if (res != OK) {
ALOGE("%s: Camera %d: Unable to set preview request to start preview: "
"%s (%d)",
__FUNCTION__, mId, strerror(-res), res);
return res;
}
mActiveRequest = type;
mPaused = false;
mActiveStreamIds = outputStreams;
return OK;
}
Camera3Device::setStreamingRequest
这里主要作用是转换 request 的形式,并调用到 setStreamingRequestList
。
status_t Camera3Device::setStreamingRequest(const CameraMetadata &request,
int64_t* /*lastFrameNumber*/) {
ATRACE_CALL();
List<const PhysicalCameraSettingsList> requestsList;
std::list<const SurfaceMap> surfaceMaps;
convertToRequestList(requestsList, surfaceMaps, request);
return setStreamingRequestList(requestsList, /*surfaceMap*/surfaceMaps,
/*lastFrameNumber*/NULL);
}
Camera3Device::setStreamingRequestList
此处主要是对接到 submitRequestsHelper
。
status_t Camera3Device::setStreamingRequestList(
const List<const PhysicalCameraSettingsList> &requestsList,
const std::list<const SurfaceMap> &surfaceMaps, int64_t *lastFrameNumber) {
ATRACE_CALL();
return submitRequestsHelper(requestsList, surfaceMaps, /*repeating*/true, lastFrameNumber);
}
Camera3Device::submitRequestsHelper
此处逻辑如下:
第 11 行,目的是获取 RequestList,它是以 Camera3Device 内部定义的类 CaptureRequest 为基础的链表,此处还需要注意传入的参数中 repeating 的值是 true;
第 19 行,由于 repeating 为 true,所以走了 setRepeatingRequest,这是 API2 启预览的接口;
第 25 行,注意传入的 active 参数为 true,会等待 mStatus 变成 STATUS_ACTIVE。
status_t Camera3Device::submitRequestsHelper(
const List<const PhysicalCameraSettingsList> &requests,
const std::list<const SurfaceMap> &surfaceMaps,
bool repeating,
/*out*/
int64_t *lastFrameNumber) {
// NOTE: N Lines are omitted here
RequestList requestList;
res = convertMetadataListToRequestListLocked(requests, surfaceMaps,
repeating, /*out*/&requestList);
if (res != OK) {
// error logged by previous call
return res;
}
if (repeating) {
res = mRequestThread->setRepeatingRequests(requestList, lastFrameNumber);
} else {
res = mRequestThread->queueRequestList(requestList, lastFrameNumber);
}
if (res == OK) {
waitUntilStateThenRelock(/*active*/true, kActiveTimeout);
if (res != OK) {
SET_ERR_L("Can't transition to active in %f seconds!",
kActiveTimeout/1e9);
}
ALOGV("Camera %s: Capture request %" PRId32 " enqueued", mId.string(),
(*(requestList.begin()))->mResultExtras.requestId);
} else {
CLOGE("Cannot queue request. Impossible.");
return BAD_VALUE;
}
return res;
}
Camera3Device::convertMetadataListToRequestListLocked
此处比较关键的是第 16 行,目的是获取 CaptureRequest 实例。
status_t Camera3Device::convertMetadataListToRequestListLocked(
const List<const PhysicalCameraSettingsList> &metadataList,
const std::list<const SurfaceMap> &surfaceMaps,
bool repeating,
RequestList *requestList) {
if (requestList == NULL) {
CLOGE("requestList cannot be NULL.");
return BAD_VALUE;
}
int32_t burstId = 0;
List<const PhysicalCameraSettingsList>::const_iterator metadataIt = metadataList.begin();
std::list<const SurfaceMap>::const_iterator surfaceMapIt = surfaceMaps.begin();
for (; metadataIt != metadataList.end() && surfaceMapIt != surfaceMaps.end();
++metadataIt, ++surfaceMapIt) {
sp<CaptureRequest> newRequest = setUpRequestLocked(*metadataIt, *surfaceMapIt);
if (newRequest == 0) {
CLOGE("Can't create capture request");
return BAD_VALUE;
}
newRequest->mRepeating = repeating;
// NOTE: N Lines are omitted here
requestList->push_back(newRequest);
ALOGV("%s: requestId = %" PRId32, __FUNCTION__, newRequest->mResultExtras.requestId);
}
// NOTE: N Lines are omitted here
return OK;
}
Camera3Device::setUpRequestLocked
此处逻辑如下:
第 5 行,注意此处 mStatus 是 STATUS_CONFIGURED 并且 mNeedConfig 为 false,所以这块分支都不会走;
第 21 行,创建 CaptureRequest 实例,这里面做的事和 startPreview 时一样,就不赘述了。
sp<Camera3Device::CaptureRequest> Camera3Device::setUpRequestLocked(
const PhysicalCameraSettingsList &request, const SurfaceMap &surfaceMap) {
status_t res;
if (mStatus == STATUS_UNCONFIGURED || mNeedConfig) {
// This point should only be reached via API1 (API2 must explicitly call configureStreams)
// so unilaterally select normal operating mode.
res = filterParamsAndConfigureLocked(request.begin()->metadata,
CAMERA3_STREAM_CONFIGURATION_NORMAL_MODE);
// Stream configuration failed. Client might try other configuraitons.
if (res != OK) {
CLOGE("Can't set up streams: %s (%d)", strerror(-res), res);
return NULL;
} else if (mStatus == STATUS_UNCONFIGURED) {
// Stream configuration successfully configure to empty stream configuration.
CLOGE("No streams configured");
return NULL;
}
}
sp<CaptureRequest> newRequest = createCaptureRequest(request, surfaceMap);
return newRequest;
}
Camera3Device::RequestThread::setRepeatingRequests
再次来到 setRepeatingRequests
:
第 10~11 行,这里先清除了 mRepeatingRequests 里的内容,把新创建的 CaptureRequest 加了进来;
第 14 行,此处会触发一次 mRequestSignal 的 signal,会直接影响到 waitForNextRequestLocked。
status_t Camera3Device::RequestThread::setRepeatingRequests(
const RequestList &requests,
/*out*/
int64_t *lastFrameNumber) {
ATRACE_CALL();
Mutex::Autolock l(mRequestLock);
if (lastFrameNumber != NULL) {
*lastFrameNumber = mRepeatingLastFrameNumber;
}
mRepeatingRequests.clear();
mRepeatingRequests.insert(mRepeatingRequests.begin(),
requests.begin(), requests.end());
unpauseForNewRequests();
mRepeatingLastFrameNumber = hardware::camera2::ICameraDeviceUser::NO_IN_FLIGHT_REPEATING_FRAMES;
return OK;
}