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 #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