| /* |
| * Copyright 2021 The Chromium OS Authors. All rights reserved. |
| * Use of this source code is governed by a BSD-style license that can be |
| * found in the LICENSE file. |
| */ |
| |
| #include "camera/features/feature_profile.h" |
| |
| #include <iomanip> |
| #include <string> |
| #include <utility> |
| |
| #include "cros-camera/common.h" |
| |
| namespace cros { |
| |
| namespace { |
| |
| base::Optional<FeatureProfile::FeatureType> GetFeatureType( |
| const std::string& feature_key) { |
| if (feature_key == "face_detection") { |
| return FeatureProfile::FeatureType::kFaceDetection; |
| } else if (feature_key == "gcam_ae") { |
| return FeatureProfile::FeatureType::kGcamAe; |
| } else if (feature_key == "hdrnet") { |
| return FeatureProfile::FeatureType::kHdrnet; |
| } |
| return base::nullopt; |
| } |
| |
| } // namespace |
| |
| FeatureProfile::FeatureProfile(base::Optional<base::Value> feature_config, |
| base::Optional<DeviceConfig> device_config) |
| : config_file_(base::FilePath(kFeatureProfileFilePath)), |
| device_config_(device_config ? std::move(device_config).value() |
| : DeviceConfig::Create()) { |
| if (feature_config.has_value()) { |
| OnOptionsUpdated(feature_config.value()); |
| } else { |
| config_file_.SetCallback(base::BindRepeating( |
| &FeatureProfile::OnOptionsUpdated, base::Unretained(this))); |
| } |
| } |
| |
| bool FeatureProfile::IsEnabled(FeatureType feature) const { |
| return feature_settings_.find(feature) != feature_settings_.end(); |
| } |
| |
| base::FilePath FeatureProfile::GetConfigFilePath(FeatureType feature) const { |
| auto setting = feature_settings_.find(feature); |
| if (setting == feature_settings_.end()) { |
| return base::FilePath(); |
| } |
| return setting->second.config_file_path; |
| } |
| |
| void FeatureProfile::OnOptionsUpdated(const base::Value& json_values) { |
| // Feature config file schema: |
| // |
| // { |
| // <model>: { |
| // "feature_set": [ |
| // {"type": <feature_type>, "config_file_path": <config_file_path>}, |
| // ... |
| // ] |
| // }, |
| // ... |
| // } |
| // |
| // <model>: String of device model name, e.g. "redrix". |
| // <feature_type>: String for the type of the feature, e.g. "face_detection" |
| // or "hdrnet". |
| // <config_file_path>: String specifying the path to the feature config file. |
| |
| constexpr char kKeyFeatureSet[] = "feature_set"; |
| constexpr char kKeyType[] = "type"; |
| constexpr char kKeyConfigFilePath[] = "config_file_path"; |
| |
| if (!device_config_.has_value()) { |
| LOGF(WARNING) << "Device config is invalid, cannot determine model name"; |
| return; |
| } |
| |
| if (!json_values.is_dict()) { |
| LOGF(ERROR) << "Feature config must be a dict"; |
| return; |
| } |
| |
| // Get the per-model feature profile from the top-level. |
| const base::Value* feature_profile = |
| json_values.FindDictKey(device_config_->GetModelName()); |
| if (feature_profile == nullptr) { |
| LOGF(ERROR) << "Cannot find feature profile as dict for device model " |
| << std::quoted(device_config_->GetModelName()); |
| return; |
| } |
| |
| // Extract "feature_set" info from the feature profile. |
| const base::Value* feature_set = feature_profile->FindListKey(kKeyFeatureSet); |
| if (feature_set == nullptr) { |
| LOGF(ERROR) << "Cannot find " << std::quoted(kKeyFeatureSet) |
| << " as list in the feature profile of " |
| << std::quoted(device_config_->GetModelName()); |
| return; |
| } |
| |
| // Construct the complete feature settings. |
| for (const auto& v : feature_set->GetList()) { |
| if (!v.is_dict()) { |
| LOGF(ERROR) << "Feature setting in " << std::quoted(kKeyFeatureSet) |
| << " must be a dict"; |
| continue; |
| } |
| const std::string* type_str = v.FindStringKey(kKeyType); |
| if (type_str == nullptr) { |
| LOGF(ERROR) << "Malformed feature setting: Cannot find key " |
| << std::quoted(kKeyType); |
| continue; |
| } |
| base::Optional<FeatureType> type = GetFeatureType(*type_str); |
| if (!type.has_value()) { |
| LOGF(ERROR) << "Unknown feature " << std::quoted(*type_str); |
| continue; |
| } |
| const std::string* path_str = v.FindStringKey(kKeyConfigFilePath); |
| if (type_str == nullptr) { |
| LOGF(ERROR) << "Malformed feature setting: Cannot find key " |
| << std::quoted(kKeyConfigFilePath); |
| continue; |
| } |
| feature_settings_.insert( |
| {*type, {.config_file_path = base::FilePath(*path_str)}}); |
| } |
| } |
| |
| } // namespace cros |