1 /* 2 * Copyright (C) 2016 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 // #define LOG_NDEBUG 0 18 #define LOG_TAG "StaticProperties" 19 20 #include "static_properties.h" 21 22 #include <cutils/log.h> 23 #include <hardware/camera3.h> 24 #include <system/camera.h> 25 26 #include "metadata/metadata_reader.h" 27 28 namespace default_camera_hal { 29 30 // Build stream capabilities from configs + stall durations. 31 static bool ConstructStreamCapabilities( 32 const std::vector<StreamConfiguration>& configs, 33 const std::vector<StreamStallDuration>& stalls, 34 StaticProperties::CapabilitiesMap* capabilities) { 35 // Extract directional capabilities from the configs. 36 for (const auto& config : configs) { 37 switch (config.direction) { 38 case ANDROID_SCALER_AVAILABLE_STREAM_CONFIGURATIONS_OUTPUT: 39 (*capabilities)[config.spec].output_supported = true; 40 break; 41 case ANDROID_SCALER_AVAILABLE_STREAM_CONFIGURATIONS_INPUT: 42 (*capabilities)[config.spec].input_supported = true; 43 break; 44 default: 45 // Should never happen when using the MetadataReader; 46 // it should validate directions. 47 ALOGE("%s: Unrecognized stream config direction %d.", 48 __func__, 49 config.direction); 50 return false; 51 } 52 } 53 54 // Extract stall durations from the stalls. 55 for (const auto& stall : stalls) { 56 (*capabilities)[stall.spec].stall_duration = stall.duration; 57 } 58 59 return true; 60 } 61 62 // Check that each output config has a valid corresponding stall duration 63 // (extra durations not matching any output config are ignored). 64 static bool ValidateStreamCapabilities( 65 StaticProperties::CapabilitiesMap capabilities) { 66 for (const auto& spec_capabilities : capabilities) { 67 // Only non-negative stall durations are valid. This should only happen 68 // due to output streams without an associated stall duration, as 69 // MetadataReader validates the metadata stall durations. 70 if (spec_capabilities.second.output_supported && 71 spec_capabilities.second.stall_duration < 0) { 72 ALOGE( 73 "%s: Static metadata does not have a stall duration for " 74 "each output configuration. ", 75 __func__); 76 return false; 77 } 78 } 79 return true; 80 } 81 82 // Validate that the input/output formats map matches up with 83 // the capabilities listed for all formats. 84 bool ValidateReprocessFormats( 85 const StaticProperties::CapabilitiesMap& capabilities, 86 const ReprocessFormatMap& reprocess_map) { 87 // Get input formats. 88 std::set<int32_t> all_input_formats; 89 std::set<int32_t> all_output_formats; 90 for (const auto& spec_capabilities : capabilities) { 91 if (spec_capabilities.second.input_supported) { 92 all_input_formats.insert(spec_capabilities.first.format); 93 } 94 if (spec_capabilities.second.output_supported) { 95 all_output_formats.insert(spec_capabilities.first.format); 96 } 97 } 98 99 // Must be at least one input format. 100 if (all_input_formats.size() < 1) { 101 ALOGE("%s: No input formats, reprocessing can't be supported.", __func__); 102 return false; 103 } 104 105 // Check that the reprocess map input formats are exactly all available 106 // input formats (check size here, then checking for actual value 107 // matches will happen as part of the loop below). 108 if (all_input_formats.size() != reprocess_map.size()) { 109 ALOGE( 110 "%s: Stream configuration input formats do not match " 111 "input/output format map input formats.", 112 __func__); 113 return false; 114 } 115 116 // Check that each input format has at least one matching output format. 117 for (const auto& input_format : all_input_formats) { 118 const auto input_outputs_iterator = reprocess_map.find(input_format); 119 if (input_outputs_iterator == reprocess_map.end()) { 120 ALOGE( 121 "%s: No output formats for input format %d.", __func__, input_format); 122 return false; 123 } 124 // No need to check that the output formats vector is non-empty; 125 // MetadataReader validates this. Instead just check that 126 // all outputs are actually output formats. 127 for (const auto& output_format : input_outputs_iterator->second) { 128 if (all_output_formats.count(output_format) < 1) { 129 ALOGE( 130 "%s: Output format %d for input format %d " 131 "is not a supported output format.", 132 __func__, 133 input_format, 134 output_format); 135 return false; 136 } 137 } 138 } 139 140 return true; 141 } 142 143 StaticProperties* StaticProperties::NewStaticProperties( 144 std::unique_ptr<const MetadataReader> metadata_reader) { 145 int facing = 0; 146 int orientation = 0; 147 int32_t max_input_streams = 0; 148 int32_t max_raw_output_streams = 0; 149 int32_t max_non_stalling_output_streams = 0; 150 int32_t max_stalling_output_streams = 0; 151 std::set<uint8_t> request_capabilities; 152 std::vector<StreamConfiguration> configs; 153 std::vector<StreamStallDuration> stalls; 154 CapabilitiesMap stream_capabilities; 155 ReprocessFormatMap reprocess_map; 156 157 // If reading any data returns an error, something is wrong. 158 if (metadata_reader->Facing(&facing) || 159 metadata_reader->Orientation(&orientation) || 160 metadata_reader->MaxInputStreams(&max_input_streams) || 161 metadata_reader->MaxOutputStreams(&max_raw_output_streams, 162 &max_non_stalling_output_streams, 163 &max_stalling_output_streams) || 164 metadata_reader->RequestCapabilities(&request_capabilities) || 165 metadata_reader->StreamConfigurations(&configs) || 166 metadata_reader->StreamStallDurations(&stalls) || 167 !ConstructStreamCapabilities(configs, stalls, &stream_capabilities) || 168 // MetadataReader validates configs and stall seperately, 169 // but not that they match. 170 !ValidateStreamCapabilities(stream_capabilities) || 171 // Reprocessing metadata only necessary if input streams are allowed. 172 (max_input_streams > 0 && 173 (metadata_reader->ReprocessFormats(&reprocess_map) || 174 // MetadataReader validates configs and the reprocess map seperately, 175 // but not that they match. 176 !ValidateReprocessFormats(stream_capabilities, reprocess_map)))) { 177 return nullptr; 178 } 179 180 return new StaticProperties(std::move(metadata_reader), 181 facing, 182 orientation, 183 max_input_streams, 184 max_raw_output_streams, 185 max_non_stalling_output_streams, 186 max_stalling_output_streams, 187 std::move(request_capabilities), 188 std::move(stream_capabilities), 189 std::move(reprocess_map)); 190 } 191 192 StaticProperties::StaticProperties( 193 std::unique_ptr<const MetadataReader> metadata_reader, 194 int facing, 195 int orientation, 196 int32_t max_input_streams, 197 int32_t max_raw_output_streams, 198 int32_t max_non_stalling_output_streams, 199 int32_t max_stalling_output_streams, 200 std::set<uint8_t> request_capabilities, 201 CapabilitiesMap stream_capabilities, 202 ReprocessFormatMap supported_reprocess_outputs) 203 : metadata_reader_(std::move(metadata_reader)), 204 facing_(facing), 205 orientation_(orientation), 206 max_input_streams_(max_input_streams), 207 max_raw_output_streams_(max_raw_output_streams), 208 max_non_stalling_output_streams_(max_non_stalling_output_streams), 209 max_stalling_output_streams_(max_stalling_output_streams), 210 request_capabilities_(std::move(request_capabilities)), 211 stream_capabilities_(std::move(stream_capabilities)), 212 supported_reprocess_outputs_(std::move(supported_reprocess_outputs)) {} 213 214 bool StaticProperties::TemplateSupported(int type) { 215 uint8_t required_capability = 0; 216 switch (type) { 217 case CAMERA3_TEMPLATE_PREVIEW: 218 // Preview is always supported. 219 return true; 220 case CAMERA3_TEMPLATE_MANUAL: 221 required_capability = 222 ANDROID_REQUEST_AVAILABLE_CAPABILITIES_MANUAL_SENSOR; 223 break; 224 case CAMERA3_TEMPLATE_ZERO_SHUTTER_LAG: 225 required_capability = 226 ANDROID_REQUEST_AVAILABLE_CAPABILITIES_PRIVATE_REPROCESSING; 227 break; 228 default: 229 required_capability = 230 ANDROID_REQUEST_AVAILABLE_CAPABILITIES_BACKWARD_COMPATIBLE; 231 return true; 232 } 233 234 return request_capabilities_.count(required_capability) > 0; 235 } 236 237 // Helper functions for checking stream properties when verifying support. 238 static bool IsInputType(int stream_type) { 239 return stream_type == CAMERA3_STREAM_INPUT || 240 stream_type == CAMERA3_STREAM_BIDIRECTIONAL; 241 } 242 243 static bool IsOutputType(int stream_type) { 244 return stream_type == CAMERA3_STREAM_OUTPUT || 245 stream_type == CAMERA3_STREAM_BIDIRECTIONAL; 246 } 247 248 static bool IsRawFormat(int format) { 249 return format == HAL_PIXEL_FORMAT_RAW10 || format == HAL_PIXEL_FORMAT_RAW12 || 250 format == HAL_PIXEL_FORMAT_RAW16 || 251 format == HAL_PIXEL_FORMAT_RAW_OPAQUE; 252 } 253 254 bool StaticProperties::StreamConfigurationSupported( 255 const camera3_stream_configuration_t* stream_config) { 256 return SanityCheckStreamConfiguration(stream_config) && 257 InputStreamsSupported(stream_config) && 258 OutputStreamsSupported(stream_config) && 259 OperationModeSupported(stream_config); 260 } 261 262 bool StaticProperties::SanityCheckStreamConfiguration( 263 const camera3_stream_configuration_t* stream_config) { 264 // Check for null/empty values. 265 if (stream_config == nullptr) { 266 ALOGE("%s: NULL stream configuration array", __func__); 267 return false; 268 } else if (stream_config->num_streams == 0) { 269 ALOGE("%s: Empty stream configuration array", __func__); 270 return false; 271 } else if (stream_config->streams == nullptr) { 272 ALOGE("%s: NULL stream configuration streams", __func__); 273 return false; 274 } 275 276 // Check that all streams are either inputs or outputs (or both). 277 for (size_t i = 0; i < stream_config->num_streams; ++i) { 278 const camera3_stream_t* stream = stream_config->streams[i]; 279 if (stream == nullptr) { 280 ALOGE("%s: Stream %zu is null", __func__, i); 281 return false; 282 } else if (!IsInputType(stream->stream_type) && 283 !IsOutputType(stream->stream_type)) { 284 ALOGE("%s: Stream %zu type %d is neither an input nor an output type", 285 __func__, 286 i, 287 stream->stream_type); 288 return false; 289 } 290 } 291 292 return true; 293 } 294 295 bool StaticProperties::InputStreamsSupported( 296 const camera3_stream_configuration_t* stream_config) { 297 // Find the input stream(s). 298 int32_t num_input_streams = 0; 299 int input_format = -1; 300 for (size_t i = 0; i < stream_config->num_streams; ++i) { 301 const camera3_stream_t* stream = stream_config->streams[i]; 302 if (IsInputType(stream->stream_type)) { 303 // Check that this stream is valid as an input. 304 const auto capabilities_iterator = stream_capabilities_.find(stream); 305 if (capabilities_iterator == stream_capabilities_.end() || 306 !capabilities_iterator->second.input_supported) { 307 ALOGE("%s: %d x %d stream of format %d is not a supported input setup.", 308 __func__, 309 stream->width, 310 stream->height, 311 stream->format); 312 return false; 313 } 314 315 // Valid input stream; count it. 316 ++num_input_streams; 317 input_format = stream->format; 318 } 319 } 320 321 // Check the count. 322 if (num_input_streams > max_input_streams_) { 323 ALOGE( 324 "%s: Requested number of input streams %d is greater than " 325 "the maximum number supported by the device (%d).", 326 __func__, 327 num_input_streams, 328 max_input_streams_); 329 return false; 330 } 331 if (num_input_streams > 1) { 332 ALOGE("%s: Camera HAL 3.4 only supports 1 input stream max.", __func__); 333 return false; 334 } 335 336 // If there's an input stream, the configuration must have at least one 337 // supported output format for reprocessing that input. 338 if (num_input_streams > 0) { 339 const auto input_output_formats_iterator = 340 supported_reprocess_outputs_.find(input_format); 341 if (input_output_formats_iterator == supported_reprocess_outputs_.end()) { 342 // Should never happen; factory should verify that all valid inputs 343 // have one or more valid outputs. 344 ALOGE("%s: No valid output formats for input format %d.", 345 __func__, 346 input_format); 347 return false; 348 } 349 bool match_found = false; 350 // Go through outputs looking for a supported one. 351 for (size_t i = 0; i < stream_config->num_streams; ++i) { 352 const camera3_stream_t* stream = stream_config->streams[i]; 353 if (IsOutputType(stream->stream_type)) { 354 if (input_output_formats_iterator->second.count(stream->format) > 0) { 355 match_found = true; 356 break; 357 } 358 } 359 } 360 if (!match_found) { 361 ALOGE("%s: No supported output format provided for input format %d.", 362 __func__, 363 input_format); 364 return false; 365 } 366 } 367 368 return true; 369 } 370 371 bool StaticProperties::OutputStreamsSupported( 372 const camera3_stream_configuration_t* stream_config) { 373 // Find and count output streams. 374 int32_t num_raw = 0; 375 int32_t num_stalling = 0; 376 int32_t num_non_stalling = 0; 377 for (size_t i = 0; i < stream_config->num_streams; ++i) { 378 const camera3_stream_t* stream = stream_config->streams[i]; 379 if (IsOutputType(stream->stream_type)) { 380 // Check that this stream is valid as an output. 381 const auto capabilities_iterator = stream_capabilities_.find(stream); 382 if (capabilities_iterator == stream_capabilities_.end() || 383 !capabilities_iterator->second.output_supported) { 384 ALOGE( 385 "%s: %d x %d stream of format %d " 386 "is not a supported output setup.", 387 __func__, 388 stream->width, 389 stream->height, 390 stream->format); 391 return false; 392 } 393 394 // Valid output; count it. 395 if (IsRawFormat(stream->format)) { 396 ++num_raw; 397 } else if (capabilities_iterator->second.stall_duration > 0) { 398 ++num_stalling; 399 } else { 400 ++num_non_stalling; 401 } 402 } 403 } 404 405 // Check that the counts are within bounds. 406 if (num_raw > max_raw_output_streams_) { 407 ALOGE( 408 "%s: Requested stream configuration exceeds maximum supported " 409 "raw output streams %d (requested %d).", 410 __func__, 411 max_raw_output_streams_, 412 num_raw); 413 return false; 414 } else if (num_stalling > max_stalling_output_streams_) { 415 ALOGE( 416 "%s: Requested stream configuration exceeds maximum supported " 417 "stalling output streams %d (requested %u).", 418 __func__, 419 max_stalling_output_streams_, 420 num_stalling); 421 return false; 422 } else if (num_non_stalling > max_non_stalling_output_streams_) { 423 ALOGE( 424 "%s: Requested stream configuration exceeds maximum supported " 425 "non-stalling output streams %d (requested %d).", 426 __func__, 427 max_non_stalling_output_streams_, 428 num_non_stalling); 429 return false; 430 } 431 432 return true; 433 } 434 435 bool StaticProperties::OperationModeSupported( 436 const camera3_stream_configuration_t* stream_config) { 437 switch (stream_config->operation_mode) { 438 case CAMERA3_STREAM_CONFIGURATION_NORMAL_MODE: 439 return true; 440 case CAMERA3_STREAM_CONFIGURATION_CONSTRAINED_HIGH_SPEED_MODE: 441 // TODO(b/31370792): Check metadata for high speed support, 442 // check that requested streams have support for high speed. 443 ALOGE("%s: Support for CONSTRAINED_HIGH_SPEED not implemented", __func__); 444 return false; 445 default: 446 ALOGE("%s: Unrecognized stream configuration mode: %d", 447 __func__, 448 stream_config->operation_mode); 449 return false; 450 } 451 } 452 453 bool StaticProperties::ReprocessingSupported( 454 const camera3_stream_t* input_stream, 455 const std::set<const camera3_stream_t*>& output_streams) { 456 // There must be an input. 457 if (!input_stream) { 458 ALOGE("%s: No input stream.", __func__); 459 return false; 460 } 461 // There must be an output. 462 if (output_streams.size() < 1) { 463 ALOGE("%s: No output stream.", __func__); 464 return false; 465 } 466 467 const auto input_output_formats = 468 supported_reprocess_outputs_.find(input_stream->format); 469 if (input_output_formats == supported_reprocess_outputs_.end()) { 470 // Should never happen for a valid input stream. 471 ALOGE("%s: Input format %d does not support any output formats.", 472 __func__, 473 input_stream->format); 474 return false; 475 } 476 477 // Check that all output streams can be outputs for the input stream. 478 const std::set<int32_t>& supported_output_formats = 479 input_output_formats->second; 480 for (const auto output_stream : output_streams) { 481 if (supported_output_formats.count(output_stream->format) < 1) { 482 ALOGE( 483 "%s: Output format %d is not a supported output " 484 "for request input format %d.", 485 __func__, 486 output_stream->format, 487 input_stream->format); 488 return false; 489 } 490 } 491 492 return true; 493 } 494 495 } // namespace default_camera_hal 496