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.
ConstructStreamCapabilities(const std::vector<StreamConfiguration> & configs,const std::vector<StreamStallDuration> & stalls,StaticProperties::CapabilitiesMap * capabilities)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).
ValidateStreamCapabilities(StaticProperties::CapabilitiesMap capabilities)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.
ValidateReprocessFormats(const StaticProperties::CapabilitiesMap & capabilities,const ReprocessFormatMap & reprocess_map)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
NewStaticProperties(std::unique_ptr<const MetadataReader> metadata_reader)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
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)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
TemplateSupported(int type)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.
IsInputType(int stream_type)237 static bool IsInputType(int stream_type) {
238 return stream_type == CAMERA3_STREAM_INPUT ||
239 stream_type == CAMERA3_STREAM_BIDIRECTIONAL;
240 }
241
IsOutputType(int stream_type)242 static bool IsOutputType(int stream_type) {
243 return stream_type == CAMERA3_STREAM_OUTPUT ||
244 stream_type == CAMERA3_STREAM_BIDIRECTIONAL;
245 }
246
IsRawFormat(int format)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
StreamConfigurationSupported(const camera3_stream_configuration_t * stream_config)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
SanityCheckStreamConfiguration(const camera3_stream_configuration_t * stream_config)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
InputStreamsSupported(const camera3_stream_configuration_t * stream_config)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
OutputStreamsSupported(const camera3_stream_configuration_t * stream_config)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
OperationModeSupported(const camera3_stream_configuration_t * stream_config)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
ReprocessingSupported(const camera3_stream_t * input_stream,const std::set<const camera3_stream_t * > & output_streams)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