camx camera initial

news2024/11/24 3:12:55

 qnx 平台中的camera hal 接口

HAL3Module:chi_hal_override_entry

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

camhal3module.cpp 中的构造函数HAL3Module中

CHIHALOverrideEntry funcCHIHALOverrideEntry = reinterpret_cast<CHIHALOverrideEntry>( 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


/// @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<const camera_module_t*>(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<vendor_tag_ops_t*>(&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<camera3_device_t*>(localDevice);
                m_CamDevices.insert(std::pair<uint32_t, camera3_device_t*>(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<camera3_device*>(&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<const camera3_device_t*>(&m_camera3Device),
                                                          &m_HALCallbacks,
                                                          reinterpret_cast<camera3_stream_configuration_t*>(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<camera_metadata_t*>(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<camera_metadata_t*>(
                                            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<camera3_stream_configuration_t*>(
                CHX_CALLOC(sizeof(camera3_stream_configuration_t)));
            m_pStreamConfig[logicalCameraId]->streams = static_cast<camera3_stream_t**>(
                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<VOID*>(pUsecaseXR);
    }

    if (UsecaseId::Auto == usecaseId)
    {
        pReturnUsecase = reinterpret_cast<VOID*>(pUsecaseAuto);
    }
#else
    pReturnUsecase = reinterpret_cast<VOID*>(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博客

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/989605.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

即拼七人拼团系统开发模式的奖励机制都有哪些?

即拼七人拼团是市场上非常火爆的商业模式之一&#xff0c;它通过团购机制、互动社交和抽奖等方式&#xff0c;有效解决了电商平台的复购难题。不仅可以降低商品价格&#xff0c;还能够增加用户的参与感和购物乐趣&#xff0c;提升平台的用户粘性和产品销量。下面就来具体说一下…

驱动轴相机参数设置Web前端界面开发

一、基于Django的Web应用界面的开发&#xff1a; 在Realtimeresults.html上添加一个按钮组件&#xff0c;获取检测到的轴型和车轮信息&#xff0c;点击后可以获取package.json里存放的json数据&#xff0c;效果如下&#xff1a; 实现逻辑&#xff1a;需要从URL设置、视图函数、…

YOLOV8从零搭建一套目标检测系统(修改model结构必看)附一份工业缺陷检测数据集

目录 1.YOLOV8介绍 2.YOLOV8安装 2.1环境配置 3.数据集准备 1.YOLOV8介绍 Yolov8结构图&#xff1a; YoloV8相对于YoloV5的改进点&#xff1a; Replace the C3 module with the C2f module. Replace the first 6x6 Conv with 3x3 Conv in the Backbone. Delete two Convs …

Mysql--事务

事务 开始之前&#xff0c;让我们先想一个场景&#xff0c;有的时候&#xff0c;为了完成某个工作&#xff0c;需要完成多种sql操作 比如转账 再比如下单 第一步 我的账户余额减少 第二步 商品的库存要减少 第三步 订单表中要新增一项 事务的本质&#xff0c;就是为了把多个操…

Excel数学、工程和科学计算插件:FORMULADESK Studio

如果 Excel 是您的武器 - 让我们磨砺您的剑&#xff01;为整天使用 Excel 的人们提供创新的 Excel 加载项&#xff0c;你需要这个 FORMULADESK Studio。。。 Excel 插件为任何使用 Excel 执行数学、工程和科学计算的人提供了必备工具。 * 将公式视为真正的数学方程 * 为您的公…

vue3中如何实现通过点击不同的按钮切换不同的页面

完成以上需求&#xff0c;我们可以使用vue中的component标签来实现。 component是Vue.js中一个特殊的标签&#xff0c;用于动态地绑定其它组件。它可以与v-bind:is指令一起使用&#xff0c;来决定要渲染哪个组件。下面是示例代码 <template><div class"app-conte…

OpenCV 07(图像滤波器)

一、卷积 什么是图片卷积? 图像卷积就是卷积核在图像上按行滑动遍历像素时不断的相乘求和的过程 步长 步长就是卷积核在图像上移动的步幅. 上面例子中卷积核每次移动一个像素步长的结果, 如果将这个步长修改为2, 结果会如何? 为了充分扫描图片, 步长一般设为1. padding …

【操作系统】电脑上没有IIS怎么办

文章目录 前言一、查看二、解决 前言 有的新机刚开始在计算机-管理-服务下没有IIS网络服务怎么办。 一、查看 桌面计算机/此电脑 鼠标右键&#xff1a;管理 服务和应用 发现没有IIS 二、解决 控制面板 程序和功能 启动或关闭Windows功能 IIS相关的所有功能选中&#xff…

【JavaScript】JS语法入门到实战

文章目录 一、初识JavaScript1. 什么是JavaScript&#xff1f;2. JavaScript 和 HTML 和 CSS 之间的关系3. JavaScript的运行过程4. JavaScript的组成 二、JavaScript的书写形式三、变量1. 输入输出2. 变量的使用3. 数据类型 四、运算符五、分支和循环语句1. 分支语句2. 循环语…

将PyCharm中的终端运行前面的PS修改成当前环境

最近使用Pycharm中的Terminal来pip安装一些pakage&#xff0c;发现Terminal运行前面的显示的是PS&#xff0c;然后输入安装指令报错。“python无法将“pip”项识别为 cmdlet、函数、脚本文件或可运行程序的名称。” 解决方法&#xff1a; 只需要在pycharm的设置中修改一些termi…

Java缓存理解

CPU占用&#xff1a;如果你有某些应用需要消耗大量的cpu去计算&#xff0c;比如正则表达式&#xff0c;如果你使用正则表达式比较频繁&#xff0c;而其又占用了很多CPU的话&#xff0c;那你就应该使用缓存将正则表达式的结果给缓存下来。 数据库IO性能&#xff1a;如果发现有大…

基于YOLOv8和WiderFace数据集的人脸目标检测系统(PyTorch+Pyside6+YOLOv8模型)

摘要&#xff1a;基于YOLOv8和WiderFace数据集的人脸目标检测系统可用于日常生活中检测与定位人脸目标&#xff0c;利用深度学习算法可实现图片、视频、摄像头等方式的目标检测&#xff0c;另外本系统还支持图片、视频等格式的结果可视化与结果导出。本系统采用YOLOv8目标检测算…

数据结构(C语言版)概念、数据类型、线性表

数据结构&#xff08;C语言&#xff09;基本概念 数据的基本单位 数据的基本单位是位&#xff08;bit&#xff09;和字节&#xff08;byte&#xff09;。位是最小的存储单位&#xff0c;它可以表示一个二进制的0或1。字节由8个位组成&#xff0c;用于表示一个字符或数字。在计…

STM32 Nucleo-144开发板开箱bring-up

文章目录 1. 开篇2. 开发环境搭建2.1 下载官方例程2.2 ST-Link安装 3. STM32F446ZE demo工程3.1 STM32F446ZE简介3.2 跑个demo试一试 1. 开篇 最近做项目&#xff0c;用到STM32F446ZET6这款MCU&#xff0c;为了赶进度&#xff0c;前期软件需要提前开发&#xff0c;于是在某宝买…

基于FPGA的RGB图像转Ycbcr实现,包括tb测试文件以及MATLAB辅助验证

目录 1.算法运行效果图预览 2.算法运行软件版本 3.部分核心程序 4.算法理论概述 5.算法完整程序工程 1.算法运行效果图预览 将FPGA的数据导入到matlab进行显示 2.算法运行软件版本 Vivado2019.2 matlab2022a 3.部分核心程序 timescale 1ns / 1ps // // Company: // E…

企业微信后台管理-关联小程序、H5/web

企业微信后台管理-小程序、web 应用-关联小程序应用-绑定h5(web页面的app)企业微信-工作台 应用-关联小程序 企业微信后台管理地址&#xff0c;管理员扫码登录后台管理&#xff0c;找到应用管理-自建-创建应用/小程序。 填写项目相关信息之后&#xff0c;如下图。 点击关联小…

Cpp/Qtday030908cpp基础

目录 目录 自行封装一个栈的类&#xff0c;包含私有成员属性&#xff1a;栈的数组、记录栈顶的变量 成员函数完成&#xff1a;构造函数、析构函数、拷贝构造函数、入栈、出栈、清空栈、判空、判满、获取栈顶元素、求栈的大小 头文件&#xff1a;stack.h 源文件: stack.cp…

数据结构之队列的实现(附源码)

目录 一、队列的概念及结构 二、队列的实现 拓展&#xff1a;循环队列 三、初学的队列以及栈和队列结合的练习题 一、队列的概念及结构 队列&#xff1a;只允许在一端进行插入数据操作&#xff0c;在另一端进行删除数据操作的特殊线性表&#xff0c;队列具有先进先出FIFO(Fi…

jmeter 线程组 Open Model Thread Group 阶梯式压测、高峰流量压测

简介 Open Model Thread Group 是5.4.1 版本中引入的一个实验性线程组&#xff0c;可以弹性模拟负载测试。例如设置多个线程模式&#xff0c;再根据这些线程模式调整不同的并发数、暂停时间。由于Open Model Thread Group 是一个实验性线程组&#xff0c;可能会存在一些限制和不…

英语单词(1)

1.void:空的 2.main:主要的 3.class:类 4.system:系统 5.out: 输出 6.print:打印 7.public:公共的,公用的 8.static:静态的,静止的 9.oracle:甲骨文公司 10.eclipse: java编程语言