MTK平台Metadata的加载(二)——Sensor和3A相关Static加载

Camera static metadata 在 camerahalserver 进程启动时就会进行加载。

(1)CameraService的启动

camerahalserver: 透过 init service 启动。

在这里插入图片描述
(A)Android.mk文件

ifneq ($(MYKCAM_USE_LEGACY_HAL_API),yes)
#-----------------------------------------------------------
ifeq ($(MTK_CAM_LAZY_HAL), yes)
LOCAL_SRC_FILES += serviceLazy.cpp
else
LOCAL_SRC_FILES += service.cpp
endif

ifeq ($(MTK_CAM_LAZY_HAL), yes)
LOCAL_INIT_RC := camerahalserverLazy.rc
else ifneq ($(strip $(FPGA_EARLY_PORTING)), yes)
LOCAL_INIT_RC := camerahalserver.rc
endif

LOCAL_MODULE := camerahalserver
LOCAL_MODULE_RELATIVE_PATH := hw
LOCAL_MODULE_OWNER := mtk
LOCAL_PROPRIETARY_MODULE := true
LOCAL_MULTILIB := first

//...

通过ProjectConfig.mk当中MTK_CAM_LAZY_HAL来加载不同的mode。

(B)camerahalserver.rc

service camerahalserver /vendor/bin/hw/camerahalserver
    class main
    user cameraserver
    group audio camera input drmrpc sdcard_rw system media graphics
    ioprio rt 4
    capabilities SYS_NICE
    task_profiles CameraServiceCapacity MaxPerformance

(C)service.cpp

在 camerahalserver 中注册相关的 HIDL service。

using android::hardware::registerPassthroughServiceImplementation;

auto err = registerPassthroughServiceImplementation<ICameraProvider>("internal/0" /*"internal" for binderized mode*/);
auto err = registerPassthroughServiceImplementation<IAdvCamControl>("internal/0" /*"internal" for binderized mode*/);
 auto err = registerPassthroughServiceImplementation<ILomoEffect>("internal/0" /*"internal" for binderized mode*/);
auto err = registerPassthroughServiceImplementation<ICCAPControl>("internal/0" /*"internal" for binderized mode*/);
auto err = registerPassthroughServiceImplementation<IISPModule>("internal/0" /*"internal" for binderized mode*/);
auto err = registerPassthroughServiceImplementation<IISPModule>("internal/0" /*"internal" for binderized mode*/);
auto err = registerPassthroughServiceImplementation<IPostDevice>("internal/0" /*"internal" for binderized mode*/);
auto err = registerPassthroughServiceImplementation<IFRHandler>("internal/0" /*"internal" for binderized mode*/);
auto err = registerPassthroughServiceImplementation<IBGService>("internal/0" /*"internal" for binderized mode*/);

通过registerPassthroughServiceImplementation调用到HIDL_FETCH_ICameraProvider函数,我们来看看HIDL_FETCH_ICameraProvider函数的具体实现。

//vendor/mediatek/proprietary/hardware/mtkcam3/main/hal/devicemgr/depend/instance.cpp

extern "C"
ICameraProvider*
createICameraProvider_V2_6(const char* providerName, NSCam::ICameraDeviceManager* manager);

extern "C"
ICameraProvider*
HIDL_FETCH_ICameraProvider(const char* name)
{
    //...
    
    return createICameraProvider_V2_6(name, getCameraDeviceManager());
}
//vendor/mediatek/proprietary/hardware/mtkcam3/main/hal/entry/hidl/provider/2.6/HidlCameraProvider.cpp

extern "C"
ICameraProvider*
createICameraProvider_V2_6(const char* providerName, ICameraDeviceManager* manager)
{
    MY_LOGI("+ %s", providerName);
    //
    if ( ! manager ) {
        MY_LOGE("bad camera device manager");
        return nullptr;
    }
    //
    auto provider = new HidlCameraProvider(providerName, manager);
    if ( ! provider ) {
        MY_LOGE("cannot allocate camera provider %s", providerName);
        return nullptr;
    }
    //
    if ( ! provider->initialize() ) {
        MY_LOGE("camera provider %s initialize failed", providerName);
        delete provider;
        provider = nullptr;
    }
    //
    MY_LOGI("- %s provider:%p manager:%p", providerName, provider, manager);
    return provider;
}

在 HIDL_FETCH_ICameraProvider() 中,调用careateICameraProvier_V2_6(name, getCameraDeviceManager())。

//vendor/mediatek/proprietary/hardware/mtkcam3/main/hal/devicemgr/depend/instance.cpp

extern "C"
NSCam::ICameraDeviceManager*
getCameraDeviceManager()
{
    MY_LOGI("[hidldc] getCameraDeviceManager");
    static NSCam::CameraDeviceManagerImpl singleton(getProviderType().c_str());
    static bool init = singleton.initialize();
    if ( ! init ) {
        MY_LOGE("CameraDeviceManagerImpl::initialize fail %p", &singleton);
        return nullptr;
    }
    return &singleton;
}

在 getCameraDeviceManager 中创建 CameraDeviceManagerImpl 实例并 initialize()。

最终会调用到 CameraDeviceManagerImpl 中的 onEnumerateDevicesLocked()。

(D)CameraDeviceManagerImpl.cpp

这里开始即进入Camera Hal的逻辑,我们在这里查看onEnumerateDevicesLocked()。

//vendor/mediatek/proprietary/hardware/mtkcam3/main/hal/devicemgr/depend/CameraDeviceManagerImpl.cpp

auto
CameraDeviceManagerImpl::
onEnumerateDevicesLocked() -> ::android::status_t
{
    NSMetadataProviderManager::clear();
    mPhysEnumDeviceMap.clear();

    //IHalSensorList*const pHalSensorList = MAKE_HalSensorList();
    //size_t const sensorNum = pHalSensorList->searchSensors();
    ///
    IHalLogicalDeviceList* pHalDeviceList = MAKE_HalLogicalDeviceList();
    if(pHalDeviceList == nullptr) {
        MY_LOGE("Cannot get logical device list");
        return -ENODEV;
    }

//(1)加载sensor & 3A相关的static metadata
    size_t const deviceNum = pHalDeviceList->searchDevices();
    CAM_ULOGMI("pHalDeviceList:%p searchDevices:%zu queryNumberOfDevices:%d", pHalDeviceList, deviceNum, pHalDeviceList->queryNumberOfDevices());

    mVirtEnumDeviceMap.setCapacity(deviceNum*2);
    uint32_t virtualInstanceId = 0;
    for (size_t instanceId = 0; instanceId < deviceNum; instanceId++)
    {
        virtualInstanceId = pHalDeviceList->getVirtualInstanceId(instanceId);
        bool isHidden = false;
        isHidden = pHalDeviceList->isCameraHidden(instanceId);
        
        //(2)加载其他的static metadata
        sp<IMetadataProvider> pMetadataProvider;
        pMetadataProvider = IMetadataProvider::create(instanceId);
        if(pMetadataProvider)
        {
            std::map<uint32_t, sp<IMetadataProvider>> physicalMetaProviders;
            NSMetadataProviderManager::add(instanceId, pMetadataProvider.get());
            MY_LOGD("[0x%02zx] vid: 0x%02" PRIu32 " isHidden:%d IMetadataProvider:%p sensor:%s",
                            instanceId,
                            virtualInstanceId,
                            isHidden,
                            pMetadataProvider.get(),
                            pHalDeviceList->queryDriverName(instanceId));
            //check if the virtual device backuped by multiple physical devices
            IMetadata::IEntry const& capbilities = pMetadataProvider->getMtkStaticCharacteristics().entryFor(MTK_REQUEST_AVAILABLE_CAPABILITIES);

            addVirtualDevicesLocked(instanceId, virtualInstanceId, isHidden, pMetadataProvider, physicalMetaProviders);
        }
        else
        {
            MY_LOGE("Create metadata provider failed, id %zu", instanceId);
        }
    }

//...

在 onEnumerateDevicesLocked()中首先会通过 pHalDeviceList->searchDevices()加载 sensor 与 3A 相关
的 static metadata,然后再通过 IMetadataProvider::create(instatceId++)加载其他 static metadata。

(2)searchSensor以及加载Metadata

//vendor/mediatek/proprietary/hardware/mtkcam/utils/LogicalCam/HalLogicalDeviceList.cpp

MUINT HalLogicalDeviceList::searchDevices()
{
    if( mDeviceSensorMap.size() == 0 )
    {
        MY_LOGD("Create logical device map");
        createDeviceMap();
    }
    return mDeviceSensorMap.size();
}


MINT32 HalLogicalDeviceList::createDeviceMap()
{
    SensorInfo_t vTempInfo;
    unsigned int i = 0;

    // firstly, we create a logical camera device per physical camera
    IHalSensorList* const pHalSensorList = MAKE_HalSensorList();
    if(CC_UNLIKELY(!pHalSensorList))
    {
        MY_LOGA("create pHalSensorList fail");
        return 1;
    }
    size_t const sensorNum = pHalSensorList->searchSensors();
    MY_LOGD("sensorNum : %zu", sensorNum);
    for(i = 0; i < sensorNum; i++)
    {
    	//...
    }
}

最终会调用到 HalSensorList.cpp 中的 searchSensors()开始加载 static metadata。

备注:MT6771 平台及之后平台加载是是 common/v1_1下面的,可查看如下Android.mk确认。

//vendor/mediatek/proprietary/hardware/mtkcam/drv/src/sensor/mtxxxx/Android.mk

SENINF_COMMON_SRC = ../common/v1_1

(A)HalSensorList::searchSensor()

//vendor/mediatek/proprietary/hardware/mtkcam/drv/src/sensor/common/v1_1/HalSensorList.cpp

MUINT
HalSensorList::
searchSensors()
{
    Mutex::Autolock _l(mEnumSensorMutex);

    MY_LOGD("searchSensors");

    SeninfDrv *const pSeninfDrv = SeninfDrv::getInstance();

	//(1)SeninfDrv的init
    if(!pSeninfDrv || pSeninfDrv->init() < 0) {
        MY_LOGE("pSeninfDrv->init() fail");
        return 0;
    }

#ifdef MTK_CAM_MAX_NUMBER_OF_CAMERA
    MUINT max_index_of_camera = MTK_CAM_MAX_NUMBER_OF_CAMERA - 1;
#else
    MUINT max_index_of_camera = IMGSENSOR_SENSOR_IDX_SUB;
#endif
    MY_LOGD("impSearchSensor search to %d\n", max_index_of_camera);
    for (MUINT i = IMGSENSOR_SENSOR_IDX_MIN_NUM; i <= max_index_of_camera; i++) {
        ImgSensorDrv *pSensorDrv = ImgSensorDrv::getInstance((IMGSENSOR_SENSOR_IDX)i);

		//(2)ImgSensorDrv的init
        if(!pSensorDrv || pSensorDrv->init((IMGSENSOR_SENSOR_IDX)i) != SENSOR_NO_ERROR)
            continue;

        //...

		//(3)searchSensor动作
        if(pSensorDrv->searchSensor() == SENSOR_NO_ERROR) {
            //query sensorinfo
            querySensorInfo((IMGSENSOR_SENSOR_IDX)i);
            //fill in metadata
            buildSensorMetadata((IMGSENSOR_SENSOR_IDX)i);
            addAndInitSensorEnumInfo_Locked(
                (IMGSENSOR_SENSOR_IDX)i,
                mapToSensorType(pSensorDrv->getType()),
                (char *)pSensorDrv->getName());
            
            //...
        }
	}

    return  mEnumSensorList.size();
}
//vendor/mediatek/proprietary/hardware/mtkcam/drv/src/sensor/common/v1_1/HalSensorList.cpp

HalSensorList::EnumInfo const*
HalSensorList::
addAndInitSensorEnumInfo_Locked(
    IMGSENSOR_SENSOR_IDX eSensorDev,
    MUINT eSensorType,
    char *szSensorDrvName
)
{
	//返回的SensorList
    mEnumSensorList.push_back(EnumInfo());

    EnumInfo& rEnumInfo = mEnumSensorList.editTop();

   ///...
   
    std::string drvName(szSensorDrvName);
    std::transform(drvName.begin(), drvName.end(), drvName.begin(), ::toupper);
    rEnumInfo.setDeviceId(eSensorDev);
    rEnumInfo.setSensorType(eSensorType);
    rEnumInfo.setBackSide(bBackSide);
    std::stringstream sstream;
    sstream << "SENSOR_DRVNAME_" << drvName.c_str();
    rEnumInfo.setSensorDrvName(sstream.str());

    buildStaticInfo(rEnumInfo, rEnumInfo.mMetadata);

    return  &rEnumInfo;
}

最终会调用buildStaticInfo()从 camera metadata 配置文件加载 sensor 与 3A 相关的 static metadata 或者自动生成特定的 static metadata。

(B)HalSensorList::buildStaticInfo()

//vendor/mediatek/proprietary/hardware/mtkcam/drv/src/sensor/common/v1_1/HalSensorList.cpp

MBOOL
HalSensorList::buildStaticInfo(Info const& rInfo, IMetadata& rMetadata) const {
    const SensorStaticInfo *pSensorStaticInfo =
        &sensorStaticInfo[rInfo.getDeviceId()];

    MUINT8 u8Para = 0;

#if MTKCAM_CUSTOM_METADATA_COMMON
    bool v1 = true;
    if (property_get_int32("vendor.debug.camera.static_meta.version", 1) != 0) {
    
    	//(1)通过impBuildStaticInfo_v1来加载metadata
        if (!impBuildStaticInfo_v1(rInfo, rMetadata)) {
            v1 = false;
            MY_LOGW("V1: Fail to build static info for %s index:%d type:%d",
                    rInfo.getSensorDrvName().c_str(), rInfo.getDeviceId(),
                    rInfo.getSensorType());
        } else {
            checkSensorData(rMetadata);
            updateAFData(rMetadata);
            goto lbLoadDone;
        }
    }
#endif

	//(2)通过impBuildStaticInfo来加载metadata
    if (!impBuildStaticInfo(rInfo, rMetadata))
    {
        MY_LOGE(
            "Fail to build static info for %s index:%d",
            rInfo.getSensorDrvName().c_str(), rInfo.getDeviceId()
        );
        //return  MFALSE;
    }

lbLoadDone:
    // METEDATA Ref: system/media/camera/docs/docs.html
    // using full size
    {
	
		//(3)自动生成相应的Metadata
        IMetadata::IEntry entryA(MTK_SENSOR_INFO_ACTIVE_ARRAY_REGION);
        MRect region1(
        			MPoint(pSensorStaticInfo->SensorGrabStartX_CAP,pSensorStaticInfo->SensorGrabStartY_CAP),
                    MSize(pSensorStaticInfo->captureWidth,pSensorStaticInfo->captureHeight)
                    );
        entryA.push_back(region1, Type2Type<MRect>());
        if (rMetadata.update(MTK_SENSOR_INFO_ACTIVE_ARRAY_REGION, entryA) < 0)
          MY_LOGE("update Metadata SENSOR_INFO_ACTIVE_ARRAY_REGION failed");
    }
	
	//...

	#if MTKCAM_CUSTOM_METADATA_COMMON
    if ( v1 )
    
    	//(4)通过impBuildStaticInfo_v1_overwrite来加载metadata
        impBuildStaticInfo_v1_overwrite(rInfo, rMetadata);
	#endif

    rMetadata.sort();

    return  MTRUE;
}

我们首先看一下impBuildStaticInfo函数。

(C)HalSensorList::impBuildStaticInfo()

ImpBuidStaticInfo 会先从
/vendor/mediatek/proprietary/custom/mtxxxx/hal/imgsensor_metadata/imxxxx_raw中加载对应类型的 metadata。

如果这一类型从此目录下没有找到,那么就会到
/vendor/mediatek/proprietary/ custom/mtxxxx/hal/imgsensor_metadata/common 目录下加载对应的类型。

//vendor/mediatek/proprietary/hardware/mtkcam/drv/src/sensor/common/v1_1/HalSensorList.cpp

static
char const*const
kStaticMetadataTypeNames[] = {
    "LENS",
    "SENSOR",
    "TUNING_3A",
    "FLASHLIGHT",
    "SCALER",
    "FEATURE",
    "CAMERA",
    "REQUEST",
    NULL
};

static MBOOL impBuildStaticInfo(
    Info const& rInfo,
    IMetadata& rMetadata) {
    std::stringstream sstream;
    for (unsigned int i = 0; NULL != kStaticMetadataTypeNames[i]; i++) {
        char const* const pTypeName = kStaticMetadataTypeNames[i];

    MBOOL status = MTRUE;

	//DEVICE
	sstream.str("");
    sstream << PREFIX_FUNCTION_STATIC_METADATA << "_DEVICE_" << pTypeName << "_"
            << rInfo.getSensorDrvName().c_str();
        std::string const s8Symbol_Sensor = sstream.str();
        status = impConstructStaticMetadata_by_SymbolName(s8Symbol_Sensor,
                                                        rInfo, rMetadata);
        if (MTRUE == status) {
            continue;
        }

        sstream.str("");
    sstream << PREFIX_FUNCTION_STATIC_METADATA << "_DEVICE_" << pTypeName << "_"
            << "COMMON";
        std::string const s8Symbol_Common = sstream.str();
        status = impConstructStaticMetadata_by_SymbolName(s8Symbol_Common,
                                                        rInfo, rMetadata);
        if (MTRUE == status) {
            continue;
        }

        MY_LOGE_IF(0, "Fail for both %s & %s", s8Symbol_Sensor.c_str(),
                    s8Symbol_Common.c_str());
    }

	//PROJECT
    for (unsigned int i = 0; NULL != kStaticMetadataTypeNames[i]; i++) {
        char const* const pTypeName = kStaticMetadataTypeNames[i];
	
	
    return MTRUE;
}

对应的类型有:LENS、SENSOR、TUNING_3A、FLASHLIGHT、SCALER、FEATURE、CAMERA、REQUEST。

上面部分使用类型等参数从 Camera metadata 配置文件中找到对应文件中的函数指针进行加载,这里以Lens为例:

 sstream << PREFIX_FUNCTION_STATIC_METADATA << "_DEVICE_" << pTypeName << "_" << rInfo.getSensorDrvName().c_str();
  • PREFIX_FUNCTION_STATIC_METADATA = STATIC_METADATA2_BEGIN
  • pTypeName = LENS
  • rInfo.getSensorDrvName().c_str() = sensorName

上面字符串对应的函数指针就是STATIC_METADATA2_BEGIN(DEVICE, LENS, SENSOR_DRVNAM
E_XXXX_MIPI_RAW),对应加载的配置文件就是函数所属文件:config_static_metadata.lens.xxxxmipira
w.h。

(D)加载的so和metadata文件

HalSensorList.cpp 中加载的是 Sensor 与 3A 的 metadata。open 的是 libcam.halsensor.so
这个动态库。而这个动态库保存的就是 Sensor 与 3A 相关的 metadata。

static MBOOL impConstructStaticMetadata_by_SymbolName(
    std::string const& s8Symbol,
    Info const& rInfo,
    IMetadata& rMetadata) {
    typedef MBOOL (*PFN_T)(
        IMetadata & metadata,
        Info const& info);

    PFN_T pfn;
    MBOOL ret = MTRUE;

    std::stringstream sstream;
    sstream << "libcam.halsensor.so";
    std::string s8LibPath = sstream.str();
    void* handle = ::dlopen(s8LibPath.c_str(), RTLD_GLOBAL);

    if (!handle) {
        char const* err_str = ::dlerror();
        MY_LOGW("dlopen library=%s %s", s8LibPath.c_str(),
                err_str ? err_str : "unknown");
        ret = MFALSE;
        goto lbExit;
    }
    pfn = (PFN_T)::dlsym(handle, s8Symbol.c_str());
    if (!pfn) {
        // MY_LOGW("%s not found", s8Symbol.c_str());
        ret = MFALSE;
        goto lbExit;
    }

    ret = pfn(rMetadata, rInfo);
    MY_LOGW_IF(!ret, "%s fail", s8Symbol.c_str());

lbExit:
    if (handle) {
        ::dlclose(handle);
        handle = NULL;
    }
    return ret;
}

那么sensor 与 3A 相关的metadata是如何被加载到libcam.halsensor.so中的呢?

如下是表示Android P 版 camera metadata 配置的文件夹。

在这里插入图片描述

文件中的命名有三种:

  • config_request_metadata_*.h
  • config_static_metadata_*.h
  • config_static_metadata.*.h

libcam.halsensor.so 默认会加载 libcam.halsensor.custom 这个 static lib,
而这个 static lib 加载的是"config_static_metadata.*.h"类型的文件。

(E)Android.mk

如下的Android.mk显示,libcam.halsensor.custom只加载"config_static_metadata.*.h"类型的文件。

  • config_static_metadata.lens.gc8034mipiraw.h
  • config_static_metadata.project.camera.gc8034mipiraw.h
  • config_static_metadata.project.flashlight.gc8034mipiraw.h
  • config_static_metadata.project.flashlight.gc8034mipiraw.h
  • config_static_metadata.tuning_3a.gc8034mipiraw.h
//vendor/mediatek/proprietary/hardware/mtkcam/drv/src/sensor/mtxxxx/custom/Android.mk

define my-all-config.sensor-metadata-under
$(patsubst ./%,%, \
  $(shell find $(1)  -maxdepth 2 \( -name "config_static_metadata.*.h" \) -and -not -name ".*") \
 )
endef

LOCAL_MODULE := libcam.halsensor.custom
LOCAL_PROPRIETARY_MODULE := true
LOCAL_MODULE_CLASS := STATIC_LIBRARIES

而"config_request_metadata_.h"与"config_static_metadata_.h"类型的文件则会被后面将要介绍的
libmtkcam_metastore.so加载(其他的static metadata、RequsetTemplate)。

加载数据库元数据和相关文件时,具体的实现方式会根据不同的数据库类型和文件类型而有所不同。以下是一个示例,演示如何使用Python中的sqlite3库加载SQLite数据库的元数据和相关文件: ```python import os import sqlite3 def open_database(database_name): # 定义数据库文件的路径 database_file = f'/path/to/database/{database_name}.db' # 检查数据库文件是否存在 if not os.path.exists(database_file): print(f"数据库文件 '{database_file}' 不存在!") return # 连接到数据库 conn = sqlite3.connect(database_file) # 创建游标对象 cursor = conn.cursor() # 加载数据库元数据 cursor.execute("SELECT name FROM sqlite_master WHERE type='table';") tables = cursor.fetchall() # 加载数据库相关文件 files = load_files(database_name) # 关闭游标和连接 cursor.close() conn.close() # 返回元数据和文件列表 return tables, files def load_files(database_name): # 加载数据库相关文件的代码 files = [] # 在这里编写加载数据库相关文件的逻辑 # 可以使用适合你的文件类型的库或方法来加载文件 # 例如,如果是文本文件,可以使用Python内置的文件操作方法来读取文件内容 return files # 示例用法 database_name = 'my_database' metadata, files = open_database(database_name) if metadata and files: print(f"成功打开数据库 '{database_name}'!") print("数据库表:", metadata) print("相关文件:", files) ``` 请注意,此示例假定使用SQLite数据库,并使用sqlite3库来连接和查询数据库。对于其他类型的数据库和文件,你需要使用相应的库或方法来加载数据。确保根据实际情况进行适当的修改和调整。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

雪舞飞影

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值