• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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.
ConstructStreamCapabilities(const std::vector<StreamConfiguration> & configs,const std::vector<StreamStallDuration> & stalls,StaticProperties::CapabilitiesMap * capabilities)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).
ValidateStreamCapabilities(StaticProperties::CapabilitiesMap capabilities)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.
ValidateReprocessFormats(const StaticProperties::CapabilitiesMap & capabilities,const ReprocessFormatMap & reprocess_map)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 
NewStaticProperties(std::unique_ptr<const MetadataReader> metadata_reader)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 
StaticProperties(std::unique_ptr<const MetadataReader> metadata_reader,int facing,int orientation,int32_t max_input_streams,int32_t max_raw_output_streams,int32_t max_non_stalling_output_streams,int32_t max_stalling_output_streams,std::set<uint8_t> request_capabilities,CapabilitiesMap stream_capabilities,ReprocessFormatMap supported_reprocess_outputs)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 
TemplateSupported(int type)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.
IsInputType(int stream_type)238 static bool IsInputType(int stream_type) {
239   return stream_type == CAMERA3_STREAM_INPUT ||
240          stream_type == CAMERA3_STREAM_BIDIRECTIONAL;
241 }
242 
IsOutputType(int stream_type)243 static bool IsOutputType(int stream_type) {
244   return stream_type == CAMERA3_STREAM_OUTPUT ||
245          stream_type == CAMERA3_STREAM_BIDIRECTIONAL;
246 }
247 
IsRawFormat(int format)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 
StreamConfigurationSupported(const camera3_stream_configuration_t * stream_config)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 
SanityCheckStreamConfiguration(const camera3_stream_configuration_t * stream_config)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 
InputStreamsSupported(const camera3_stream_configuration_t * stream_config)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 
OutputStreamsSupported(const camera3_stream_configuration_t * stream_config)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 
OperationModeSupported(const camera3_stream_configuration_t * stream_config)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 
ReprocessingSupported(const camera3_stream_t * input_stream,const std::set<const camera3_stream_t * > & output_streams)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