需求:
在低配机器上使用三方算法
在非低配机器上使用平台自带算法
实现方案
- 在3rdparty/customer/costomer_scenario_mgr.cpp中添加三方算法宏定义:
#define TP_FEATURE_COMBINATION_THIRDPARTY ...
- 同样的文件添加客制化的gCustomerScenarioFeaturesMaps_lowram,只添加需要兼容的部分即可。在customer_get_features_table_by_scenario方法中添加判断条件。判断是需要兼容的场景时,根据获取到的机器配置对scenarioFeaturesMap进行对应的赋值
- 经过上述两步修改之后,验证发现可以实现低配机器匹配三方算法,非低配机器匹配平台算法的需求,但仍有一个问题:不管是低配还是非低配,打开相机时平台算法与三方算法的构造函数都会调用,但只会调用一个算法的process函数用于处理图像数据。
- 进一步排查log,查找算法注册的地方。查找算法关键字,发现如下信息:
01-02 16:32:17.549 16884 17147 D mtkcam-FeatureSettingPolicy: [PluginWrapper] find provider… name:…
找到对应代码:
for (auto& provider : mProviderPtrsSortedByPriorty) {
const Property& property = provider->property();
MY_LOGD("find provider... name:%s, algo(%#" PRIx64"), priority(0x%x)", property.mName, property.mFeatures, property.mPriority);
}
往上找mProviderPtrsSortedByPriorty赋值的位置:
auto providers = mInstancePtr->getProviders();
mProviderPtrsSortedByPriorty = providers;
- 查找getProviders方法的定义,找到PipelinePlugin.cpp文件:
函数主体就是对一个list便利调用构造函数和set函数,然后push_back:
for(auto r : Registry::ofProvider()) {
typename IProvider::Ptr provider = r.mConstruct();
provider->set(mOpenId, mOpenId2);
mpProviders.push_back(provider);
}
看起来可以从这里跳过调用冗余算法的构造函数调用
6. 寻找判断当前是哪种算法的条件:
查找ofProvider()的定义:
static ProviderRegistry& ofProvider() {
return sProviderRegistry;
}
sProviderRegistry的定义:
static ProviderRegistry sProviderRegistry;
ProviderRegistry 的定义:
typedef std::vector\<ConstructProviderEntry\> ProviderRegistry
ConstructProviderEntry的定义, 定义了两个构造函数和两个变量:
struct ConstructProviderEntry
{
ConstructProviderEntry(ConstructProvider c)
:mConstruct(c), mID(0)
{}
ConstructProviderEntry(ConstructProvider c, PLUGIN_ID_TYPE id)
:mConstruct(c), mID(id)
{}
ConstructProvider mConstruct;
PLUGIN_ID_TYPE mID;
};
此处mID看起来是可以标志不同算法的,添加log打印出来。
7. 打印结果:平台算法与三方算法的r.mID都是0,猜测是调用了第一个构造函数。查找关键字ConstructProviderEntry,没有看到较明显的实例化调用,由于时间有限,使用一个偷懒的方法:直接搜索算法构造函数关键字,找到如下结果:
平台算法:
REGISTER_PLUGIN_PROVIDER(T, MTKconstruct);
三方算法:
REGISTER_PLUGIN_PROVIDER(T, thirdpratyconstruct);
搜索定义:
#define REGISTER_PLUGIN_PROVIDER(T, type) ……
同时可以在紧挨着的下面看到另一个宏定义:
#define REGISTER_PLUGIN_PROVIDER_DYNAMIC(T, type, id) ……
查找REGISTER_PLUGIN_PROVIDER_DYNAMIC的使用方法:id处赋值mtk_feature_type.h和customer_feature_type.h中算法对应的定义
8. 将平台算法与三分算法的REGISTER_PLUGIN_PROVIDER修改为REGISTER_PLUGIN_PROVIDER_DYNAMIC,并再次打印id:可以得到对应的算法id。
9. 最后一步:在getProviders方法中for循环的最开始,判断当前遍历到的算法与机器配置。当遍历到当前配置不需要的算法时,直接continue跳过构造函数与set函数的调用,开始下一个元素的处理。
修改验证:与需求相符,且没有加载冗余算法。