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