#include "EngineCommon.h" #include "PackageInfo.h" #include "HardwareDetector.h" #include "IOpenCVEngine.h" #include "StringUtils.h" #include #include #include #include using namespace std; map PackageInfo::InitPlatformNameMap() { map result; // TODO: Do not forget to add Platrfom constant to HardwareDetector.h result[PLATFORM_TEGRA] = PLATFORM_TEGRA_NAME; result[PLATFORM_TEGRA2] = PLATFORM_TEGRA2_NAME; result[PLATFORM_TEGRA3] = PLATFORM_TEGRA3_NAME; result[PLATFORM_TEGRA4] = PLATFORM_TEGRA4_NAME; result[PLATFORM_TEGRA4i] = PLATFORM_TEGRA4_NAME; result[PLATFORM_TEGRA5] = PLATFORM_TEGRA5_NAME; return result; } const map PackageInfo::PlatformNameMap = InitPlatformNameMap(); const string PackageInfo::BasePackageName = "org.opencv.lib"; const string DEFAULT_ENGINE_INSTALL_PATH = "/data/data/org.opencv.engine"; inline string JoinARMFeatures(int cpu_id) { string result; if (FEATURES_HAS_NEON2 & cpu_id) { if (!((ARCH_ARMv5 & cpu_id) || (ARCH_ARMv6 & cpu_id) ||(ARCH_ARMv7 & cpu_id))) result = string(FEATURES_HAS_NEON2_NAME); } else if (FEATURES_HAS_NEON & cpu_id) { if (!((ARCH_ARMv5 & cpu_id) || (ARCH_ARMv6 & cpu_id))) result = string(FEATURES_HAS_NEON_NAME); } else if (FEATURES_HAS_VFPv3 & cpu_id) { if ((ARCH_ARMv5 & cpu_id) || (ARCH_ARMv6 & cpu_id)) result = string(FEATURES_HAS_VFPv3_NAME); } else if (FEATURES_HAS_VFPv3d16 & cpu_id) { if ((ARCH_ARMv5 & cpu_id) || (ARCH_ARMv6 & cpu_id)) result = string(FEATURES_HAS_VFPv3d16_NAME); } return result; } inline int SplitARMFeatures(const vector& features) { int result = 0; for (size_t i = 3; i < features.size(); i++) { if (FEATURES_HAS_VFPv3_NAME == features[i]) { result |= FEATURES_HAS_VFPv3; } else if (FEATURES_HAS_VFPv3d16_NAME == features[i]) { result |= FEATURES_HAS_VFPv3d16; } else if (FEATURES_HAS_NEON_NAME == features[i]) { result |= FEATURES_HAS_NEON; } else if (FEATURES_HAS_NEON2_NAME == features[i]) { result |= FEATURES_HAS_NEON2; } } return result; } inline string JoinIntelFeatures(int cpu_id) { string result; if (FEATURES_HAS_SSSE3 & cpu_id) { result = FEATURES_HAS_SSSE3_NAME; } else if (FEATURES_HAS_SSE2 & cpu_id) { result = FEATURES_HAS_SSE2_NAME; } else if (FEATURES_HAS_SSE & cpu_id) { result = FEATURES_HAS_SSE_NAME; } return result; } inline int SplitIntelFeatures(const vector& features) { int result = 0; for (size_t i = 3; i < features.size(); i++) { if (FEATURES_HAS_SSSE3_NAME == features[i]) { result |= FEATURES_HAS_SSSE3; } else if (FEATURES_HAS_SSE2_NAME == features[i]) { result |= FEATURES_HAS_SSE2; } else if (FEATURES_HAS_SSE_NAME == features[i]) { result |= FEATURES_HAS_SSE; } } return result; } inline int SplitVersion(const vector& features, const string& package_version) { int result = 0; if ((features.size() > 1) && ('v' == features[1][0])) { // Taking major and minor mart of library version from package name string tmp1 = features[1].substr(1); result += atoi(tmp1.substr(0,1).c_str())*1000000 + atoi(tmp1.substr(1,1).c_str())*10000; // Taking release and build number from package revision vector tmp2 = SplitStringVector(package_version, '.'); if (tmp2.size() == 2) { // the 2nd digit is revision result += atoi(tmp2[0].c_str())*100 + 00; } else { // the 2nd digit is part of library version // the 3rd digit is revision result += atoi(tmp2[0].c_str())*100 + atoi(tmp2[1].c_str()); } } else { // TODO: Report package name format error } return result; } inline string JoinPlatform(int platform) { string result; map::const_iterator it = PackageInfo::PlatformNameMap.find(platform); assert(PackageInfo::PlatformNameMap.end() != it); result = it->second; return result; } inline int SplitPlatform(const vector& features) { int result = 0; if (features.size() > 2) { string tmp = features[2]; if (PLATFORM_TEGRA_NAME == tmp) { result = PLATFORM_TEGRA; } else if (PLATFORM_TEGRA2_NAME == tmp) { result = PLATFORM_TEGRA2; } else if (PLATFORM_TEGRA3_NAME == tmp) { result = PLATFORM_TEGRA3; } else if (PLATFORM_TEGRA4_NAME == tmp) { result = PLATFORM_TEGRA4; } } else { // TODO: Report package name format error } return result; } /* Package naming convention * All parts of package name separated by "_" symbol * First part is base namespace. * Second part is version. Version starts from "v" symbol. After "v" symbol version nomber without dot symbol added. * If platform is known third part is platform name * If platform is unknown it is defined by hardware capabilities using pattern: __ * Example: armv7_neon */ PackageInfo::PackageInfo(int version, int platform, int cpu_id, std::string install_path): Version(version), Platform(platform), CpuID(cpu_id), InstallPath("") { #ifndef __SUPPORT_TEGRA3 Platform = PLATFORM_UNKNOWN; #endif int major_version = version/1000000; int minor_version = version/10000 - major_version*100; char tmp[32]; sprintf(tmp, "%d%d", major_version, minor_version); FullName = BasePackageName + std::string("_v") + std::string(tmp); if (PLATFORM_UNKNOWN != Platform) { FullName += string("_") + JoinPlatform(platform); } else { if (ARCH_UNKNOWN != CpuID) { if (ARCH_X86 & CpuID) { LOGD("PackageInfo::PackageInfo: package arch x86"); FullName += string("_") + ARCH_X86_NAME; #ifdef __SUPPORT_INTEL_FEATURES string features = JoinIntelFeatures(CpuID); if (!features.empty()) { FullName += string("_") + features; } #endif } else if (ARCH_X64 & CpuID) { LOGD("PackageInfo::PackageInfo: package arch x64"); #ifdef __SUPPORT_INTEL_x64 FullName += string("_") + ARCH_X64_NAME; #else FullName += string("_") + ARCH_X86_NAME; #endif #ifdef __SUPPORT_INTEL_FEATURES string features = JoinIntelFeatures(CpuID); if (!features.empty()) { FullName += string("_") + features; } #endif } else if (ARCH_ARMv5 & CpuID) { LOGD("PackageInfo::PackageInfo: package arch ARMv5"); FullName += string("_") + ARCH_ARMv5_NAME; #ifdef __SUPPORT_ARMEABI_FEATURES string features = JoinARMFeatures(CpuID); if (!features.empty()) { FullName += string("_") + features; } #endif } else if (ARCH_ARMv6 & CpuID) { LOGD("PackageInfo::PackageInfo: package arch ARMv6"); // NOTE: ARM v5 used instead ARM v6 //FullName += string("_") + ARCH_ARMv6_NAME; FullName += string("_") + ARCH_ARMv5_NAME; #ifdef __SUPPORT_ARMEABI_FEATURES string features = JoinARMFeatures(CpuID); if (!features.empty()) { FullName += string("_") + features; } #endif } else if (ARCH_ARMv7 & CpuID) { LOGD("PackageInfo::PackageInfo: package arch ARMv7"); FullName += string("_") + ARCH_ARMv7_NAME; #ifdef __SUPPORT_ARMEABI_V7A_FEATURES string features = JoinARMFeatures(CpuID); if (!features.empty()) { FullName += string("_") + features; } #endif } #ifdef __SUPPORT_AARCH64 else if (ARCH_AARCH64 & CpuID) { LOGD("PackageInfo::PackageInfo: package arch AARCH64"); FullName += string("_") + ARCH_AARCH64_NAME; } #endif #ifdef __SUPPORT_MIPS else if (ARCH_MIPS & CpuID) { FullName += string("_") + ARCH_MIPS_NAME; } #endif else { LOGD("PackageInfo::PackageInfo: package arch unknown"); Version = 0; CpuID = ARCH_UNKNOWN; Platform = PLATFORM_UNKNOWN; } } else { LOGD("PackageInfo::PackageInfo: package arch unknown"); Version = 0; CpuID = ARCH_UNKNOWN; Platform = PLATFORM_UNKNOWN; } } if (!FullName.empty()) { InstallPath = install_path + FullName + "/lib"; } } PackageInfo::PackageInfo(const string& fullname, const string& install_path, string package_version): FullName(fullname), InstallPath(install_path) { LOGD("PackageInfo::PackageInfo(\"%s\", \"%s\", \"%s\")", fullname.c_str(), install_path.c_str(), package_version.c_str()); assert(!fullname.empty()); assert(!install_path.empty()); if (OPENCV_ENGINE_PACKAGE == fullname) { // Science version 1.7 OpenCV Manager has it's own version of OpenCV inside // Load libopencv_info.so to understand OpenCV version, platform and other features std::string tmp; if (install_path.empty()) { tmp = std::string(DEFAULT_ENGINE_INSTALL_PATH) + "/" + LIB_OPENCV_INFO_NAME; } else { tmp = install_path + "/" + LIB_OPENCV_INFO_NAME; } LOGD("Trying to load info library \"%s\"", tmp.c_str()); void* handle; InfoFunctionType name_func; InfoFunctionType revision_func; handle = dlopen(tmp.c_str(), RTLD_LAZY); if (handle) { const char* error; dlerror(); name_func = (InfoFunctionType)dlsym(handle, "GetPackageName"); revision_func = (InfoFunctionType)dlsym(handle, "GetRevision"); error = dlerror(); if (!error && revision_func && name_func) { FullName = std::string((*name_func)()); package_version = std::string((*revision_func)()); dlclose(handle); LOGI("OpenCV package \"%s\" revision \"%s\" found", FullName.c_str(), package_version.c_str()); } else { LOGE("Library loading error (%p, %p): \"%s\"", name_func, revision_func, error); } } else { LOGI("Info library not found in package"); LOGI("OpenCV Manager package does not contain any verison of OpenCV library"); Version = 0; CpuID = ARCH_UNKNOWN; Platform = PLATFORM_UNKNOWN; return; } } vector features = SplitStringVector(FullName, '_'); if (!features.empty() && (BasePackageName == features[0])) { Version = SplitVersion(features, package_version); if (0 == Version) { CpuID = ARCH_UNKNOWN; Platform = PLATFORM_UNKNOWN; return; } Platform = SplitPlatform(features); if (PLATFORM_UNKNOWN != Platform) { switch (Platform) { case PLATFORM_TEGRA2: { CpuID = ARCH_ARMv7 | FEATURES_HAS_VFPv3d16; } break; case PLATFORM_TEGRA3: { CpuID = ARCH_ARMv7 | FEATURES_HAS_VFPv3 | FEATURES_HAS_NEON; } break; case PLATFORM_TEGRA4: { CpuID = ARCH_ARMv7 | FEATURES_HAS_VFPv3 | FEATURES_HAS_NEON; } break; } } else { if (features.size() < 3) { LOGD("It is not OpenCV library package for this platform"); Version = 0; CpuID = ARCH_UNKNOWN; Platform = PLATFORM_UNKNOWN; return; } else if (ARCH_ARMv5_NAME == features[2]) { CpuID = ARCH_ARMv5 | SplitARMFeatures(features); } else if (ARCH_ARMv6_NAME == features[2]) { CpuID = ARCH_ARMv6 | SplitARMFeatures(features); } else if (ARCH_ARMv7_NAME == features[2]) { CpuID = ARCH_ARMv7 | SplitARMFeatures(features); } #ifdef __SUPPORT_AARCH64 else if (ARCH_AARCH64_NAME == features[2]) { CpuID = ARCH_AARCH64 | SplitARMFeatures(features); } #endif else if (ARCH_X86_NAME == features[2]) { CpuID = ARCH_X86 | SplitIntelFeatures(features); } #ifdef __SUPPORT_INTEL_x64 else if (ARCH_X64_NAME == features[2]) { CpuID = ARCH_X64 | SplitIntelFeatures(features); } #endif #ifdef __SUPPORT_MIPS else if (ARCH_MIPS_NAME == features[2]) { CpuID = ARCH_MIPS; } #endif else { LOGD("It is not OpenCV library package for this platform"); Version = 0; CpuID = ARCH_UNKNOWN; Platform = PLATFORM_UNKNOWN; return; } } } else { LOGD("It is not OpenCV library package for this platform"); Version = 0; CpuID = ARCH_UNKNOWN; Platform = PLATFORM_UNKNOWN; return; } } bool PackageInfo::IsValid() const { return !((0 == Version) && (PLATFORM_UNKNOWN == Platform) && (ARCH_UNKNOWN == CpuID)); } int PackageInfo::GetPlatform() const { return Platform; } int PackageInfo::GetCpuID() const { return CpuID; } string PackageInfo::GetFullName() const { return FullName; } int PackageInfo::GetVersion() const { return Version; } string PackageInfo::GetInstalationPath() const { return InstallPath; } bool PackageInfo::operator==(const PackageInfo& package) const { return (package.FullName == FullName); }