[Android P] CameraAPI1 转 HAL3 预览流程(二) — startPreview

本文详细分析了Android P中,从CameraAPI1的startPreview接口如何转换到HAL3的预览流程。主要涉及Camera2Client、StreamingProcessor和Camera3Device类的相关方法,包括startPreview、updatePreviewStream和setStreamingRequest等步骤,解析了创建和配置preview stream的过程,以及与HAL层的交互。
摘要由CSDN通过智能技术生成

系列文章

总览

三方应用调用 Camera API1 的 startPreview 接口时, Framework 部分的时序图如下,其中注意几个点:

  • API1 转 HAL3 的主要逻辑都在 Camera2Client 中,只有在底层 HAL3 的情况下调用 API1 会走到这(在 openCamera 时会有相关的实例化逻辑);
  • Camera3Device 相当于 HAL3 架构下 Framework 层中与 HAL 层进行对接的实例,这部分不区分 API1 还是 API2;
  • startPreview 只打开一路 Stream,对应上 StreamingProcessor。其流程中对应 configureStream 这一动作的逻辑是在 startStream 调用期间完成的。

startPreview

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

  1. Camera2Client/frameworks/av/services/camera/libcameraservice/api1/Camera2Client.cpp
  2. StreamingProcessor/frameworks/av/services/camera/libcameraservice/api1/client2/StreamingProcessor.cpp
  3. Camera3Device && Camera3Device::RequestThread/frameworks/av/services/camera/libcameraservice/device3/Camera3Device.cpp

接下来我会照着上面的时序图,结合具体代码进行更深入一些的解释。

代码分析

下面这部分我只会写我关注到的部分,没有完整覆盖所有的调用逻辑以及相应细节,建议有空时自己走一遍这个流程,印象、理解会深刻许多。

根据时序图来看,可以分成三个重点部分来看:

  1. Camera2Client 中的 startPreview
  2. StreamingProcessor 中的 updatePreviewStream;
  3. 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” 代替。

下面来看一下这里面的流程:

  1. 第 5 行,先把 state 设置为 STOPPED;
  2. 第 6 行,从 StreamingProcessor 实例中获取 preview stream 的 ID,由于是第一次打开预览,这里返回的是 NO_STREAM
  3. 第 8 行,执行 StreamingProcessor 实例的 updatePreviewStream 方法,这个方法后续单独拿出来分析,这里主要作用是创建 preview 这一路 stream,对应地会生成 streamID;
  4. 第 20~22 行,注意这里 previewCallbackFlags 一般是需要 preview callback stream 时候才会设置,而首次打开预览时候这里的 callbacksEnabled 最终值会是 false
  5. 第 26~31 行中,一般走的是 else 分支里面的 deleteStream
  6. 第 33 行,这里把从 StreamingProcessor 创建的 preview stream 加入到 outputStreams 中,这是一个 int 型的 vector,相当于当前 output stream 的 ID 列表;
  7. 第 38~46 行,最开始时说过,传入的参数 restart 为 false,所以会先执行一次 updatePreviewRequest,这个函数主要是把 API1 风格的参数 Parameters 转换成 API2 风格的参数 Metadata;
  8. 第 47 行,这里调用了 startStream,这里面的逻辑会更复杂一些,后面会详细分析,需要注意的是这里会对接到 configureStreams 流程,与 HAL 存在交互;
  9. 第 53 行,预览启动完毕,将 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;

    // 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

关于这段代码:

  1. 第 5~15 行,由于当前还没有 preview stream,所以需要调用 createStream 方法去创建一个 OuputStream,需要注意这里的 device 对应的是 Camera3Device 的实例;
  2. 第 17 行,创建 Stream 完毕后,要给它设置一下 Transform 的信息,这个函数就不深究了。
status_t StreamingProcessor::updatePreviewStream(const Parameters &params) {
   
    
    // 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. 第 1~19 行,这个 createStream 是首先调用到的,它会调用真正实现创建 stream 的 createStream 函数;
  2. 第 31~54 行,这里面走的是 STATUS_UNCONFIGURED 的分支,即直接跳出 switch 逻辑;
  3. 第 61~78 行,这里走的是 HAL_PIXEL_FORMAT_RAW_OPAQUE 分支的部分,主要是第 69~71 行创建了 Camera3OutputStream 实例;
  4. 第 82、84 行,对新创建的 stream 进行一些基本配置,主要关于 StatusTracker 和 BufferManager,这部分就不继续深入了;
  5. 第 86 行,此处把新创建的 stream 加入到 Camera3Device 的成员变量 mOutputStreams 中,它是一个 Set,其中
  • 1
    点赞
  • 13
    收藏
    觉得还不错? 一键收藏
  • 5
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值