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