Home | History | Annotate | Download | only in 3_4
      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