| /* |
| * 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 <log/log.h> |
| |
| 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<android_pixel_format_t>( |
| 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<android_pixel_format_t>( |
| 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<android_pixel_format_t>( |
| 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<android_pixel_format_t>( |
| 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<android_pixel_format_t>(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<android_pixel_format_t>(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 |