camx camera initial

 qnx 平台中的camera hal 接口

HAL3Module:chi_hal_override_entry

在android 的中使用Camx 打开com.qti.chi.override.so进行注册hal ops 操作接口

camhal3module.cpp 中的构造函数HAL3Module中

CHIHALOverrideEntry funcCHIHALOverrideEntry = reinterpret_cast( CamX::OsUtils::LibGetAddr(m_hChiOverrideModuleHandle, "chi_hal_override_entry"));

qnx 中的so 路径 ./camera_qcx/build/qnx/cdk_qcx/core/lib/aarch64/dll-le/com.qti.chi.override.so

camx camera initial_第1张图片


/// @brief HAL Override entry

void chi_hal_override_entry(
    chi_hal_callback_ops_t* callbacks)
{
    ExtensionModule* pExtensionModule = ExtensionModule::GetInstance();

    CHX_ASSERT(NULL != callbacks);

    if (NULL != pExtensionModule)
    {
        callbacks->chi_get_num_cameras                  = chi_get_num_cameras;
        callbacks->chi_get_camera_info                  = chi_get_camera_info;
        callbacks->chi_get_info                         = chi_get_info;
        callbacks->chi_initialize_override_session      = chi_initialize_override_session;
        callbacks->chi_finalize_override_session        = chi_finalize_override_session;
        callbacks->chi_override_process_request         = chi_override_process_request;
        callbacks->chi_teardown_override_session        = chi_teardown_override_session;
        callbacks->chi_extend_open                      = chi_extend_open;
        callbacks->chi_extend_close                     = chi_extend_close;
        callbacks->chi_remap_camera_id                  = chi_remap_camera_id;
        callbacks->chi_modify_settings                  = chi_modify_settings;
        callbacks->chi_get_default_request_settings     = chi_get_default_request_settings;
        callbacks->chi_override_flush                   = chi_override_flush;
        callbacks->chi_override_signal_stream_flush     = chi_override_signal_stream_flush;
        callbacks->chi_override_dump                    = chi_override_dump;
        callbacks->chi_get_physical_camera_info         = chi_get_physical_camera_info;
        callbacks->chi_is_stream_combination_supported  = chi_is_stream_combination_supported;

        callbacks->chi_is_concurrent_stream_combination_supported = chi_is_concurrent_stream_combination_supported;
#if CAMERA3_API_HIGH_PERF
        callbacks->chi_override_start_recurrent_capture_requests  = chi_override_start_recurrent_capture_requests;
        callbacks->chi_override_stop_recurrent_capture_requests   = chi_override_stop_recurrent_capture_requests;
        callbacks->chi_override_set_settings                      = chi_override_set_settings;
        callbacks->chi_override_activate_channel                  = chi_override_activate_channel;
#endif // CAMERA3_API_HIGH_PERF
    }
}

CAMXHAL::Init

类似于android hardware\interfaces\camera\provider\2.4\default\cameraProvider.cpp 的函数CameraProvider::initialize 对camera 进行初始化操作获取注册注册的操作接口camera_common

最终获取的是chi_hal_override_entry注册接口

/**
* @brief
* Initialize CAMX HAL and CSL.
*
* @return
* Status as defined in CamStatus_e.
*/
CamStatus_e CAMXHAL::Init()
{
    CamStatus_e rc = CAMERA_SUCCESS;
    const hw_module_t* hw_module = NULL;

    CAM_TRACE_LOG(STREAM_MGR, "CAMXHAL::Init");
    int ret = hw_get_module(CAMERA_HARDWARE_MODULE_ID, &hw_module);
    if (0 != ret)
    {
        QCX_LOG(STREAM_MGR, ERROR, "Camera module not found");
        rc = CAMERA_EFAILED;
    }
    else
    {
        m_CameraModule = reinterpret_cast(hw_module);
        m_CameraModule->get_vendor_tag_ops(&m_Vtags);
        ret = m_CameraModule->init();
        if (0 != ret)
        {
            QCX_LOG(STREAM_MGR, ERROR, "Camera module init failed");
            rc = CAMERA_EFAILED;
        }
        else
        {
            ret = set_camera_metadata_vendor_ops(const_cast(&m_Vtags));
            if (0 != ret)
            {
                QCX_LOG(STREAM_MGR, ERROR, "set vendor tag ops failed (ret = %d)", ret);
                rc = CAMERA_EFAILED;
            }
            else
            {
                MetaData metaData(&m_Vtags);
                const char sectionName[] = "org.quic.camera.qtimer";
                const char tagName[]     = "timestamp";
                uint32_t   tagId         = 0;
                rc = metaData.GetTagId(tagName, sectionName, &tagId);
                if (CAMERA_SUCCESS != rc)
                {
                    QCX_LOG(STREAM_MGR, ERROR, "GetTagId failed, tagName = %s (result = 0x%x)",
                            tagName, rc);
                }
                else
                {
                    QCX_LOG(STREAM_MGR, DEBUG, "GetTagId successful, time stamp tagId = %u", tagId);
                    m_TimeStampTagId = tagId;
                }
            }
        }
        if (CAMERA_SUCCESS == rc)
        {
            m_NumOfCameras = m_CameraModule->get_number_of_cameras();
            if (m_NumOfCameras < 0)
            {
                QCX_LOG(STREAM_MGR, ERROR, "No camera found");
                rc = CAMERA_EFAILED;
            }
            else
            {
                QCX_LOG(STREAM_MGR, HIGH, "Camera module init success, no. of camera: %u",
                        m_NumOfCameras);
            }
        }

        if (CAMERA_SUCCESS == rc)
        {
            rc = BuildCameraIdMap();
            if (CAMERA_SUCCESS != rc)
            {
                QCX_LOG(STREAM_MGR, ERROR, "Populating logical camera Ids failed(result = 0x%x)",
                        rc);
            }
            else
            {
                QCX_LOG(STREAM_MGR, DEBUG, "Logical camera Ids obtained");
            }
        }
    }
    CAM_TRACE_LOG(STREAM_MGR, "CAMXHAL::Init : End");
    return rc;
}

 CAMXHAL::OpenCamera

调用的是 chi_extend_open函数进行camera的open

Android 中与之对应的是hardware\qcom\camera\qcamera2\QCamera2Factory.cpp

QCamera2Factory::cameraDeviceOpen

/**
 * @brief
 *   Open camera corresponding Stream Session.
 *
 * @param pSession [in, out]
 *   pointer to Stream Session.
 *
 * @return
 *   Status as defined in CamStatus_e.
 */
CamStatus_e CAMXHAL::OpenCamera(StreamSession* pSession)
{
    CamStatus_e rc      = CAMERA_SUCCESS;
    CamStatus_e rcMutex = CAMERA_SUCCESS;
    rcMutex = OSAL_CriticalSectionEnter(m_CamxMutex);
    CAM_TRACE_LOG(STREAM_MGR, "CAMXHAL::OpenCamera");
    if (CAMERA_SUCCESS != rcMutex)
    {
        QCX_LOG(STREAM_MGR, ERROR, "Failed in OSAL_CriticalSectionEnter(rc=%u)", rcMutex);
        rc = rcMutex;
    }
    else
    {
        hw_device_t* localDevice = nullptr;

        uint32_t logicalId = 0xFFFFFFFFU;
        for (uint32_t i = 0; i < pSession->m_NumInputs; i++)
        {
            if (m_CamIdMap.find(pSession->m_InputId[i]) == m_CamIdMap.end())
            {
                QCX_LOG(STREAM_MGR, ERROR, "Logical camera Id not found for physical CamId=%u",
                        pSession->m_InputId[i]);
                rc = CAMERA_EBADPARAM;
                break;
            }
            else
            {
                if (0xFFFFFFFFU == logicalId)
                {
                    logicalId = m_CamIdMap[pSession->m_InputId[i]];
                }
                else
                {
                    if (m_CamIdMap[pSession->m_InputId[i]] != logicalId)
                    {
                        QCX_LOG(STREAM_MGR, ERROR, "Logical camera Id %u for input Id %u is invalid",
                                logicalId, pSession->m_InputId[i]);
                        rc = CAMERA_EBADPARAM;
                        break;
                    }
                }
            }
        }
        if (CAMERA_SUCCESS == rc)
        {
            pSession->m_logicalCameraId = logicalId;
            int ret = m_CameraModule->common.methods->open((const hw_module_t*)m_CameraModule,
                std::to_string(logicalId).c_str(), &localDevice);

            if ((0 != ret) || (nullptr == localDevice))
            {
                QCX_LOG(STREAM_MGR, ERROR, "Camera open failed for camera id: %u", logicalId);
                rc = CAMERA_EFAILED;
            }
            else
            {
                QCX_LOG(STREAM_MGR, HIGH, "Camera opened for camera id: %u", logicalId);
                camera3_device_t* camDevice = reinterpret_cast(localDevice);
                m_CamDevices.insert(std::pair(logicalId, camDevice));
                ret = camDevice->ops->initialize(camDevice, this);
                if (0 != ret)
                {
                    QCX_LOG(STREAM_MGR, ERROR, "Camera device initialize failed for"
                            "camera id: %u", logicalId);
                    rc = CAMERA_EFAILED;
                }
                else
                {
                    QCX_LOG(STREAM_MGR, HIGH, "Camera device initialized for Camera Id: %u",
                            logicalId);
                }
            }
        }
        rcMutex = OSAL_CriticalSectionLeave(m_CamxMutex);
        if (CAMERA_SUCCESS != rcMutex)
        {
            QCX_LOG(STREAM_MGR, ERROR, "Failed in OSAL_CriticalSectionLeave(rc=%u)",rcMutex);
            if (CAMERA_SUCCESS == rc)
            {
                rc = rcMutex;
            }
        }
    }
    CAM_TRACE_LOG(STREAM_MGR, "CAMXHAL::OpenCamera : End");
    return rc;
}

 camDevice->ops->initialize=CamX::initialize 初始化

m_HALCallbacks.ProcessCaptureResult = ProcessCaptureResult

camx 找到在camera hal层的函数指针的映射关系。
  映射到:vendor/qcom/proprietary/camx/src/core/hal/camxhal3entry.cpp 中的

  static Dispatch g_dispatchHAL3(&g_jumpTableHAL3);:
  定义了g_camera3DeviceOps变量: 

static camera3_device_ops_t g_camera3DeviceOps =
{
    CamX::initialize,
    CamX::configure_streams,
    NULL,
    CamX::construct_default_request_settings,
    CamX::process_capture_request,
    NULL,
    CamX::dump,
    CamX::flush,
    {0},
};

camera.provider中如何实现到camera hal层的跳跃,camera service调用到camera provider中的接口方法,现在调用到 camera provider中的 hardware/interfaces/camera/device/3.2/default/CameraDeviceSession.cpp 中的processCaptureRequest(…)方法,最终会调用到

mDevice->ops->process_capture_request 

 initialize

该方法在调用open后紧接着被调用,主要用于将上层的回调接口传入HAL中,一旦有数据或者事件产生,CamX便会通过这些回调接口将数据或者事件上传至调用者,其内部的实现较为简单。

initialize方法中有两个参数,分别是之前通过open方法获取的camera3_device_t结构体和实现了camera3_callback_ops_t的CameraDevice,很显然camera3_device_t结构体并不是重点,所以该方法的主要工作是将camera3_callback_ops_t与CamX关联上,一旦数据准备完成便通过这里camera3_callback_ops_t中回调方法将数据回传到Camera Provider中的CameraDevice中,基本流程可以总结为以下几点:

1.实例化了一个Camera3CbOpsRedirect对象并将其加入了g_HAL3Entry.m_cbOpsList队列中,这样方便之后需要的时候能够顺利拿到该对象。
2.将本地的process_capture_result以及notify方法地址分别赋值给Camera3CbOpsRedirect.cbOps中的process_capture_result以及notify函数指针。
3.将上层传入的回调方法结构体指针pCamera3CbOpsAPI赋值给Camera3CbOpsRedirect.pCbOpsAPI,并将Camera3CbOpsRedirect.cbOps赋值给pCamera3CbOpsAPI,通过JumpTableHal3的initialize方法将pCamera3CbOpsAPI传给HALDevice中的m_pCamera3CbOps成员变量,这样HALDevice中的m_pCamera3CbOps就指向了CamX中本地方法process_capture_result以及notify。

经过这样的一番操作之后,一旦CHI有数据传入便会首先进入到本地方法ProcessCaptureResult,然后在该方法中获取到HALDevice的成员变量m_pCamera3CbOps,进而调用m_pCamera3CbOps中的process_capture_result方法,即camxhal3entry.cpp中定义的process_capture_result方法,然后这个方法中会去调用JumpTableHAL3.process_capture_result方法,该方法最终会去调用Camera3CbOpsRedirect.pCbOpsAPI中的process_capture_result方法,这样就调到从Provider传入的回调方法,将数据顺利给到了CameraCaptureSession中。

配置相机设备数据流

在打开相机应用过程中,App在获取并打开相机设备之后,会调用CameraDevice.createCaptureSession来获取CameraDeviceSession,并且通过Camera api v2标准接口,通知Camera Service,调用其CameraDeviceClient.endConfigure方法,在该方法内部又会去通过HIDL接口ICameraDeviceSession::configureStreams_3_4通知Provider开始处理此次配置需求,在Provider内部,会去通过在调用open流程中获取的camera3_device_t结构体的configure_streams方法来将数据流的配置传入CamX-CHI中,之后由CamX-CHI完成对数据流的配置工作,接下来我们来详细分析下CamX-CHI对于该标准HAL3接口 configure_streams的具体实现:

高通Camera驱动(3)-- configure_streams_高通camx configurestreams_Cam_韦的博客-CSDN博客

 vendor/qcom/proprietary/camx/src/core/hal/camxhaldevice.cpp

CamxResult HALDevice::ConfigureStreams(
    Camera3StreamConfig* pStreamConfigs)
{
    CamxResult result = CamxResultSuccess;
 
    // Validate the incoming stream configurations
    result = CheckValidStreamConfig(pStreamConfigs);
 
    if ((StreamConfigModeConstrainedHighSpeed == pStreamConfigs->operationMode) ||
        (StreamConfigModeSuperSlowMotionFRC == pStreamConfigs->operationMode))
    {
        SearchNumBatchedFrames (pStreamConfigs, &m_usecaseNumBatchedFrames, &m_FPSValue);
        CAMX_ASSERT(m_usecaseNumBatchedFrames > 1);
    }
    else
    {
        // Not a HFR usecase batch frames value need to set to 1.
        m_usecaseNumBatchedFrames = 1;
    }
 
    if (CamxResultSuccess == result)
    {
        ClearFrameworkRequestBuffer();
 
        m_numPipelines = 0;
 
        if (TRUE == m_bCHIModuleInitialized)
        {
            GetCHIAppCallbacks()->chi_teardown_override_session(reinterpret_cast(&m_camera3Device), 0, NULL);
        }
 
        m_bCHIModuleInitialized = CHIModuleInitialize(pStreamConfigs);
 
        if (FALSE == m_bCHIModuleInitialized)
        {
            CAMX_LOG_ERROR(CamxLogGroupHAL, "CHI Module failed to configure streams");
            result = CamxResultEFailed;
        }
        else
        {
            CAMX_LOG_VERBOSE(CamxLogGroupHAL, "CHI Module configured streams ... CHI is in control!");
        }
    }
 
    return result;
}
  

1)如果之前有过配流的操作,m_bCHIModuleInitialized会被赋值,然后销毁 session的操作

2)同文件下调用CHIModuleInitialize函数操作,然后m_bCHIModuleInitialized赋值

BOOL HALDevice::CHIModuleInitialize(
    Camera3StreamConfig* pStreamConfigs)
{
    BOOL isOverrideEnabled = FALSE;
 
    if (TRUE == HAL3Module::GetInstance()->IsCHIOverrideModulePresent())
    {
        /// @todo (CAMX-1518) Handle private data from Override module
        VOID*                   pPrivateData;
        chi_hal_callback_ops_t* pCHIAppCallbacks  = GetCHIAppCallbacks();
 
        pCHIAppCallbacks->chi_initialize_override_session(GetCameraId(),
                                                          reinterpret_cast(&m_camera3Device),
                                                          &m_HALCallbacks,
                                                          reinterpret_cast(pStreamConfigs),
                                                          &isOverrideEnabled,
                                                          &pPrivateData);
    }
 
    return isOverrideEnabled;
}

vendor/qcom/proprietary/chi-cdk/vendor/chioverride/default/chxextensioninterface.cpp

static CDKResult chi_initialize_override_session(
    uint32_t                        cameraId,
    const camera3_device_t*         camera3_device,
    const chi_hal_ops_t*            chiHalOps,
    camera3_stream_configuration_t* stream_config,
    int*                            override_config,
    void**                          priv)
{
    ExtensionModule* pExtensionModule = ExtensionModule::GetInstance();
 
    pExtensionModule->InitializeOverrideSession(cameraId, camera3_device, chiHalOps, stream_config, override_config, priv);
 
    return CDKResultSuccess;
}

 vendor/qcom/proprietary/chi-cdk/vendor/chioverride/default/chxextensionmodule.cpp

CDKResult ExtensionModule::InitializeOverrideSession(
    uint32_t                        logicalCameraId,
    const camera3_device_t*         pCamera3Device,
    const chi_hal_ops_t*            chiHalOps,
    camera3_stream_configuration_t* pStreamConfig,
    int*                            pIsOverrideEnabled,
    VOID**                          pPrivate)
{
    CDKResult          result             = CDKResultSuccess;
    UINT32             modeCount          = 0;
    ChiSensorModeInfo* pAllModes          = NULL;
    UINT32             fps                = *m_pDefaultMaxFPS;
    BOOL               isVideoMode        = FALSE;
    uint32_t           operation_mode;
    static BOOL        fovcModeCheck      = EnableFOVCUseCase();
    UsecaseId          selectedUsecaseId  = UsecaseId::NoMatch;
    UINT               minSessionFps      = 0;
    UINT               maxSessionFps      = 0;
 
    *pPrivate             = NULL;
    *pIsOverrideEnabled   = FALSE;
    m_aFlushInProgress    = FALSE;
    m_firstResult         = FALSE;
    m_hasFlushOccurred    = FALSE;
 
    if (NULL == m_hCHIContext)
    {
        m_hCHIContext = g_chiContextOps.pOpenContext();
    }
 
    ChiVendorTagsOps vendorTagOps = { 0 };
    g_chiContextOps.pTagOps(&vendorTagOps);
    operation_mode                = pStreamConfig->operation_mode >> 16;
    operation_mode                = operation_mode & 0x000F;
    pStreamConfig->operation_mode = pStreamConfig->operation_mode & 0xFFFF;
 
    for (UINT32 stream = 0; stream < pStreamConfig->num_streams; stream++)
    {
        if (0 != (pStreamConfig->streams[stream]->usage & GrallocUsageHwVideoEncoder))
        {
            isVideoMode = TRUE;
            break;
        }
    }
 
    if ((isVideoMode == TRUE) && (operation_mode != 0))
    {
        UINT32             numSensorModes  = m_logicalCameraInfo[logicalCameraId].m_cameraCaps.numSensorModes;
        CHISENSORMODEINFO* pAllSensorModes = m_logicalCameraInfo[logicalCameraId].pSensorModeInfo;
 
        if ((operation_mode - 1) >= numSensorModes)
        {
            result = CDKResultEOverflow;
            CHX_LOG_ERROR("operation_mode: %d, numSensorModes: %d", operation_mode, numSensorModes);
        }
        else
        {
            fps = pAllSensorModes[operation_mode - 1].frameRate;
        }
    }
    m_pResourcesUsedLock->Lock();
 
    if (m_totalResourceBudget > CostOfAnyCurrentlyOpenLogicalCameras())
    {
        UINT32 myLogicalCamCost = CostOfLogicalCamera(logicalCameraId, pStreamConfig);
        if (myLogicalCamCost > (m_totalResourceBudget - CostOfAnyCurrentlyOpenLogicalCameras()))
        {
            CHX_LOG_ERROR("Insufficient HW resources! myLogicalCamCost = %d, remaining cost = %d",
                myLogicalCamCost, (m_totalResourceBudget - CostOfAnyCurrentlyOpenLogicalCameras()));
            result = CamxResultEResource;
        }
        else
        {
            m_IFEResourceCost[logicalCameraId] = myLogicalCamCost;
            m_resourcesUsed                   += myLogicalCamCost;
        }
    }
    else
    {
        CHX_LOG_ERROR("Insufficient HW resources! TotalResourceCost = %d, CostOfAnyCurrentlyOpencamera = %d",
            m_totalResourceBudget, CostOfAnyCurrentlyOpenLogicalCameras());
        result = CamxResultEResource;
    }
    m_pResourcesUsedLock->Unlock();
 
    if (CDKResultSuccess == result)
    {
#if defined(CAMX_ANDROID_API) && (CAMX_ANDROID_API >= 28) //Android-P or better
        camera_metadata_t *metadata = const_cast(pStreamConfig->session_parameters);
 
        camera_metadata_entry_t entry = { 0 };
        entry.tag = ANDROID_CONTROL_AE_TARGET_FPS_RANGE;
 
        // The client may choose to send NULL sesssion parameter, which is fine. For example, torch mode
        // will have NULL session param.
        if (metadata != NULL)
        {
            int ret = find_camera_metadata_entry(metadata, entry.tag, &entry);
 
            if(ret == 0) {
                minSessionFps = entry.data.i32[0];
                maxSessionFps = entry.data.i32[1];
                m_usecaseMaxFPS = maxSessionFps;
            }
        }
#endif
 
        CHIHANDLE    staticMetaDataHandle = const_cast(
                                            m_logicalCameraInfo[logicalCameraId].m_cameraInfo.static_camera_characteristics);
        UINT32       metaTagPreviewFPS    = 0;
        UINT32       metaTagVideoFPS      = 0;
        CHITAGSOPS   vendorTagOps;
 
        m_previewFPS           = 0;
        m_videoFPS             = 0;
        GetInstance()->GetVendorTagOps(&vendorTagOps);
 
        result = vendorTagOps.pQueryVendorTagLocation("org.quic.camera2.streamBasedFPS.info", "PreviewFPS",
                                                      &metaTagPreviewFPS);
        if (CDKResultSuccess == result)
        {
            vendorTagOps.pGetMetaData(staticMetaDataHandle, metaTagPreviewFPS, &m_previewFPS,
                                      sizeof(m_previewFPS));
        }
 
        result = vendorTagOps.pQueryVendorTagLocation("org.quic.camera2.streamBasedFPS.info", "VideoFPS", &metaTagVideoFPS);
        if (CDKResultSuccess == result)
        {
            vendorTagOps.pGetMetaData(staticMetaDataHandle, metaTagVideoFPS, &m_videoFPS,
                                      sizeof(m_videoFPS));
        }
 
        if ((StreamConfigModeConstrainedHighSpeed == pStreamConfig->operation_mode) ||
            (StreamConfigModeSuperSlowMotionFRC == pStreamConfig->operation_mode))
        {
            SearchNumBatchedFrames(logicalCameraId, pStreamConfig,
                                   &m_usecaseNumBatchedFrames, &m_usecaseMaxFPS, maxSessionFps);
            if (480 > m_usecaseMaxFPS)
            {
                m_CurrentpowerHint = PERF_LOCK_POWER_HINT_VIDEO_ENCODE_HFR;
            }
            else
            {
                // For 480FPS or higher, require more aggresive power hint
                m_CurrentpowerHint = PERF_LOCK_POWER_HINT_VIDEO_ENCODE_HFR_480FPS;
            }
        }
        else
        {
            // Not a HFR usecase, batch frames value need to be set to 1.
            m_usecaseNumBatchedFrames = 1;
            if (maxSessionFps == 0)
            {
                m_usecaseMaxFPS = fps;
            }
            if (TRUE == isVideoMode)
            {
                if (30 >= m_usecaseMaxFPS)
                {
                    m_CurrentpowerHint = PERF_LOCK_POWER_HINT_VIDEO_ENCODE;
                }
                else
                {
                    m_CurrentpowerHint = PERF_LOCK_POWER_HINT_VIDEO_ENCODE_60FPS;
                }
            }
            else
            {
                m_CurrentpowerHint = PERF_LOCK_POWER_HINT_PREVIEW;
            }
        }
 
        if ((NULL != m_pPerfLockManager[logicalCameraId]) && (m_CurrentpowerHint != m_previousPowerHint))
        {
            m_pPerfLockManager[logicalCameraId]->ReleasePerfLock(m_previousPowerHint);
        }
 
        // Example [B == batch]: (240 FPS / 4 FPB = 60 BPS) / 30 FPS (Stats frequency goal) = 2 BPF i.e. skip every other stats
        *m_pStatsSkipPattern = m_usecaseMaxFPS / m_usecaseNumBatchedFrames / 30;
        if (*m_pStatsSkipPattern < 1)
        {
            *m_pStatsSkipPattern = 1;
        }
 
        m_VideoHDRMode = (StreamConfigModeVideoHdr == pStreamConfig->operation_mode);
 
        m_torchWidgetUsecase = (StreamConfigModeQTITorchWidget == pStreamConfig->operation_mode);
 
        // this check is introduced to avoid set *m_pEnableFOVC == 1 if fovcEnable is disabled in
        // overridesettings & fovc bit is set in operation mode.
        // as well as to avoid set,when we switch Usecases.
        if (TRUE == fovcModeCheck)
        {
            *m_pEnableFOVC = ((pStreamConfig->operation_mode & StreamConfigModeQTIFOVC) == StreamConfigModeQTIFOVC) ? 1 : 0;
        }
 
        SetHALOps(chiHalOps, logicalCameraId);
 
        m_logicalCameraInfo[logicalCameraId].m_pCamera3Device = pCamera3Device;
 
        selectedUsecaseId = m_pUsecaseSelector->GetMatchingUsecase(&m_logicalCameraInfo[logicalCameraId],
                                                                   pStreamConfig);
 
        CHX_LOG_CONFIG("Session_parameters FPS range %d:%d, previewFPS %d, videoFPS %d,"
                       "BatchSize: %u FPS: %u SkipPattern: %u,"
                       "cameraId = %d selected use case = %d",
                       minSessionFps,
                       maxSessionFps,
                       m_previewFPS,
                       m_videoFPS,
                       m_usecaseNumBatchedFrames,
                       m_usecaseMaxFPS,
                       *m_pStatsSkipPattern,
                       logicalCameraId,
                       selectedUsecaseId);
 
        // FastShutter mode supported only in ZSL usecase.
        if ((pStreamConfig->operation_mode == StreamConfigModeFastShutter) &&
            (UsecaseId::PreviewZSL         != selectedUsecaseId))
        {
            pStreamConfig->operation_mode = StreamConfigModeNormal;
        }
        m_operationMode[logicalCameraId] = pStreamConfig->operation_mode;
    }
 
    if (UsecaseId::NoMatch != selectedUsecaseId)
    {
        m_pSelectedUsecase[logicalCameraId] =
            m_pUsecaseFactory->CreateUsecaseObject(&m_logicalCameraInfo[logicalCameraId],
                                                   selectedUsecaseId, pStreamConfig);
 
        if (NULL != m_pSelectedUsecase[logicalCameraId])
        {
            m_pStreamConfig[logicalCameraId] = static_cast(
                CHX_CALLOC(sizeof(camera3_stream_configuration_t)));
            m_pStreamConfig[logicalCameraId]->streams = static_cast(
                CHX_CALLOC(sizeof(camera3_stream_t*) * pStreamConfig->num_streams));
            m_pStreamConfig[logicalCameraId]->num_streams = pStreamConfig->num_streams;
 
            for (UINT32 i = 0; i< m_pStreamConfig[logicalCameraId]->num_streams; i++)
            {
                m_pStreamConfig[logicalCameraId]->streams[i] = pStreamConfig->streams[i];
            }
 
            m_pStreamConfig[logicalCameraId]->operation_mode = pStreamConfig->operation_mode;
 
            // use camera device / used for recovery only for regular session
            m_SelectedUsecaseId[logicalCameraId] = (UINT32)selectedUsecaseId;
            CHX_LOG_CONFIG("Logical cam Id = %d usecase addr = %p", logicalCameraId, m_pSelectedUsecase[
                logicalCameraId]);
 
            m_pCameraDeviceInfo[logicalCameraId].m_pCamera3Device = pCamera3Device;
 
            *pIsOverrideEnabled = TRUE;
        }
        else
        {
            CHX_LOG_ERROR("For cameraId = %d CreateUsecaseObject failed", logicalCameraId);
            m_logicalCameraInfo[logicalCameraId].m_pCamera3Device = NULL;
 
            m_pResourcesUsedLock->Lock();
            // Reset the m_resourcesUsed & m_IFEResourceCost if usecase creation failed
            if (m_resourcesUsed >= m_IFEResourceCost[logicalCameraId])                   // to avoid underflow
            {
                m_resourcesUsed                   -= m_IFEResourceCost[logicalCameraId]; // reduce the total cost
                m_IFEResourceCost[logicalCameraId] = 0;
            }
            m_pResourcesUsedLock->Unlock();
        }
    }
 
    return result;
}

     (1) 判断是否是视频模式,做帧率的操作

     (2) 获取camera资源消耗情况,并对相关参数赋值

   (3)根据logicalCameraId 匹配 usecase

   (4)根据usecaseId 创建usecase

 vendor/qcom/proprietary/chi-cdk/vendor/chioverride/default/chxutils.cpp

UsecaseId UsecaseSelector::GetMatchingUsecase(
    const LogicalCameraInfo*        pCamInfo,
    camera3_stream_configuration_t* pStreamConfig)
{
    UsecaseId usecaseId = UsecaseId::Default;
    UINT32 VRDCEnable = ExtensionModule::GetInstance()->GetDCVRMode();
    if ((pStreamConfig->num_streams == 2) && IsQuadCFASensor(pCamInfo) &&
        (LogicalCameraType_Default == pCamInfo->logicalCameraType))
    {
        // need to validate preview size <= binning size, otherwise return error
 
        /// If snapshot size is less than sensor binning size, select defaut zsl usecase.
        /// Only if snapshot size is larger than sensor binning size, select QuadCFA usecase.
        /// Which means for snapshot in QuadCFA usecase,
        ///   - either do upscale from sensor binning size,
        ///   - or change sensor mode to full size quadra mode.
        if (TRUE == QuadCFAMatchingUsecase(pCamInfo, pStreamConfig))
        {
            usecaseId = UsecaseId::QuadCFA;
            CHX_LOG_CONFIG("Quad CFA usecase selected");
            return usecaseId;
        }
    }
 
    if (pStreamConfig->operation_mode == StreamConfigModeSuperSlowMotionFRC)
    {
        usecaseId = UsecaseId::SuperSlowMotionFRC;
        CHX_LOG_CONFIG("SuperSlowMotionFRC usecase selected");
        return usecaseId;
    }
 
    /// Reset the usecase flags
    VideoEISV2Usecase   = 0;
    VideoEISV3Usecase   = 0;
    GPURotationUsecase  = FALSE;
    GPUDownscaleUsecase = FALSE;
 
    if ((NULL != pCamInfo) && (pCamInfo->numPhysicalCameras > 1) && VRDCEnable)
    {
        CHX_LOG_CONFIG("MultiCameraVR usecase selected");
        usecaseId = UsecaseId::MultiCameraVR;
    }
    else if ((NULL != pCamInfo) && (pCamInfo->numPhysicalCameras > 1) && (pStreamConfig->num_streams > 1))
    {
        CHX_LOG_CONFIG("MultiCamera usecase selected");
        usecaseId = UsecaseId::MultiCamera;
    }
    else
    {
        switch (pStreamConfig->num_streams)
        {
            case 2:
                if (TRUE == IsRawJPEGStreamConfig(pStreamConfig))
                {
                    CHX_LOG_CONFIG("Raw + JPEG usecase selected");
                    usecaseId = UsecaseId::RawJPEG;
                    break;
                }
 
                /// @todo Enable ZSL by setting overrideDisableZSL to FALSE
                if (FALSE == m_pExtModule->DisableZSL())
                {
                    if (TRUE == IsPreviewZSLStreamConfig(pStreamConfig))
                    {
                        usecaseId = UsecaseId::PreviewZSL;
                        CHX_LOG_CONFIG("ZSL usecase selected");
                    }
                }
 
                if(TRUE == m_pExtModule->UseGPURotationUsecase())
                {
                    CHX_LOG_CONFIG("GPU Rotation usecase flag set");
                    GPURotationUsecase = TRUE;
                }
 
                if (TRUE == m_pExtModule->UseGPUDownscaleUsecase())
                {
                    CHX_LOG_CONFIG("GPU Downscale usecase flag set");
                    GPUDownscaleUsecase = TRUE;
                }
 
                if (TRUE == m_pExtModule->EnableMFNRUsecase())
                {
                    if (TRUE == MFNRMatchingUsecase(pStreamConfig))
                    {
                        usecaseId = UsecaseId::MFNR;
                        CHX_LOG_CONFIG("MFNR usecase selected");
                    }
                }
 
                if (TRUE == m_pExtModule->EnableHFRNo3AUsecas())
                {
                    CHX_LOG_CONFIG("HFR without 3A usecase flag set");
                    HFRNo3AUsecase = TRUE;
                }
 
                break;
 
            case 3:
                VideoEISV2Usecase = m_pExtModule->EnableEISV2Usecase();
                VideoEISV3Usecase = m_pExtModule->EnableEISV3Usecase();
 
                if(TRUE == IsRawJPEGStreamConfig(pStreamConfig))
                {
                    CHX_LOG_CONFIG("Raw + JPEG usecase selected");
                    usecaseId = UsecaseId::RawJPEG;
                }
                else if((FALSE == IsVideoEISV2Enabled(pStreamConfig)) && (FALSE == IsVideoEISV3Enabled(pStreamConfig)) &&
                    (TRUE == IsVideoLiveShotConfig(pStreamConfig)))
                {
                    CHX_LOG_CONFIG("Video With Liveshot, ZSL usecase selected");
                    usecaseId = UsecaseId::VideoLiveShot;
                }
 
                break;
 
            case 4:
                if(TRUE == IsYUVInBlobOutConfig(pStreamConfig))
                {
                    CHX_LOG_CONFIG("YUV callback and Blob");
                    usecaseId = UsecaseId::YUVInBlobOut;
                }
 
                break;
 
            default:
                CHX_LOG_CONFIG("Default usecase selected");
                break;
 
        }
    }
 
    if (TRUE == ExtensionModule::GetInstance()->IsTorchWidgetUsecase())
    {
        CHX_LOG_CONFIG("Torch widget usecase selected");
        usecaseId = UsecaseId::Torch;
    }
 
    CHX_LOG_INFO("usecase ID:%d",usecaseId);
    return usecaseId;
}

 (1)匹配usecase:根据 stream_number、operation_mode、numPhysicalCameras来判断选择哪个usecaseId

  vendor/qcom/proprietary/chi-cdk/vendor/chioverride/default/chxusecaseutils.cpp 

Usecase* UsecaseFactory::CreateUsecaseObject(
    LogicalCameraInfo*              pLogicalCameraInfo,     ///< camera info
    UsecaseId                       usecaseId,              ///< Usecase Id
    camera3_stream_configuration_t* pStreamConfig)          ///< Stream config
{
    Usecase* pUsecase  = NULL;
    UINT     camera0Id = pLogicalCameraInfo->ppDeviceInfo[0]->cameraId;
 
    switch (usecaseId)
    {
        case UsecaseId::PreviewZSL:
        case UsecaseId::VideoLiveShot:
            pUsecase = AdvancedCameraUsecase::Create(pLogicalCameraInfo, pStreamConfig, usecaseId);
            break;
        case UsecaseId::MultiCamera:
            {
#if defined(CAMX_ANDROID_API) && (CAMX_ANDROID_API >= 28) //Android-P or better
 
                LogicalCameraType logicalCameraType = m_pExtModule->GetCameraType(pLogicalCameraInfo->cameraId);
 
                if (LogicalCameraType_DualApp == logicalCameraType)
                {
                    pUsecase = UsecaseDualCamera::Create(pLogicalCameraInfo, pStreamConfig);
                }
                else
#endif
                {
                    pUsecase = UsecaseMultiCamera::Create(pLogicalCameraInfo, pStreamConfig);
                }
                break;
            }
        case UsecaseId::MultiCameraVR:
            //pUsecase = UsecaseMultiVRCamera::Create(pLogicalCameraInfo, pStreamConfig);
            break;
        case UsecaseId::QuadCFA:
            if (TRUE == ExtensionModule::GetInstance()->UseFeatureForQuadCFA())
            {
                pUsecase = AdvancedCameraUsecase::Create(pLogicalCameraInfo, pStreamConfig, usecaseId);
            }
            else
            {
                pUsecase = UsecaseQuadCFA::Create(pLogicalCameraInfo, pStreamConfig);
            }
            break;
        case UsecaseId::Torch:
            pUsecase = UsecaseTorch::Create(camera0Id, pStreamConfig);
            break;
#if (!defined(LE_CAMERA)) // SuperSlowMotion not supported in LE
        case UsecaseId::SuperSlowMotionFRC:
            pUsecase = UsecaseSuperSlowMotionFRC::Create(pLogicalCameraInfo, pStreamConfig);
            break;
#endif
        default:
            pUsecase = AdvancedCameraUsecase::Create(pLogicalCameraInfo, pStreamConfig, usecaseId);
            break;
    }
 
    return pUsecase;
}

  

(1)创建usecase:根据usecaseId选择,创建不同的usecase(AdvancedCameraUsecase :                                                                                             ZSL、VideoLiveShot

                                                                                      UsecaseDualCamera:双摄

                                                                                       UsecaseMultiCamera:多摄

                                                                                       UsecaseQuadCFA:四合一、九合一处理

                                                                                       UsecaseTorch:闪光灯模式

                                                                                        UsecaseSuperSlowMotionFRC:慢动作

qnx  UsecaseFactory::CreateUsecaseObject
apps/qnx_ap/AMSS/multimedia/qcamera/camera_qcx/cdk_qcx/core/chiusecase/chxusecaseutils.cpp


// UsecaseFactory::CreateUsecaseObject

VOID* UsecaseFactory::CreateUsecaseObject(
    LogicalCameraInfo*              pLogicalCameraInfo,     ///< camera info
    UsecaseId                       usecaseId,              ///< Usecase Id
    camera3_stream_configuration_t* pStreamConfig,          ///< Stream config
    ChiMcxConfigHandle              hDescriptorConfig)      ///< mcx config
{
    Usecase*     pUsecase       = NULL;
    UsecaseXR*   pUsecaseXR     = NULL;
    UsecaseAuto* pUsecaseAuto   = NULL;
    VOID*        pReturnUsecase = NULL;

    switch (usecaseId)
    {
        case UsecaseId::MultiCameraVR:
            //pUsecase = UsecaseMultiVRCamera::Create(pLogicalCameraInfo, pStreamConfig);
            break;
#ifndef __QNXNTO__
        case UsecaseId::Torch:
            pUsecase = UsecaseTorch::Create(pLogicalCameraInfo, pStreamConfig);
            break;
        case UsecaseId::AON:
            pUsecase = CHXUsecaseAON::Create(pLogicalCameraInfo);
            break;
#endif // !defined(QNXNTO)
#if CAMERA3_API_HIGH_PERF
#ifndef __QNXNTO__
        case UsecaseId::XR:
            pUsecaseXR = UsecaseXR::Create(pLogicalCameraInfo, pStreamConfig);
            break;
#endif // !defined(QNXNTO)
        case UsecaseId::Auto:
            pUsecaseAuto = UsecaseAuto::Create(pLogicalCameraInfo, pStreamConfig);
            break;
        default:
            break;
#else
        case UsecaseId::PreviewZSL:
#ifndef __QNXNTO__
        case UsecaseId::VideoLiveShot:
            pUsecase = AdvancedCameraUsecase::Create(pLogicalCameraInfo, pStreamConfig, usecaseId);
            break;
#if !defined(LE_CAMERA) && !defined(__QNXNTO__)
        case UsecaseId::MultiCamera:
            if ((LogicalCameraType::LogicalCameraType_Default == pLogicalCameraInfo->logicalCameraType) &&
                (pLogicalCameraInfo->numPhysicalCameras > 1))
            {
                pUsecase = ChiMulticameraBase::Create(pLogicalCameraInfo, pStreamConfig, hDescriptorConfig);
            }
            break;
#endif // !defined(LE_CAMERA)
        case UsecaseId::QuadCFA:
            pUsecase = AdvancedCameraUsecase::Create(pLogicalCameraInfo, pStreamConfig, usecaseId);
            break;
        case UsecaseId::Depth:
            pUsecase = AdvancedCameraUsecase::Create(pLogicalCameraInfo, pStreamConfig, usecaseId);
            break;
#endif // !defined(QNXNTO)
#if CAMERA3_API_HIGH_PERF
        case UsecaseId::Auto:
            pUsecaseAuto = UsecaseAuto::Create(pLogicalCameraInfo, pStreamConfig);
            break;
#endif // CAMERA3_API_HIGH_PERF
        default:
#ifndef __QNXNTO__
            pUsecase = AdvancedCameraUsecase::Create(pLogicalCameraInfo, pStreamConfig, usecaseId);
#endif
            break;
#endif // CAMERA3_API_HIGH_PERF
    }

#if CAMERA3_API_HIGH_PERF
    if (UsecaseId::XR == usecaseId)
    {
        pReturnUsecase = reinterpret_cast(pUsecaseXR);
    }

    if (UsecaseId::Auto == usecaseId)
    {
        pReturnUsecase = reinterpret_cast(pUsecaseAuto);
    }
#else
    pReturnUsecase = reinterpret_cast(pUsecase);
#endif // CAMERA3_API_HIGH_PERF

    return pReturnUsecase;
}

配置数据流是整个CamX-CHI流程比较重要的一环,其中主要包括两个阶段:

1.选择UsecaseId
2.根据选择的UsecaseId创建Usecase

 Camx 基本组件及其结构关系_yaoming168的博客-CSDN博客

Camera camx代码结构、编译、代码流程简介_camx 编译-CSDN博客

Camera 初始化(Open)二(HAL3中Open过程)_cameramodule::open_zhuyong006的博客-CSDN博客

你可能感兴趣的:(c++)