Android : Camera之camx hal架構

1、camx的代碼結構node

  目前主流的機型都使用camx架構,這個架構和以前架構的主要區別就是 芯片接口層的代碼從hardware/qcom 遷移到 vendor/qcom/proprietary/下面,
  咱們主要關注的camera hal層的源碼也是放在vendor/qcom/proprietary/camx/下面。
  android

 

2、camx 編譯:shell

  camx的核心目錄是 vendor/qcom/proprietary/camx/src/ 目錄下面:session

total 40
drwxrwxr-x 10 lxl lxl 4096  4月  4 10:52 ./
drwxrwxr-x  4 lxl lxl 4096  4月  4 10:52 ../
drwxrwxr-x  3 lxl lxl 4096  4月  4 10:52 chiiqutils/
drwxrwxr-x  7 lxl lxl 4096  4月  4 10:56 core/
drwxrwxr-x  7 lxl lxl 4096  4月  4 10:52 csl/
drwxrwxr-x 14 lxl lxl 4096  4月  4 10:52 hwl/
drwxrwxr-x  3 lxl lx 4096  4月  4 10:52 lib/
drwxrwxr-x  3 lxl lxl 4096  4月  4 10:52 osutils/
drwxrwxr-x 11 lxl lxl 4096  4月  4 10:52 swl/
drwxrwxr-x  3 lxl lxl 4096  4月  4 10:52 utils/

  核心的Android.mk在 ./lib/build/android/Android.mk 中。
  其中包括的靜態庫以下:架構

# Libraries to link
LOCAL_STATIC_LIBRARIES :=   \
    libcamxcore             \
    libcamxchi              \
    libcamxcsl              \
    libcamxofflinestats     \
    libnc                   \
    libcamxncs              \
    libifestriping          \
    libstriping

LOCAL_WHOLE_STATIC_LIBRARIES := \
    libcamxdspstreamer          \
    libcamxhwlbps               \
    libcamxgenerated            \
    libcamxhal                  \
    libcamxhalutils             \
    libcamxhwlfd                \
    libcamxhwlife               \
    libcamxhwlipe               \
    libcamxhwliqmodule          \
    libcamxswlfdmanager         \
    libcamxswljpeg              \
    libcamxhwljpeg              \
    libcamxhwllrme              \
    libcamxswlransac            \
    libcamxhwltitan17x          \
    libcamxiqsetting            \
    libcamxosutils              \
    libcamxstats                \
    libcamxsensor               \
    libcamxutils

  這些靜態庫都是camx或者其餘的目錄下編譯的,編譯工程的時候,咱們要先編譯這些靜態庫,而後編譯camx的動態庫(/vendor/lib/hw/camera.qcom.so)。app

 

3、camx 代碼流程分析:ide

  camera.provider中如何實現到camera hal層的跳躍,camera service調用到camera provider中的接口方法,如今調用到 camera provider中的 hardware/interfaces/camera/device/3.2/default/CameraDeviceSession.cpp 中的processCaptureRequest(...)方法,最終會調用到:
  status_t ret = mDevice->ops->process_capture_request(mDevice, &halRequest);
  這個mDevice->ops 就是 hardware/libhardware/include/hardware/camera3.h 中的 camera3_device_ops 結構體: (參考:https://www.jianshu.com/p/099cc3b0ab25函數

typedef struct camera3_device_ops {
    int (*initialize)(const struct camera3_device *,
            const camera3_callback_ops_t *callback_ops);
    int (*configure_streams)(const struct camera3_device *,
            camera3_stream_configuration_t *stream_list);
    int (*register_stream_buffers)(const struct camera3_device *,
            const camera3_stream_buffer_set_t *buffer_set);
    const camera_metadata_t* (*construct_default_request_settings)(
            const struct camera3_device *,
            int type);
    int (*process_capture_request)(const struct camera3_device *,
            camera3_capture_request_t *request);
    void (*get_metadata_vendor_tag_ops)(const struct camera3_device*,
            vendor_tag_query_ops_t* ops);
    void (*dump)(const struct camera3_device *, int fd);
    int (*flush)(const struct camera3_device *);
 
    /* reserved for future use */
    void *reserved[8];
} camera3_device_ops_t;

  camera3_device_ops_t 映射函數指針操做: hardware/libhardware/modules/camera/3_0/Camera.cppui

const camera3_device_ops_t Camera::sOps = {
    .initialize = default_camera_hal::initialize,
    .configure_streams = default_camera_hal::configure_streams,
    .register_stream_buffers = default_camera_hal::register_stream_buffers,
    .construct_default_request_settings
        = default_camera_hal::construct_default_request_settings,
    .process_capture_request = default_camera_hal::process_capture_request,
    .get_metadata_vendor_tag_ops = NULL,
    .dump = default_camera_hal::dump,
    .flush = default_camera_hal::flush,
    .reserved = {0},
};

  這樣找到在camera hal層的函數指針的映射關係。
  映射到:vendor/qcom/proprietary/camx/src/core/hal/camxhal3entry.cpp 中的:this

  // Global dispatch   static Dispatch g_dispatchHAL3(&g_jumpTableHAL3);
/// Array containing camera3_device_ops_t methods
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},
};
  定義了g_camera3DeviceOps變量:
/// Array containing camera3_device_ops_t methods
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},
};

  並在\vendor\qcom\proprietary\camx\src\core\hal\camxhaldevice.cpp的Initialize方法中經過GetCamera3DeviceOps獲取,創建聯繫:

CamxResult HALDevice::Initialize(
    const HwModule* pHwModule,
    UINT32          cameraId)
{
    CamxResult result = CamxResultSuccess;

    m_cameraId = cameraId;

    if (CamxResultSuccess == result)
    {
        m_camera3Device.hwDevice.tag     = HARDWARE_DEVICE_TAG; /// @todo (CAMX-351) Get from local macro
        m_camera3Device.hwDevice.version = CAMERA_DEVICE_API_VERSION_3_3;
        m_camera3Device.hwDevice.close   = reinterpret_cast<CloseFunc>(GetHwDeviceCloseFunc());
        m_camera3Device.pDeviceOps = reinterpret_cast<Camera3DeviceOps*>(GetCamera3DeviceOps());
        m_camera3Device.pPrivateData     = this;
        // NOWHINE CP036a: Need exception here
        m_camera3Device.hwDevice.pModule = const_cast<HwModule*>(pHwModule);

        m_HALCallbacks.ProcessCaptureResult = ProcessCaptureResult;
        m_HALCallbacks.NotifyResult         = Notify;
        CamX::ChiOverrideBypass(&m_HALCallbacks);
    }

    m_pHALSession = NULL;
    Utils::Memset(m_flushRequest, 0, sizeof(m_flushRequest));

    return result;
}

  看一下g_jumpTableHAL3 變量:在 vendor/qcom/proprietary/camx/src/core/hal/camxhal3.cpp 中定義的:

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// Jump table for HAL3
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
JumpTableHAL3 g_jumpTableHAL3 =
{
    open,
    get_number_of_cameras,
    get_camera_info,
    set_callbacks,
    get_vendor_tag_ops,
    open_legacy,
    set_torch_mode,
    init,
    parallelQuery,
    setCallBack,
    get_tag_count,
    get_all_tags,
    get_section_name,
    get_tag_name,
    get_tag_type,
    close,
    initialize,
    configure_streams,
    construct_default_request_settings,
    process_capture_request,
    dump,
    flush,
    camera_device_status_change,
    torch_mode_status_change,
    process_capture_result,
    notify
};

  這兒直接構成了指針函數的映射關係(對應camxhaldevice.cpp中的函數)。

  vendor/qcom/proprietary/camx/src/core/chi/camxchitypes.h中定義了CHIAppCallbacks結構體,以下:

struct CHIAppCallbacks
{
    /// @brief Called by the driver to get number of cameras
    INT(*CHIGetNumCameras)(
        UINT32* pNumFwCameras,
        UINT32* pNumLogicalCameras);
 
    /// @brief Called by the driver to get the camera info for the camera id
    CamxResult (*CHIGetCameraInfo)(
        UINT32      cameraId,
        CameraInfo* pCameraInfo);
 
    /// @brief Defines the prototype for the device status change callback method from to the framework. Please refer to
    ///        the camera_device_status_change documentation in hardware/camera_common.h.
    VOID (*CHIInitializeOverrideSession)(
        UINT32               cameraId,
        const Camera3Device* pCamera3Device,
        const HALCallbacks*  pHALCallbacks,
        Camera3StreamConfig* pStreamConfig,
        BOOL*                isOverrideEnabled,
        VOID**               ppPrivate);
 
    /// @brief Defines the prototype for the torch mode status change callback method from to the framework. Please refer to
    ///        the torch_mode_status_change documentation in hardware/camera_common.h.
    VOID (*CHIFinalizeOverrideSession)(
        const Camera3Device* pCamera3Device,
        UINT64*              pSession,
        VOID**               ppPrivate);
 
    /// @brief Called by the driver to inform about session closing
    VOID (*CHITeardownOverrideSession)(
        const Camera3Device* pCamera3Device,
        UINT64*              pSession,
        VOID*                pPrivate);
 
    /// @brief Called by the driver to pass on capture request call to CHI
    INT (*CHIOverrideProcessRequest)(
        const Camera3Device*    pCamera3Device,
        Camera3CaptureRequest*  pCaptureRequest,
        VOID*                   pPrivate);
 
    /// @brief Called by the driver to allow for additional override processing during open()
    INT(*CHIExtendOpen)(
        UINT32  cameraId,
        VOID*   pPrivateData);
 
    /// @brief Called by the driver to allow for additional override processing during close()
    INT(*CHIExtendClose)(
        UINT32  cameraId,
        VOID*   pPrivateData);
 
    /// @brief Called by the driver to allow override to remap special camera IDs into logical camera IDs
    UINT32(*CHIRemapCameraId)(
        UINT32              frameworkCameraId,
        CameraIdRemapMode   mode);
 
    /// @brief Interface to allow various override-specific settings to be toggled.
    UINT32(*CHIModifySettings)(
        VOID*   pPrivateData);
 
    /// @brief Get any vendor tag specific request settings the override wants to get added to the default settings
    VOID (*CHIGetDefaultRequestSettings)(
        UINT32           frameworkCameraId,
        INT              requestTemplate,
        const Metadata** pAdditionalMetadata);
 
    /// @brief Called by the driver to allow for flush()
    INT(*CHIOverrideFlush)(
        const Camera3Device*    pCamera3Device);
    INT(*CHIParallelQuery) (INT num, char* list[]);
    INT(*CHISetCallback) (void*);
 
};
 
typedef VOID(*CHIHALOverrideEntry)(
    CHIAppCallbacks* pCHIAppCallbacks);

  這個結構體是函數指針,映射關係:
  vendor/qcom/proprietary/camx/src/core/hal/camxhal3module.h 中定義了 CHIAppCallbacks m_ChiAppCallbacks;

    CHIAppCallbacks       m_ChiAppCallbacks;                    ///< CHI HAL override entry

  vendor/qcom/proprietary/camx/src/core/hal/camxhal3module.cpp中的 HAL3Module構造函數中,存在下面的執行語句:

CHIHALOverrideEntry funcCHIHALOverrideEntry =
    reinterpret_cast<CHIHALOverrideEntry>(
        CamX::OsUtils::LibGetAddr(m_hChiOverrideModuleHandle, "chi_hal_override_entry"));
 
if (NULL != funcCHIHALOverrideEntry)
{
    funcCHIHALOverrideEntry(&m_ChiAppCallbacks); //對應到 chxextensioninterface.cpp 中的chi_hal_override_entry函數
 
    CAMX_ASSERT(NULL != m_ChiAppCallbacks.CHIGetNumCameras);
    CAMX_ASSERT(NULL != m_ChiAppCallbacks.CHIGetCameraInfo);
    CAMX_ASSERT(NULL != m_ChiAppCallbacks.CHIFinalizeOverrideSession);
    CAMX_ASSERT(NULL != m_ChiAppCallbacks.CHIInitializeOverrideSession);
    CAMX_ASSERT(NULL != m_ChiAppCallbacks.CHIOverrideProcessRequest);
    CAMX_ASSERT(NULL != m_ChiAppCallbacks.CHIOverrideFlush);
    CAMX_ASSERT(NULL != m_ChiAppCallbacks.CHITeardownOverrideSession);
    CAMX_ASSERT(NULL != m_ChiAppCallbacks.CHIExtendOpen);
    CAMX_ASSERT(NULL != m_ChiAppCallbacks.CHIExtendClose);
    CAMX_ASSERT(NULL != m_ChiAppCallbacks.CHIRemapCameraId);
    CAMX_ASSERT(NULL != m_ChiAppCallbacks.CHIModifySettings);
    CAMX_ASSERT(NULL != m_ChiAppCallbacks.CHIParallelQuery);
    CAMX_ASSERT(NULL != m_ChiAppCallbacks.CHISetCallback);
 
    if ((NULL != m_ChiAppCallbacks.CHIGetNumCameras)             &&
        (NULL != m_ChiAppCallbacks.CHIGetCameraInfo)             &&
        (NULL != m_ChiAppCallbacks.CHIFinalizeOverrideSession)   &&
        (NULL != m_ChiAppCallbacks.CHIInitializeOverrideSession) &&
        (NULL != m_ChiAppCallbacks.CHIOverrideProcessRequest)    &&
        (NULL != m_ChiAppCallbacks.CHIOverrideFlush)             &&
        (NULL != m_ChiAppCallbacks.CHITeardownOverrideSession)   &&
        (NULL != m_ChiAppCallbacks.CHIExtendOpen)                &&
        (NULL != m_ChiAppCallbacks.CHIExtendClose)               &&
        (NULL != m_ChiAppCallbacks.CHIRemapCameraId)             &&
        (NULL != m_ChiAppCallbacks.CHIModifySettings)            &&
        (NULL != m_ChiAppCallbacks.CHIParallelQuery)             &&
        (NULL != m_ChiAppCallbacks.CHISetCallback))
    {
        CAMX_LOG_WARN(CamxLogGroupHAL, "CHI Module library function pointers exchanged");
    }
}

  m_ChiAppCallbacks 經過 funcCHIHALOverrideEntry 映射到 chi_hal_override_entry這個 chi_hal_override_entry 就是指 vendor/qcom/proprietary/chi-cdk/vendor/chioverride/default/chxextensioninterface.cpp 中的 chi_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_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_parallelquery                = chi_parallelquery;
        callbacks->chi_setcallback                  = chi_setcallback;
    }
}

  這樣就創建了 CHIAppCallbacks 中函數指針的一一映射關係。

  

  vendor/qcom/proprietary/chi-cdk/vendor/chioverride/default/chxextensionmodule.cpp 中的 ExtensionModule::OverrideProcessRequest 函數中執行了 m_pUsecaseFactory->CreateUsecaseObject,以下:

m_pSelectedUsecase[logicalCameraId] =
            m_pUsecaseFactory->CreateUsecaseObject(&m_logicalCameraInfo[logicalCameraId],
                static_cast<UsecaseId>(m_SelectedUsecaseId[logicalCameraId]),
                m_pStreamConfig[logicalCameraId]);

  直接調用到: vendor/qcom/proprietary/chi-cdk/vendor/chioverride/default/chxusecaseutils.cpp 中的 UsecaseFactory::CreateUsecaseObject 函數:

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;
    CHX_LOG_ERROR("UsecaseFactory::CreateUsecaseObject id = %d", usecaseId);
    switch (usecaseId)
    {
        case UsecaseId::PreviewZSL:
            pUsecase = AdvancedCameraUsecase::Create(pLogicalCameraInfo, pStreamConfig, usecaseId);
            break;
        case UsecaseId::MultiCamera:
            pUsecase = UsecaseMultiCamera::Create(pLogicalCameraInfo, pStreamConfig);
            break;
        case UsecaseId::MultiCameraVR:
            pUsecase = UsecaseMultiVRCamera::Create(pLogicalCameraInfo, pStreamConfig);
            break;
        case UsecaseId::MFNR:
            pUsecase = UsecaseMFNR::Create(camera0Id, pStreamConfig);
            break;
        case UsecaseId::QuadCFA:
            pUsecase = UsecaseQuadCFA::Create(pLogicalCameraInfo, pStreamConfig);
            break;
        case UsecaseId::Torch:
            pUsecase = UsecaseTorch::Create(camera0Id, pStreamConfig);
            break;
        default:
            pUsecase = AdvancedCameraUsecase::Create(pLogicalCameraInfo, pStreamConfig, usecaseId);
            break;
    }
 
    return pUsecase;
}
enum class UsecaseId
{
    NoMatch         = 0,
    Default         = 1,
    Preview         = 2,
    PreviewZSL      = 3,
    MFNR            = 4,
    MFSR            = 5,
    MultiCamera     = 6,
    QuadCFA         = 7,
    RawJPEG         = 8,
    MultiCameraVR   = 9,
    Torch           = 10,
    YUVInBlobOut    = 11,
    MaxUsecases     = 12,
};

  前置攝像頭的UsecaseId是 PreviewZSL,是單攝,後置攝像頭的UsecaseId是 MultiCamera,是多攝。

  

 



  camx-usecase

  

  vendor/qcom/proprietary/camx/src/core/chi/camxchi.cpp中的 ChiEntry函數以下:

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/// ChiEntry
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
CAMX_VISIBILITY_PUBLIC VOID ChiEntry(
    ChiContextOps* pChiContextOps)
{
    if (NULL != pChiContextOps)
    {
        pChiContextOps->size                       = sizeof(ChiContextOps);
 
        pChiContextOps->majorVersion               = CHI_API_MAJOR_VERSION;
        pChiContextOps->minorVersion               = CHI_API_MINOR_VERSION;
        pChiContextOps->pOpenContext               = CamX::ChiOpenContext;
        pChiContextOps->pCloseContext              = CamX::ChiCloseContext;
        pChiContextOps->pGetNumCameras             = CamX::ChiGetNumCameras;
        pChiContextOps->pGetCameraInfo             = CamX::ChiGetCameraInfo;
        pChiContextOps->pEnumerateSensorModes      = CamX::ChiEnumerateSensorModes;
        pChiContextOps->pCreatePipelineDescriptor  = CamX::ChiCreatePipelineDescriptor;
        pChiContextOps->pDestroyPipelineDescriptor = CamX::ChiDestroyPipelineDescriptor;
        pChiContextOps->pCreateSession             = CamX::ChiCreateSession;
        pChiContextOps->pDestroySession            = CamX::ChiDestroySession;
        pChiContextOps->pFlushSession              = CamX::ChiFlushSession;
        pChiContextOps->pActivatePipeline          = CamX::ChiActivatePipeline;
        pChiContextOps->pDeactivatePipeline        = CamX::ChiDeactivatePipeline;
        pChiContextOps->pSubmitPipelineRequest     = CamX::ChiSubmitPipelineRequest;
        pChiContextOps->pTagOps                    = CamX::ChiGetTagOps;
    }
 
    // This is the workaround for presil HAL3test on Windows
    // On Device, set_camera_metadata_vendor_ops will be call the set the
    // static vendor tag operation in camera_metadata.c
    //
    // On Windows side, theoretically hal3test should mimic what Android framework
    // does and call the set_camera_metadata_vendor_ops function in libcamxext library
    // However, in Windows, if both hal3test.exe and hal.dll link to libcamxext library,
    // there are two different instance of static varibles sit in different memory location.
    // Even if set_camera_metadata_vendor_ops is called in hal3test, when hal try to
    // access to vendor tag ops, it is still not set.
    //
    // This is also a workaround to call vendor tag ops in Chi at GetNumCameras which happens to get called before
    // GetVendorTagOps
    CamX::g_vendorTagOps.get_all_tags     = CamX::ChiGetAllTags;
    CamX::g_vendorTagOps.get_section_name = CamX::ChiGetSectionName;
    CamX::g_vendorTagOps.get_tag_count    = CamX::ChiGetTagCount;
    CamX::g_vendorTagOps.get_tag_name     = CamX::ChiGetTagName;
    CamX::g_vendorTagOps.get_tag_type     = CamX::ChiGetTagType;
 
    set_camera_metadata_vendor_ops(&(CamX::g_vendorTagOps));
}

  這個函數映射關係很重要,也在camx chi中比較常見,直接映射在此文件的CamxChi類中。都是從 vendor/qcom/proprietary/chi-cdk/vendor/chioverride/default/chxextensionmodule.cpp中調用過來的。

  下面是預覽時capture request 處理流程圖:

  

 check這段流程的時候咱們最關注應該是5個重要的處理類型:

    1.UseCase , vendor/qcom/proprietary/chi-cdk/vendor/chioverride/default/chxusecase.h 上面有介紹類圖。UseCase在camx中頗有不少衍生類,這是camx針對不一樣的stream來創建不一樣的usecase對象,用來管理選擇feature,而且建立 pipeline以及session。
    2.ChiFeature, vendor/qcom/proprietary/chi-cdk/vendor/chioverride/default/chxfeature.h, usecase選擇相應的feature,關聯一組pipeline,收到request請求,根據request選擇對應的feature。
    3.Node , vendro/qcom/propriatary/camx/src/core/camxnode.h ,下面有類圖。Node是camx中很是重要的一個父類,是camx中處理camera 請求的一箇中間節點,用於處理pipeline下發的請求,下面有類圖介紹,比較重要**的Node子類已經標出來了。
    4.pipeline , 一連串node的集合,經過pipeline下發給各個node處理。
    5.session , 若干個有關聯的pipeline的集合,用來管理pipeline,使用pipeline處理請求。

 注: Node 節點在camx chi架構中相當重要,數據的處理都是經過封裝好的Node節點來進行的。

  

  camxnode結構圖:

  

  

  node節點的建立地方在vendor/qcom/proprietary/camx/src/hwl/titian17x/camxtitian17xfactory.cpp

Node* Titan17xFactory::HwCreateNode(
    const NodeCreateInputData* pCreateInputData,
    NodeCreateOutputData*      pCreateOutputData
    ) const
{
    Node* pNode = NULL;
 
    switch (pCreateInputData->pNodeInfo->nodeId)
    {
        case AutoFocus:
            pNode = AutoFocusNode::Create(pCreateInputData, pCreateOutputData);
            break;
        case BPS:
            pNode = BPSNode::Create(pCreateInputData, pCreateOutputData);
            break;
        case IFE:
            pNode = IFENode::Create(pCreateInputData, pCreateOutputData);
            break;
        case IPE:
            pNode = IPENode::Create(pCreateInputData, pCreateOutputData);
            break;
        case Sensor:
            pNode = SensorNode::Create(pCreateInputData, pCreateOutputData);
            break;
        case StatsProcessing:
            pNode = StatsProcessingNode::Create(pCreateInputData, pCreateOutputData);
            break;
        case JPEG:
            pNode = JPEGEncNode::Create(pCreateInputData, pCreateOutputData);
            break;
        case JPEGAggregator:
            pNode = JPEGAggrNode::Create(pCreateInputData, pCreateOutputData);
            break;
        case StatsParse:
            pNode = StatsParseNode::Create(pCreateInputData, pCreateOutputData);
            break;
        case ChiExternalNode:
            pNode = ChiNodeWrapper::Create(pCreateInputData, pCreateOutputData);
            break;
        case FDHw:
            pNode = FDHwNode::Create(pCreateInputData, pCreateOutputData);
            break;
        case FDManager:
            pNode = FDManagerNode::Create(pCreateInputData, pCreateOutputData);
            break;
        case OfflineStats:
            pNode = OfflineStatsNode::Create(pCreateInputData, pCreateOutputData);
            break;
        case Torch:
            pNode = TorchNode::Create(pCreateInputData, pCreateOutputData);
            break;
        case LRME:
            pNode = LRMENode::Create(pCreateInputData, pCreateOutputData);
            break;
        case RANSAC:
            pNode = RANSACNode::Create(pCreateInputData, pCreateOutputData);
            break;
        default:
            CAMX_ASSERT_ALWAYS_MESSAGE("Unexpected node type");
            break;
    }
 
    return pNode;
}

  

   camx_feature:

  

  在 vendor/qcom/proprietary/chi-cdk/vendor/chioverride/default/chxadvancedcamerausecase.cpp中的SelectFeatures(...)函數中有這些feature的建立代碼。 

  拍照的場景分爲前置和後置,前置是單攝,後置是多攝,前面也有介紹,單攝和多攝使用的usecase是不一樣:

  前置拍照建立的pipeline有:

MiuiZSLSnapshotJpeg at index 0 for session 0, session's pipeline 0, camera id:1
MiuiZSLPreviewRaw at index 1 for session 1, session's pipeline 0, camera id:1
BinningZSLYuv2Jpeg at index 2 for session 2, session's pipeline 0, camera id:1
BinningMerge3YuvCustomTo1Yuv at index 3 for session 3, session's pipeline 0, camera id:1
ZSLSnapshotYUV at index 4 for session 4, session's pipeline 0, camera id:1
AdvancedAsdMeta at index 5 for session 5, session's pipeline 0, camera id:1
SWMFClearShotYuv at index 6 for session 6, session's pipeline 0, camera id:1
BinningZSLSnapshotYUV at index 7 for session 7, session's pipeline 0, camera id:1

  後置拍照建立的pipeline有:

 
BackCameraJpegEncode at index 0 for session 0, session's pipeline 0, camera id:0
MfnrPrefilter at index 1 for session 0, session's pipeline 1, camera id:0
MfnrBlend at index 2 for session 0, session's pipeline 2, camera id:0
MfnrPostFilter at index 3 for session 0, session's pipeline 3, camera id:0
MfnrScale at index 4 for session 0, session's pipeline 4, camera id:0
Merge3YuvCustomTo1Yuv at index 5 for session 1, session's pipeline 0, camera id:0
ZSLSnapshotYUV at index 6 for session 2, session's pipeline 0, camera id:0
ZSLSnapshotYUVAux at index 7 for session 3, session's pipeline 0, camera id:3
SWMFSRYuv at index 8 for session 4, session's pipeline 0, camera id:0
AdvancedAsdMeta at index 9 for session 5, session's pipeline 0, camera id:0

  pipeline在camx中的配置文件是:vendor/qcom/proprietary/chi-cdk/vendor/topology/default/titan17x_usecases.xml,編譯時會根據此xml的配置生成對應vendor\qcom\proprietary\chi-cdk\vendor\chioverride\default\g_pipelines.h,
  vendor\qcom\proprietary\chi-cdk\vendor\chioverride\default\build\android\Android.mk:

...
$(info $(shell perl $(CAMX_CDK_PATH)/topology/usecaseconverter.pl $(CAMX_VENDOR_PATH)/topology/default/titan17x_usecases.xml $(LOCAL_PATH)/g_pipelines.h))
...

   而後在\vendor\qcom\proprietary\chi-cdk\vendor\chioverride\default\chxusecaseutils.cpp中會根據pStreamConfig->num_streams選擇到對應的Usecases(g_pipelines.h中定義):

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// UsecaseSelector::DefaultMatchingUsecase
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
ChiUsecase* UsecaseSelector::DefaultMatchingUsecase(
    camera3_stream_configuration_t* pStreamConfig)
{
...
  pSelectedUsecase = &pChiTargetUsecases->pChiUsecases[i];
...

}

  DefaultMatchingUsecase方法即在 \vendor\qcom\proprietary\chi-cdk\vendor\chioverride\default\chxadvancedcamerausecase.cpp 被調用:

CDKResult AdvancedCameraUsecase::SelectUsecaseConfig(
    LogicalCameraInfo*              pCameraInfo,   ///< Camera info
    camera3_stream_configuration_t* pStreamConfig)  ///< Stream configuration
{
...
        m_pChiUsecase = UsecaseSelector::DefaultMatchingUsecase(pStreamConfig);
...
}

 

4、調試:

修改 \vendor\qcom\proprietary\camx\src\core\camxsettings.xml 設置 log 打印級別,如:

overrideLogLevels=0x1F
logInfoMask=0x40080
logVerboseMask=0x40000

 

-end-

相關文章
相關標籤/搜索