Android Q 之MTK代码分析(五)--Camera Hal3 configureStreams

MTK Camera configureStream 流程 

0、前文回顾

 前文已经简单说明CameraHalService服务、Serarch Sensor的过程、以及open、close相机的动作。

 强力建议熟读Camera3.h   Startup and general expected operation sequence

https://www.androidos.net.cn/android/10.0.0_r6/xref/hardware/libhardware/include/hardware/camera3.h

1、camera configureStreams 流程

 1.1 相机api简述

      as we all know Android Camera API的 步骤

  (1)、监听和枚举相机设备  

    get_number_of_cameras、get_camera_characteristic

  (2)、打开设备并连接监听器

    connect、open

  (3)、配\置目标使用情形的输出(如static 、capture、video等)

     configure_stream

    (4)、为目标使用情形创建请求  (5)捕获/重复请求和连拍

    process_capture_request

    (6) 、接受结果metadata和图片数据

    proces_capture_result

    (7)、切换使用情形时,返回第三步

   

1.2 原文阅读

    * 4. The framework calls camera3_device_t->ops->configure_streams() with a list * of input/output streams to the HAL device.

简单翻译-->

framework调用结构体camera_device方法ops调用结构体camera3_device_ops的configure_streams方法配流,camera3_device_t-> ops-> configure_streams(),并把input stream&output stream 的列表作为参数送到Hal层。

1.3 结构体

 hardware/libhardware/include/hardware/camera3.h

camera3_device_ops_t 映射函数指针操作: hardware/libhardware/modules/camera/3_0/Camera.cpp

frameworks/av/services/camera/libcameraservice/device3/Camera3Device.cpp

status_t Camera3Device::configureStreamsLocked(int operatingMode,
        const CameraMetadata& sessionParams, bool notifyRequestThread) {
   

    // Start configuring the streams
    ALOGV("%s: Camera %s: Starting stream configuration", __FUNCTION__, mId.string());

  略...

    config.streams = streams.editArray();

    // Do the HAL configuration; will potentially touch stream
    // max_buffers, usage, and priv fields, as well as data_space and format
    // fields for IMPLEMENTATION_DEFINED formats.

    const camera_metadata_t *sessionBuffer = sessionParams.getAndLock();
    res = mInterface->configureStreams(sessionBuffer, &config, bufferSizes);
    sessionParams.unlock(sessionBuffer);

    if (res == BAD_VALUE) {
        // HAL rejected this set of streams as unsupported, clean up config
        // attempt and return to unconfigured state
        CLOGE("Set of requested inputs/outputs not supported by HAL");
        cancelStreamsConfigurationLocked();
        return BAD_VALUE;
    } else if (res != OK) {
        // Some other kind of error from configure_streams - this is not
        // expected
        SET_ERR_L("Unable to configure streams with HAL: %s (%d)",
                strerror(-res), res);
        return res;
    }

    // Finish all stream configuration immediately.
    // TODO: Try to relax this later back to lazy completion, which should be
    // faster

    if (mInputStream != NULL && mInputStream->isConfiguring()) {
        bool streamReConfigured = false;
        res = mInputStream->finishConfiguration(&streamReConfigured);
        if (res != OK) {
            CLOGE("Can't finish configuring input stream %d: %s (%d)",
                    mInputStream->getId(), strerror(-res), res);
            cancelStreamsConfigurationLocked();
            if ((res == NO_INIT || res == DEAD_OBJECT) && mInputStream->isAbandoned()) {
                return DEAD_OBJECT;
            }
            return BAD_VALUE;
        }
        if (streamReConfigured) {
            mInterface->onStreamReConfigured(mInputStream->getId());
        }
    }

    for (size_t i = 0; i < mOutputStreams.size(); i++) {
        sp<Camera3OutputStreamInterface> outputStream = mOutputStreams[i];
        if (outputStream->isConfiguring() && !outputStream->isConsumerConfigurationDeferred()) {
            bool streamReConfigured = false;
            res = outputStream->finishConfiguration(&streamReConfigured);
            if (res != OK) {
                CLOGE("Can't finish configuring output stream %d: %s (%d)",
                        outputStream->getId(), strerror(-res), res);
                cancelStreamsConfigurationLocked();
                if ((res == NO_INIT || res == DEAD_OBJECT) && outputStream->isAbandoned()) {
                    return DEAD_OBJECT;
                }
                return BAD_VALUE;
            }
            if (streamReConfigured) {
                mInterface->onStreamReConfigured(outputStream->getId());
            }
        }
    }

    // Request thread needs to know to avoid using repeat-last-settings protocol
    // across configure_streams() calls
    if (notifyRequestThread) {
        mRequestThread->configurationComplete(mIsConstrainedHighSpeedConfiguration, sessionParams);
    }

    // Update device state
    const camera_metadata_t *newSessionParams = sessionParams.getAndLock();
    const camera_metadata_t *currentSessionParams = mSessionParams.getAndLock();
    bool updateSessionParams = (newSessionParams != currentSessionParams) ? true : false;
    sessionParams.unlock(newSessionParams);
    mSessionParams.unlock(currentSessionParams);
    if (updateSessionParams)  {
        mSessionParams = sessionParams;
    }

    ALOGV("%s: Camera %s: Stream configuration complete", __FUNCTION__, mId.string());

    // tear down the deleted streams after configure streams.
    mDeletedStreams.clear();

    return OK;
}

status_t Camera3Device::HalInterface::configureStreams(const camera_metadata_t *sessionParams,
        camera3_stream_configuration *config, const std::vector<uint32_t>& bufferSizes) {
    ATRACE_NAME("CameraHal::configureStreams");
 略...

    // See which version of HAL we have
    if (mHidlSession_3_5 != nullptr) {
       略...
    } else if (mHidlSession_3_4 != nullptr) {
        // We do; use v3.4 for the call
        ALOGV("%s: v3.4 device found", __FUNCTION__);
        auto err = mHidlSession_3_4->configureStreams_3_4(
                requestedConfiguration3_4, configStream34Cb);
        res = postprocConfigStream34(err);
        if (res != OK) {
            return res;
        }
    } 
   略...

    return res;
}

vendor/mediatek/proprietary/hardware/mtkcam3/main/hal/device/3.x/device/CameraDevice3SessionImpl.cpp

//V3_4
Return<void>
ThisNamespace::
configureStreams_3_3(const V3_2::StreamConfiguration& requestedConfiguration, configureStreams_3_3_cb _hidl_cb)
{
    CAM_ULOG_APILIFE_GUARD(MOD_CAMERA_DEVICE);
    CAM_TRACE_CALL();

    ::android::status_t status = OK;
    String8 const stateTag(String8::format("-> configure (operationMode:%#x)", requestedConfiguration.operationMode));
    mStateLog.add(stateTag + " +");

    WrappedHalStreamConfiguration halStreamConfiguration;
    {
        ::android::Mutex::Autolock _lOpsLock(mOpsLock);

        int err = NO_INIT;
        status = tryRunCommandLocked(getWaitCommandTimeout(), "onConfigureStreamsLocked", [&, this](){
            err = onConfigureStreamsLocked(requestedConfiguration, halStreamConfiguration);
        });
        if ( status == OK ) {
            status = err;
        }
    }

    _hidl_cb(mapToHidlCameraStatus(status), halStreamConfiguration);

    mStateLog.add(stateTag + " - " + (0==status ? "OK" : ::strerror(-status)));
    return Void();
}

vendor/mediatek/proprietary/hardware/mtkcam3/main/hal/device/3.x/device/CameraDevice3SessionImpl.cpp

auto
ThisNamespace::
onConfigureStreamsLocked(
    const WrappedStreamConfiguration& requestedConfiguration,
    WrappedHalStreamConfiguration& halConfiguration
) -> ::android::status_t
{
    MY_LOGD("+");
    CAM_ULOG_FUNCLIFE_GUARD(MOD_CAMERA_DEVICE);

    ::android::status_t err = OK;

    if  ( ! waitUntilOpenDoneLocked() ) {
        return NO_INIT;
    }
    //
    {
        disableRequesting();
        flushAndWait();
    }
    //
    //
    IAppStreamManager::ConfigAppStreams appStreams;
    auto pAppStreamManager = getSafeAppStreamManager();
    if  ( pAppStreamManager == 0 ) {
        MY_LOGE("Bad AppStreamManager");
        return NO_INIT;
    }
    //
    err = pAppStreamManager->beginConfigureStreams(requestedConfiguration, halConfiguration, appStreams);
    if  ( OK != err ) {
        MY_LOGE("fail to beginConfigureStreams");
        return err;
    }
    //
    //
    {
        auto pPipelineModel = getSafePipelineModel();
        if  ( pPipelineModel == 0 ) {
            MY_LOGE("Bad PipelineModel");
            return NO_INIT;
        }
        //
        auto pParams = std::make_shared<UserConfigurationParams>();
        if ( ! pParams ) {
            MY_LOGE("Bad UserConfigurationParams");
            return NO_INIT;
        }
        pParams->operationMode      = static_cast<uint32_t>(((V3_4::StreamConfiguration&)requestedConfiguration).operationMode);
        //read session parameters
        if ( ((V3_4::StreamConfiguration&)requestedConfiguration).sessionParams.size() > 0 ) {
            // read settings from session parameters
            if ( ! mStaticInfo.mMetadataConverter->convertFromHidl(&((V3_4::StreamConfiguration&)requestedConfiguration).sessionParams, pParams->sessionParams) ) {
                MY_LOGE("Bad Session parameters");
                return -ENODEV;
                }
                //if (getLogLevel() >= 2) {
                    mStaticInfo.mMetadataConverter->dumpAll(pParams->sessionParams, 0);
                //}
        }
        //
        pParams->pStreamInfoBuilderFactory = pAppStreamManager->getAppStreamInfoBuilderFactory();
        //
        {
         CAM_TRACE_NAME("_CLONE_");
#define _CLONE_(dst, src) \
            do { \
                dst.clear(); \
                for ( size_t j=0; j<src.size(); ++j) { \
                    dst.emplace( std::make_pair(src.keyAt(j), src.valueAt(j) ) ); \
                } \
            } while (0) \

        _CLONE_(pParams->vImageStreams,         appStreams.vImageStreams);
        _CLONE_(pParams->vMetaStreams,          appStreams.vMetaStreams);
        _CLONE_(pParams->vMetaStreams_physical, appStreams.vMetaStreams_physical);
        _CLONE_(pParams->vMinFrameDuration,     appStreams.vMinFrameDuration);
        _CLONE_(pParams->vStallFrameDuration,   appStreams.vStallFrameDuration);

#undef _CLONE_
        }
        pParams->vPhysicCameras = appStreams.vPhysicCameras;
        MY_LOGD("pParams.vPhysicCameras(%zu)", pParams->vPhysicCameras.size());
        pParams->configTimestamp = mConfigTimestamp;
        //
        err = pPipelineModel->configure(pParams);   //配置pipeline
        if  ( OK != err ) {
            MY_LOGE("fail to configure pipeline");
            return err;
        }
    }
    //
    //
    err = pAppStreamManager->endConfigureStreams(halConfiguration);
    if  ( OK != err ) {
        MY_LOGE("fail to endConfigureStreams");
        return err;
    }
    //
    //
    enableRequesting();
    MY_LOGD("-");
    return OK;
}

vendor/mediatek/proprietary/hardware/mtkcam3/main/hal/device/3.x/app/AppStreamMgr.cpp

auto
AppStreamMgr::
beginConfigureStreams(
    const V3_5::StreamConfiguration& requestedConfiguration,
    V3_4::HalStreamConfiguration& halConfiguration,
    ConfigAppStreams& rStreams
)   -> int
{
    CAM_ULOGM_FUNCLIFE();

    MY_LOGD("StreamConfiguration=%s", toString(requestedConfiguration).c_str());

    Mutex::Autolock _l(mInterfaceLock);
    //
    auto err = mConfigHandler->beginConfigureStreams(requestedConfiguration, halConfiguration, rStreams);
    //
    //  An emtpy settings buffer cannot be used as the first submitted request
    //  after a configure_streams() call.
    if ( OK == err ) {
        mRequestHandler->reset();
    }
    //
    return err;
}

vendor/mediatek/proprietary/hardware/mtkcam/main/hal/device/3.x/app/AppStreamMgr.ConfigHandler.cpp

简述下这里面干了些啥事

(1)、检测stream

(2)、设置OperationMode

(3)、生成MetaStreamInfo,并把前者加到Stream中

auto
ThisNamespace::
beginConfigureStreams(
    const V3_5::StreamConfiguration& requestedConfiguration,
    V3_4::HalStreamConfiguration& halConfiguration,
    ConfigAppStreams& rStreams
)   -> int
{
    auto addFrameDuration = [this](auto& rStreams, auto const pStreamInfo) {
        for (size_t j = 0; j < mEntryMinDuration.count(); j+=4) {
            if (mEntryMinDuration.itemAt(j    , Type2Type<MINT64>()) == (MINT64)pStreamInfo->getOriImgFormat() &&
                mEntryMinDuration.itemAt(j + 1, Type2Type<MINT64>()) == (MINT64)pStreamInfo->getLandscapeSize().w &&
                mEntryMinDuration.itemAt(j + 2, Type2Type<MINT64>()) == (MINT64)pStreamInfo->getLandscapeSize().h)
            {
                rStreams.vMinFrameDuration.add(
                    pStreamInfo->getStreamId(),
                    mEntryMinDuration.itemAt(j + 3, Type2Type<MINT64>())
                );
                rStreams.vStallFrameDuration.add(
                    pStreamInfo->getStreamId(),
                    mEntryStallDuration.itemAt(j + 3, Type2Type<MINT64>())
                );
                MY_LOGI("[addFrameDuration] format:%" PRId64 " size:%" PRId64 "x%" PRId64 " min_duration:%" PRId64 ", stall_duration:%" PRId64 ,
                    mEntryMinDuration.itemAt(j, Type2Type<MINT64>()),
                    mEntryMinDuration.itemAt(j + 1, Type2Type<MINT64>()),
                    mEntryMinDuration.itemAt(j + 2, Type2Type<MINT64>()),
                    mEntryMinDuration.itemAt(j + 3, Type2Type<MINT64>()),
                    mEntryStallDuration.itemAt(j + 3, Type2Type<MINT64>()));
                break;
            }
        }
        return;
    };
    //
    //
    int err = OK;
    err = checkStreams(requestedConfiguration.v3_4.streams);
    if  ( OK != err ) {
        MY_LOGE("checkStreams failed - StreamConfiguration=%s", toString(requestedConfiguration.v3_4).c_str());
        return err;
    }
    //
    mFrameHandler->setOperationMode((uint32_t)requestedConfiguration.v3_4.operationMode);
    //
    {
        StreamId_T const streamId = eSTREAMID_END_OF_FWK;
        std::string const streamName = "Meta:App:Control";
        auto pStreamInfo = createMetaStreamInfo(streamName.c_str(), streamId);
        mFrameHandler->addConfigStream(pStreamInfo);

        rStreams.vMetaStreams.add(streamId, pStreamInfo);
    }

    mspParsedSMVRBatchInfo = extractSMVRBatchInfo(requestedConfiguration.v3_4);

    //
    halConfiguration.streams.resize(requestedConfiguration.v3_4.streams.size());
    rStreams.vImageStreams.setCapacity(requestedConfiguration.v3_4.streams.size());
    for ( size_t i = 0; i < requestedConfiguration.v3_4.streams.size(); i++ )
    {
        const auto& srcStream = requestedConfiguration.v3_4.streams[i];
              auto& dstStream = halConfiguration.streams[i];
        StreamId_T streamId = srcStream.v3_2.id;
        //
        sp<AppImageStreamInfo> pStreamInfo = mFrameHandler->getConfigImageStream(streamId);
        if ( pStreamInfo == nullptr )                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                          
        {
            pStreamInfo = createImageStreamInfo(srcStream, dstStream);
            if ( pStreamInfo == nullptr ) {
                MY_LOGE("createImageStreamInfo failed - Stream=%s", toString(srcStream).c_str());
                return -ENODEV;
            }
            mFrameHandler->addConfigStream(pStreamInfo.get(), false/*keepBufferCache*/);
        }
        else
        {
            auto generateLogString = [=]() {
                return String8::format("streamId:%d type(%d:%d) "
                    "size(%dx%d:%dx%d) format(%d:%d) dataSpace(%d:%d) "
                    "usage(%#" PRIx64 ":%#" PRIx64 ")",
                    srcStream.v3_2.id, pStreamInfo->getStream().v3_2.streamType, srcStream.v3_2.streamType,
                    pStreamInfo->getStream().v3_2.width, pStreamInfo->getStream().v3_2.height, srcStream.v3_2.width, srcStream.v3_2.height,
                    pStreamInfo->getStream().v3_2.format, srcStream.v3_2.format,
                    pStreamInfo->getStream().v3_2.dataSpace, srcStream.v3_2.dataSpace,
                    pStreamInfo->getStream().v3_2.usage, srcStream.v3_2.usage
                );
            };

            MY_LOGI("stream re-configuration: %s", generateLogString().c_str());

            // refer to google default wrapper implementation:
            // width/height/format must not change, but usage/rotation might need to change
            bool check1 = (srcStream.v3_2.streamType == pStreamInfo->getStream().v3_2.streamType
                        && srcStream.v3_2.width      == pStreamInfo->getStream().v3_2.width
                        && srcStream.v3_2.height     == pStreamInfo->getStream().v3_2.height
                        // && srcStream.v3_2.dataSpace  == pStreamInfo->getStream().v3_2.dataSpace
                        );
            bool check2 = true || (srcStream.v3_2.format == pStreamInfo->getStream().v3_2.format
                        ||(srcStream.v3_2.format == (PixelFormat)pStreamInfo->getImgFormat() &&
                           PixelFormat::IMPLEMENTATION_DEFINED == pStreamInfo->getStream().v3_2.format)
                      //||(pStreamInfo->getStream().v3_2.format == real format of srcStream.v3_2.format &&
                      //   PixelFormat::IMPLEMENTATION_DEFINED == srcStream.v3_2.format)
                        );
            if ( ! check1 || ! check2 ) {
                MY_LOGE("stream configuration changed! %s", generateLogString().c_str());
                return -ENODEV;
            }

            // If usage is chaged, it implies that
            // the real format (flexible yuv/implementation_defined)
            // and the buffer layout may change.
            // In this case, should HAL and Frameworks have to cleanup the buffer handle cache?
            if ( pStreamInfo->getStream().v3_2.usage != srcStream.v3_2.usage ) {
                MY_LOGW("stream usage changed! %s", generateLogString().c_str());
                MY_LOGW("shall HAL and Frameworks have to clear buffer handle cache?");
            }

            // Create a new stream to override the old one, since usage/rotation might need to change.
            pStreamInfo = createImageStreamInfo(srcStream, dstStream);
            mFrameHandler->addConfigStream(pStreamInfo.get(), true/*keepBufferCache*/);
        }

        // check hidl_stream contain physic id or not.
        if(srcStream.physicalCameraId.size() != 0)
        {
            auto& sensorList = rStreams.vPhysicCameras;
            MINT32 vid = std::stoi((std::string)srcStream.physicalCameraId);
            auto pcId = MAKE_HalLogicalDeviceList()->getDeviceIdByVID(vid);
            MY_LOGD("pcid(%d:%s)", pcId, ((std::string)srcStream.physicalCameraId).c_str());
            auto iter = std::find(
                                    sensorList.begin(),
                                    sensorList.end(),
                                    pcId);
            if(iter == sensorList.end())
            {
                sensorList.push_back(pcId);
                //physical settings
                String8 const streamName = String8::format("Meta:App:Physical_%s", ((std::string)srcStream.physicalCameraId).c_str());
                StreamId_T const streamId = eSTREAMID_BEGIN_OF_PHYSIC_ID + (int64_t)pcId;
                auto pMetaStreamInfo = createMetaStreamInfo(streamName.c_str(), streamId, pcId);
                mFrameHandler->addConfigStream(pMetaStreamInfo);
                rStreams.vMetaStreams_physical.add(pcId, pMetaStreamInfo);
            }
        }

        rStreams.vImageStreams.add(streamId, pStreamInfo);
        addFrameDuration(rStreams, pStreamInfo);

        MY_LOGD_IF(getLogLevel()>=2, "Stream: id:%d streamType:%d %dx%d format:0x%x usage:0x%" PRIx64 " dataSpace:0x%x rotation:%d",
                srcStream.v3_2.id, srcStream.v3_2.streamType, srcStream.v3_2.width, srcStream.v3_2.height,
                srcStream.v3_2.format, srcStream.v3_2.usage, srcStream.v3_2.dataSpace, srcStream.v3_2.rotation);
    }
#ifdef MERLINCOMMON_DIFF_720P
    if(requestedConfiguration.v3_4.streams.size() >= 2)
    {
        uint32_t EIS_ON_720P = 0x8104;  //operationmode for eis on 720P video ispprofile
        uint32_t EIS_OFF_720P = 0xf110;  //operationmode for eis off 720p video ispprofile
        uint32_t EIS_ON_DEFAULT = 0x8004;  //operationmode for default eis on (1080P)video ispprofile
        uint32_t EIS_OFF_DEFAULT = 0xf010;  //operationmode for default eis off (1080P)video ispprofile
        uint32_t DEC_720P = 1280;   //width to decide if 720P
        uint32_t operation = (uint32_t)requestedConfiguration.v3_4.operationMode;
        uint32_t videoWidth = (uint32_t)requestedConfiguration.v3_4.streams[1].v3_2.width;  //format 35 size
        uint32_t videoWidth1 = (uint32_t)requestedConfiguration.v3_4.streams[0].v3_2.width;  //format 34 capture size
        MY_LOGD("operationmode %d videoWidth is %d videoWidth1 is %d",operation,videoWidth,videoWidth1);
        if((videoWidth == videoWidth1) && (videoWidth == DEC_720P))
        {
            if(operation == EIS_OFF_DEFAULT)
            {
                MY_LOGD("720P close eis operationmode 0xf110");
                mFrameHandler->setOperationMode(EIS_OFF_720P);
            }
            else if(operation == EIS_ON_DEFAULT)
            {
                MY_LOGD("720P open eis operationmode 0x8104");
                mFrameHandler->setOperationMode(EIS_ON_720P);
            }
        }
    }
#endif

#ifdef LANCELOTCOMMON_VIDEO_CAPTURE_DIFF_720P
    if(requestedConfiguration.v3_4.streams.size() >= 2){
        uint32_t operation = (uint32_t)requestedConfiguration.v3_4.operationMode;
        uint32_t videoWidth = (uint32_t)requestedConfiguration.v3_4.streams[1].v3_2.width;  //format 35 size
        uint32_t videoWidth1 = (uint32_t)requestedConfiguration.v3_4.streams[0].v3_2.width;  //format 34 capture size
        MY_LOGD("operationmode %d videoWidth is %d videoWidth1 is %d",operation,videoWidth,videoWidth1);
            if((videoWidth == videoWidth1) && (videoWidth == 1280)){
                mFrameHandler->setOperationMode(0x810a);
            }
    }
#endif
    //
    return OK;
}

vendor/mediatek/proprietary/hardware/mtkcam3/main/hal/device/3.x/app/AppStreamMgr.FrameHandler.cpp

这块有一些具体的函数就不继续罗列了

2、结语

代码熟练度还不够溜,MTK Code细节不够火候,还需继续深入。我会不定期分享,以便查漏补缺,相互学习。奥里给!!!

猜你喜欢

转载自blog.csdn.net/weixin_38328785/article/details/108581219