blob: 7ec437127e6620890e12547041bf2ef0762c92f1 [file] [log] [blame]
/* Copyright 2016 The Chromium OS Authors. All rights reserved.
* Use of this source code is governed by a BSD-style license that can be
* found in the LICENSE file.
*/
#include "hal/usb/metadata_handler.h"
#include <cmath>
#include <limits>
#include <unordered_map>
#include <vector>
#include "common/utils/camera_config.h"
#include "cros-camera/common.h"
#include "hal/usb/stream_format.h"
#define ARRAY_SIZE(a) (sizeof(a) / sizeof(a[0]))
#define UPDATE(tag, data, size) \
do { \
if (metadata->update((tag), (data), (size))) { \
LOGF(ERROR) << "Update " << #tag << " failed"; \
return -EINVAL; \
} \
} while (0)
namespace cros {
MetadataHandler::MetadataHandler(const camera_metadata_t& metadata)
: af_trigger_(false) {
// MetadataBase::operator= will make a copy of camera_metadata_t.
metadata_ = &metadata;
// camera3_request_template_t starts at 1.
for (int i = 1; i < CAMERA3_TEMPLATE_COUNT; i++) {
template_settings_[i] = CreateDefaultRequestSettings(i);
}
thread_checker_.DetachFromThread();
}
MetadataHandler::~MetadataHandler() {}
int MetadataHandler::FillDefaultMetadata(android::CameraMetadata* metadata) {
// android.colorCorrection
const uint8_t available_aberration_modes[] = {
ANDROID_COLOR_CORRECTION_ABERRATION_MODE_FAST,
ANDROID_COLOR_CORRECTION_ABERRATION_MODE_HIGH_QUALITY};
UPDATE(ANDROID_COLOR_CORRECTION_AVAILABLE_ABERRATION_MODES,
available_aberration_modes, ARRAY_SIZE(available_aberration_modes));
UPDATE(ANDROID_COLOR_CORRECTION_ABERRATION_MODE,
&available_aberration_modes[0], 1);
// android.control
// We don't support AE compensation.
const int32_t control_ae_compensation_range[] = {0, 0};
UPDATE(ANDROID_CONTROL_AE_COMPENSATION_RANGE, control_ae_compensation_range,
ARRAY_SIZE(control_ae_compensation_range));
const camera_metadata_rational_t control_ae_compensation_step[] = {{0, 1}};
UPDATE(ANDROID_CONTROL_AE_COMPENSATION_STEP, control_ae_compensation_step,
ARRAY_SIZE(control_ae_compensation_step));
const int32_t control_max_regions[] = {/*AE*/ 0, /*AWB*/ 0, /*AF*/ 0};
UPDATE(ANDROID_CONTROL_MAX_REGIONS, control_max_regions,
ARRAY_SIZE(control_max_regions));
const uint8_t video_stabilization_mode =
ANDROID_CONTROL_VIDEO_STABILIZATION_MODE_OFF;
UPDATE(ANDROID_CONTROL_AVAILABLE_VIDEO_STABILIZATION_MODES,
&video_stabilization_mode, 1);
UPDATE(ANDROID_CONTROL_VIDEO_STABILIZATION_MODE, &video_stabilization_mode,
1);
const uint8_t awb_available_mode = ANDROID_CONTROL_AWB_MODE_AUTO;
UPDATE(ANDROID_CONTROL_AWB_AVAILABLE_MODES, &awb_available_mode, 1);
UPDATE(ANDROID_CONTROL_AWB_MODE, &awb_available_mode, 1);
const uint8_t ae_available_mode = ANDROID_CONTROL_AE_MODE_ON;
UPDATE(ANDROID_CONTROL_AE_AVAILABLE_MODES, &ae_available_mode, 1);
// ON means auto-exposure is active with no flash control.
UPDATE(ANDROID_CONTROL_AE_MODE, &ae_available_mode, 1);
const int32_t ae_exposure_compensation = 0;
UPDATE(ANDROID_CONTROL_AE_EXPOSURE_COMPENSATION, &ae_exposure_compensation,
1);
const uint8_t ae_precapture_trigger =
ANDROID_CONTROL_AE_PRECAPTURE_TRIGGER_IDLE;
UPDATE(ANDROID_CONTROL_AE_PRECAPTURE_TRIGGER, &ae_precapture_trigger, 1);
const uint8_t af_available_modes[] = {ANDROID_CONTROL_AF_MODE_AUTO,
ANDROID_CONTROL_AF_MODE_OFF};
UPDATE(ANDROID_CONTROL_AF_AVAILABLE_MODES, af_available_modes,
ARRAY_SIZE(af_available_modes));
UPDATE(ANDROID_CONTROL_AF_MODE, &af_available_modes[0], 1);
const uint8_t af_trigger = ANDROID_CONTROL_AF_TRIGGER_IDLE;
UPDATE(ANDROID_CONTROL_AF_TRIGGER, &af_trigger, 1);
const uint8_t available_scene_mode = ANDROID_CONTROL_SCENE_MODE_DISABLED;
UPDATE(ANDROID_CONTROL_AVAILABLE_SCENE_MODES, &available_scene_mode, 1);
UPDATE(ANDROID_CONTROL_SCENE_MODE, &available_scene_mode, 1);
const uint8_t available_effect = ANDROID_CONTROL_EFFECT_MODE_OFF;
UPDATE(ANDROID_CONTROL_AVAILABLE_EFFECTS, &available_effect, 1);
UPDATE(ANDROID_CONTROL_EFFECT_MODE, &available_effect, 1);
const uint8_t ae_lock_available = ANDROID_CONTROL_AE_LOCK_AVAILABLE_FALSE;
UPDATE(ANDROID_CONTROL_AE_LOCK_AVAILABLE, &ae_lock_available, 1);
const uint8_t awb_lock_available = ANDROID_CONTROL_AWB_LOCK_AVAILABLE_FALSE;
UPDATE(ANDROID_CONTROL_AWB_LOCK_AVAILABLE, &awb_lock_available, 1);
const uint8_t control_available_modes[] = {ANDROID_CONTROL_MODE_OFF,
ANDROID_CONTROL_MODE_AUTO};
UPDATE(ANDROID_CONTROL_AVAILABLE_MODES, control_available_modes,
ARRAY_SIZE(control_available_modes));
// android.flash
const uint8_t flash_info = ANDROID_FLASH_INFO_AVAILABLE_FALSE;
UPDATE(ANDROID_FLASH_INFO_AVAILABLE, &flash_info, 1);
const uint8_t flash_state = ANDROID_FLASH_STATE_UNAVAILABLE;
UPDATE(ANDROID_FLASH_STATE, &flash_state, 1);
const uint8_t flash_mode = ANDROID_FLASH_MODE_OFF;
UPDATE(ANDROID_FLASH_MODE, &flash_mode, 1);
// android.jpeg
const int32_t jpeg_max_size[] = {13 * 1024 * 1024}; // 13MB
UPDATE(ANDROID_JPEG_MAX_SIZE, jpeg_max_size, ARRAY_SIZE(jpeg_max_size));
const uint8_t jpeg_quality = 90;
UPDATE(ANDROID_JPEG_QUALITY, &jpeg_quality, 1);
UPDATE(ANDROID_JPEG_THUMBNAIL_QUALITY, &jpeg_quality, 1);
const int32_t jpeg_orientation = 0;
UPDATE(ANDROID_JPEG_ORIENTATION, &jpeg_orientation, 1);
// android.lens
// This should not be needed.
const float hyper_focal_distance = 0.0f;
UPDATE(ANDROID_LENS_INFO_HYPERFOCAL_DISTANCE, &hyper_focal_distance, 1);
const uint8_t optical_stabilization_mode =
ANDROID_LENS_OPTICAL_STABILIZATION_MODE_OFF;
UPDATE(ANDROID_LENS_INFO_AVAILABLE_OPTICAL_STABILIZATION,
&optical_stabilization_mode, 1);
UPDATE(ANDROID_LENS_OPTICAL_STABILIZATION_MODE, &optical_stabilization_mode,
1);
// android.noiseReduction
const uint8_t noise_reduction_mode = ANDROID_NOISE_REDUCTION_MODE_OFF;
UPDATE(ANDROID_NOISE_REDUCTION_AVAILABLE_NOISE_REDUCTION_MODES,
&noise_reduction_mode, 1);
UPDATE(ANDROID_NOISE_REDUCTION_MODE, &noise_reduction_mode, 1);
// android.request
const uint8_t available_capabilities[] = {
ANDROID_REQUEST_AVAILABLE_CAPABILITIES_BACKWARD_COMPATIBLE};
UPDATE(ANDROID_REQUEST_AVAILABLE_CAPABILITIES, available_capabilities,
ARRAY_SIZE(available_capabilities));
const int32_t partial_result_count = 1;
UPDATE(ANDROID_REQUEST_PARTIAL_RESULT_COUNT, &partial_result_count, 1);
// This means pipeline latency of X frame intervals. The maximum number is 4.
const uint8_t request_pipeline_max_depth = 4;
UPDATE(ANDROID_REQUEST_PIPELINE_MAX_DEPTH, &request_pipeline_max_depth, 1);
UPDATE(ANDROID_REQUEST_PIPELINE_DEPTH, &request_pipeline_max_depth, 1);
// Three numbers represent the maximum numbers of different types of output
// streams simultaneously. The types are raw sensor, processed (but not
// stalling), and processed (but stalling). For usb limited mode, raw sensor
// is not supported. Stalling stream is JPEG. Non-stalling streams are
// YUV_420_888, NV21, or YV12.
const int32_t request_max_num_output_streams[] = {0, 2, 1};
UPDATE(ANDROID_REQUEST_MAX_NUM_OUTPUT_STREAMS, request_max_num_output_streams,
ARRAY_SIZE(request_max_num_output_streams));
// Limited mode doesn't support reprocessing.
const int32_t request_max_num_input_streams = 0;
UPDATE(ANDROID_REQUEST_MAX_NUM_INPUT_STREAMS, &request_max_num_input_streams,
1);
// android.scaler
const float scaler_available_max_digital_zoom[] = {1};
UPDATE(ANDROID_SCALER_AVAILABLE_MAX_DIGITAL_ZOOM,
scaler_available_max_digital_zoom,
ARRAY_SIZE(scaler_available_max_digital_zoom));
const uint8_t cropping_type = ANDROID_SCALER_CROPPING_TYPE_CENTER_ONLY;
UPDATE(ANDROID_SCALER_CROPPING_TYPE, &cropping_type, 1);
const int32_t test_pattern_modes[] = {
ANDROID_SENSOR_TEST_PATTERN_MODE_OFF,
ANDROID_SENSOR_TEST_PATTERN_MODE_COLOR_BARS_FADE_TO_GRAY};
UPDATE(ANDROID_SENSOR_AVAILABLE_TEST_PATTERN_MODES, test_pattern_modes,
ARRAY_SIZE(test_pattern_modes));
UPDATE(ANDROID_SENSOR_TEST_PATTERN_MODE, &test_pattern_modes[0], 1);
const uint8_t timestamp_source = ANDROID_SENSOR_INFO_TIMESTAMP_SOURCE_UNKNOWN;
UPDATE(ANDROID_SENSOR_INFO_TIMESTAMP_SOURCE, &timestamp_source, 1);
// android.shading
const uint8_t availabe_mode = ANDROID_SHADING_MODE_FAST;
UPDATE(ANDROID_SHADING_AVAILABLE_MODES, &availabe_mode, 1);
// android.statistics
const uint8_t face_detect_mode = ANDROID_STATISTICS_FACE_DETECT_MODE_OFF;
UPDATE(ANDROID_STATISTICS_INFO_AVAILABLE_FACE_DETECT_MODES, &face_detect_mode,
1);
UPDATE(ANDROID_STATISTICS_FACE_DETECT_MODE, &face_detect_mode, 1);
const int32_t max_face_count = 0;
UPDATE(ANDROID_STATISTICS_INFO_MAX_FACE_COUNT, &max_face_count, 1);
const uint8_t available_hotpixel_mode =
ANDROID_STATISTICS_HOT_PIXEL_MAP_MODE_OFF;
UPDATE(ANDROID_STATISTICS_INFO_AVAILABLE_HOT_PIXEL_MAP_MODES,
&available_hotpixel_mode, 1);
UPDATE(ANDROID_STATISTICS_HOT_PIXEL_MAP_MODE, &available_hotpixel_mode, 1);
const uint8_t lens_shading_map_mode =
ANDROID_STATISTICS_LENS_SHADING_MAP_MODE_OFF;
UPDATE(ANDROID_STATISTICS_INFO_AVAILABLE_LENS_SHADING_MAP_MODES,
&lens_shading_map_mode, 1);
// android.sync
const int32_t max_latency = ANDROID_SYNC_MAX_LATENCY_UNKNOWN;
UPDATE(ANDROID_SYNC_MAX_LATENCY, &max_latency, 1);
return 0;
}
int MetadataHandler::FillMetadataFromSupportedFormats(
const SupportedFormats& supported_formats,
android::CameraMetadata* metadata,
bool is_external) {
if (supported_formats.empty()) {
return -EINVAL;
}
std::vector<int32_t> stream_configurations;
std::vector<int64_t> min_frame_durations;
std::vector<int64_t> stall_durations;
// The min fps <= 15 must be supported in CTS.
const int32_t kMinFpsMax = 1;
const int64_t kOneSecOfNanoUnit = 1000000000LL;
int32_t max_fps = std::numeric_limits<int32_t>::min();
int32_t min_fps = kMinFpsMax;
int64_t max_frame_duration = kOneSecOfNanoUnit / min_fps;
std::vector<int> hal_formats{HAL_PIXEL_FORMAT_BLOB,
HAL_PIXEL_FORMAT_YCbCr_420_888,
HAL_PIXEL_FORMAT_IMPLEMENTATION_DEFINED};
std::unordered_map<int, int> max_hal_width_by_format;
std::unordered_map<int, int> max_hal_height_by_format;
CameraConfig camera_config(constants::kCrosCameraConfigPathString);
max_hal_width_by_format[HAL_PIXEL_FORMAT_BLOB] = camera_config.GetInteger(
constants::kCrosMaxBlobWidth, std::numeric_limits<int>::max());
max_hal_width_by_format[HAL_PIXEL_FORMAT_YCbCr_420_888] =
camera_config.GetInteger(constants::kCrosMaxYuvWidth,
std::numeric_limits<int>::max());
max_hal_width_by_format[HAL_PIXEL_FORMAT_IMPLEMENTATION_DEFINED] =
camera_config.GetInteger(constants::kCrosMaxPrivateWidth,
std::numeric_limits<int>::max());
max_hal_height_by_format[HAL_PIXEL_FORMAT_BLOB] = camera_config.GetInteger(
constants::kCrosMaxBlobHeight, std::numeric_limits<int>::max());
max_hal_height_by_format[HAL_PIXEL_FORMAT_YCbCr_420_888] =
camera_config.GetInteger(constants::kCrosMaxYuvHeight,
std::numeric_limits<int>::max());
max_hal_height_by_format[HAL_PIXEL_FORMAT_IMPLEMENTATION_DEFINED] =
camera_config.GetInteger(constants::kCrosMaxPrivateHeight,
std::numeric_limits<int>::max());
for (const auto& supported_format : supported_formats) {
int64_t min_frame_duration = std::numeric_limits<int64_t>::max();
int32_t per_format_max_fps = std::numeric_limits<int32_t>::min();
for (const auto& frame_rate : supported_format.frame_rates) {
// To prevent floating point precision problem we cast the floating point
// to double here.
int64_t frame_duration =
kOneSecOfNanoUnit / static_cast<double>(frame_rate);
if (frame_duration < min_frame_duration) {
min_frame_duration = frame_duration;
}
if (frame_duration > max_frame_duration) {
max_frame_duration = frame_duration;
}
if (per_format_max_fps < static_cast<int32_t>(frame_rate)) {
per_format_max_fps = static_cast<int32_t>(frame_rate);
}
}
if (per_format_max_fps > max_fps) {
max_fps = per_format_max_fps;
}
for (const auto& format : hal_formats) {
if (supported_format.width > max_hal_width_by_format[format]) {
LOGF(INFO) << "Filter Format: 0x" << std::hex << format << std::dec
<< "-width " << supported_format.width << ". max is "
<< max_hal_width_by_format[format];
continue;
}
if (supported_format.height > max_hal_height_by_format[format]) {
LOGF(INFO) << "Filter Format: 0x" << std::hex << format << std::dec
<< "-height " << supported_format.height << ". max is "
<< max_hal_height_by_format[format];
continue;
}
// We filter the resolution which cannot support 30 fps out.
if (format == HAL_PIXEL_FORMAT_BLOB || per_format_max_fps == 30) {
stream_configurations.push_back(format);
stream_configurations.push_back(supported_format.width);
stream_configurations.push_back(supported_format.height);
stream_configurations.push_back(
ANDROID_SCALER_AVAILABLE_STREAM_CONFIGURATIONS_OUTPUT);
min_frame_durations.push_back(format);
min_frame_durations.push_back(supported_format.width);
min_frame_durations.push_back(supported_format.height);
min_frame_durations.push_back(min_frame_duration);
}
}
// The stall duration is 0 for non-jpeg formats. For JPEG format, stall
// duration can be 0 if JPEG is small. 5MP JPEG takes 700ms to decode
// and encode. Here we choose 1 sec for JPEG.
for (const auto& format : hal_formats) {
// For non-jpeg formats, the camera orientation workaround crops,
// rotates, and scales the frames. Theoretically the stall duration of
// huge resolution may be bigger than 0. Set it to 0 for now.
int64_t stall_duration =
(format == HAL_PIXEL_FORMAT_BLOB) ? 1000000000 : 0;
stall_durations.push_back(format);
stall_durations.push_back(supported_format.width);
stall_durations.push_back(supported_format.height);
stall_durations.push_back(stall_duration);
}
}
// The document in aeAvailableTargetFpsRanges section says the min_fps should
// not be larger than 15.
// We cannot support fixed 30fps but Android requires (min, max) and
// (max, max) ranges.
int32_t fps_ranges[] = {min_fps, max_fps, max_fps, max_fps};
UPDATE(ANDROID_CONTROL_AE_AVAILABLE_TARGET_FPS_RANGES, fps_ranges,
ARRAY_SIZE(fps_ranges));
// CTS expects the (maxFps == minFps) for recording.
int32_t ae_fps_ranges[] = {max_fps, max_fps};
UPDATE(ANDROID_CONTROL_AE_TARGET_FPS_RANGE, ae_fps_ranges, 2);
UPDATE(ANDROID_SCALER_AVAILABLE_STREAM_CONFIGURATIONS,
stream_configurations.data(), stream_configurations.size());
UPDATE(ANDROID_SCALER_AVAILABLE_MIN_FRAME_DURATIONS,
min_frame_durations.data(), min_frame_durations.size());
UPDATE(ANDROID_SCALER_AVAILABLE_STALL_DURATIONS, stall_durations.data(),
stall_durations.size());
std::vector<int32_t> jpeg_available_thumbnail_sizes =
GetJpegAvailableThumbnailSizes(supported_formats);
UPDATE(ANDROID_JPEG_AVAILABLE_THUMBNAIL_SIZES,
jpeg_available_thumbnail_sizes.data(),
jpeg_available_thumbnail_sizes.size());
UPDATE(ANDROID_JPEG_THUMBNAIL_SIZE,
&jpeg_available_thumbnail_sizes.back() - 1, 2);
UPDATE(ANDROID_SENSOR_INFO_MAX_FRAME_DURATION, &max_frame_duration, 1);
SupportedFormat maximum_format = GetMaximumFormat(supported_formats);
int32_t active_array_size[] = {0, 0,
static_cast<int32_t>(maximum_format.width),
static_cast<int32_t>(maximum_format.height)};
UPDATE(ANDROID_SENSOR_INFO_PRE_CORRECTION_ACTIVE_ARRAY_SIZE,
active_array_size, ARRAY_SIZE(active_array_size));
UPDATE(ANDROID_SENSOR_INFO_ACTIVE_ARRAY_SIZE, active_array_size,
ARRAY_SIZE(active_array_size));
if (is_external) {
// It's a sensible value for external camera, since it's required on all
// devices per spec. For built-in camera, this would be filled in
// FillMetadataFromDeviceInfo() using the value from the configuration file.
// References:
// * The official document for this field
// https://developer.android.com/reference/android/hardware/camera2/CameraCharacteristics.html#SENSOR_INFO_PIXEL_ARRAY_SIZE
// * The implementation of external camera in Android P
// https://googleplex-android.git.corp.google.com/platform/hardware/interfaces/+/6ad8708bf8b631561fa11eb1f4889907d1772d78/camera/device/3.4/default/ExternalCameraDevice.cpp#687
int32_t pixel_array_size[] = {static_cast<int32_t>(maximum_format.width),
static_cast<int32_t>(maximum_format.height)};
UPDATE(ANDROID_SENSOR_INFO_PIXEL_ARRAY_SIZE, pixel_array_size,
ARRAY_SIZE(pixel_array_size));
}
return 0;
}
int MetadataHandler::FillMetadataFromDeviceInfo(
const DeviceInfo& device_info, android::CameraMetadata* metadata) {
bool is_external = device_info.lens_facing == ANDROID_LENS_FACING_EXTERNAL;
bool is_builtin = !is_external;
std::vector<int32_t> available_request_keys = {
ANDROID_COLOR_CORRECTION_ABERRATION_MODE,
ANDROID_CONTROL_AE_ANTIBANDING_MODE,
ANDROID_CONTROL_AE_EXPOSURE_COMPENSATION,
ANDROID_CONTROL_AE_LOCK,
ANDROID_CONTROL_AE_MODE,
ANDROID_CONTROL_AE_PRECAPTURE_TRIGGER,
ANDROID_CONTROL_AE_TARGET_FPS_RANGE,
ANDROID_CONTROL_AF_MODE,
ANDROID_CONTROL_AF_TRIGGER,
ANDROID_CONTROL_AWB_LOCK,
ANDROID_CONTROL_AWB_MODE,
ANDROID_CONTROL_CAPTURE_INTENT,
ANDROID_CONTROL_EFFECT_MODE,
ANDROID_CONTROL_MODE,
ANDROID_CONTROL_SCENE_MODE,
ANDROID_CONTROL_VIDEO_STABILIZATION_MODE,
ANDROID_FLASH_MODE,
ANDROID_JPEG_ORIENTATION,
ANDROID_JPEG_QUALITY,
ANDROID_JPEG_THUMBNAIL_QUALITY,
ANDROID_JPEG_THUMBNAIL_SIZE,
ANDROID_LENS_OPTICAL_STABILIZATION_MODE,
ANDROID_NOISE_REDUCTION_MODE,
ANDROID_SCALER_CROP_REGION,
ANDROID_SENSOR_TEST_PATTERN_MODE,
ANDROID_STATISTICS_FACE_DETECT_MODE,
ANDROID_STATISTICS_HOT_PIXEL_MAP_MODE,
};
if (is_builtin) {
available_request_keys.insert(
available_request_keys.end(),
{
ANDROID_LENS_APERTURE, ANDROID_LENS_FOCAL_LENGTH,
ANDROID_LENS_FOCUS_DISTANCE,
});
}
UPDATE(ANDROID_REQUEST_AVAILABLE_REQUEST_KEYS, available_request_keys.data(),
available_request_keys.size());
// TODO(shik): All properties listed for capture requests can also be queried
// on the capture result, to determine the final values used for capture. We
// shuold build this list from |available_request_keys|.
// ref:
// https://developer.android.com/reference/android/hardware/camera2/CaptureResult
std::vector<int32_t> available_result_keys = {
ANDROID_COLOR_CORRECTION_ABERRATION_MODE,
ANDROID_CONTROL_AE_ANTIBANDING_MODE,
ANDROID_CONTROL_AE_EXPOSURE_COMPENSATION,
ANDROID_CONTROL_AE_LOCK,
ANDROID_CONTROL_AE_MODE,
ANDROID_CONTROL_AE_PRECAPTURE_TRIGGER,
ANDROID_CONTROL_AE_STATE,
ANDROID_CONTROL_AE_TARGET_FPS_RANGE,
ANDROID_CONTROL_AF_MODE,
ANDROID_CONTROL_AF_STATE,
ANDROID_CONTROL_AF_TRIGGER,
ANDROID_CONTROL_AWB_LOCK,
ANDROID_CONTROL_AWB_MODE,
ANDROID_CONTROL_AWB_STATE,
ANDROID_CONTROL_CAPTURE_INTENT,
ANDROID_CONTROL_EFFECT_MODE,
ANDROID_CONTROL_MODE,
ANDROID_CONTROL_SCENE_MODE,
ANDROID_CONTROL_VIDEO_STABILIZATION_MODE,
ANDROID_FLASH_MODE,
ANDROID_FLASH_STATE,
ANDROID_JPEG_ORIENTATION,
ANDROID_JPEG_QUALITY,
ANDROID_JPEG_THUMBNAIL_QUALITY,
ANDROID_JPEG_THUMBNAIL_SIZE,
ANDROID_LENS_OPTICAL_STABILIZATION_MODE,
ANDROID_LENS_STATE,
ANDROID_NOISE_REDUCTION_MODE,
ANDROID_REQUEST_PIPELINE_DEPTH,
ANDROID_SCALER_CROP_REGION,
ANDROID_SENSOR_ROLLING_SHUTTER_SKEW,
ANDROID_SENSOR_TEST_PATTERN_MODE,
ANDROID_SENSOR_TIMESTAMP,
ANDROID_STATISTICS_FACE_DETECT_MODE,
ANDROID_STATISTICS_HOT_PIXEL_MAP_MODE,
ANDROID_STATISTICS_LENS_SHADING_MAP_MODE,
ANDROID_STATISTICS_SCENE_FLICKER,
};
if (is_builtin) {
available_result_keys.insert(
available_result_keys.end(),
{
ANDROID_LENS_APERTURE, ANDROID_LENS_FOCAL_LENGTH,
ANDROID_LENS_FOCUS_DISTANCE,
});
}
UPDATE(ANDROID_REQUEST_AVAILABLE_RESULT_KEYS, available_result_keys.data(),
available_result_keys.size());
// TODO(shik): The HAL must not have any tags in its static info that are not
// listed either here or in the vendor tag list. Some request/result metadata
// entries are also presented in the static info now, and we should fix it.
// ref:
// https://android.googlesource.com/platform/system/media/+/a8cff157ff0ed02fa7e29438f4889a9933c37768/camera/docs/docs.html#16298
std::vector<int32_t> available_characteristics_keys = {
ANDROID_COLOR_CORRECTION_AVAILABLE_ABERRATION_MODES,
ANDROID_CONTROL_AE_AVAILABLE_ANTIBANDING_MODES,
ANDROID_CONTROL_AE_AVAILABLE_MODES,
ANDROID_CONTROL_AE_AVAILABLE_TARGET_FPS_RANGES,
ANDROID_CONTROL_AE_COMPENSATION_RANGE,
ANDROID_CONTROL_AE_COMPENSATION_STEP,
ANDROID_CONTROL_AE_LOCK_AVAILABLE,
ANDROID_CONTROL_AF_AVAILABLE_MODES,
ANDROID_CONTROL_AVAILABLE_EFFECTS,
ANDROID_CONTROL_AVAILABLE_MODES,
ANDROID_CONTROL_AVAILABLE_SCENE_MODES,
ANDROID_CONTROL_AVAILABLE_VIDEO_STABILIZATION_MODES,
ANDROID_CONTROL_AWB_AVAILABLE_MODES,
ANDROID_CONTROL_AWB_LOCK_AVAILABLE,
ANDROID_CONTROL_MAX_REGIONS,
ANDROID_FLASH_INFO_AVAILABLE,
ANDROID_INFO_SUPPORTED_HARDWARE_LEVEL,
ANDROID_JPEG_AVAILABLE_THUMBNAIL_SIZES,
ANDROID_JPEG_MAX_SIZE,
ANDROID_LENS_FACING,
ANDROID_LENS_INFO_AVAILABLE_OPTICAL_STABILIZATION,
ANDROID_LENS_INFO_FOCUS_DISTANCE_CALIBRATION,
ANDROID_LENS_INFO_HYPERFOCAL_DISTANCE,
ANDROID_NOISE_REDUCTION_AVAILABLE_NOISE_REDUCTION_MODES,
ANDROID_REQUEST_AVAILABLE_CAPABILITIES,
ANDROID_REQUEST_MAX_NUM_INPUT_STREAMS,
ANDROID_REQUEST_MAX_NUM_OUTPUT_STREAMS,
ANDROID_REQUEST_PARTIAL_RESULT_COUNT,
ANDROID_REQUEST_PIPELINE_MAX_DEPTH,
ANDROID_SCALER_AVAILABLE_MAX_DIGITAL_ZOOM,
ANDROID_SCALER_AVAILABLE_STREAM_CONFIGURATIONS,
ANDROID_SCALER_CROPPING_TYPE,
ANDROID_SENSOR_AVAILABLE_TEST_PATTERN_MODES,
ANDROID_SENSOR_INFO_ACTIVE_ARRAY_SIZE,
ANDROID_SENSOR_INFO_MAX_FRAME_DURATION,
ANDROID_SENSOR_INFO_PIXEL_ARRAY_SIZE,
ANDROID_SENSOR_INFO_PRE_CORRECTION_ACTIVE_ARRAY_SIZE,
ANDROID_SENSOR_INFO_TIMESTAMP_SOURCE,
ANDROID_SENSOR_ORIENTATION,
ANDROID_SHADING_AVAILABLE_MODES,
ANDROID_STATISTICS_INFO_AVAILABLE_FACE_DETECT_MODES,
ANDROID_STATISTICS_INFO_AVAILABLE_HOT_PIXEL_MAP_MODES,
ANDROID_STATISTICS_INFO_AVAILABLE_LENS_SHADING_MAP_MODES,
ANDROID_STATISTICS_INFO_MAX_FACE_COUNT,
ANDROID_SYNC_MAX_LATENCY,
};
if (is_builtin) {
available_characteristics_keys.insert(
available_characteristics_keys.end(),
{
ANDROID_LENS_INFO_AVAILABLE_APERTURES,
ANDROID_LENS_INFO_AVAILABLE_FOCAL_LENGTHS,
ANDROID_LENS_INFO_MINIMUM_FOCUS_DISTANCE,
ANDROID_SENSOR_INFO_PHYSICAL_SIZE,
});
}
UPDATE(ANDROID_REQUEST_AVAILABLE_CHARACTERISTICS_KEYS,
available_characteristics_keys.data(),
available_characteristics_keys.size());
UPDATE(ANDROID_SENSOR_ORIENTATION, &device_info.sensor_orientation, 1);
uint8_t lens_facing = device_info.lens_facing;
UPDATE(ANDROID_LENS_FACING, &lens_facing, 1);
if (is_builtin) {
uint8_t hardware_level = ANDROID_INFO_SUPPORTED_HARDWARE_LEVEL_LIMITED;
UPDATE(ANDROID_INFO_SUPPORTED_HARDWARE_LEVEL, &hardware_level, 1);
UPDATE(ANDROID_LENS_INFO_AVAILABLE_APERTURES,
device_info.lens_info_available_apertures.data(),
device_info.lens_info_available_apertures.size());
UPDATE(ANDROID_LENS_APERTURE,
&device_info.lens_info_available_apertures.data()[0], 1);
UPDATE(ANDROID_LENS_INFO_AVAILABLE_FOCAL_LENGTHS,
device_info.lens_info_available_focal_lengths.data(),
device_info.lens_info_available_focal_lengths.size());
UPDATE(ANDROID_LENS_FOCAL_LENGTH,
&device_info.lens_info_available_focal_lengths.data()[0], 1);
UPDATE(ANDROID_LENS_INFO_MINIMUM_FOCUS_DISTANCE,
&device_info.lens_info_minimum_focus_distance, 1);
UPDATE(ANDROID_LENS_FOCUS_DISTANCE,
&device_info.lens_info_optimal_focus_distance, 1);
float physical_size[] = {device_info.sensor_info_physical_size_width,
device_info.sensor_info_physical_size_height};
UPDATE(ANDROID_SENSOR_INFO_PHYSICAL_SIZE, physical_size,
ARRAY_SIZE(physical_size));
int32_t pixel_array_size[] = {
device_info.sensor_info_pixel_array_size_width,
device_info.sensor_info_pixel_array_size_height};
UPDATE(ANDROID_SENSOR_INFO_PIXEL_ARRAY_SIZE, pixel_array_size,
ARRAY_SIZE(pixel_array_size));
} else {
uint8_t hardware_level = ANDROID_INFO_SUPPORTED_HARDWARE_LEVEL_EXTERNAL;
UPDATE(ANDROID_INFO_SUPPORTED_HARDWARE_LEVEL, &hardware_level, 1);
}
uint8_t focus_distance_calibration =
ANDROID_LENS_INFO_FOCUS_DISTANCE_CALIBRATION_UNCALIBRATED;
UPDATE(ANDROID_LENS_INFO_FOCUS_DISTANCE_CALIBRATION,
&focus_distance_calibration, 1);
std::vector<uint8_t> ae_antibanding_modes;
uint8_t ae_antibanding_mode;
if (device_info.power_line_frequency == PowerLineFrequency::FREQ_AUTO) {
ae_antibanding_modes.push_back(ANDROID_CONTROL_AE_ANTIBANDING_MODE_AUTO);
ae_antibanding_mode = ANDROID_CONTROL_AE_ANTIBANDING_MODE_AUTO;
} else if (is_external && device_info.power_line_frequency ==
PowerLineFrequency::FREQ_ERROR) {
ae_antibanding_modes.push_back(ANDROID_CONTROL_AE_ANTIBANDING_MODE_OFF);
ae_antibanding_mode = ANDROID_CONTROL_AE_ANTIBANDING_MODE_OFF;
} else {
ae_antibanding_modes.push_back(ANDROID_CONTROL_AE_ANTIBANDING_MODE_50HZ);
ae_antibanding_modes.push_back(ANDROID_CONTROL_AE_ANTIBANDING_MODE_60HZ);
if (device_info.power_line_frequency == PowerLineFrequency::FREQ_50HZ) {
ae_antibanding_mode = ANDROID_CONTROL_AE_ANTIBANDING_MODE_50HZ;
} else if (device_info.power_line_frequency ==
PowerLineFrequency::FREQ_60HZ) {
ae_antibanding_mode = ANDROID_CONTROL_AE_ANTIBANDING_MODE_60HZ;
} else {
LOGF(ERROR) << "Invalid power line frequency setting: "
<< static_cast<int>(device_info.power_line_frequency);
return -EINVAL;
}
}
UPDATE(ANDROID_CONTROL_AE_AVAILABLE_ANTIBANDING_MODES,
ae_antibanding_modes.data(), ae_antibanding_modes.size());
UPDATE(ANDROID_CONTROL_AE_ANTIBANDING_MODE, &ae_antibanding_mode, 1);
return 0;
}
const camera_metadata_t* MetadataHandler::GetDefaultRequestSettings(
int template_type) {
if (!IsValidTemplateType(template_type)) {
LOGF(ERROR) << "Invalid template request type: " << template_type;
return nullptr;
}
return template_settings_[template_type].get();
}
void MetadataHandler::PreHandleRequest(
int frame_number, const android::CameraMetadata& metadata) {
DCHECK(thread_checker_.CalledOnValidThread());
if (metadata.exists(ANDROID_CONTROL_AF_TRIGGER)) {
camera_metadata_ro_entry entry = metadata.find(ANDROID_CONTROL_AF_TRIGGER);
if (entry.data.u8[0] == ANDROID_CONTROL_AF_TRIGGER_START) {
af_trigger_ = true;
} else if (entry.data.u8[0] == ANDROID_CONTROL_AF_TRIGGER_CANCEL) {
af_trigger_ = false;
}
}
current_frame_number_ = frame_number;
}
int MetadataHandler::PostHandleRequest(int frame_number,
int64_t timestamp,
android::CameraMetadata* metadata) {
DCHECK(thread_checker_.CalledOnValidThread());
if (current_frame_number_ != frame_number) {
LOGF(ERROR)
<< "Frame number mismatch in PreHandleRequest and PostHandleRequest";
return -EINVAL;
}
// android.control
// For USB camera, we don't know the AE state. Set the state to converged to
// indicate the frame should be good to use. Then apps don't have to wait the
// AE state.
const uint8_t ae_state = ANDROID_CONTROL_AE_STATE_CONVERGED;
UPDATE(ANDROID_CONTROL_AE_STATE, &ae_state, 1);
const uint8_t ae_lock = ANDROID_CONTROL_AE_LOCK_OFF;
UPDATE(ANDROID_CONTROL_AE_LOCK, &ae_lock, 1);
// For USB camera, the USB camera handles everything and we don't have control
// over AF. We only simply fake the AF metadata based on the request
// received here.
uint8_t af_state;
if (af_trigger_) {
af_state = ANDROID_CONTROL_AF_STATE_FOCUSED_LOCKED;
} else {
af_state = ANDROID_CONTROL_AF_STATE_INACTIVE;
}
UPDATE(ANDROID_CONTROL_AF_STATE, &af_state, 1);
// Set AWB state to converged to indicate the frame should be good to use.
const uint8_t awb_state = ANDROID_CONTROL_AWB_STATE_CONVERGED;
UPDATE(ANDROID_CONTROL_AWB_STATE, &awb_state, 1);
const uint8_t awb_lock = ANDROID_CONTROL_AWB_LOCK_OFF;
UPDATE(ANDROID_CONTROL_AWB_LOCK, &awb_lock, 1);
camera_metadata_entry active_array_size =
metadata->find(ANDROID_SENSOR_INFO_ACTIVE_ARRAY_SIZE);
if (active_array_size.count == 0) {
LOGF(ERROR) << "Active array size is not found.";
return -EINVAL;
}
// android.lens
// Since android.lens.focalLength, android.lens.focusDistance and
// android.lens.aperture are all fixed. And we don't support
// android.lens.filterDensity so we can set the state to stationary.
const uint8_t lens_state = ANDROID_LENS_STATE_STATIONARY;
UPDATE(ANDROID_LENS_STATE, &lens_state, 1);
// android.scaler
const int32_t crop_region[] = {
active_array_size.data.i32[0], active_array_size.data.i32[1],
active_array_size.data.i32[2], active_array_size.data.i32[3],
};
UPDATE(ANDROID_SCALER_CROP_REGION, crop_region, ARRAY_SIZE(crop_region));
// android.sensor
UPDATE(ANDROID_SENSOR_TIMESTAMP, &timestamp, 1);
const int64_t rolling_shutter_skew = 0;
UPDATE(ANDROID_SENSOR_ROLLING_SHUTTER_SKEW, &rolling_shutter_skew, 1);
// android.statistics
const uint8_t lens_shading_map_mode =
ANDROID_STATISTICS_LENS_SHADING_MAP_MODE_OFF;
UPDATE(ANDROID_STATISTICS_LENS_SHADING_MAP_MODE, &lens_shading_map_mode, 1);
const uint8_t scene_flicker = ANDROID_STATISTICS_SCENE_FLICKER_NONE;
UPDATE(ANDROID_STATISTICS_SCENE_FLICKER, &scene_flicker, 1);
return 0;
}
bool MetadataHandler::IsValidTemplateType(int template_type) {
return template_type > 0 && template_type < CAMERA3_TEMPLATE_COUNT;
}
CameraMetadataUniquePtr MetadataHandler::CreateDefaultRequestSettings(
int template_type) {
android::CameraMetadata data(metadata_);
int ret;
switch (template_type) {
case CAMERA3_TEMPLATE_PREVIEW:
ret = FillDefaultPreviewSettings(&data);
break;
case CAMERA3_TEMPLATE_STILL_CAPTURE:
ret = FillDefaultStillCaptureSettings(&data);
break;
case CAMERA3_TEMPLATE_VIDEO_RECORD:
ret = FillDefaultVideoRecordSettings(&data);
break;
case CAMERA3_TEMPLATE_VIDEO_SNAPSHOT:
ret = FillDefaultVideoSnapshotSettings(&data);
break;
case CAMERA3_TEMPLATE_ZERO_SHUTTER_LAG:
ret = FillDefaultZeroShutterLagSettings(&data);
break;
case CAMERA3_TEMPLATE_MANUAL:
ret = FillDefaultManualSettings(&data);
break;
default:
LOGF(ERROR) << "Invalid template request type: " << template_type;
return NULL;
}
if (ret) {
return CameraMetadataUniquePtr();
}
return CameraMetadataUniquePtr(data.release());
}
int MetadataHandler::FillDefaultPreviewSettings(
android::CameraMetadata* metadata) {
// android.control
const uint8_t capture_intent = ANDROID_CONTROL_CAPTURE_INTENT_PREVIEW;
UPDATE(ANDROID_CONTROL_CAPTURE_INTENT, &capture_intent, 1);
const uint8_t control_mode = ANDROID_CONTROL_MODE_AUTO;
UPDATE(ANDROID_CONTROL_MODE, &control_mode, 1);
return 0;
}
int MetadataHandler::FillDefaultStillCaptureSettings(
android::CameraMetadata* metadata) {
// android.colorCorrection
const uint8_t color_aberration_mode =
ANDROID_COLOR_CORRECTION_ABERRATION_MODE_HIGH_QUALITY;
UPDATE(ANDROID_COLOR_CORRECTION_ABERRATION_MODE, &color_aberration_mode, 1);
// android.control
const uint8_t capture_intent = ANDROID_CONTROL_CAPTURE_INTENT_STILL_CAPTURE;
UPDATE(ANDROID_CONTROL_CAPTURE_INTENT, &capture_intent, 1);
const uint8_t control_mode = ANDROID_CONTROL_MODE_AUTO;
UPDATE(ANDROID_CONTROL_MODE, &control_mode, 1);
return 0;
}
int MetadataHandler::FillDefaultVideoRecordSettings(
android::CameraMetadata* metadata) {
// android.control
const uint8_t capture_intent = ANDROID_CONTROL_CAPTURE_INTENT_VIDEO_RECORD;
UPDATE(ANDROID_CONTROL_CAPTURE_INTENT, &capture_intent, 1);
const uint8_t control_mode = ANDROID_CONTROL_MODE_AUTO;
UPDATE(ANDROID_CONTROL_MODE, &control_mode, 1);
return 0;
}
int MetadataHandler::FillDefaultVideoSnapshotSettings(
android::CameraMetadata* metadata) {
// android.control
const uint8_t capture_intent = ANDROID_CONTROL_CAPTURE_INTENT_VIDEO_SNAPSHOT;
UPDATE(ANDROID_CONTROL_CAPTURE_INTENT, &capture_intent, 1);
const uint8_t control_mode = ANDROID_CONTROL_MODE_AUTO;
UPDATE(ANDROID_CONTROL_MODE, &control_mode, 1);
return 0;
}
int MetadataHandler::FillDefaultZeroShutterLagSettings(
android::CameraMetadata* /*metadata*/) {
// Do not support ZSL template.
return -EINVAL;
}
int MetadataHandler::FillDefaultManualSettings(
android::CameraMetadata* /*metadata*/) {
// Do not support manual template.
return -EINVAL;
}
} // namespace cros