/* * Copyright (C) 2016 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #ifndef V4L2_CAMERA_HAL_METADATA_CONTROL_FACTORY_H_ #define V4L2_CAMERA_HAL_METADATA_CONTROL_FACTORY_H_ #include "common.h" #include "control.h" #include "menu_control_options.h" #include "no_effect_control_delegate.h" #include "ranged_converter.h" #include "slider_control_options.h" #include "state.h" #include "tagged_control_delegate.h" #include "tagged_control_options.h" #include "v4l2_control_delegate.h" namespace v4l2_camera_hal { enum class ControlType { kMenu, kSlider }; // Static functions to create partial metadata. Nullptr is returned on failures. // FixedState: A state that doesn't change. template static std::unique_ptr> FixedState(int32_t tag, T value); // NoEffectOptionlessControl: A control that accepts any value, // and has no effect. A default value is given. template static std::unique_ptr> NoEffectOptionlessControl( int32_t delegate_tag, T default_value); // NoEffectMenuControl: Some menu options, but they have no effect. template static std::unique_ptr> NoEffectMenuControl( int32_t delegate_tag, int32_t options_tag, const std::vector& options, std::map default_values = {}); // NoEffectSliderControl: A slider of options, but they have no effect. template static std::unique_ptr> NoEffectSliderControl( int32_t delegate_tag, int32_t options_tag, T min, T max, std::map default_values = {}); // NoEffectControl: A control with no effect and only a single allowable // value. Chooses an appropriate ControlOptionsInterface depending on type. template static std::unique_ptr> NoEffectControl( ControlType type, int32_t delegate_tag, int32_t options_tag, T value, std::map default_values = {}); // V4L2Control: A control corresponding to a V4L2 control. template static std::unique_ptr> V4L2Control( ControlType type, int32_t delegate_tag, int32_t options_tag, std::shared_ptr device, int control_id, std::shared_ptr> converter, std::map default_values = {}); // V4L2ControlOrDefault: Like V4L2Control, but if the V4L2Control fails to // initialize for some reason, this method will fall back to NoEffectControl // with an initial value defined by |fallback_default|. template static std::unique_ptr> V4L2ControlOrDefault( ControlType type, int32_t delegate_tag, int32_t options_tag, std::shared_ptr device, int control_id, std::shared_ptr> converter, T fallback_default, std::map default_values = {}); // ----------------------------------------------------------------------------- template std::unique_ptr> FixedState(int32_t tag, T value) { HAL_LOG_ENTER(); // Take advantage of ControlDelegate inheriting from StateDelegate; // This will only expose GetValue, not SetValue, so the default will // always be returned. return std::make_unique>( tag, std::make_unique>(value)); } template std::unique_ptr> NoEffectOptionlessControl(int32_t delegate_tag, T default_value) { HAL_LOG_ENTER(); return std::make_unique>( std::make_unique>( delegate_tag, std::make_unique>(default_value)), nullptr); } template std::unique_ptr> NoEffectMenuControl( int32_t delegate_tag, int32_t options_tag, const std::vector& options, std::map default_values) { HAL_LOG_ENTER(); if (options.empty()) { HAL_LOGE("At least one option must be provided."); return nullptr; } return std::make_unique>( std::make_unique>( delegate_tag, std::make_unique>(options[0])), std::make_unique>( options_tag, std::make_unique>(options, default_values))); } template std::unique_ptr> NoEffectSliderControl( int32_t delegate_tag, int32_t options_tag, T min, T max, std::map default_values) { HAL_LOG_ENTER(); return std::make_unique>( std::make_unique>( delegate_tag, std::make_unique>(min)), std::make_unique>( options_tag, std::make_unique>(min, max, default_values))); } template std::unique_ptr> NoEffectControl(ControlType type, int32_t delegate_tag, int32_t options_tag, T value, std::map default_values) { HAL_LOG_ENTER(); switch (type) { case ControlType::kMenu: return NoEffectMenuControl( delegate_tag, options_tag, {value}, default_values); case ControlType::kSlider: return NoEffectSliderControl( delegate_tag, options_tag, value, value, default_values); } } template std::unique_ptr> V4L2Control( ControlType type, int32_t delegate_tag, int32_t options_tag, std::shared_ptr device, int control_id, std::shared_ptr> converter, std::map default_values) { HAL_LOG_ENTER(); // Query the device. v4l2_query_ext_ctrl control_query; int res = device->QueryControl(control_id, &control_query); if (res) { HAL_LOGE("Failed to query control %d.", control_id); return nullptr; } int32_t control_min = static_cast(control_query.minimum); int32_t control_max = static_cast(control_query.maximum); int32_t control_step = static_cast(control_query.step); if (control_min > control_max) { HAL_LOGE("No acceptable values (min %d is greater than max %d).", control_min, control_max); return nullptr; } // Variables needed by the various switch statements. std::vector options; T metadata_val; T metadata_min; T metadata_max; // Set up the result converter and result options based on type. std::shared_ptr> result_converter(converter); std::unique_ptr> result_options; switch (control_query.type) { case V4L2_CTRL_TYPE_BOOLEAN: if (type != ControlType::kMenu) { HAL_LOGE( "V4L2 control %d is of type %d, which isn't compatible with " "desired metadata control type %d", control_id, control_query.type, type); return nullptr; } // Convert each available option, // ignoring ones without a known conversion. for (int32_t i = control_min; i <= control_max; i += control_step) { res = converter->V4L2ToMetadata(i, &metadata_val); if (res == -EINVAL) { HAL_LOGV("V4L2 value %d for control %d has no metadata equivalent.", i, control_id); continue; } else if (res) { HAL_LOGE("Error converting value %d for control %d.", i, control_id); return nullptr; } options.push_back(metadata_val); } // Check to make sure there's at least one option. if (options.empty()) { HAL_LOGE("No valid options for control %d.", control_id); return nullptr; } result_options.reset(new MenuControlOptions(options, default_values)); // No converter changes necessary. break; case V4L2_CTRL_TYPE_INTEGER: if (type != ControlType::kSlider) { HAL_LOGE( "V4L2 control %d is of type %d, which isn't compatible with " "desired metadata control type %d", control_id, control_query.type, type); return nullptr; } // Upgrade to a range/step-clamping converter. result_converter.reset(new RangedConverter( converter, control_min, control_max, control_step)); // Convert the min and max. res = result_converter->V4L2ToMetadata(control_min, &metadata_min); if (res) { HAL_LOGE( "Failed to convert V4L2 min value %d for control %d to metadata.", control_min, control_id); return nullptr; } res = result_converter->V4L2ToMetadata(control_max, &metadata_max); if (res) { HAL_LOGE( "Failed to convert V4L2 max value %d for control %d to metadata.", control_max, control_id); return nullptr; } result_options.reset(new SliderControlOptions( metadata_min, metadata_max, default_values)); break; default: HAL_LOGE("Control %d (%s) is of unsupported type %d", control_id, control_query.name, control_query.type); return nullptr; } // Construct the control. return std::make_unique>( std::make_unique>( delegate_tag, std::make_unique>( device, control_id, result_converter)), std::make_unique>(options_tag, std::move(result_options))); } template std::unique_ptr> V4L2ControlOrDefault( ControlType type, int32_t delegate_tag, int32_t options_tag, std::shared_ptr device, int control_id, std::shared_ptr> converter, T fallback_default, std::map default_values) { HAL_LOG_ENTER(); std::unique_ptr> result = V4L2Control(type, delegate_tag, options_tag, device, control_id, converter, default_values); if (!result) { result = NoEffectControl( type, delegate_tag, options_tag, fallback_default, default_values); } return result; } } // namespace v4l2_camera_hal #endif // V4L2_CAMERA_HAL_METADATA_CONTROL_FACTORY_H_