/* * Copyright (C) 2019 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. */ #define LOG_TAG "StreamConfigurationMap" #include "StreamConfigurationMap.h" #include namespace android { const uint32_t kScalerStreamConfigurations = ANDROID_SCALER_AVAILABLE_STREAM_CONFIGURATIONS; const uint32_t kScalerStreamConfigurationsMaxRes = ANDROID_SCALER_AVAILABLE_STREAM_CONFIGURATIONS_MAXIMUM_RESOLUTION; const uint32_t kDepthStreamConfigurations = ANDROID_DEPTH_AVAILABLE_DEPTH_STREAM_CONFIGURATIONS; const uint32_t kDepthStreamConfigurationsMaxRes = ANDROID_DEPTH_AVAILABLE_DEPTH_STREAM_CONFIGURATIONS_MAXIMUM_RESOLUTION; const uint32_t kScalerMinFrameDurations = ANDROID_SCALER_AVAILABLE_MIN_FRAME_DURATIONS; const uint32_t kScalerMinFrameDurationsMaxRes = ANDROID_SCALER_AVAILABLE_MIN_FRAME_DURATIONS_MAXIMUM_RESOLUTION; const uint32_t kDepthMinFrameDurations = ANDROID_DEPTH_AVAILABLE_DEPTH_MIN_FRAME_DURATIONS; const uint32_t kDepthMinFrameDurationsMaxRes = ANDROID_DEPTH_AVAILABLE_DEPTH_MIN_FRAME_DURATIONS_MAXIMUM_RESOLUTION; const uint32_t kScalerStallDurations = ANDROID_SCALER_AVAILABLE_STALL_DURATIONS; const uint32_t kScalerStallDurationsMaxRes = ANDROID_SCALER_AVAILABLE_STREAM_CONFIGURATIONS_MAXIMUM_RESOLUTION; const uint32_t kScalerInputOutputFormatsMap = ANDROID_SCALER_AVAILABLE_INPUT_OUTPUT_FORMATS_MAP; const uint32_t kScalerInputOutputFormatsMapMaxRes = ANDROID_SCALER_AVAILABLE_INPUT_OUTPUT_FORMATS_MAP_MAXIMUM_RESOLUTION; const uint32_t kDepthStallDurations = ANDROID_DEPTH_AVAILABLE_DEPTH_STALL_DURATIONS; const uint32_t kDepthStallDurationsMaxRes = ANDROID_DEPTH_AVAILABLE_DEPTH_STALL_DURATIONS_MAXIMUM_RESOLUTION; void StreamConfigurationMap::AppendAvailableStreamConfigurations( const camera_metadata_ro_entry& entry) { for (size_t i = 0; i < entry.count; i += kStreamConfigurationSize) { int32_t width = entry.data.i32[i + kStreamWidthOffset]; int32_t height = entry.data.i32[i + kStreamHeightOffset]; auto format = static_cast( entry.data.i32[i + kStreamFormatOffset]); int32_t isInput = entry.data.i32[i + kStreamIsInputOffset]; if (!isInput) { stream_output_formats_.insert(format); stream_output_size_map_[format].insert(std::make_pair(width, height)); } } } void StreamConfigurationMap::AppendAvailableDynamicPhysicalStreamConfigurations( const camera_metadata_ro_entry& entry) { for (size_t i = 0; i < entry.count; i += kStreamConfigurationSize) { int32_t width = entry.data.i32[i + kStreamWidthOffset]; int32_t height = entry.data.i32[i + kStreamHeightOffset]; auto format = static_cast( entry.data.i32[i + kStreamFormatOffset]); // Both input and output dynamic stream sizes need to be supported as an // output stream. dynamic_physical_stream_output_formats_.insert(format); dynamic_physical_stream_output_size_map_[format].insert( std::make_pair(width, height)); } } void StreamConfigurationMap::AppendAvailableStreamMinDurations( const camera_metadata_ro_entry_t& entry) { for (size_t i = 0; i < entry.count; i += kStreamConfigurationSize) { auto format = static_cast( entry.data.i64[i + kStreamFormatOffset]); uint32_t width = entry.data.i64[i + kStreamWidthOffset]; uint32_t height = entry.data.i64[i + kStreamHeightOffset]; nsecs_t duration = entry.data.i64[i + kStreamMinDurationOffset]; auto streamConfiguration = std::make_pair(format, std::make_pair(width, height)); stream_min_duration_map_[streamConfiguration] = duration; } } void StreamConfigurationMap::AppendAvailableStreamStallDurations( const camera_metadata_ro_entry& entry) { for (size_t i = 0; i < entry.count; i += kStreamConfigurationSize) { auto format = static_cast( entry.data.i64[i + kStreamFormatOffset]); uint32_t width = entry.data.i64[i + kStreamWidthOffset]; uint32_t height = entry.data.i64[i + kStreamHeightOffset]; nsecs_t duration = entry.data.i64[i + kStreamStallDurationOffset]; auto streamConfiguration = std::make_pair(format, std::make_pair(width, height)); stream_stall_map_[streamConfiguration] = duration; } } StreamConfigurationMap::StreamConfigurationMap(const HalCameraMetadata& chars, bool maxResolution) { camera_metadata_ro_entry_t entry; const char* maxResolutionStr = maxResolution ? "true" : "false"; auto ret = chars.Get(maxResolution ? kScalerStreamConfigurationsMaxRes : kScalerStreamConfigurations, &entry); if (ret != OK) { ALOGW( "%s: ANDROID_SCALER_AVAILABLE_STREAM_CONFIGURATIONS missing, " "maxResolution ? %s!", __FUNCTION__, maxResolutionStr); entry.count = 0; } AppendAvailableStreamConfigurations(entry); ret = chars.Get(maxResolution ? kDepthStreamConfigurationsMaxRes : kDepthStreamConfigurations, &entry); if (ret == OK) { AppendAvailableStreamConfigurations(entry); } ret = chars.Get( maxResolution ? kScalerMinFrameDurationsMaxRes : kScalerMinFrameDurations, &entry); if (ret != OK) { ALOGW( "%s: ANDROID_SCALER_AVAILABLE_MIN_FRAME_DURATIONS missing!, max " "resolution ? %s", __FUNCTION__, maxResolutionStr); entry.count = 0; } AppendAvailableStreamMinDurations(entry); ret = chars.Get( maxResolution ? kDepthMinFrameDurationsMaxRes : kDepthMinFrameDurations, &entry); if (ret == OK) { AppendAvailableStreamMinDurations(entry); } ret = chars.Get( maxResolution ? kScalerStallDurationsMaxRes : kScalerStallDurations, &entry); if (ret != OK) { ALOGW( "%s: ANDROID_SCALER_AVAILABLE_STALL_DURATIONS missing! maxResolution ? " "%s", __FUNCTION__, maxResolutionStr); entry.count = 0; } AppendAvailableStreamStallDurations(entry); ret = chars.Get( maxResolution ? kDepthStallDurationsMaxRes : kDepthStallDurations, &entry); if (ret == OK) { AppendAvailableStreamStallDurations(entry); } ret = chars.Get(maxResolution ? kScalerInputOutputFormatsMapMaxRes : kScalerInputOutputFormatsMap, &entry); if (ret == OK) { size_t i = 0; while (i < entry.count) { auto input_format = static_cast(entry.data.i32[i++]); auto output_format_count = entry.data.i32[i++]; if (output_format_count <= 0 || ((output_format_count + i) > entry.count)) { ALOGE("%s: Invalid output format count: %d!", __func__, output_format_count); break; } size_t output_formats_end = output_format_count + i; for (; i < output_formats_end; i++) { stream_input_output_map_[input_format].insert( static_cast(entry.data.i32[i])); } stream_input_formats_.insert(input_format); } } ret = chars.Get( ANDROID_SCALER_PHYSICAL_CAMERA_MULTI_RESOLUTION_STREAM_CONFIGURATIONS, &entry); if (ret == OK) { AppendAvailableDynamicPhysicalStreamConfigurations(entry); } } } // namespace android