blob: fe2ff859fa9d772dd0d35e20aaf1ca354e583393 [file] [log] [blame]
/*
* Copyright (C) 2016 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include "metadata_reader.h"
// #define LOG_NDEBUG 0
#define LOG_TAG "MetadataReader"
#include <cutils/log.h>
#include <system/camera.h>
#include "metadata_common.h"
namespace default_camera_hal {
MetadataReader::MetadataReader(
std::unique_ptr<const android::CameraMetadata> metadata)
: metadata_(std::move(metadata)) {}
MetadataReader::~MetadataReader() {}
int MetadataReader::Facing(int* facing) const {
uint8_t metadata_facing = 0;
int res = v4l2_camera_hal::SingleTagValue(
*metadata_, ANDROID_LENS_FACING, &metadata_facing);
if (res) {
ALOGE("%s: Failed to get facing from static metadata.", __func__);
return res;
}
switch (metadata_facing) {
case (ANDROID_LENS_FACING_FRONT):
*facing = CAMERA_FACING_FRONT;
break;
case (ANDROID_LENS_FACING_BACK):
*facing = CAMERA_FACING_BACK;
break;
case (ANDROID_LENS_FACING_EXTERNAL):
*facing = CAMERA_FACING_EXTERNAL;
break;
default:
ALOGE("%s: Invalid facing from static metadata: %d.",
__func__,
metadata_facing);
return -EINVAL;
}
return 0;
}
int MetadataReader::Orientation(int* orientation) const {
int32_t metadata_orientation = 0;
int res = v4l2_camera_hal::SingleTagValue(
*metadata_, ANDROID_SENSOR_ORIENTATION, &metadata_orientation);
if (res) {
ALOGE("%s: Failed to get orientation from static metadata.", __func__);
return res;
}
// Orientation must be 0, 90, 180, or 270.
if (metadata_orientation < 0 || metadata_orientation > 270 ||
metadata_orientation % 90 != 0) {
ALOGE(
"%s: Invalid orientation %d "
"(must be a 90-degree increment in [0, 360)).",
__func__,
metadata_orientation);
return -EINVAL;
}
*orientation = static_cast<int>(metadata_orientation);
return 0;
}
int MetadataReader::MaxInputStreams(int32_t* max_input) const {
int res = v4l2_camera_hal::SingleTagValue(
*metadata_, ANDROID_REQUEST_MAX_NUM_INPUT_STREAMS, max_input);
if (res == -ENOENT) {
// Not required; default to 0.
*max_input = 0;
} else if (res) {
ALOGE("%s: Failed to get max output streams from static metadata.",
__func__);
return res;
}
return 0;
}
int MetadataReader::MaxOutputStreams(int32_t* max_raw,
int32_t* max_non_stalling,
int32_t* max_stalling) const {
std::array<int32_t, 3> max_output_streams;
int res = v4l2_camera_hal::SingleTagValue(
*metadata_, ANDROID_REQUEST_MAX_NUM_OUTPUT_STREAMS, &max_output_streams);
if (res) {
ALOGE("%s: Failed to get max output streams from static metadata.",
__func__);
return res;
}
*max_raw = max_output_streams[0];
*max_non_stalling = max_output_streams[1];
*max_stalling = max_output_streams[2];
return 0;
}
int MetadataReader::RequestCapabilities(std::set<uint8_t>* capabilities) const {
std::vector<uint8_t> raw_capabilities;
int res = v4l2_camera_hal::VectorTagValue(
*metadata_, ANDROID_REQUEST_AVAILABLE_CAPABILITIES, &raw_capabilities);
if (res) {
ALOGE("%s: Failed to get request capabilities from static metadata.",
__func__);
return res;
}
// Move from vector to set.
capabilities->insert(raw_capabilities.begin(), raw_capabilities.end());
return 0;
}
int MetadataReader::StreamConfigurations(
std::vector<StreamConfiguration>* configs) const {
std::vector<RawStreamConfiguration> raw_stream_configs;
int res = v4l2_camera_hal::VectorTagValue(
*metadata_,
ANDROID_SCALER_AVAILABLE_STREAM_CONFIGURATIONS,
&raw_stream_configs);
if (res) {
ALOGE("%s: Failed to get stream configs from static metadata.", __func__);
return res;
}
// TODO(b/31384253): check for required configs.
// Convert from raw.
configs->insert(
configs->end(), raw_stream_configs.begin(), raw_stream_configs.end());
// Check that all configs are valid.
for (const auto& config : *configs) {
// Must have positive dimensions.
if (config.spec.width < 1 || config.spec.height < 1) {
ALOGE("%s: Invalid stream config: non-positive dimensions (%d, %d).",
__func__,
config.spec.width,
config.spec.height);
return -EINVAL;
}
// Must have a known direction enum.
switch (config.direction) {
case ANDROID_SCALER_AVAILABLE_STREAM_CONFIGURATIONS_OUTPUT:
case ANDROID_SCALER_AVAILABLE_STREAM_CONFIGURATIONS_INPUT:
break;
default:
ALOGE("%s: Invalid stream config direction: %d.",
__func__,
config.direction);
return -EINVAL;
}
}
return 0;
}
int MetadataReader::StreamStallDurations(
std::vector<StreamStallDuration>* stalls) const {
std::vector<RawStreamStallDuration> raw_stream_stall_durations;
int res =
v4l2_camera_hal::VectorTagValue(*metadata_,
ANDROID_SCALER_AVAILABLE_STALL_DURATIONS,
&raw_stream_stall_durations);
if (res) {
ALOGE("%s: Failed to get stall durations from static metadata.", __func__);
return res;
}
// Convert from raw.
stalls->insert(stalls->end(),
raw_stream_stall_durations.begin(),
raw_stream_stall_durations.end());
// Check that all stalls are valid.
for (const auto& stall : *stalls) {
// Must have positive dimensions.
if (stall.spec.width < 1 || stall.spec.height < 1) {
ALOGE("%s: Invalid stall duration: non-positive dimensions (%d, %d).",
__func__,
stall.spec.width,
stall.spec.height);
return -EINVAL;
}
// Must have a non-negative stall.
if (stall.duration < 0) {
ALOGE("%s: Invalid stall duration: negative stall %d.",
__func__,
stall.duration);
return -EINVAL;
}
// TODO(b/31384253): YUV_420_888, RAW10, RAW12, RAW_OPAQUE,
// and IMPLEMENTATION_DEFINED must have 0 stall duration.
}
return 0;
}
int MetadataReader::ReprocessFormats(ReprocessFormatMap* reprocess_map) const {
std::vector<int32_t> input_output_formats;
int res = v4l2_camera_hal::VectorTagValue(
*metadata_,
ANDROID_SCALER_AVAILABLE_INPUT_OUTPUT_FORMATS_MAP,
&input_output_formats);
if (res) {
ALOGE("%s: Failed to get input output format map from static metadata.",
__func__);
return res;
}
// Convert from the raw vector.
for (size_t i = 0; i < input_output_formats.size();) {
// The map is represented as variable-length entries of the format
// input, num_outputs, <outputs>.
// Get the input format.
int32_t input_format = input_output_formats[i++];
// Find the output begin and end for this format.
int32_t num_output_formats = input_output_formats[i++];
if (num_output_formats < 1) {
ALOGE(
"%s: No output formats for input format %d.", __func__, input_format);
return -EINVAL;
}
size_t outputs_end = i + num_output_formats;
if (outputs_end > input_output_formats.size()) {
ALOGE("%s: Input format %d requests more data than available.",
__func__,
input_format);
return -EINVAL;
}
// Copy all the output formats into the map.
(*reprocess_map)[input_format].insert(
input_output_formats.data() + i,
input_output_formats.data() + outputs_end);
// Move on to the next entry.
i = outputs_end;
}
// TODO(b/31384253): check for required mappings.
return 0;
}
} // namespace default_camera_hal