[Android P] CameraAPI1 转 HAL3 预览流程(三) — setPreviewCallbackFlag

总览
注意一下,虽然题目主要写的是 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。

setPreviewCallbackFlag

主要涉及到的类及其对应的代码地址分别是:

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 &params, 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 &params, 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 &params) {
    // 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;
}

  • 1
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值