Android Q 删除逻辑摄像头数量异常问题

问题说明

如果有配置双摄模式,Dual Camera 也会生成一个 Camera ID,提供打开双摄模式时使用

多出的Dual Camera ID也称为逻辑摄像头

Android Q 在 Framework 层会删除逻辑摄像头的ID,让上层获取最大摄像头数量时,只获取到物理摄像头的数量

但在删除逻辑摄像头数量时,Google的代码逻辑有点问题,会多删除一个物理摄像头的数量,导致获取最大相机数量时,少了一个物理摄像头(少的是搭配组成双摄的副摄)


代码说明

假设物理摄像头一共有4颗,main 和 main2 组成双摄,会多出一个逻辑摄像头ID
Camera ID:main(ID0),sub(ID1),main2(ID2),sub2(ID3),DualCam(ID4)

frameworks/av/services/camera/libcameraservice/common/CameraProviderManager.cpp 此文件中

std::vector<std::string> CameraProviderManager::getAPI1CompatibleCameraDeviceIds() const {
    std::lock_guard<std::mutex> lock(mInterfaceMutex);
    std::vector<std::string> deviceIds;
    for (auto& provider : mProviders) {
        std::vector<std::string> providerDeviceIds = provider->mUniqueAPI1CompatibleCameraIds;

        // API1 app doesn't handle logical and physical camera devices well. So
        // for each camera facing, only take the first id advertised by HAL in
        // all [logical, physical1, physical2, ...] id combos, and filter out the rest.
        filterLogicalCameraIdsLocked(providerDeviceIds);  '此函数的调用就是为了删除逻辑摄像头'
        // Hidden secure camera ids are not to be exposed to camera1 api.
        providerDeviceIds.erase(std::remove_if(providerDeviceIds.begin(), providerDeviceIds.end(),
                [this](const std::string& s) {
                    return this->isPublicallyHiddenSecureCameraLocked(s);}),
                providerDeviceIds.end());
        deviceIds.insert(deviceIds.end(), providerDeviceIds.begin(), providerDeviceIds.end());
    }

void CameraProviderManager::filterLogicalCameraIdsLocked(	'函数的实现'
        std::vector<std::string>& deviceIds) const
{
    // Map between camera facing and camera IDs related to logical camera.
    std::map<int, std::unordered_set<std::string>> idCombos;

    // Collect all logical and its underlying physical camera IDs for each
    // facing.
    for (auto& deviceId : deviceIds) {
        auto deviceInfo = findDeviceInfoLocked(deviceId);
        if (deviceInfo == nullptr) continue;

        if (!deviceInfo->mIsLogicalCamera) {	'这里判断是否是逻辑摄像头'
            continue;
        }

        // combo contains the ids of a logical camera and its physical cameras
        std::vector<std::string> combo = deviceInfo->mPhysicalIds;	'当遍历到ID4时,会把main 和 main2 的ID赋值给combo,ID0 和 ID2'
        combo.push_back(deviceId);	'这里又添加了双摄ID4,combo变成了3个成员'

        hardware::CameraInfo info;
        status_t res = deviceInfo->getCameraInfo(&info);
        if (res != OK) {
            ALOGE("%s: Error reading camera info: %s (%d)", __FUNCTION__, strerror(-res), res);
            continue;
        }
        idCombos[info.facing].insert(combo.begin(), combo.end());	'这里添加了准备删除的Camera ID:ID0、ID2、ID4'
    }

    // Only expose one camera ID per facing for all logical and underlying
    // physical camera IDs.
    for (auto& r : idCombos) {
        auto& removedIds = r.second;	'准备删除的ID,从0开始遍历'

        for (auto& id : deviceIds) {
            auto foundId = std::find(removedIds.begin(), removedIds.end(), id);
            if (foundId == removedIds.end()) {
                continue;
            }

            removedIds.erase(foundId);	'这里删除了ID0'
            break;						'接着就跳出循环了,没有把物理摄像头 main2(ID2)给删除'
        }								'removedIds 里还有 ID2 和 ID4'

        deviceIds.erase(std::remove_if(deviceIds.begin(), deviceIds.end(),
                [&removedIds](const std::string& s) {
                return removedIds.find(s) != removedIds.end();}),
                deviceIds.end());	'这里把 ID2 和 ID4 删除了'
    }								'所以最大相机数量变成 5 - 2 = 3,多减去了一个物理摄像头'
}

所以当配置了双摄的时候,上层获取最大相机数量时,数量是错误的


修改方案

void CameraProviderManager::filterLogicalCameraIdsLocked(
        std::vector<std::string>& deviceIds) const
{
		……
        // combo contains the ids of a logical camera and its physical cameras
        '这里不添加 ID0 和 ID2'
        std::vector<std::string> combo;	// = deviceInfo->mPhysicalIds;
        combo.push_back(deviceId);	'combo中只有一个ID4'
        ……

		'注掉下面这段代码'
   /*   for (auto& id : deviceIds) {
            auto foundId = std::find(removedIds.begin(), removedIds.end(), id);
            if (foundId == removedIds.end()) {
                continue;
            }

            removedIds.erase(foundId);
            break;	
        }	*/

        deviceIds.erase(std::remove_if(deviceIds.begin(), deviceIds.end(),
                [&removedIds](const std::string& s) {
                return removedIds.find(s) != removedIds.end();}),
                deviceIds.end());	'这里删除的时候只会删除ID4了'

PS

对比了 Android P 的代码,发现也是有问题的

frameworks/av/services/camera/libcameraservice/common/CameraProviderManager.cpp

void CameraProviderManager::filterLogicalCameraIdsLocked(
        std::vector<std::string>& deviceIds) const
{
		……
        for (auto& id : deviceIds) {
            auto foundId = std::find(idCombo.begin(), idCombo.end(), id);
            if (foundId == idCombo.end()) {
                continue;
            }

            idCombo.erase(foundId);		'先把ID4从idCombo中删除了'
            removedIds.insert(idCombo.begin(), idCombo.end());	'这里添加准备删除的逻辑摄像头就是空的'
            break;
        }
    }

    deviceIds.erase(std::remove_if(deviceIds.begin(), deviceIds.end(),
            [&removedIds](const std::string& s) {return removedIds.find(s) != removedIds.end();}),
            deviceIds.end());
}

所以 Android P 中并没有删除逻辑摄像头ID

  • 1
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值