Add configs & validation to static properties
Static properties read and validate stream configurations, stall durations, and reprocess formats. Static properties can be used to validate a given camera3_stream_configuration_t to check if the streams all work together as defined by the metadata properties. BUG: 31044638 TEST: unit tests pass Change-Id: I2c8eecb680cd86fbe0340c07e4d73bd25429b4e9
This commit is contained in:
parent
737cfd31a6
commit
ffb9b72e4e
4 changed files with 1041 additions and 9 deletions
|
@ -31,6 +31,13 @@ class MetadataReaderMock : public MetadataReader {
|
|||
MOCK_CONST_METHOD0(raw_metadata, const camera_metadata_t*());
|
||||
MOCK_CONST_METHOD1(Facing, int(int*));
|
||||
MOCK_CONST_METHOD1(Orientation, int(int*));
|
||||
MOCK_CONST_METHOD1(MaxInputStreams, int(int32_t*));
|
||||
MOCK_CONST_METHOD3(MaxOutputStreams, int(int32_t*, int32_t*, int32_t*));
|
||||
MOCK_CONST_METHOD1(StreamConfigurations,
|
||||
int(std::vector<StreamConfiguration>*));
|
||||
MOCK_CONST_METHOD1(StreamStallDurations,
|
||||
int(std::vector<StreamStallDuration>*));
|
||||
MOCK_CONST_METHOD1(ReprocessFormats, int(ReprocessFormatMap*));
|
||||
};
|
||||
|
||||
} // namespace default_camera_hal
|
||||
|
|
|
@ -25,25 +25,441 @@
|
|||
|
||||
namespace default_camera_hal {
|
||||
|
||||
// Build and capabilities from configs + stall durations.
|
||||
static bool ConstructCapabilities(
|
||||
const std::vector<StreamConfiguration>& configs,
|
||||
const std::vector<StreamStallDuration>& stalls,
|
||||
StaticProperties::CapabilitiesMap* capabilities) {
|
||||
// Extract directional capabilities from the configs.
|
||||
for (const auto& config : configs) {
|
||||
switch (config.direction) {
|
||||
case ANDROID_SCALER_AVAILABLE_STREAM_CONFIGURATIONS_OUTPUT:
|
||||
(*capabilities)[config.spec].output_supported = true;
|
||||
break;
|
||||
case ANDROID_SCALER_AVAILABLE_STREAM_CONFIGURATIONS_INPUT:
|
||||
(*capabilities)[config.spec].input_supported = true;
|
||||
break;
|
||||
default:
|
||||
// Should never happen when using the MetadataReader;
|
||||
// it should validate directions.
|
||||
ALOGE("%s: Unrecognized stream config direction %d.",
|
||||
__func__,
|
||||
config.direction);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
// Extract stall durations from the stalls.
|
||||
for (const auto& stall : stalls) {
|
||||
(*capabilities)[stall.spec].stall_duration = stall.duration;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
// Check that each output config has a valid corresponding stall duration
|
||||
// (extra durations not matching any output config are ignored).
|
||||
static bool ValidateCapabilities(
|
||||
StaticProperties::CapabilitiesMap capabilities) {
|
||||
for (const auto& spec_capabilities : capabilities) {
|
||||
// Only non-negative stall durations are valid. This should only happen
|
||||
// due to output streams without an associated stall duration, as
|
||||
// MetadataReader validates the metadata stall durations.
|
||||
if (spec_capabilities.second.output_supported &&
|
||||
spec_capabilities.second.stall_duration < 0) {
|
||||
ALOGE(
|
||||
"%s: Static metadata does not have a stall duration for "
|
||||
"each output configuration. ",
|
||||
__func__);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
// Validate that the input/output formats map matches up with
|
||||
// the capabilities listed for all formats.
|
||||
bool ValidateReprocessFormats(
|
||||
const StaticProperties::CapabilitiesMap& capabilities,
|
||||
const ReprocessFormatMap& reprocess_map) {
|
||||
// Get input formats.
|
||||
std::set<int32_t> all_input_formats;
|
||||
std::set<int32_t> all_output_formats;
|
||||
for (const auto& spec_capabilities : capabilities) {
|
||||
if (spec_capabilities.second.input_supported) {
|
||||
all_input_formats.insert(spec_capabilities.first.format);
|
||||
}
|
||||
if (spec_capabilities.second.output_supported) {
|
||||
all_output_formats.insert(spec_capabilities.first.format);
|
||||
}
|
||||
}
|
||||
|
||||
// Must be at least one input format.
|
||||
if (all_input_formats.size() < 1) {
|
||||
ALOGE("%s: No input formats, reprocessing can't be supported.", __func__);
|
||||
return false;
|
||||
}
|
||||
|
||||
// Check that the reprocess map input formats are exactly all available
|
||||
// input formats (check size here, then checking for actual value
|
||||
// matches will happen as part of the loop below).
|
||||
if (all_input_formats.size() != reprocess_map.size()) {
|
||||
ALOGE(
|
||||
"%s: Stream configuration input formats do not match "
|
||||
"input/output format map input formats.",
|
||||
__func__);
|
||||
return false;
|
||||
}
|
||||
|
||||
// Check that each input format has at least one matching output format.
|
||||
for (const auto& input_format : all_input_formats) {
|
||||
const auto input_outputs_iterator = reprocess_map.find(input_format);
|
||||
if (input_outputs_iterator == reprocess_map.end()) {
|
||||
ALOGE(
|
||||
"%s: No output formats for input format %d.", __func__, input_format);
|
||||
return false;
|
||||
}
|
||||
// No need to check that the output formats vector is non-empty;
|
||||
// MetadataReader validates this. Instead just check that
|
||||
// all outputs are actually output formats.
|
||||
for (const auto& output_format : input_outputs_iterator->second) {
|
||||
if (all_output_formats.count(output_format) < 1) {
|
||||
ALOGE(
|
||||
"%s: Output format %d for input format %d "
|
||||
"is not a supported output format.",
|
||||
__func__,
|
||||
input_format,
|
||||
output_format);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
StaticProperties* StaticProperties::NewStaticProperties(
|
||||
std::unique_ptr<const MetadataReader> metadata_reader) {
|
||||
int facing = 0;
|
||||
int orientation = 0;
|
||||
int32_t max_input_streams = 0;
|
||||
int32_t max_raw_output_streams = 0;
|
||||
int32_t max_non_stalling_output_streams = 0;
|
||||
int32_t max_stalling_output_streams = 0;
|
||||
std::vector<StreamConfiguration> configs;
|
||||
std::vector<StreamStallDuration> stalls;
|
||||
CapabilitiesMap capabilities;
|
||||
ReprocessFormatMap reprocess_map;
|
||||
|
||||
// If reading any data returns an error, something is wrong.
|
||||
if (metadata_reader->Facing(&facing) ||
|
||||
metadata_reader->Orientation(&orientation)) {
|
||||
metadata_reader->Orientation(&orientation) ||
|
||||
metadata_reader->MaxInputStreams(&max_input_streams) ||
|
||||
metadata_reader->MaxOutputStreams(&max_raw_output_streams,
|
||||
&max_non_stalling_output_streams,
|
||||
&max_stalling_output_streams) ||
|
||||
metadata_reader->StreamConfigurations(&configs) ||
|
||||
metadata_reader->StreamStallDurations(&stalls) ||
|
||||
!ConstructCapabilities(configs, stalls, &capabilities) ||
|
||||
// MetadataReader validates configs and stall seperately,
|
||||
// but not that they match.
|
||||
!ValidateCapabilities(capabilities) ||
|
||||
// Reprocessing metadata only necessary if input streams are allowed.
|
||||
(max_input_streams > 0 &&
|
||||
(metadata_reader->ReprocessFormats(&reprocess_map) ||
|
||||
// MetadataReader validates configs and the reprocess map seperately,
|
||||
// but not that they match.
|
||||
!ValidateReprocessFormats(capabilities, reprocess_map)))) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
return new StaticProperties(std::move(metadata_reader), facing, orientation);
|
||||
return new StaticProperties(std::move(metadata_reader),
|
||||
facing,
|
||||
orientation,
|
||||
max_input_streams,
|
||||
max_raw_output_streams,
|
||||
max_non_stalling_output_streams,
|
||||
max_stalling_output_streams,
|
||||
std::move(capabilities),
|
||||
std::move(reprocess_map));
|
||||
}
|
||||
|
||||
StaticProperties::StaticProperties(
|
||||
std::unique_ptr<const MetadataReader> metadata_reader,
|
||||
int facing,
|
||||
int orientation)
|
||||
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,
|
||||
CapabilitiesMap stream_capabilities,
|
||||
ReprocessFormatMap supported_reprocess_outputs)
|
||||
: metadata_reader_(std::move(metadata_reader)),
|
||||
facing_(facing),
|
||||
orientation_(orientation) {}
|
||||
orientation_(orientation),
|
||||
max_input_streams_(max_input_streams),
|
||||
max_raw_output_streams_(max_raw_output_streams),
|
||||
max_non_stalling_output_streams_(max_non_stalling_output_streams),
|
||||
max_stalling_output_streams_(max_stalling_output_streams),
|
||||
stream_capabilities_(std::move(stream_capabilities)),
|
||||
supported_reprocess_outputs_(std::move(supported_reprocess_outputs)) {}
|
||||
|
||||
// Helper functions for checking stream properties when verifying support.
|
||||
static bool IsInputType(int stream_type) {
|
||||
return stream_type == CAMERA3_STREAM_INPUT ||
|
||||
stream_type == CAMERA3_STREAM_BIDIRECTIONAL;
|
||||
}
|
||||
|
||||
static bool IsOutputType(int stream_type) {
|
||||
return stream_type == CAMERA3_STREAM_OUTPUT ||
|
||||
stream_type == CAMERA3_STREAM_BIDIRECTIONAL;
|
||||
}
|
||||
|
||||
static bool IsRawFormat(int format) {
|
||||
return format == HAL_PIXEL_FORMAT_RAW10 || format == HAL_PIXEL_FORMAT_RAW12 ||
|
||||
format == HAL_PIXEL_FORMAT_RAW16 ||
|
||||
format == HAL_PIXEL_FORMAT_RAW_OPAQUE;
|
||||
}
|
||||
|
||||
bool StaticProperties::StreamConfigurationSupported(
|
||||
const camera3_stream_configuration_t* stream_config) {
|
||||
return SanityCheckStreamConfiguration(stream_config) &&
|
||||
InputStreamsSupported(stream_config) &&
|
||||
OutputStreamsSupported(stream_config) &&
|
||||
OperationModeSupported(stream_config);
|
||||
}
|
||||
|
||||
bool StaticProperties::SanityCheckStreamConfiguration(
|
||||
const camera3_stream_configuration_t* stream_config) {
|
||||
// Check for null/empty values.
|
||||
if (stream_config == nullptr) {
|
||||
ALOGE("%s: NULL stream configuration array", __func__);
|
||||
return false;
|
||||
} else if (stream_config->num_streams == 0) {
|
||||
ALOGE("%s: Empty stream configuration array", __func__);
|
||||
return false;
|
||||
} else if (stream_config->streams == nullptr) {
|
||||
ALOGE("%s: NULL stream configuration streams", __func__);
|
||||
return false;
|
||||
}
|
||||
|
||||
// Check that all streams are either inputs or outputs (or both).
|
||||
for (size_t i = 0; i < stream_config->num_streams; ++i) {
|
||||
const camera3_stream_t* stream = stream_config->streams[i];
|
||||
if (stream == nullptr) {
|
||||
ALOGE("%s: Stream %d is null", __func__, i);
|
||||
return false;
|
||||
} else if (!IsInputType(stream->stream_type) &&
|
||||
!IsOutputType(stream->stream_type)) {
|
||||
ALOGE("%s: Stream %d type %d is neither an input nor an output type",
|
||||
__func__,
|
||||
i,
|
||||
stream->stream_type);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool StaticProperties::InputStreamsSupported(
|
||||
const camera3_stream_configuration_t* stream_config) {
|
||||
// Find the input stream(s).
|
||||
size_t num_input_streams;
|
||||
int input_format;
|
||||
for (size_t i = 0; i < stream_config->num_streams; ++i) {
|
||||
const camera3_stream_t* stream = stream_config->streams[i];
|
||||
if (IsInputType(stream->stream_type)) {
|
||||
// Check that this stream is valid as an input.
|
||||
const auto capabilities_iterator = stream_capabilities_.find(stream);
|
||||
if (capabilities_iterator == stream_capabilities_.end() ||
|
||||
!capabilities_iterator->second.input_supported) {
|
||||
ALOGE("%s: %d x %d stream of format %d is not a supported input setup.",
|
||||
__func__,
|
||||
stream->width,
|
||||
stream->height,
|
||||
stream->format);
|
||||
return false;
|
||||
}
|
||||
|
||||
// Valid input stream; count it.
|
||||
++num_input_streams;
|
||||
input_format = stream->format;
|
||||
}
|
||||
}
|
||||
|
||||
// Check the count.
|
||||
if (num_input_streams > max_input_streams_) {
|
||||
ALOGE(
|
||||
"%s: Requested number of input streams %d is greater than "
|
||||
"the maximum number supported by the device (%d).",
|
||||
__func__,
|
||||
num_input_streams,
|
||||
max_input_streams_);
|
||||
return false;
|
||||
}
|
||||
if (num_input_streams > 1) {
|
||||
ALOGE("%s: Camera HAL 3.4 only supports 1 input stream max.", __func__);
|
||||
return false;
|
||||
}
|
||||
|
||||
// If there's an input stream, the configuration must have at least one
|
||||
// supported output format for reprocessing that input.
|
||||
if (num_input_streams > 0) {
|
||||
const auto input_output_formats_iterator =
|
||||
supported_reprocess_outputs_.find(input_format);
|
||||
if (input_output_formats_iterator == supported_reprocess_outputs_.end()) {
|
||||
// Should never happen; factory should verify that all valid inputs
|
||||
// have one or more valid outputs.
|
||||
ALOGE("%s: No valid output formats for input format %d.",
|
||||
__func__,
|
||||
input_format);
|
||||
return false;
|
||||
}
|
||||
bool match_found = false;
|
||||
// Go through outputs looking for a supported one.
|
||||
for (size_t i = 0; i < stream_config->num_streams; ++i) {
|
||||
const camera3_stream_t* stream = stream_config->streams[i];
|
||||
if (IsOutputType(stream->stream_type)) {
|
||||
if (input_output_formats_iterator->second.count(stream->format) > 0) {
|
||||
match_found = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (!match_found) {
|
||||
ALOGE("%s: No supported output format provided for input format %d.",
|
||||
__func__,
|
||||
input_format);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool StaticProperties::OutputStreamsSupported(
|
||||
const camera3_stream_configuration_t* stream_config) {
|
||||
// Find and count output streams.
|
||||
size_t num_raw = 0;
|
||||
size_t num_stalling = 0;
|
||||
size_t num_non_stalling = 0;
|
||||
for (int i = 0; i < stream_config->num_streams; ++i) {
|
||||
const camera3_stream_t* stream = stream_config->streams[i];
|
||||
if (IsOutputType(stream->stream_type)) {
|
||||
// Check that this stream is valid as an output.
|
||||
const auto capabilities_iterator = stream_capabilities_.find(stream);
|
||||
if (capabilities_iterator == stream_capabilities_.end() ||
|
||||
!capabilities_iterator->second.output_supported) {
|
||||
ALOGE(
|
||||
"%s: %d x %d stream of format %d "
|
||||
"is not a supported output setup.",
|
||||
__func__,
|
||||
stream->width,
|
||||
stream->height,
|
||||
stream->format);
|
||||
return false;
|
||||
}
|
||||
|
||||
// Valid output; count it.
|
||||
if (IsRawFormat(stream->format)) {
|
||||
++num_raw;
|
||||
} else if (capabilities_iterator->second.stall_duration > 0) {
|
||||
++num_stalling;
|
||||
} else {
|
||||
++num_non_stalling;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Check that the counts are within bounds.
|
||||
if (num_raw > max_raw_output_streams_) {
|
||||
ALOGE(
|
||||
"%s: Requested stream configuration exceeds maximum supported "
|
||||
"raw output streams %d (requested %d).",
|
||||
__func__,
|
||||
max_raw_output_streams_,
|
||||
num_raw);
|
||||
return false;
|
||||
} else if (num_stalling > max_stalling_output_streams_) {
|
||||
ALOGE(
|
||||
"%s: Requested stream configuration exceeds maximum supported "
|
||||
"stalling output streams %d (requested %d).",
|
||||
__func__,
|
||||
max_stalling_output_streams_,
|
||||
num_stalling);
|
||||
return false;
|
||||
} else if (num_non_stalling > max_non_stalling_output_streams_) {
|
||||
ALOGE(
|
||||
"%s: Requested stream configuration exceeds maximum supported "
|
||||
"non-stalling output streams %d (requested %d).",
|
||||
__func__,
|
||||
max_non_stalling_output_streams_,
|
||||
num_non_stalling);
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool StaticProperties::OperationModeSupported(
|
||||
const camera3_stream_configuration_t* stream_config) {
|
||||
switch (stream_config->operation_mode) {
|
||||
case CAMERA3_STREAM_CONFIGURATION_NORMAL_MODE:
|
||||
return true;
|
||||
case CAMERA3_STREAM_CONFIGURATION_CONSTRAINED_HIGH_SPEED_MODE:
|
||||
// TODO(b/31370792): Check metadata for high speed support,
|
||||
// check that requested streams have support for high speed.
|
||||
ALOGE("%s: Support for CONSTRAINED_HIGH_SPEED not implemented", __func__);
|
||||
return false;
|
||||
default:
|
||||
ALOGE("%s: Unrecognized stream configuration mode: %d",
|
||||
__func__,
|
||||
stream_config->operation_mode);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
bool StaticProperties::ReprocessingSupported(
|
||||
const camera3_stream_t* input_stream,
|
||||
const std::set<const camera3_stream_t*>& output_streams) {
|
||||
// There must be an input.
|
||||
if (!input_stream) {
|
||||
ALOGE("%s: No input stream.", __func__);
|
||||
return false;
|
||||
}
|
||||
// There must be an output.
|
||||
if (output_streams.size() < 1) {
|
||||
ALOGE("%s: No output stream.", __func__);
|
||||
return false;
|
||||
}
|
||||
|
||||
const auto input_output_formats =
|
||||
supported_reprocess_outputs_.find(input_stream->format);
|
||||
if (input_output_formats == supported_reprocess_outputs_.end()) {
|
||||
// Should never happen for a valid input stream.
|
||||
ALOGE("%s: Input format %d does not support any output formats.",
|
||||
__func__,
|
||||
input_stream->format);
|
||||
return false;
|
||||
}
|
||||
|
||||
// Check that all output streams can be outputs for the input stream.
|
||||
const std::set<int32_t>& supported_output_formats =
|
||||
input_output_formats->second;
|
||||
for (const auto output_stream : output_streams) {
|
||||
if (supported_output_formats.count(output_stream->format) < 1) {
|
||||
ALOGE(
|
||||
"%s: Output format %d is not a supported output "
|
||||
"for request input format %d.",
|
||||
__func__,
|
||||
output_stream->format,
|
||||
input_stream->format);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
} // namespace default_camera_hal
|
||||
|
|
|
@ -18,15 +18,34 @@
|
|||
#define DEFAULT_CAMERA_HAL_STATIC_PROPERTIES_H_
|
||||
|
||||
#include <memory>
|
||||
#include <set>
|
||||
|
||||
#include <hardware/camera3.h>
|
||||
|
||||
#include "common.h"
|
||||
#include "metadata/metadata_reader.h"
|
||||
#include "metadata/types.h"
|
||||
|
||||
namespace default_camera_hal {
|
||||
|
||||
// StaticProperties provides a wrapper around useful static metadata entries.
|
||||
class StaticProperties {
|
||||
public:
|
||||
// Helpful types for interpreting some static properties.
|
||||
struct StreamCapabilities {
|
||||
int64_t stall_duration;
|
||||
int32_t input_supported;
|
||||
int32_t output_supported;
|
||||
// Default constructor ensures no support
|
||||
// and an invalid stall duration.
|
||||
StreamCapabilities()
|
||||
: stall_duration(-1), input_supported(0), output_supported(0) {}
|
||||
};
|
||||
// Map stream spec (format, size) to their
|
||||
// capabilities (input, output, stall).
|
||||
typedef std::map<StreamSpec, StreamCapabilities, StreamSpec::Compare>
|
||||
CapabilitiesMap;
|
||||
|
||||
// Use this method to create StaticProperties objects.
|
||||
// Functionally equivalent to "new StaticProperties",
|
||||
// except that it may return nullptr in case of failure (missing entries).
|
||||
|
@ -34,6 +53,7 @@ class StaticProperties {
|
|||
std::unique_ptr<const MetadataReader> metadata_reader);
|
||||
virtual ~StaticProperties(){};
|
||||
|
||||
// Simple accessors.
|
||||
int facing() const { return facing_; };
|
||||
int orientation() const { return orientation_; };
|
||||
// Carrying on the promise of the underlying reader,
|
||||
|
@ -42,16 +62,47 @@ class StaticProperties {
|
|||
return metadata_reader_->raw_metadata();
|
||||
};
|
||||
|
||||
// Validators (check that values are consistent with the capabilities
|
||||
// this object represents/base requirements of the camera HAL).
|
||||
bool StreamConfigurationSupported(
|
||||
const camera3_stream_configuration_t* stream_config);
|
||||
// Check that the inputs and outputs for a request don't conflict.
|
||||
bool ReprocessingSupported(
|
||||
const camera3_stream_t* input_stream,
|
||||
const std::set<const camera3_stream_t*>& output_streams);
|
||||
|
||||
private:
|
||||
// Constructor private to allow failing on bad input.
|
||||
// Use NewStaticProperties instead.
|
||||
StaticProperties(std::unique_ptr<const MetadataReader> metadata_reader,
|
||||
int facing,
|
||||
int orientation);
|
||||
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,
|
||||
CapabilitiesMap stream_capabilities,
|
||||
ReprocessFormatMap supported_reprocess_outputs);
|
||||
|
||||
// Helper functions for StreamConfigurationSupported.
|
||||
bool SanityCheckStreamConfiguration(
|
||||
const camera3_stream_configuration_t* stream_config);
|
||||
bool InputStreamsSupported(
|
||||
const camera3_stream_configuration_t* stream_config);
|
||||
bool OutputStreamsSupported(
|
||||
const camera3_stream_configuration_t* stream_config);
|
||||
bool OperationModeSupported(
|
||||
const camera3_stream_configuration_t* stream_config);
|
||||
|
||||
const std::unique_ptr<const MetadataReader> metadata_reader_;
|
||||
const int facing_;
|
||||
const int orientation_;
|
||||
const int32_t max_input_streams_;
|
||||
const int32_t max_raw_output_streams_;
|
||||
const int32_t max_non_stalling_output_streams_;
|
||||
const int32_t max_stalling_output_streams_;
|
||||
const CapabilitiesMap stream_capabilities_;
|
||||
const ReprocessFormatMap supported_reprocess_outputs_;
|
||||
|
||||
DISALLOW_COPY_AND_ASSIGN(StaticProperties);
|
||||
};
|
||||
|
|
|
@ -18,6 +18,7 @@
|
|||
|
||||
#include <gmock/gmock.h>
|
||||
#include <gtest/gtest.h>
|
||||
#include <hardware/camera3.h>
|
||||
#include <system/camera.h>
|
||||
|
||||
#include "metadata/metadata_reader_mock.h"
|
||||
|
@ -33,7 +34,7 @@ namespace default_camera_hal {
|
|||
|
||||
class StaticPropertiesTest : public Test {
|
||||
protected:
|
||||
void SetUp() {
|
||||
virtual void SetUp() {
|
||||
// Ensure tests will probably fail if PrepareDUT isn't called.
|
||||
dut_.reset();
|
||||
mock_reader_ = std::make_unique<MetadataReaderMock>();
|
||||
|
@ -43,6 +44,12 @@ class StaticPropertiesTest : public Test {
|
|||
dut_.reset(StaticProperties::NewStaticProperties(std::move(mock_reader_)));
|
||||
}
|
||||
|
||||
void PrepareDefaultDUT() {
|
||||
SetDefaultExpectations();
|
||||
PrepareDUT();
|
||||
ASSERT_NE(dut_, nullptr);
|
||||
}
|
||||
|
||||
void SetDefaultExpectations() {
|
||||
EXPECT_CALL(*mock_reader_, Facing(_))
|
||||
.Times(AtMost(1))
|
||||
|
@ -50,21 +57,142 @@ class StaticPropertiesTest : public Test {
|
|||
EXPECT_CALL(*mock_reader_, Orientation(_))
|
||||
.Times(AtMost(1))
|
||||
.WillOnce(DoAll(SetArgPointee<0>(test_orientation_), Return(0)));
|
||||
EXPECT_CALL(*mock_reader_, MaxInputStreams(_))
|
||||
.Times(AtMost(1))
|
||||
.WillOnce(DoAll(SetArgPointee<0>(test_max_inputs_), Return(0)));
|
||||
EXPECT_CALL(*mock_reader_, MaxOutputStreams(_, _, _))
|
||||
.Times(AtMost(1))
|
||||
.WillOnce(DoAll(SetArgPointee<0>(test_max_raw_outputs_),
|
||||
SetArgPointee<1>(test_max_non_stalling_outputs_),
|
||||
SetArgPointee<2>(test_max_stalling_outputs_),
|
||||
Return(0)));
|
||||
EXPECT_CALL(*mock_reader_, StreamConfigurations(_))
|
||||
.Times(AtMost(1))
|
||||
.WillOnce(DoAll(SetArgPointee<0>(test_configs_), Return(0)));
|
||||
EXPECT_CALL(*mock_reader_, StreamStallDurations(_))
|
||||
.Times(AtMost(1))
|
||||
.WillOnce(DoAll(SetArgPointee<0>(test_stalls_), Return(0)));
|
||||
EXPECT_CALL(*mock_reader_, ReprocessFormats(_))
|
||||
.Times(AtMost(1))
|
||||
.WillOnce(DoAll(SetArgPointee<0>(test_reprocess_map_), Return(0)));
|
||||
}
|
||||
|
||||
camera3_stream_t MakeStream(int32_t format,
|
||||
bool output = true,
|
||||
bool input = false,
|
||||
int32_t width = kWidth,
|
||||
int32_t height = kHeight) {
|
||||
int type = -1;
|
||||
if (output && input) {
|
||||
type = CAMERA3_STREAM_BIDIRECTIONAL;
|
||||
} else if (output) {
|
||||
type = CAMERA3_STREAM_OUTPUT;
|
||||
} else if (input) {
|
||||
type = CAMERA3_STREAM_INPUT;
|
||||
}
|
||||
return {static_cast<int>(type),
|
||||
static_cast<uint32_t>(width),
|
||||
static_cast<uint32_t>(height),
|
||||
static_cast<int>(format)};
|
||||
}
|
||||
|
||||
void ExpectConfigurationSupported(std::vector<camera3_stream_t>& streams,
|
||||
bool expected) {
|
||||
std::vector<camera3_stream_t*> stream_addresses;
|
||||
for (size_t i = 0; i < streams.size(); ++i) {
|
||||
stream_addresses.push_back(&streams[i]);
|
||||
}
|
||||
camera3_stream_configuration_t config = {
|
||||
stream_addresses.size(),
|
||||
stream_addresses.data(),
|
||||
CAMERA3_STREAM_CONFIGURATION_NORMAL_MODE};
|
||||
PrepareDefaultDUT();
|
||||
EXPECT_EQ(dut_->StreamConfigurationSupported(&config), expected);
|
||||
}
|
||||
|
||||
std::unique_ptr<StaticProperties> dut_;
|
||||
std::unique_ptr<MetadataReaderMock> mock_reader_;
|
||||
|
||||
// Some helper values used for stream testing.
|
||||
static constexpr int32_t kWidth = 320;
|
||||
static constexpr int32_t kHeight = 240;
|
||||
static constexpr int32_t kAlternateWidth = 640;
|
||||
static constexpr int32_t kAlternateHeight = 480;
|
||||
|
||||
const int test_facing_ = CAMERA_FACING_FRONT;
|
||||
const int test_orientation_ = 90;
|
||||
const int32_t test_max_inputs_ = 3;
|
||||
const int32_t test_max_raw_outputs_ = 1;
|
||||
const int32_t test_max_non_stalling_outputs_ = 2;
|
||||
const int32_t test_max_stalling_outputs_ = 3;
|
||||
|
||||
// Some formats for various purposes (in various combinations,
|
||||
// these types should be capable of testing all failure conditions).
|
||||
const int32_t output_multisize_non_stalling_ = 1;
|
||||
const int32_t bidirectional_self_supporting_stalling_ = 2;
|
||||
const int32_t bidirectional_raw_ = HAL_PIXEL_FORMAT_RAW10;
|
||||
const int32_t input_ = 3;
|
||||
const int32_t other = input_;
|
||||
|
||||
const std::vector<StreamConfiguration> test_configs_ = {
|
||||
{{{output_multisize_non_stalling_,
|
||||
kWidth,
|
||||
kHeight,
|
||||
ANDROID_SCALER_AVAILABLE_STREAM_CONFIGURATIONS_OUTPUT}}},
|
||||
{{{output_multisize_non_stalling_,
|
||||
kAlternateWidth,
|
||||
kAlternateHeight,
|
||||
ANDROID_SCALER_AVAILABLE_STREAM_CONFIGURATIONS_OUTPUT}}},
|
||||
{{{bidirectional_self_supporting_stalling_,
|
||||
kWidth,
|
||||
kHeight,
|
||||
ANDROID_SCALER_AVAILABLE_STREAM_CONFIGURATIONS_INPUT}}},
|
||||
{{{bidirectional_self_supporting_stalling_,
|
||||
kWidth,
|
||||
kHeight,
|
||||
ANDROID_SCALER_AVAILABLE_STREAM_CONFIGURATIONS_OUTPUT}}},
|
||||
{{{bidirectional_raw_,
|
||||
kWidth,
|
||||
kHeight,
|
||||
ANDROID_SCALER_AVAILABLE_STREAM_CONFIGURATIONS_INPUT}}},
|
||||
{{{bidirectional_raw_,
|
||||
kWidth,
|
||||
kHeight,
|
||||
ANDROID_SCALER_AVAILABLE_STREAM_CONFIGURATIONS_OUTPUT}}},
|
||||
{{{input_,
|
||||
kWidth,
|
||||
kHeight,
|
||||
ANDROID_SCALER_AVAILABLE_STREAM_CONFIGURATIONS_INPUT}}}};
|
||||
// Raw having a stall duration shouldn't matter,
|
||||
// it should still be counted as the raw type.
|
||||
const std::vector<StreamStallDuration> test_stalls_ = {
|
||||
{{{output_multisize_non_stalling_, kWidth, kHeight, 0}}},
|
||||
{{{output_multisize_non_stalling_,
|
||||
kAlternateWidth,
|
||||
kAlternateHeight,
|
||||
0}}},
|
||||
{{{bidirectional_self_supporting_stalling_, kWidth, kHeight, 10}}},
|
||||
{{{bidirectional_raw_, kWidth, kHeight, 15}}}};
|
||||
// Format 2 can go to itself or 1. 3 and RAW can only go to 1.
|
||||
const ReprocessFormatMap test_reprocess_map_ = {
|
||||
{bidirectional_self_supporting_stalling_,
|
||||
{output_multisize_non_stalling_,
|
||||
bidirectional_self_supporting_stalling_}},
|
||||
{bidirectional_raw_, {output_multisize_non_stalling_}},
|
||||
{input_, {output_multisize_non_stalling_}}};
|
||||
// Codify the above information about format capabilities in some helpful
|
||||
// vectors.
|
||||
int32_t multi_size_format_ = 1;
|
||||
const std::vector<int32_t> input_formats_ = {2, 3, HAL_PIXEL_FORMAT_RAW10};
|
||||
const std::vector<int32_t> output_formats_ = {1, 2, HAL_PIXEL_FORMAT_RAW10};
|
||||
};
|
||||
|
||||
TEST_F(StaticPropertiesTest, FactorySuccess) {
|
||||
SetDefaultExpectations();
|
||||
PrepareDUT();
|
||||
ASSERT_NE(dut_, nullptr);
|
||||
PrepareDefaultDUT();
|
||||
EXPECT_EQ(dut_->facing(), test_facing_);
|
||||
EXPECT_EQ(dut_->orientation(), test_orientation_);
|
||||
|
||||
// Stream configurations tested seperately.
|
||||
}
|
||||
|
||||
TEST_F(StaticPropertiesTest, FactoryFailedFacing) {
|
||||
|
@ -83,4 +211,434 @@ TEST_F(StaticPropertiesTest, FactoryFailedOrientation) {
|
|||
EXPECT_EQ(dut_, nullptr);
|
||||
}
|
||||
|
||||
TEST_F(StaticPropertiesTest, FactoryFailedMaxInputs) {
|
||||
SetDefaultExpectations();
|
||||
// Override with a failure expectation.
|
||||
EXPECT_CALL(*mock_reader_, MaxInputStreams(_)).WillOnce(Return(99));
|
||||
PrepareDUT();
|
||||
EXPECT_EQ(dut_, nullptr);
|
||||
}
|
||||
|
||||
TEST_F(StaticPropertiesTest, FactoryFailedMaxOutputs) {
|
||||
SetDefaultExpectations();
|
||||
// Override with a failure expectation.
|
||||
EXPECT_CALL(*mock_reader_, MaxOutputStreams(_, _, _)).WillOnce(Return(99));
|
||||
PrepareDUT();
|
||||
EXPECT_EQ(dut_, nullptr);
|
||||
}
|
||||
|
||||
TEST_F(StaticPropertiesTest, FactoryFailedStreamConfigs) {
|
||||
SetDefaultExpectations();
|
||||
// Override with a failure expectation.
|
||||
EXPECT_CALL(*mock_reader_, StreamConfigurations(_)).WillOnce(Return(99));
|
||||
PrepareDUT();
|
||||
EXPECT_EQ(dut_, nullptr);
|
||||
}
|
||||
|
||||
TEST_F(StaticPropertiesTest, FactoryFailedStallDurations) {
|
||||
SetDefaultExpectations();
|
||||
// Override with a failure expectation.
|
||||
EXPECT_CALL(*mock_reader_, StreamStallDurations(_)).WillOnce(Return(99));
|
||||
PrepareDUT();
|
||||
EXPECT_EQ(dut_, nullptr);
|
||||
}
|
||||
|
||||
TEST_F(StaticPropertiesTest, FactoryFailedReprocessFormats) {
|
||||
SetDefaultExpectations();
|
||||
// Override with a failure expectation.
|
||||
EXPECT_CALL(*mock_reader_, ReprocessFormats(_)).WillOnce(Return(99));
|
||||
PrepareDUT();
|
||||
EXPECT_EQ(dut_, nullptr);
|
||||
}
|
||||
|
||||
TEST_F(StaticPropertiesTest, FactoryNoReprocessFormats) {
|
||||
// If there are no inputs allowed, the reprocess formats shouldn't matter.
|
||||
SetDefaultExpectations();
|
||||
// Override max inputs.
|
||||
EXPECT_CALL(*mock_reader_, MaxInputStreams(_))
|
||||
.WillOnce(DoAll(SetArgPointee<0>(0), Return(0)));
|
||||
// Override reprocess formats with a failure expectation.
|
||||
EXPECT_CALL(*mock_reader_, ReprocessFormats(_))
|
||||
.Times(AtMost(1))
|
||||
.WillOnce(Return(99));
|
||||
PrepareDUT();
|
||||
// Should be ok.
|
||||
EXPECT_NE(dut_, nullptr);
|
||||
}
|
||||
|
||||
TEST_F(StaticPropertiesTest, FactoryInvalidCapabilities) {
|
||||
SetDefaultExpectations();
|
||||
// Override configs with an extra output format.
|
||||
std::vector<StreamConfiguration> configs = test_configs_;
|
||||
configs.push_back(
|
||||
{{{5,
|
||||
kWidth,
|
||||
kHeight,
|
||||
ANDROID_SCALER_AVAILABLE_STREAM_CONFIGURATIONS_OUTPUT}}});
|
||||
EXPECT_CALL(*mock_reader_, StreamConfigurations(_))
|
||||
.WillOnce(DoAll(SetArgPointee<0>(configs), Return(0)));
|
||||
PrepareDUT();
|
||||
// Should fail because not every output has a stall.
|
||||
EXPECT_EQ(dut_, nullptr);
|
||||
}
|
||||
|
||||
TEST_F(StaticPropertiesTest, InvalidReprocessNoInputs) {
|
||||
SetDefaultExpectations();
|
||||
// Override configs by removing all inputs.
|
||||
std::vector<StreamConfiguration> configs = test_configs_;
|
||||
for (auto it = configs.begin(); it != configs.end();) {
|
||||
if ((*it).direction ==
|
||||
ANDROID_SCALER_AVAILABLE_STREAM_CONFIGURATIONS_INPUT) {
|
||||
it = configs.erase(it);
|
||||
} else {
|
||||
++it;
|
||||
}
|
||||
}
|
||||
EXPECT_CALL(*mock_reader_, StreamConfigurations(_))
|
||||
.WillOnce(DoAll(SetArgPointee<0>(configs), Return(0)));
|
||||
PrepareDUT();
|
||||
// Should fail because inputs are supported but there are no input formats.
|
||||
EXPECT_EQ(dut_, nullptr);
|
||||
}
|
||||
|
||||
TEST_F(StaticPropertiesTest, InvalidReprocessExtraInput) {
|
||||
SetDefaultExpectations();
|
||||
// Override configs with an extra input format.
|
||||
std::vector<StreamConfiguration> configs = test_configs_;
|
||||
configs.push_back({{{5,
|
||||
kWidth,
|
||||
kHeight,
|
||||
ANDROID_SCALER_AVAILABLE_STREAM_CONFIGURATIONS_INPUT}}});
|
||||
EXPECT_CALL(*mock_reader_, StreamConfigurations(_))
|
||||
.WillOnce(DoAll(SetArgPointee<0>(configs), Return(0)));
|
||||
PrepareDUT();
|
||||
// Should fail because no reprocess outputs are listed for the extra input.
|
||||
EXPECT_EQ(dut_, nullptr);
|
||||
}
|
||||
|
||||
TEST_F(StaticPropertiesTest, InvalidReprocessExtraMapEntry) {
|
||||
SetDefaultExpectations();
|
||||
// Override the reprocess map with an extra entry.
|
||||
ReprocessFormatMap reprocess_map = test_reprocess_map_;
|
||||
reprocess_map[5] = {1};
|
||||
EXPECT_CALL(*mock_reader_, ReprocessFormats(_))
|
||||
.WillOnce(DoAll(SetArgPointee<0>(reprocess_map), Return(0)));
|
||||
PrepareDUT();
|
||||
// Should fail because the extra map entry doesn't correspond to an input.
|
||||
EXPECT_EQ(dut_, nullptr);
|
||||
}
|
||||
|
||||
TEST_F(StaticPropertiesTest, InvalidReprocessWrongMapEntries) {
|
||||
SetDefaultExpectations();
|
||||
// Override the reprocess map replacing the entry for the
|
||||
// input-only format with the output-only format.
|
||||
ReprocessFormatMap reprocess_map = test_reprocess_map_;
|
||||
reprocess_map.erase(input_);
|
||||
reprocess_map[output_multisize_non_stalling_] = {1};
|
||||
EXPECT_CALL(*mock_reader_, ReprocessFormats(_))
|
||||
.WillOnce(DoAll(SetArgPointee<0>(reprocess_map), Return(0)));
|
||||
PrepareDUT();
|
||||
// Should fail because not all input formats are present/
|
||||
// one of the map "input" formats is output only.
|
||||
EXPECT_EQ(dut_, nullptr);
|
||||
}
|
||||
|
||||
TEST_F(StaticPropertiesTest, InvalidReprocessNotAnOutput) {
|
||||
SetDefaultExpectations();
|
||||
// Override the reprocess map with a non-output output entry.
|
||||
ReprocessFormatMap reprocess_map = test_reprocess_map_;
|
||||
reprocess_map[input_].insert(input_);
|
||||
EXPECT_CALL(*mock_reader_, ReprocessFormats(_))
|
||||
.WillOnce(DoAll(SetArgPointee<0>(reprocess_map), Return(0)));
|
||||
PrepareDUT();
|
||||
// Should fail because a specified output format doesn't support output.
|
||||
EXPECT_EQ(dut_, nullptr);
|
||||
}
|
||||
|
||||
TEST_F(StaticPropertiesTest, ConfigureSingleOutput) {
|
||||
std::vector<camera3_stream_t> streams;
|
||||
streams.push_back(MakeStream(output_multisize_non_stalling_));
|
||||
ExpectConfigurationSupported(streams, true);
|
||||
}
|
||||
|
||||
TEST_F(StaticPropertiesTest, ConfigureMultipleOutputs) {
|
||||
std::vector<camera3_stream_t> streams;
|
||||
// 2 outputs, of different sizes.
|
||||
streams.push_back(MakeStream(bidirectional_raw_));
|
||||
// Use the alternate size.
|
||||
streams.push_back(MakeStream(output_multisize_non_stalling_,
|
||||
true,
|
||||
false,
|
||||
kAlternateWidth,
|
||||
kAlternateHeight));
|
||||
ExpectConfigurationSupported(streams, true);
|
||||
}
|
||||
|
||||
TEST_F(StaticPropertiesTest, ConfigureInput) {
|
||||
std::vector<camera3_stream_t> streams;
|
||||
// Single input -> different output.
|
||||
streams.push_back(MakeStream(input_, false, true));
|
||||
// Use the alternate size, it should be ok.
|
||||
streams.push_back(MakeStream(output_multisize_non_stalling_,
|
||||
true,
|
||||
false,
|
||||
kAlternateWidth,
|
||||
kAlternateHeight));
|
||||
ExpectConfigurationSupported(streams, true);
|
||||
}
|
||||
|
||||
TEST_F(StaticPropertiesTest, ConfigureBidirectional) {
|
||||
std::vector<camera3_stream_t> streams;
|
||||
// Single input -> same output.
|
||||
streams.push_back(
|
||||
MakeStream(bidirectional_self_supporting_stalling_, true, true));
|
||||
ExpectConfigurationSupported(streams, true);
|
||||
}
|
||||
|
||||
TEST_F(StaticPropertiesTest, ConfigureMultipleReprocess) {
|
||||
std::vector<camera3_stream_t> streams;
|
||||
// Single input -> multiple outputs.
|
||||
streams.push_back(
|
||||
MakeStream(bidirectional_self_supporting_stalling_, true, true));
|
||||
streams.push_back(MakeStream(output_multisize_non_stalling_));
|
||||
ExpectConfigurationSupported(streams, true);
|
||||
}
|
||||
|
||||
TEST_F(StaticPropertiesTest, ConfigureNull) {
|
||||
PrepareDefaultDUT();
|
||||
EXPECT_FALSE(dut_->StreamConfigurationSupported(nullptr));
|
||||
}
|
||||
|
||||
TEST_F(StaticPropertiesTest, ConfigureEmptyStreams) {
|
||||
std::vector<camera3_stream_t*> streams(1);
|
||||
camera3_stream_configuration_t config = {
|
||||
0, streams.data(), CAMERA3_STREAM_CONFIGURATION_NORMAL_MODE};
|
||||
PrepareDefaultDUT();
|
||||
EXPECT_FALSE(dut_->StreamConfigurationSupported(&config));
|
||||
}
|
||||
|
||||
TEST_F(StaticPropertiesTest, ConfigureNullStreams) {
|
||||
std::vector<camera3_stream_t*> streams(2, nullptr);
|
||||
camera3_stream_configuration_t config = {
|
||||
streams.size(), streams.data(), CAMERA3_STREAM_CONFIGURATION_NORMAL_MODE};
|
||||
PrepareDefaultDUT();
|
||||
EXPECT_FALSE(dut_->StreamConfigurationSupported(&config));
|
||||
}
|
||||
|
||||
TEST_F(StaticPropertiesTest, ConfigureNullStreamVector) {
|
||||
// Even if the camera claims to have multiple streams, check for null.
|
||||
camera3_stream_configuration_t config = {
|
||||
3, nullptr, CAMERA3_STREAM_CONFIGURATION_NORMAL_MODE};
|
||||
PrepareDefaultDUT();
|
||||
EXPECT_FALSE(dut_->StreamConfigurationSupported(&config));
|
||||
}
|
||||
|
||||
TEST_F(StaticPropertiesTest, ConfigureNoOutput) {
|
||||
std::vector<camera3_stream_t> streams;
|
||||
// Only an input stream, no output.
|
||||
streams.push_back(MakeStream(input_, false, true));
|
||||
ExpectConfigurationSupported(streams, false);
|
||||
}
|
||||
|
||||
TEST_F(StaticPropertiesTest, ConfigureInvalidType) {
|
||||
std::vector<camera3_stream_t> streams;
|
||||
// Not input, output, or bidirectional.
|
||||
streams.push_back(MakeStream(output_multisize_non_stalling_, false, false));
|
||||
ExpectConfigurationSupported(streams, false);
|
||||
}
|
||||
|
||||
TEST_F(StaticPropertiesTest, ConfigureSpecFormatDoesNotExist) {
|
||||
std::vector<camera3_stream_t> streams;
|
||||
// Format 99 is not supported in any form.
|
||||
streams.push_back(MakeStream(99));
|
||||
ExpectConfigurationSupported(streams, false);
|
||||
}
|
||||
|
||||
TEST_F(StaticPropertiesTest, ConfigureSpecSizeDoesNotExist) {
|
||||
std::vector<camera3_stream_t> streams;
|
||||
// Size 99 x 99 not supported for the output format.
|
||||
streams.push_back(
|
||||
MakeStream(output_multisize_non_stalling_, true, false, 99, 99));
|
||||
ExpectConfigurationSupported(streams, false);
|
||||
}
|
||||
|
||||
TEST_F(StaticPropertiesTest, ConfigureNotAnInput) {
|
||||
std::vector<camera3_stream_t> streams;
|
||||
streams.push_back(MakeStream(output_multisize_non_stalling_));
|
||||
// Can't use output-only format as an input.
|
||||
streams.push_back(MakeStream(output_multisize_non_stalling_, false, true));
|
||||
ExpectConfigurationSupported(streams, false);
|
||||
}
|
||||
|
||||
TEST_F(StaticPropertiesTest, ConfigureNotAnOutput) {
|
||||
std::vector<camera3_stream_t> streams;
|
||||
// Can't use input-only format as an output.
|
||||
streams.push_back(MakeStream(input_));
|
||||
ExpectConfigurationSupported(streams, false);
|
||||
}
|
||||
|
||||
TEST_F(StaticPropertiesTest, ConfigureTooManyInputs) {
|
||||
std::vector<camera3_stream_t> streams;
|
||||
// At the threshold is ok.
|
||||
for (int32_t i = 0; i < test_max_inputs_; ++i) {
|
||||
streams.push_back(MakeStream(input_, false, true));
|
||||
}
|
||||
// Have a valid output still.
|
||||
streams.push_back(MakeStream(output_multisize_non_stalling_));
|
||||
ExpectConfigurationSupported(streams, false);
|
||||
|
||||
// Reset.
|
||||
mock_reader_ = std::make_unique<MetadataReaderMock>();
|
||||
streams.clear();
|
||||
|
||||
// Try again with too many.
|
||||
for (int32_t i = 0; i <= test_max_inputs_; ++i) {
|
||||
streams.push_back(MakeStream(input_, false, true));
|
||||
}
|
||||
// Have a valid output still.
|
||||
streams.push_back(MakeStream(output_multisize_non_stalling_));
|
||||
ExpectConfigurationSupported(streams, false);
|
||||
}
|
||||
|
||||
TEST_F(StaticPropertiesTest, ConfigureTooManyRaw) {
|
||||
std::vector<camera3_stream_t> streams;
|
||||
// At the threshold is ok.
|
||||
for (int32_t i = 0; i < test_max_raw_outputs_; ++i) {
|
||||
streams.push_back(MakeStream(bidirectional_raw_));
|
||||
}
|
||||
ExpectConfigurationSupported(streams, true);
|
||||
|
||||
// Reset.
|
||||
mock_reader_ = std::make_unique<MetadataReaderMock>();
|
||||
streams.clear();
|
||||
|
||||
// Try again with too many.
|
||||
for (int32_t i = 0; i <= test_max_raw_outputs_; ++i) {
|
||||
streams.push_back(MakeStream(bidirectional_raw_));
|
||||
}
|
||||
ExpectConfigurationSupported(streams, false);
|
||||
}
|
||||
|
||||
TEST_F(StaticPropertiesTest, ConfigureTooManyStalling) {
|
||||
std::vector<camera3_stream_t> streams;
|
||||
// At the threshold is ok.
|
||||
for (int32_t i = 0; i < test_max_stalling_outputs_; ++i) {
|
||||
streams.push_back(MakeStream(bidirectional_self_supporting_stalling_));
|
||||
}
|
||||
ExpectConfigurationSupported(streams, true);
|
||||
|
||||
// Reset.
|
||||
mock_reader_ = std::make_unique<MetadataReaderMock>();
|
||||
streams.clear();
|
||||
|
||||
// Try again with too many.
|
||||
for (int32_t i = 0; i <= test_max_stalling_outputs_; ++i) {
|
||||
streams.push_back(MakeStream(bidirectional_self_supporting_stalling_));
|
||||
}
|
||||
ExpectConfigurationSupported(streams, false);
|
||||
}
|
||||
|
||||
TEST_F(StaticPropertiesTest, ConfigureTooManyNonStalling) {
|
||||
std::vector<camera3_stream_t> streams;
|
||||
// At the threshold is ok.
|
||||
for (int32_t i = 0; i < test_max_non_stalling_outputs_; ++i) {
|
||||
streams.push_back(MakeStream(output_multisize_non_stalling_));
|
||||
}
|
||||
ExpectConfigurationSupported(streams, true);
|
||||
|
||||
// Reset.
|
||||
mock_reader_ = std::make_unique<MetadataReaderMock>();
|
||||
streams.clear();
|
||||
|
||||
// Try again with too many.
|
||||
for (int32_t i = 0; i <= test_max_non_stalling_outputs_; ++i) {
|
||||
streams.push_back(MakeStream(output_multisize_non_stalling_));
|
||||
}
|
||||
ExpectConfigurationSupported(streams, false);
|
||||
}
|
||||
|
||||
TEST_F(StaticPropertiesTest, ConfigureUnuspportedInput) {
|
||||
std::vector<camera3_stream_t> streams;
|
||||
streams.push_back(MakeStream(input_, false, true));
|
||||
streams.push_back(MakeStream(bidirectional_raw_));
|
||||
// No matching output format for input.
|
||||
ExpectConfigurationSupported(streams, false);
|
||||
}
|
||||
|
||||
TEST_F(StaticPropertiesTest, ConfigureUnsupportedOutput) {
|
||||
std::vector<camera3_stream_t> streams;
|
||||
streams.push_back(MakeStream(input_, false, true));
|
||||
// The universal output does match input.
|
||||
streams.push_back(MakeStream(output_multisize_non_stalling_));
|
||||
// Raw does not match input.
|
||||
streams.push_back(MakeStream(bidirectional_raw_));
|
||||
// Input is matched; it's ok that raw doesn't match (only the actual
|
||||
// requests care).
|
||||
ExpectConfigurationSupported(streams, true);
|
||||
}
|
||||
|
||||
TEST_F(StaticPropertiesTest, ConfigureUnsupportedBidirectional) {
|
||||
std::vector<camera3_stream_t> streams;
|
||||
// The test raw format, while supporting both input and output,
|
||||
// does not actually support itself.
|
||||
streams.push_back(MakeStream(bidirectional_raw_, true, true));
|
||||
ExpectConfigurationSupported(streams, false);
|
||||
}
|
||||
|
||||
TEST_F(StaticPropertiesTest, ConfigureBadOperationMode) {
|
||||
// A valid stream set.
|
||||
camera3_stream_t stream = MakeStream(output_multisize_non_stalling_);
|
||||
camera3_stream_t* stream_address = &stream;
|
||||
// But not a valid config.
|
||||
camera3_stream_configuration_t config = {
|
||||
1,
|
||||
&stream_address,
|
||||
99 // Not a valid operation mode.
|
||||
};
|
||||
PrepareDefaultDUT();
|
||||
EXPECT_FALSE(dut_->StreamConfigurationSupported(&config));
|
||||
}
|
||||
|
||||
TEST_F(StaticPropertiesTest, ReprocessingSingleOutput) {
|
||||
camera3_stream_t input_stream = MakeStream(input_);
|
||||
camera3_stream_t output_stream = MakeStream(output_multisize_non_stalling_);
|
||||
PrepareDefaultDUT();
|
||||
EXPECT_TRUE(dut_->ReprocessingSupported(&input_stream, {&output_stream}));
|
||||
}
|
||||
|
||||
TEST_F(StaticPropertiesTest, ReprocessingMultipleOutputs) {
|
||||
camera3_stream_t input_stream =
|
||||
MakeStream(bidirectional_self_supporting_stalling_, false, true);
|
||||
// Bi-directional self-supporting supports the universal output and itself.
|
||||
camera3_stream_t output_stream1 = MakeStream(output_multisize_non_stalling_);
|
||||
camera3_stream_t output_stream2 =
|
||||
MakeStream(bidirectional_self_supporting_stalling_);
|
||||
PrepareDefaultDUT();
|
||||
EXPECT_TRUE(dut_->ReprocessingSupported(&input_stream,
|
||||
{&output_stream1, &output_stream2}));
|
||||
}
|
||||
|
||||
TEST_F(StaticPropertiesTest, ReprocessingNoInput) {
|
||||
camera3_stream_t output_stream = MakeStream(output_multisize_non_stalling_);
|
||||
PrepareDefaultDUT();
|
||||
EXPECT_FALSE(dut_->ReprocessingSupported(nullptr, {&output_stream}));
|
||||
}
|
||||
|
||||
TEST_F(StaticPropertiesTest, ReprocessingNoOutput) {
|
||||
camera3_stream_t input_stream = MakeStream(input_);
|
||||
PrepareDefaultDUT();
|
||||
EXPECT_FALSE(dut_->ReprocessingSupported(&input_stream, {}));
|
||||
}
|
||||
|
||||
TEST_F(StaticPropertiesTest, ReprocessingInvalidOutput) {
|
||||
camera3_stream_t input_stream = MakeStream(input_, false, true);
|
||||
// The universal output does match input.
|
||||
camera3_stream_t output_stream1 = MakeStream(output_multisize_non_stalling_);
|
||||
// Raw does not match input.
|
||||
camera3_stream_t output_stream2 = MakeStream(bidirectional_raw_);
|
||||
PrepareDefaultDUT();
|
||||
EXPECT_FALSE(dut_->ReprocessingSupported(&input_stream,
|
||||
{&output_stream1, &output_stream2}));
|
||||
}
|
||||
|
||||
} // namespace default_camera_hal
|
||||
|
|
Loading…
Reference in a new issue