Plug in metadata refactor.
Replaces metadata usage in Camera/V4L2Camera with the
new Metadata class.
Switches Camera from camera_metadata_t to android::CameraMetadata
where appropriate for ease of use/clarity of ownership.
Also cleaned up some "error" logs that were potentially expected,
leaving it to the caller to log if something goes wrong, since
they were numerous and cluttering the log feed.
BUG: https://b/30140438, https://b/29335262
TEST: unit tests pass, test picture program still works,
tested setting a V4L2 control to a non-default value.
Change-Id: I24e50c9b71736dfc576debf8d09dbe36b9bbf23a
diff --git a/modules/camera/3_4/v4l2_camera.cpp b/modules/camera/3_4/v4l2_camera.cpp
index 87a7a31..9ebefeb 100644
--- a/modules/camera/3_4/v4l2_camera.cpp
+++ b/modules/camera/3_4/v4l2_camera.cpp
@@ -25,11 +25,11 @@
#include <camera/CameraMetadata.h>
#include <hardware/camera3.h>
-#include <nativehelper/ScopedFd.h>
#include "common.h"
+#include "metadata/metadata_common.h"
#include "stream_format.h"
-#include "v4l2_gralloc.h"
+#include "v4l2_metadata_factory.h"
#define ARRAY_SIZE(a) (sizeof(a) / sizeof(*(a)))
@@ -57,14 +57,23 @@
return nullptr;
}
- return new V4L2Camera(id, std::move(v4l2_wrapper));
+ std::unique_ptr<Metadata> metadata;
+ int res = GetV4L2Metadata(v4l2_wrapper, &metadata);
+ if (res) {
+ HAL_LOGE("Failed to initialize V4L2 metadata: %d", res);
+ return nullptr;
+ }
+
+ return new V4L2Camera(id, std::move(v4l2_wrapper), std::move(metadata));
}
-V4L2Camera::V4L2Camera(int id, std::shared_ptr<V4L2Wrapper> v4l2_wrapper)
+V4L2Camera::V4L2Camera(int id, std::shared_ptr<V4L2Wrapper> v4l2_wrapper,
+ std::unique_ptr<Metadata> metadata)
: default_camera_hal::Camera(id),
- mV4L2Device(std::move(v4l2_wrapper)),
- mTemplatesInitialized(false),
- mCharacteristicsInitialized(false) {
+ device_(std::move(v4l2_wrapper)),
+ metadata_(std::move(metadata)),
+ max_input_streams_(0),
+ max_output_streams_({{0, 0, 0}}) {
HAL_LOG_ENTER();
}
@@ -75,19 +84,19 @@
int V4L2Camera::connect() {
HAL_LOG_ENTER();
- if (mConnection) {
+ if (connection_) {
HAL_LOGE("Already connected. Please disconnect and try again.");
return -EIO;
}
- mConnection.reset(new V4L2Wrapper::Connection(mV4L2Device));
- if (mConnection->status()) {
+ connection_.reset(new V4L2Wrapper::Connection(device_));
+ if (connection_->status()) {
HAL_LOGE("Failed to connect to device.");
- return mConnection->status();
+ return connection_->status();
}
// TODO(b/29185945): confirm this is a supported device.
- // This is checked by the HAL, but the device at mDevicePath may
+ // This is checked by the HAL, but the device at |device_|'s path may
// not be the same one that was there when the HAL was loaded.
// (Alternatively, better hotplugging support may make this unecessary
// by disabling cameras that get disconnected and checking newly connected
@@ -101,603 +110,49 @@
void V4L2Camera::disconnect() {
HAL_LOG_ENTER();
- mConnection.reset();
+ connection_.reset();
// TODO(b/29158098): Inform service of any flashes that are available again
// because this camera is no longer in use.
}
-int V4L2Camera::initStaticInfo(camera_metadata_t** out) {
+int V4L2Camera::initStaticInfo(android::CameraMetadata* out) {
HAL_LOG_ENTER();
- android::status_t res;
- // Device characteristics need to be queried prior
- // to static info setup.
- if (!mCharacteristicsInitialized) {
- res = initCharacteristics();
- if (res) {
- return res;
- }
- }
-
- android::CameraMetadata info;
-
- // Static metadata characteristics from /system/media/camera/docs/docs.html.
-
- /* android.colorCorrection. */
-
- // No easy way to turn chromatic aberration correction OFF in v4l2,
- // though this may be supportable via a collection of other user controls.
- uint8_t avail_aberration_modes[] = {
- ANDROID_COLOR_CORRECTION_ABERRATION_MODE_FAST,
- ANDROID_COLOR_CORRECTION_ABERRATION_MODE_HIGH_QUALITY};
- res = info.update(ANDROID_COLOR_CORRECTION_AVAILABLE_ABERRATION_MODES,
- avail_aberration_modes, ARRAY_SIZE(avail_aberration_modes));
- if (res != android::OK) {
+ int res = metadata_->FillStaticMetadata(out);
+ if (res) {
+ HAL_LOGE("Failed to get static metadata.");
return res;
}
- /* android.control. */
-
- /* 3As */
-
- res = info.update(ANDROID_CONTROL_AE_AVAILABLE_ANTIBANDING_MODES,
- mAeAntibandingModes.data(), mAeAntibandingModes.size());
- if (res != android::OK) {
+ // Extract max streams for use in verifying stream configs.
+ res = SingleTagValue(*out, ANDROID_REQUEST_MAX_NUM_INPUT_STREAMS,
+ &max_input_streams_);
+ if (res) {
+ HAL_LOGE("Failed to get max num input streams from static metadata.");
+ return res;
+ }
+ res = SingleTagValue(*out, ANDROID_REQUEST_MAX_NUM_OUTPUT_STREAMS,
+ &max_output_streams_);
+ if (res) {
+ HAL_LOGE("Failed to get max num output streams from static metadata.");
return res;
}
- res = info.update(ANDROID_CONTROL_AE_AVAILABLE_MODES,
- mAeModes.data(), mAeModes.size());
- if (res != android::OK) {
- return res;
- }
-
- // Flatten mFpsRanges.
- res = info.update(ANDROID_CONTROL_AE_AVAILABLE_TARGET_FPS_RANGES,
- mFpsRanges.data(), mFpsRanges.total_num_elements());
- if (res != android::OK) {
- return res;
- }
-
- res = info.update(ANDROID_CONTROL_AE_COMPENSATION_RANGE,
- mAeCompensationRange.data(), mAeCompensationRange.size());
- if (res != android::OK) {
- return res;
- }
-
- res = info.update(ANDROID_CONTROL_AE_COMPENSATION_STEP,
- &mAeCompensationStep, 1);
- if (res != android::OK) {
- return res;
- }
-
- res = info.update(ANDROID_CONTROL_AF_AVAILABLE_MODES,
- mAfModes.data(), mAfModes.size());
- if (res != android::OK) {
- return res;
- }
-
- res = info.update(ANDROID_CONTROL_AWB_AVAILABLE_MODES,
- mAwbModes.data(), mAwbModes.size());
- if (res != android::OK) {
- return res;
- }
-
- // Couldn't find any V4L2 support for regions, though maybe it's out there.
- int32_t max_regions[] = {/*AE*/ 0,/*AWB*/ 0,/*AF*/ 0};
- res = info.update(ANDROID_CONTROL_MAX_REGIONS,
- max_regions, ARRAY_SIZE(max_regions));
- if (res != android::OK) {
- return res;
- }
-
- res = info.update(ANDROID_CONTROL_AE_LOCK_AVAILABLE,
- &mAeLockAvailable, 1);
- if (res != android::OK) {
- return res;
- }
- res = info.update(ANDROID_CONTROL_AWB_LOCK_AVAILABLE,
- &mAwbLockAvailable, 1);
- if (res != android::OK) {
- return res;
- }
-
- /* Scene modes. */
-
- res = info.update(ANDROID_CONTROL_AVAILABLE_SCENE_MODES,
- mSceneModes.data(), mSceneModes.size());
- if (res != android::OK) {
- return res;
- }
-
- // A 3-tuple of AE, AWB, AF overrides for each scene mode.
- // Ignored for DISABLED, FACE_PRIORITY and FACE_PRIORITY_LOW_LIGHT.
- uint8_t scene_mode_overrides[] = {
- /*SCENE_MODE_DISABLED*/ /*AE*/0, /*AW*/0, /*AF*/0};
- res = info.update(ANDROID_CONTROL_SCENE_MODE_OVERRIDES,
- scene_mode_overrides, ARRAY_SIZE(scene_mode_overrides));
- if (res != android::OK) {
- return res;
- }
-
- /* Top level 3A/Scenes switch. */
-
- res = info.update(ANDROID_CONTROL_AVAILABLE_MODES,
- mControlModes.data(), mControlModes.size());
- if (res != android::OK) {
- return res;
- }
-
- /* Other android.control configuration. */
-
- res = info.update(ANDROID_CONTROL_AVAILABLE_VIDEO_STABILIZATION_MODES,
- mVideoStabilizationModes.data(),
- mVideoStabilizationModes.size());
- if (res != android::OK) {
- return res;
- }
-
- res = info.update(ANDROID_CONTROL_AVAILABLE_EFFECTS,
- mEffects.data(), mEffects.size());
- if (res != android::OK) {
- return res;
- }
-
- // AVAILABLE_HIGH_SPEED_VIDEO_CONFIGURATIONS only necessary
- // for devices supporting CONSTRAINED_HIGH_SPEED_VIDEO,
- // which this HAL doesn't support.
-
- // POST_RAW_SENSITIVITY_BOOST_RANGE only necessary
- // for devices supporting RAW format outputs.
-
- /* android.edge. */
-
- // Not sure if V4L2 does or doesn't do this, but HAL documentation says
- // all devices must support FAST, and FAST can be equivalent to OFF, so
- // either way it's fine to list.
- uint8_t avail_edge_modes[] = {
- ANDROID_EDGE_MODE_FAST};
- res = info.update(ANDROID_EDGE_AVAILABLE_EDGE_MODES,
- avail_edge_modes, ARRAY_SIZE(avail_edge_modes));
- if (res != android::OK) {
- return res;
- }
-
- /* android.flash. */
-
- res = info.update(ANDROID_FLASH_INFO_AVAILABLE,
- &mFlashAvailable, 1);
- if (res != android::OK) {
- return res;
- }
-
- // info.chargeDuration, color.Temperature, maxEnergy marked FUTURE.
-
- /* android.hotPixel. */
-
- // No known V4L2 hot pixel correction. But it might be happening,
- // so we report FAST/HIGH_QUALITY.
- uint8_t avail_hot_pixel_modes[] = {
- ANDROID_HOT_PIXEL_MODE_FAST,
- ANDROID_HOT_PIXEL_MODE_HIGH_QUALITY};
- res = info.update(ANDROID_HOT_PIXEL_AVAILABLE_HOT_PIXEL_MODES,
- avail_hot_pixel_modes, ARRAY_SIZE(avail_hot_pixel_modes));
- if (res != android::OK) {
- return res;
- }
-
- /* android.jpeg. */
-
- // For now, no thumbnails available (only [0,0], the "no thumbnail" size).
- // TODO(b/29580107): Could end up with a mismatch between request & result,
- // since V4L2 doesn't actually allow for thumbnail size control.
- int32_t thumbnail_sizes[] = {
- 0, 0};
- res = info.update(ANDROID_JPEG_AVAILABLE_THUMBNAIL_SIZES,
- thumbnail_sizes, ARRAY_SIZE(thumbnail_sizes));
- if (res != android::OK) {
- return res;
- }
-
- // V4L2 can query this with VIDIOC_TRY_FMT (or VIDIOC_S_FMT if TRY
- // isn't supported), reading the fmt.pix.sizeimage for the largest
- // jpeg size. For now use a constant (defined in V4L2Gralloc.h).
- int32_t max_jpeg_size = V4L2_MAX_JPEG_SIZE;
- res = info.update(ANDROID_JPEG_MAX_SIZE,
- &max_jpeg_size, 1);
- if (res != android::OK) {
- return res;
- }
-
- /* android.lens. */
-
- /* Misc. lens control. */
-
- res = info.update(ANDROID_LENS_INFO_AVAILABLE_APERTURES,
- &mAperture, 1);
- if (res != android::OK) {
- return res;
- }
-
- res = info.update(ANDROID_LENS_INFO_AVAILABLE_FILTER_DENSITIES,
- &mFilterDensity, 1);
- if (res != android::OK) {
- return res;
- }
-
- res = info.update(ANDROID_LENS_INFO_AVAILABLE_OPTICAL_STABILIZATION,
- mOpticalStabilizationModes.data(),
- mOpticalStabilizationModes.size());
- if (res != android::OK) {
- return res;
- }
-
- // lens.info.shadingMapSize not required for non-full devices.
-
- // All V4L2 devices are considered to be external facing.
- uint8_t facing = ANDROID_LENS_FACING_EXTERNAL;
- res = info.update(ANDROID_LENS_FACING, &facing, 1);
- if (res != android::OK) {
- return res;
- }
-
- /* Zoom/Focus. */
-
- // No way to actually get the focal length in V4L2, but it's a required key,
- // so we just fake it.
- res = info.update(ANDROID_LENS_INFO_AVAILABLE_FOCAL_LENGTHS,
- &mFocalLength, 1);
- if (res != android::OK) {
- return res;
- }
-
- // V4L2 focal units do not correspond to a particular physical unit.
- uint8_t focus_calibration =
- ANDROID_LENS_INFO_FOCUS_DISTANCE_CALIBRATION_UNCALIBRATED;
- res = info.update(ANDROID_LENS_INFO_FOCUS_DISTANCE_CALIBRATION,
- &focus_calibration, 1);
- if (res != android::OK) {
- return res;
- }
-
- // info.hyperfocalDistance not required for UNCALIBRATED.
-
- res = info.update(ANDROID_LENS_INFO_MINIMUM_FOCUS_DISTANCE,
- &mFocusDistance, 1);
- if (res != android::OK) {
- return res;
- }
-
- /* Depth. */
-
- // DEPTH capability not supported by this HAL. Not implemented:
- // poseRotation
- // poseTranslation
- // intrinsicCalibration
- // radialDistortion
-
- /* anroid.noise. */
-
- // Unable to control noise reduction in V4L2 devices,
- // but FAST is allowed to be the same as OFF.
- uint8_t avail_noise_reduction_modes[] = {ANDROID_NOISE_REDUCTION_MODE_FAST};
- res = info.update(ANDROID_NOISE_REDUCTION_AVAILABLE_NOISE_REDUCTION_MODES,
- avail_noise_reduction_modes,
- ARRAY_SIZE(avail_noise_reduction_modes));
- if (res != android::OK) {
- return res;
- }
-
- /* android.request. */
-
- int32_t max_num_output_streams[] = {mMaxRawOutputStreams,
- mMaxNonStallingOutputStreams,
- mMaxStallingOutputStreams};
- res = info.update(ANDROID_REQUEST_MAX_NUM_OUTPUT_STREAMS,
- max_num_output_streams, ARRAY_SIZE(max_num_output_streams));
- if (res != android::OK) {
- return res;
- }
-
- res = info.update(ANDROID_REQUEST_MAX_NUM_INPUT_STREAMS,
- &mMaxInputStreams, 1);
- if (res != android::OK) {
- return res;
- }
-
- // No way to know for V4L2, so fake with max allowable latency.
- // Doesn't mean much without per-frame controls.
- uint8_t pipeline_max_depth = 4;
- res = info.update(ANDROID_REQUEST_PIPELINE_MAX_DEPTH,
- &pipeline_max_depth, 1);
- if (res != android::OK) {
- return res;
- }
-
- // Partial results not supported; partialResultCount defaults to 1.
-
- // Available capabilities & keys queried at very end of this method.
-
- /* android.scaler. */
-
- /* Cropping. */
-
- res = info.update(ANDROID_SCALER_AVAILABLE_MAX_DIGITAL_ZOOM,
- &mMaxZoom, 1);
- if (res != android::OK) {
- return res;
- }
-
- res = info.update(ANDROID_SCALER_CROPPING_TYPE, &mCropType, 1);
- if (res != android::OK) {
- return res;
- }
-
- /* Streams. */
-
- // availableInputOutputFormatsMap only required for reprocessing capability.
-
- // Flatten mStreamConfigs.
- res = info.update(ANDROID_SCALER_AVAILABLE_STREAM_CONFIGURATIONS,
- mStreamConfigs.data(),
- mStreamConfigs.total_num_elements());
- if (res != android::OK) {
- return res;
- }
-
- // Flatten mMinFrameDurations.
- res = info.update(ANDROID_SCALER_AVAILABLE_MIN_FRAME_DURATIONS,
- mMinFrameDurations.data(),
- mMinFrameDurations.total_num_elements());
- if (res != android::OK) {
- return res;
- }
-
- // Flatten mStallDurations.
- res = info.update(ANDROID_SCALER_AVAILABLE_STALL_DURATIONS,
- mStallDurations.data(),
- mStallDurations.total_num_elements());
- if (res != android::OK) {
- return res;
- }
-
- /* android.sensor. */
-
- /* Sizes. */
-
- res = info.update(ANDROID_SENSOR_INFO_PIXEL_ARRAY_SIZE,
- mPixelArraySize.data(), mPixelArraySize.size());
- if (res != android::OK) {
- return res;
- }
- // No V4L2 way to differentiate active vs. inactive parts of the rectangle.
- res = info.update(ANDROID_SENSOR_INFO_ACTIVE_ARRAY_SIZE,
- mPixelArraySize.data(), mPixelArraySize.size());
- if (res != android::OK) {
- return res;
- }
-
- res = info.update(ANDROID_SENSOR_INFO_PHYSICAL_SIZE,
- mPhysicalSize.data(), mPhysicalSize.size());
- if (res != android::OK) {
- return res;
- }
-
- /* Misc sensor information. */
-
- res = info.update(ANDROID_SENSOR_INFO_MAX_FRAME_DURATION,
- &mMaxFrameDuration, 1);
- if (res != android::OK) {
- return res;
- }
-
- // HAL uses BOOTTIME timestamps.
- // TODO(b/29457051): make sure timestamps are consistent throughout the HAL.
- uint8_t timestamp_source = ANDROID_SENSOR_INFO_TIMESTAMP_SOURCE_UNKNOWN;
- res = info.update(ANDROID_SENSOR_INFO_TIMESTAMP_SOURCE,
- ×tamp_source, 1);
- if (res != android::OK) {
- return res;
- }
-
- // As in initDeviceInfo, no way to actually get orientation.
- res = info.update(ANDROID_SENSOR_ORIENTATION, &mOrientation, 1);
- if (res != android::OK) {
- return res;
- }
-
- // availableTestPatternModes just defaults to OFF, which is fine.
-
- // info.exposureTimeRange, info.sensitivityRange:
- // exposure/sensitivity manual control not supported.
- // Could query V4L2_CID_ISO_SENSITIVITY to support sensitivity if desired.
-
- // info.whiteLevel, info.lensShadingApplied,
- // info.preCorrectionPixelArraySize, referenceIlluminant1/2,
- // calibrationTransform1/2, colorTransform1/2, forwardMatrix1/2,
- // blackLevelPattern, profileHueSatMapDimensions
- // all only necessary for RAW.
-
- // baseGainFactor marked FUTURE.
-
- // maxAnalogSensitivity optional for LIMITED device.
-
- // opticalBlackRegions: No known way to get in V4L2, but not necessary.
-
- // opaqueRawSize not necessary since RAW_OPAQUE format not supported.
-
- /* android.shading */
-
- // No known V4L2 lens shading. But it might be happening,
- // so we report FAST/HIGH_QUALITY.
- uint8_t avail_shading_modes[] = {
- ANDROID_SHADING_MODE_FAST,
- ANDROID_SHADING_MODE_HIGH_QUALITY};
- res = info.update(ANDROID_SHADING_AVAILABLE_MODES,
- avail_shading_modes, ARRAY_SIZE(avail_shading_modes));
- if (res != android::OK) {
- return res;
- }
-
- /* android.statistics */
-
- // Face detection not supported.
- uint8_t avail_face_detect_modes[] = {
- ANDROID_STATISTICS_FACE_DETECT_MODE_OFF};
- res = info.update(ANDROID_STATISTICS_INFO_AVAILABLE_FACE_DETECT_MODES,
- avail_face_detect_modes,
- ARRAY_SIZE(avail_face_detect_modes));
- if (res != android::OK) {
- return res;
- }
-
- int32_t max_face_count = 0;
- res = info.update(ANDROID_STATISTICS_INFO_MAX_FACE_COUNT,
- &max_face_count, 1);
- if (res != android::OK) {
- return res;
- }
-
- // info.histogramBucketCount, info.maxHistogramCount,
- // info.maxSharpnessMapValue, info.sharpnessMapSizemarked FUTURE.
-
- // ON only needs to be supported for RAW capable devices.
- uint8_t avail_hot_pixel_map_modes[] = {
- ANDROID_STATISTICS_HOT_PIXEL_MAP_MODE_OFF};
- res = info.update(ANDROID_STATISTICS_INFO_AVAILABLE_HOT_PIXEL_MAP_MODES,
- avail_hot_pixel_map_modes,
- ARRAY_SIZE(avail_hot_pixel_map_modes));
- if (res != android::OK) {
- return res;
- }
-
- // ON only needs to be supported for RAW capable devices.
- uint8_t avail_lens_shading_map_modes[] = {
- ANDROID_STATISTICS_LENS_SHADING_MAP_MODE_OFF};
- res = info.update(ANDROID_STATISTICS_INFO_AVAILABLE_LENS_SHADING_MAP_MODES,
- avail_lens_shading_map_modes,
- ARRAY_SIZE(avail_lens_shading_map_modes));
- if (res != android::OK) {
- return res;
- }
-
- /* android.tonemap. */
-
- // tonemapping only required for MANUAL_POST_PROCESSING capability.
-
- /* android.led. */
-
- // May or may not have LEDs available.
- if (!mLeds.empty()) {
- res = info.update(ANDROID_LED_AVAILABLE_LEDS, mLeds.data(), mLeds.size());
- if (res != android::OK) {
- return res;
- }
- }
-
- /* android.sync. */
-
- // "LIMITED devices are strongly encouraged to use a non-negative value.
- // If UNKNOWN is used here then app developers do not have a way to know
- // when sensor settings have been applied." - Unfortunately, V4L2 doesn't
- // really help here either. Could even be that adjusting settings mid-stream
- // blocks in V4L2, and should be avoided.
- int32_t max_latency = ANDROID_SYNC_MAX_LATENCY_UNKNOWN;
- res = info.update(ANDROID_SYNC_MAX_LATENCY,
- &max_latency, 1);
- if (res != android::OK) {
- return res;
- }
-
- /* android.reprocess. */
-
- // REPROCESSING not supported by this HAL.
-
- /* android.depth. */
-
- // DEPTH not supported by this HAL.
-
- /* Capabilities and android.info. */
-
- uint8_t hw_level = ANDROID_INFO_SUPPORTED_HARDWARE_LEVEL_LIMITED;
- res = info.update(ANDROID_INFO_SUPPORTED_HARDWARE_LEVEL,
- &hw_level, 1);
- if (res != android::OK) {
- return res;
- }
-
- uint8_t capabilities[] = {
- ANDROID_REQUEST_AVAILABLE_CAPABILITIES_BACKWARD_COMPATIBLE};
- res = info.update(ANDROID_REQUEST_AVAILABLE_CAPABILITIES,
- capabilities, ARRAY_SIZE(capabilities));
- if (res != android::OK) {
- return res;
- }
-
- // Scan a default request template for included request keys.
- if (!mTemplatesInitialized) {
- res = initTemplates();
- if (res) {
- return res;
- }
- }
- const camera_metadata_t* preview_request = nullptr;
- // Search templates from the beginning for a supported one.
- for (uint8_t template_id = 1; template_id < CAMERA3_TEMPLATE_COUNT;
- ++template_id) {
- preview_request = constructDefaultRequestSettings(template_id);
- if (preview_request != nullptr) {
- break;
- }
- }
- if (preview_request == nullptr) {
- HAL_LOGE("No valid templates, can't get request keys.");
- return -ENODEV;
- }
- std::vector<int32_t> avail_request_keys = getMetadataKeys(preview_request);
- res = info.update(ANDROID_REQUEST_AVAILABLE_REQUEST_KEYS,
- avail_request_keys.data(), avail_request_keys.size());
- if (res != android::OK) {
- return res;
- }
-
- // Result keys will be duplicated from the request, plus a few extras.
- // TODO(b/30035628): additonal available result keys.
- std::vector<int32_t> avail_result_keys(avail_request_keys);
- res = info.update(ANDROID_REQUEST_AVAILABLE_RESULT_KEYS,
- avail_result_keys.data(), avail_result_keys.size());
- if (res != android::OK) {
- return res;
- }
-
- // Last thing, once all the available characteristics have been added.
- const camera_metadata_t* static_characteristics = info.getAndLock();
- std::vector<int32_t> avail_characteristics_keys =
- getMetadataKeys(static_characteristics);
- res = info.unlock(static_characteristics);
- if (res != android::OK) {
- return res;
- }
- avail_characteristics_keys.push_back(
- ANDROID_REQUEST_AVAILABLE_CHARACTERISTICS_KEYS);
- res = info.update(ANDROID_REQUEST_AVAILABLE_CHARACTERISTICS_KEYS,
- avail_characteristics_keys.data(),
- avail_characteristics_keys.size());
- if (res != android::OK) {
- return res;
- }
-
- *out = info.release();
return 0;
}
+int V4L2Camera::initTemplate(int type, android::CameraMetadata* out) {
+ HAL_LOG_ENTER();
+
+ return metadata_->GetRequestTemplate(type, out);
+}
+
void V4L2Camera::initDeviceInfo(camera_info_t* info) {
HAL_LOG_ENTER();
+ // TODO(b/31044975): move this into device interface.
// For now, just constants.
- info->facing = CAMERA_FACING_EXTERNAL;
- info->orientation = mOrientation;
info->resource_cost = 100;
info->conflicting_devices = nullptr;
info->conflicting_devices_length = 0;
@@ -705,22 +160,14 @@
int V4L2Camera::initDevice() {
HAL_LOG_ENTER();
-
- // Templates should be set up if they haven't already been.
- if (!mTemplatesInitialized) {
- int res = initTemplates();
- if (res) {
- return res;
- }
- }
-
+ // Nothing to do.
return 0;
}
int V4L2Camera::enqueueBuffer(const camera3_stream_buffer_t* camera_buffer) {
HAL_LOG_ENTER();
- int res = mV4L2Device->EnqueueBuffer(camera_buffer);
+ int res = device_->EnqueueBuffer(camera_buffer);
if (res) {
HAL_LOGE("Device failed to enqueue buffer.");
return res;
@@ -730,7 +177,7 @@
// TODO(b/29334616): Lock around stream on/off access, only start stream
// if not already on. (For now, since it's synchronous, it will always be
// turned off before another call to this function).
- res = mV4L2Device->StreamOn();
+ res = device_->StreamOn();
if (res) {
HAL_LOGE("Device failed to turn on stream.");
return res;
@@ -741,7 +188,7 @@
// Dequeue the buffer.
v4l2_buffer result_buffer;
- res = mV4L2Device->DequeueBuffer(&result_buffer);
+ res = device_->DequeueBuffer(&result_buffer);
if (res) {
HAL_LOGE("Device failed to dequeue buffer.");
return res;
@@ -751,7 +198,7 @@
// TODO(b/29334616): Lock around stream on/off access, only stop stream if
// buffer queue is empty (synchronously, there's only ever 1 buffer in the
// queue at a time, so this is safe).
- res = mV4L2Device->StreamOff();
+ res = device_->StreamOff();
if (res) {
HAL_LOGE("Device failed to turn off stream.");
return res;
@@ -760,489 +207,26 @@
return 0;
}
-int V4L2Camera::getResultSettings(camera_metadata** metadata,
+int V4L2Camera::getResultSettings(android::CameraMetadata* metadata,
uint64_t* timestamp) {
HAL_LOG_ENTER();
- int res = 0;
- android::CameraMetadata frame_metadata(*metadata);
-
- // TODO(b/30035628): fill in.
- // For now just spoof the timestamp to a non-0 value and send it back.
- int64_t frame_time = 1;
- res = frame_metadata.update(ANDROID_SENSOR_TIMESTAMP, &frame_time, 1);
- if (res != android::OK) {
+ // Get the results.
+ int res = metadata_->FillResultMetadata(metadata);
+ if (res) {
+ HAL_LOGE("Failed to fill result metadata.");
return res;
}
- *metadata = frame_metadata.release();
- *timestamp = frame_time;
-
- return 0;
-}
-
-int V4L2Camera::initTemplates() {
- HAL_LOG_ENTER();
- int res = 0;
-
- // Device characteristics need to be queried prior
- // to template setup.
- if (!mCharacteristicsInitialized) {
- res = initCharacteristics();
- if (res) {
- return res;
- }
- }
-
- // Note: static metadata expects all templates/requests
- // to provide values for all supported keys.
-
- android::CameraMetadata base_metadata;
-
- // Start with defaults for all templates.
-
- /* android.colorCorrection. */
-
- uint8_t aberration_mode = ANDROID_COLOR_CORRECTION_ABERRATION_MODE_FAST;
- res = base_metadata.update(ANDROID_COLOR_CORRECTION_ABERRATION_MODE,
- &aberration_mode, 1);
- if (res != android::OK) {
+ // Extract the timestamp.
+ int64_t frame_time = 0;
+ res = SingleTagValue(*metadata, ANDROID_SENSOR_TIMESTAMP, &frame_time);
+ if (res) {
+ HAL_LOGE("Failed to extract timestamp from result metadata");
return res;
}
-
- uint8_t color_correction_mode = ANDROID_COLOR_CORRECTION_MODE_FAST;
- res = base_metadata.update(ANDROID_COLOR_CORRECTION_MODE,
- &color_correction_mode, 1);
- if (res != android::OK) {
- return res;
- }
-
- // transform and gains are for the unsupported MANUAL_POST_PROCESSING only.
-
- /* android.control. */
-
- /* AE. */
- uint8_t ae_antibanding_mode = ANDROID_CONTROL_AE_ANTIBANDING_MODE_AUTO;
- res = base_metadata.update(ANDROID_CONTROL_AE_ANTIBANDING_MODE,
- &ae_antibanding_mode, 1);
- if (res != android::OK) {
- return res;
- }
-
- // Only matters if AE_MODE = OFF
- int32_t ae_exposure_compensation = 0;
- res = base_metadata.update(ANDROID_CONTROL_AE_EXPOSURE_COMPENSATION,
- &ae_exposure_compensation, 1);
- if (res != android::OK) {
- return res;
- }
-
- uint8_t ae_lock = ANDROID_CONTROL_AE_LOCK_OFF;
- res = base_metadata.update(ANDROID_CONTROL_AE_LOCK, &ae_lock, 1);
- if (res != android::OK) {
- return res;
- }
-
- uint8_t ae_mode = ANDROID_CONTROL_AE_MODE_ON;
- res = base_metadata.update(ANDROID_CONTROL_AE_MODE, &ae_mode, 1);
- if (res != android::OK) {
- return res;
- }
-
- // AE regions not supported.
-
- // FPS set per-template.
-
- uint8_t ae_precapture_trigger = ANDROID_CONTROL_AE_PRECAPTURE_TRIGGER_IDLE;
- res = base_metadata.update(ANDROID_CONTROL_AE_PRECAPTURE_TRIGGER,
- &ae_precapture_trigger, 1);
- if (res != android::OK) {
- return res;
- }
-
- /* AF. */
-
- // AF mode set per-template.
-
- // AF regions not supported.
-
- uint8_t af_trigger = ANDROID_CONTROL_AF_TRIGGER_IDLE;
- res = base_metadata.update(ANDROID_CONTROL_AF_TRIGGER, &af_trigger, 1);
- if (res != android::OK) {
- return res;
- }
-
- /* AWB. */
-
- // Priority: auto > off > Whatever is available.
- uint8_t default_awb_mode = mAwbModes[0];
- if (std::count(mAwbModes.begin(), mAwbModes.end(),
- ANDROID_CONTROL_AWB_MODE_AUTO)) {
- default_awb_mode = ANDROID_CONTROL_AWB_MODE_AUTO;
- } else if (std::count(mAwbModes.begin(), mAwbModes.end(),
- ANDROID_CONTROL_AWB_MODE_OFF)) {
- default_awb_mode = ANDROID_CONTROL_AWB_MODE_OFF;
- }
- res = base_metadata.update(ANDROID_CONTROL_AWB_MODE, &default_awb_mode, 1);
- if (res != android::OK) {
- return res;
- }
-
- // AWB regions not supported.
-
- /* Other controls. */
-
- uint8_t effect_mode = ANDROID_CONTROL_EFFECT_MODE_OFF;
- res = base_metadata.update(ANDROID_CONTROL_EFFECT_MODE, &effect_mode, 1);
- if (res != android::OK) {
- return res;
- }
-
- uint8_t control_mode = ANDROID_CONTROL_MODE_AUTO;
- res = base_metadata.update(ANDROID_CONTROL_MODE, &control_mode, 1);
- if (res != android::OK) {
- return res;
- }
-
- uint8_t scene_mode = ANDROID_CONTROL_SCENE_MODE_DISABLED;
- res = base_metadata.update(ANDROID_CONTROL_SCENE_MODE,
- &scene_mode, 1);
- if (res != android::OK) {
- return res;
- }
-
- uint8_t video_stabilization = ANDROID_CONTROL_VIDEO_STABILIZATION_MODE_OFF;
- res = base_metadata.update(ANDROID_CONTROL_VIDEO_STABILIZATION_MODE,
- &video_stabilization, 1);
- if (res != android::OK) {
- return res;
- }
-
- // postRawSensitivityBoost: RAW not supported, leave null.
-
- /* android.demosaic. */
-
- // mode marked FUTURE.
-
- /* android.edge. */
-
- uint8_t edge_mode = ANDROID_EDGE_MODE_FAST;
- res = base_metadata.update(ANDROID_EDGE_MODE, &edge_mode, 1);
- if (res != android::OK) {
- return res;
- }
-
- // strength marked FUTURE.
-
- /* android.flash. */
-
- // firingPower, firingTime marked FUTURE.
-
- uint8_t flash_mode = ANDROID_FLASH_MODE_OFF;
- res = base_metadata.update(ANDROID_FLASH_MODE, &flash_mode, 1);
- if (res != android::OK) {
- return res;
- }
-
- /* android.hotPixel. */
-
- uint8_t hp_mode = ANDROID_HOT_PIXEL_MODE_FAST;
- res = base_metadata.update(ANDROID_HOT_PIXEL_MODE, &hp_mode, 1);
- if (res != android::OK) {
- return res;
- }
-
- /* android.jpeg. */
-
- double gps_coords[] = {/*latitude*/0, /*longitude*/0, /*altitude*/0};
- res = base_metadata.update(ANDROID_JPEG_GPS_COORDINATES, gps_coords, 3);
- if (res != android::OK) {
- return res;
- }
-
- uint8_t gps_processing_method[] = "none";
- res = base_metadata.update(ANDROID_JPEG_GPS_PROCESSING_METHOD,
- gps_processing_method,
- ARRAY_SIZE(gps_processing_method));
- if (res != android::OK) {
- return res;
- }
-
- int64_t gps_timestamp = 0;
- res = base_metadata.update(ANDROID_JPEG_GPS_TIMESTAMP, &gps_timestamp, 1);
- if (res != android::OK) {
- return res;
- }
-
- // JPEG orientation is relative to sensor orientation (mOrientation).
- int32_t jpeg_orientation = 0;
- res = base_metadata.update(ANDROID_JPEG_ORIENTATION, &jpeg_orientation, 1);
- if (res != android::OK) {
- return res;
- }
-
- // 1-100, larger is higher quality.
- uint8_t jpeg_quality = 80;
- res = base_metadata.update(ANDROID_JPEG_QUALITY, &jpeg_quality, 1);
- if (res != android::OK) {
- return res;
- }
-
- // TODO(b/29580107): If thumbnail quality actually matters/can be adjusted,
- // adjust this.
- uint8_t thumbnail_quality = 80;
- res = base_metadata.update(ANDROID_JPEG_THUMBNAIL_QUALITY,
- &thumbnail_quality, 1);
- if (res != android::OK) {
- return res;
- }
-
- // TODO(b/29580107): Choose a size matching the resolution.
- int32_t thumbnail_size[] = {0, 0};
- res = base_metadata.update(ANDROID_JPEG_THUMBNAIL_SIZE, thumbnail_size, 2);
- if (res != android::OK) {
- return res;
- }
-
- /* android.lens. */
-
- // Fixed values.
- res = base_metadata.update(ANDROID_LENS_APERTURE, &mAperture, 1);
- if (res != android::OK) {
- return res;
- }
- res = base_metadata.update(ANDROID_LENS_FILTER_DENSITY, &mFilterDensity, 1);
- if (res != android::OK) {
- return res;
- }
- res = base_metadata.update(ANDROID_LENS_FOCAL_LENGTH, &mFocalLength, 1);
- if (res != android::OK) {
- return res;
- }
- res = base_metadata.update(ANDROID_LENS_FOCUS_DISTANCE, &mFocusDistance, 1);
- if (res != android::OK) {
- return res;
- }
-
- uint8_t optical_stabilization = ANDROID_LENS_OPTICAL_STABILIZATION_MODE_OFF;
- res = base_metadata.update(ANDROID_LENS_OPTICAL_STABILIZATION_MODE,
- &optical_stabilization, 1);
- if (res != android::OK) {
- return res;
- }
-
- /* android.noiseReduction. */
-
- uint8_t noise_reduction_mode = ANDROID_NOISE_REDUCTION_MODE_FAST;
- res = base_metadata.update(ANDROID_NOISE_REDUCTION_MODE,
- &noise_reduction_mode, 1);
- if (res != android::OK) {
- return res;
- }
-
- // strength marked FUTURE.
-
- /* android.request. */
-
- // Request Id unused by the HAL for now, and these are just
- // templates, so just fill it in with a dummy.
- int32_t id = 0;
- res = base_metadata.update(ANDROID_REQUEST_ID, &id, 1);
- if (res != android::OK) {
- return res;
- }
-
- // metadataMode marked FUTURE.
-
- /* android.scaler. */
-
- // No cropping by default; use the full active array.
- res = base_metadata.update(ANDROID_SCALER_CROP_REGION, mPixelArraySize.data(),
- mPixelArraySize.size());
- if (res != android::OK) {
- return res;
- }
-
- /* android.sensor. */
-
- // exposureTime, sensitivity, testPattern[Data,Mode] not supported.
-
- // Ignored when AE is OFF.
- int64_t frame_duration = 33333333L; // 1/30 s.
- res = base_metadata.update(ANDROID_SENSOR_FRAME_DURATION, &frame_duration, 1);
- if (res != android::OK) {
- return res;
- }
-
- /* android.shading. */
-
- uint8_t shading_mode = ANDROID_SHADING_MODE_FAST;
- res = base_metadata.update(ANDROID_SHADING_MODE, &shading_mode, 1);
- if (res != android::OK) {
- return res;
- }
-
- /* android.statistics. */
-
- uint8_t face_detect_mode = ANDROID_STATISTICS_FACE_DETECT_MODE_OFF;
- res = base_metadata.update(ANDROID_STATISTICS_FACE_DETECT_MODE,
- &face_detect_mode, 1);
- if (res != android::OK) {
- return res;
- }
-
- // histogramMode, sharpnessMapMode marked FUTURE.
-
- uint8_t hp_map_mode = ANDROID_STATISTICS_HOT_PIXEL_MAP_MODE_OFF;
- res = base_metadata.update(ANDROID_STATISTICS_HOT_PIXEL_MAP_MODE,
- &hp_map_mode, 1);
- if (res != android::OK) {
- return res;
- }
-
- uint8_t lens_shading_map_mode = ANDROID_STATISTICS_LENS_SHADING_MAP_MODE_OFF;
- res = base_metadata.update(ANDROID_STATISTICS_LENS_SHADING_MAP_MODE,
- &lens_shading_map_mode, 1);
- if (res != android::OK) {
- return res;
- }
-
- /* android.tonemap. */
-
- // Tonemap only required for MANUAL_POST_PROCESSING capability.
-
- /* android.led. */
-
- uint8_t transmit = ANDROID_LED_TRANSMIT_ON;
- res = base_metadata.update(ANDROID_LED_TRANSMIT, &transmit, 1);
- if (res != android::OK) {
- return res;
- }
-
- /* android.reprocess */
-
- // Only needed for REPROCESS capability.
-
-
- /* Template variable values. */
-
- // Find the FPS ranges "closest" to a desired range
- // (minimum abs distance from min to min and max to max).
- // Find both a fixed rate and a variable rate, for different purposes.
- std::array<int32_t, 2> desired_flat_fps_range = {{30, 30}};
- std::array<int32_t, 2> desired_variable_fps_range = {{5, 30}};
- std::array<int32_t, 2> flat_fps_range;
- std::array<int32_t, 2> variable_fps_range;
- int32_t best_flat_distance = std::numeric_limits<int32_t>::max();
- int32_t best_variable_distance = std::numeric_limits<int32_t>::max();
- size_t num_fps_ranges = mFpsRanges.num_arrays();
- for (size_t i = 0; i < num_fps_ranges; ++i) {
- const int32_t* range = mFpsRanges[i];
- // Variable fps.
- int32_t distance = std::abs(range[0] - desired_variable_fps_range[0]) +
- std::abs(range[1] - desired_variable_fps_range[1]);
- if (distance < best_variable_distance) {
- variable_fps_range[0] = range[0];
- variable_fps_range[1] = range[1];
- best_variable_distance = distance;
- }
- // Flat fps. Only do if range is actually flat.
- // Note at least one flat range is required,
- // so something will always be filled in.
- if (range[0] == range[1]) {
- distance = std::abs(range[0] - desired_flat_fps_range[0]) +
- std::abs(range[1] - desired_flat_fps_range[1]);
- if (distance < best_flat_distance) {
- flat_fps_range[0] = range[0];
- flat_fps_range[1] = range[1];
- best_flat_distance = distance;
- }
- }
- }
-
- // Priority: continuous > auto > off > whatever is available.
- bool continuous_still_avail = std::count(
- mAfModes.begin(), mAfModes.end(),
- ANDROID_CONTROL_AF_MODE_CONTINUOUS_PICTURE);
- bool continuous_video_avail = std::count(
- mAfModes.begin(), mAfModes.end(),
- ANDROID_CONTROL_AF_MODE_CONTINUOUS_VIDEO);
- uint8_t non_continuous_af_mode = mAfModes[0];
- if (std::count(mAfModes.begin(), mAfModes.end(),
- ANDROID_CONTROL_AF_MODE_AUTO)) {
- non_continuous_af_mode = ANDROID_CONTROL_AF_MODE_AUTO;
- } else if (std::count(mAfModes.begin(), mAfModes.end(),
- ANDROID_CONTROL_AF_MODE_OFF)) {
- non_continuous_af_mode = ANDROID_CONTROL_AF_MODE_OFF;
- }
- uint8_t still_af_mode = continuous_still_avail ?
- ANDROID_CONTROL_AF_MODE_CONTINUOUS_PICTURE : non_continuous_af_mode;
- uint8_t video_af_mode = continuous_video_avail ?
- ANDROID_CONTROL_AF_MODE_CONTINUOUS_VIDEO : non_continuous_af_mode;
-
- for (uint8_t template_id = 1; template_id < CAMERA3_TEMPLATE_COUNT;
- ++template_id) {
- // General differences/support.
- uint8_t intent;
- uint8_t af_mode;
- std::array<int32_t, 2> fps_range;
- switch(template_id) {
- case CAMERA3_TEMPLATE_PREVIEW:
- intent = ANDROID_CONTROL_CAPTURE_INTENT_PREVIEW;
- af_mode = still_af_mode;
- fps_range = flat_fps_range;
- break;
- case CAMERA3_TEMPLATE_STILL_CAPTURE:
- intent = ANDROID_CONTROL_CAPTURE_INTENT_STILL_CAPTURE;
- af_mode = still_af_mode;
- fps_range = variable_fps_range;
- break;
- case CAMERA3_TEMPLATE_VIDEO_RECORD:
- intent = ANDROID_CONTROL_CAPTURE_INTENT_VIDEO_RECORD;
- af_mode = video_af_mode;
- fps_range = flat_fps_range;
- break;
- case CAMERA3_TEMPLATE_VIDEO_SNAPSHOT:
- intent = ANDROID_CONTROL_CAPTURE_INTENT_VIDEO_SNAPSHOT;
- af_mode = video_af_mode;
- fps_range = flat_fps_range;
- break;
- case CAMERA3_TEMPLATE_ZERO_SHUTTER_LAG: // Fall through.
- case CAMERA3_TEMPLATE_MANUAL: // Fall though.
- default:
- // Unsupported/unrecognized. Don't add this template; skip it.
- continue;
- }
-
- // Copy our base metadata and add the new items.
- android::CameraMetadata template_metadata(base_metadata);
- res = template_metadata.update(ANDROID_CONTROL_CAPTURE_INTENT, &intent, 1);
- if (res != android::OK) {
- return res;
- }
- res = template_metadata.update(ANDROID_CONTROL_AE_TARGET_FPS_RANGE,
- fps_range.data(), fps_range.size());
- if (res != android::OK) {
- return res;
- }
- res = template_metadata.update(ANDROID_CONTROL_AF_MODE, &af_mode, 1);
- if (res != android::OK) {
- return res;
- }
-
- const camera_metadata_t* template_raw_metadata =
- template_metadata.getAndLock();
- res = setTemplate(template_id, template_raw_metadata);
- if (res != android::OK) {
- return res;
- }
- res = template_metadata.unlock(template_raw_metadata);
- if (res != android::OK) {
- return res;
- }
- }
+ *timestamp = static_cast<uint64_t>(frame_time);
- mTemplatesInitialized = true;
return 0;
}
@@ -1292,15 +276,15 @@
}
}
- if (num_input > mMaxInputStreams ||
- num_raw > mMaxRawOutputStreams ||
- num_stalling > mMaxStallingOutputStreams ||
- num_non_stalling > mMaxNonStallingOutputStreams) {
- HAL_LOGE("Invalid stream configuration: %d input, %d RAW, %d stalling, "
- "%d non-stalling (max supported: %d input, %d RAW, %d stalling, "
- "%d non-stalling)", mMaxInputStreams, mMaxRawOutputStreams,
- mMaxStallingOutputStreams, mMaxNonStallingOutputStreams, num_input,
- num_raw, num_stalling, num_non_stalling);
+ if (num_input > max_input_streams_ ||
+ num_raw > max_output_streams_[0] ||
+ num_non_stalling > max_output_streams_[1] ||
+ num_stalling > max_output_streams_[2]) {
+ HAL_LOGE("Invalid stream configuration: %d input, %d RAW, %d non-stalling, "
+ "%d stalling (max supported: %d input, %d RAW, %d non-stalling, "
+ "%d stalling)", max_input_streams_, max_output_streams_[0],
+ max_output_streams_[1], max_output_streams_[2], num_input,
+ num_raw, num_non_stalling, num_stalling);
return false;
}
@@ -1343,7 +327,7 @@
// claims it's underdocumented; the implementation lets the HAL overwrite it.
stream->setDataSpace(HAL_DATASPACE_V0_JFIF);
- int res = mV4L2Device->SetFormat(*stream, max_buffers);
+ int res = device_->SetFormat(*stream, max_buffers);
if (res) {
HAL_LOGE("Failed to set device to correct format for stream.");
return res;
@@ -1358,230 +342,16 @@
return 0;
}
-bool V4L2Camera::isValidCaptureSettings(const camera_metadata_t* settings) {
+bool V4L2Camera::isValidCaptureSettings(const android::CameraMetadata& settings) {
HAL_LOG_ENTER();
- // TODO(b/29335262): reject capture settings this camera isn't capable of.
- return true;
+ return metadata_->IsValidRequest(settings);
}
-int V4L2Camera::initCharacteristics() {
+int V4L2Camera::setSettings(const android::CameraMetadata& new_settings) {
HAL_LOG_ENTER();
- /* Physical characteristics. */
- // No way to get these in V4L2, so faked.
- // Note: While many of these are primarily informative for post-processing
- // calculations by the app and will potentially cause bad results there,
- // focal length and physical size are actually used in framework
- // calculations (field of view, pixel pitch, etc), so faking them may
- // have unexpected results.
- mAperture = 2.0; // RPi camera v2 is f/2.0.
- mFilterDensity = 0.0;
- mFocalLength = 3.04; // RPi camera v2 is 3.04mm.
- mOrientation = 0;
- mPhysicalSize = {{3.674, 2.760}}; // RPi camera v2 is 3.674 x 2.760 mm.
-
- /* Fixed features. */
-
- // TODO(b/29394024): query VIDIOC_CROPCAP to get pixel rectangle.
- // Spoofing as 640 x 480 for now.
- mPixelArraySize = {{/*xmin*/0, /*ymin*/0, /*width*/640, /*height*/480}};
-
- // V4L2 VIDIOC_CROPCAP doesn't give a way to query this;
- // it's driver dependent. For now, assume freeform, and
- // some cameras may just behave badly.
- // TODO(b/29579652): Figure out a way to determine this.
- mCropType = ANDROID_SCALER_CROPPING_TYPE_FREEFORM;
-
- // TODO(b/29394024): query VIDIOC_CROPCAP to get cropping ranges,
- // and VIDIOC_G_CROP to determine if cropping is supported.
- // If the ioctl isn't available (or cropping has non-square pixelaspect),
- // assume no cropping/scaling.
- // May need to try setting some crops to determine what the driver actually
- // supports (including testing center vs freeform).
- mMaxZoom = 1;
-
- // TODO(b/29394024): query V4L2_CID_EXPOSURE_BIAS.
- mAeCompensationRange = {{0, 0}};
- mAeCompensationStep = {1, 1};
-
- // TODO(b/29394024): query V4L2_CID_3A_LOCK.
- mAeLockAvailable = ANDROID_CONTROL_AE_LOCK_AVAILABLE_FALSE;
- mAwbLockAvailable = ANDROID_CONTROL_AWB_LOCK_AVAILABLE_FALSE;
-
- // TODO(b/29394024): query V4L2_CID_FLASH_LED_MODE.
- mFlashAvailable = 0;
-
- // TODO(b/29394024): query V4L2_CID_FOCUS_ABSOLUTE for focus range.
- mFocusDistance = 0; // Fixed focus.
-
- // TODO(b/29939583): V4L2 can only support 1 stream at a time.
- // For now, just reporting minimum allowable for LIMITED devices.
- mMaxRawOutputStreams = 0;
- mMaxStallingOutputStreams = 1;
- mMaxNonStallingOutputStreams = 2;
- // Reprocessing not supported.
- mMaxInputStreams = 0;
-
- /* Features with (potentially) multiple options. */
-
- // TODO(b/29394024): query V4L2_CID_EXPOSURE_AUTO for ae modes.
- mAeModes.push_back(ANDROID_CONTROL_AE_MODE_ON);
-
- // TODO(b/29394024): query V4L2_CID_POWER_LINE_FREQUENCY.
- // Auto as the default, since it could mean anything, while OFF would
- // require guaranteeing no antibanding happens.
- mAeAntibandingModes.push_back(ANDROID_CONTROL_AE_ANTIBANDING_MODE_AUTO);
-
- // TODO(b/29394024): query V4L2_CID_FOCUS_AUTO for
- // CONTINUOUS_VIDEO/CONTINUOUS_PICTURE. V4L2_CID_AUTO_FOCUS_START
- // supports what Android thinks of as auto focus (single auto focus).
- // V4L2_CID_AUTO_FOCUS_RANGE allows MACRO.
- mAfModes.push_back(ANDROID_CONTROL_AF_MODE_OFF);
-
- // TODO(b/29394024): query V4L2_CID_AUTO_WHITE_BALANCE, or
- // V4L2_CID_AUTO_N_PRESET_WHITE_BALANCE if available.
- mAwbModes.push_back(ANDROID_CONTROL_AWB_MODE_AUTO);
-
- // TODO(b/29394024): query V4L2_CID_SCENE_MODE.
- mSceneModes.push_back(ANDROID_CONTROL_SCENE_MODE_DISABLED);
-
- mControlModes.push_back(ANDROID_CONTROL_MODE_AUTO);
- if (mSceneModes.size() > 1) {
- // We have some mode other than just DISABLED available.
- mControlModes.push_back(ANDROID_CONTROL_MODE_USE_SCENE_MODE);
- }
-
- // TODO(b/29394024): query V4L2_CID_COLORFX.
- mEffects.push_back(ANDROID_CONTROL_EFFECT_MODE_OFF);
-
- // TODO(b/29394024): query V4L2_CID_FLASH_INDICATOR_INTENSITY.
- // For now, no indicator LED available; nothing to push back.
- // When there is, push back ANDROID_LED_AVAILABLE_LEDS_TRANSMIT.
-
- // TODO(b/29394024): query V4L2_CID_IMAGE_STABILIZATION.
- mOpticalStabilizationModes.push_back(
- ANDROID_LENS_OPTICAL_STABILIZATION_MODE_OFF);
- mVideoStabilizationModes.push_back(
- ANDROID_CONTROL_VIDEO_STABILIZATION_MODE_OFF);
-
- // Need to be connected to query the device.
- V4L2Wrapper::Connection temp_connection(mV4L2Device);
- if (temp_connection.status()) {
- HAL_LOGE("Failed to connect to device.");
- return temp_connection.status();
- }
-
- // Get all supported formats.
- std::set<uint32_t> v4l2_formats;
- int res = mV4L2Device->GetFormats(&v4l2_formats);
- if (res) {
- HAL_LOGE("Failed to get device formats.");
- return res;
- }
- std::set<int32_t> hal_formats;
- for (auto v4l2_format : v4l2_formats) {
- int32_t hal_format = StreamFormat::V4L2ToHalPixelFormat(v4l2_format);
- if (hal_format < 0) {
- // Unrecognized/unused format. Skip it.
- continue;
- }
- hal_formats.insert(hal_format);
- }
- // In addition to well-defined formats, must support "Implementation Defined"
- // (in this case what that means is managed by the StreamFormat class).
- hal_formats.insert(HAL_PIXEL_FORMAT_IMPLEMENTATION_DEFINED);
-
- // Requirements check: need to support YCbCr_420_888 and JPEG.
- if (hal_formats.find(HAL_PIXEL_FORMAT_YCbCr_420_888) == hal_formats.end()) {
- HAL_LOGE("YCbCr_420_888 not supported by device.");
- return -ENODEV;
- } else if (hal_formats.find(HAL_PIXEL_FORMAT_BLOB) == hal_formats.end()) {
- HAL_LOGE("JPEG not supported by device.");
- return -ENODEV;
- }
-
- // Find sizes and frame durations for all formats.
- // We also want to find the smallest max frame duration amongst all formats.
- mMaxFrameDuration = std::numeric_limits<int64_t>::max();
- int64_t min_yuv_frame_duration = std::numeric_limits<int64_t>::max();
- for (auto hal_format : hal_formats) {
- uint32_t v4l2_format = StreamFormat::HalToV4L2PixelFormat(hal_format);
- if (v4l2_format == 0) {
- // Unrecognized/unused format. Should never happen since hal_formats
- // came from translating a bunch of V4L2 formats above.
- HAL_LOGE("Couldn't find V4L2 format for HAL format %d", hal_format);
- return -ENODEV;
- }
-
- std::set<std::array<int32_t, 2>> frame_sizes;
- res = mV4L2Device->GetFormatFrameSizes(v4l2_format, &frame_sizes);
- if (res) {
- HAL_LOGE("Failed to get all frame sizes for format %d", v4l2_format);
- return res;
- }
-
- for (const auto& frame_size : frame_sizes) {
- mStreamConfigs.push_back({{hal_format, frame_size[0], frame_size[1],
- ANDROID_SCALER_AVAILABLE_STREAM_CONFIGURATIONS_OUTPUT}});
-
- std::array<int64_t, 2> duration_range;
- res = mV4L2Device->GetFormatFrameDurationRange(
- v4l2_format, frame_size, &duration_range);
- if (res) {
- HAL_LOGE("Failed to get frame duration range for format %d, "
- "size %u x %u", v4l2_format, frame_size[0], frame_size[1]);
- return res;
- }
-
- int64_t min_frame_duration = duration_range[0];
- int64_t max_frame_duration = duration_range[1];
-
- mMinFrameDurations.push_back(
- {{hal_format, frame_size[0], frame_size[1], min_frame_duration}});
-
- // In theory max frame duration (min frame rate) should be consistent
- // between all formats, but we check and only advertise the smallest
- // available max duration just in case.
- if (max_frame_duration < mMaxFrameDuration) {
- mMaxFrameDuration = max_frame_duration;
- }
-
- // We only care about min frame duration (max frame rate) for YUV.
- if (hal_format == HAL_PIXEL_FORMAT_YCbCr_420_888 &&
- min_frame_duration < min_yuv_frame_duration) {
- min_yuv_frame_duration = min_frame_duration;
- }
-
- // Usually 0 for non-jpeg, non-zero for JPEG.
- // Randomly choosing absurd 1 sec for JPEG. Unsure what this breaks.
- int64_t stall_duration = 0;
- if (hal_format == HAL_PIXEL_FORMAT_BLOB) {
- stall_duration = 1000000000;
- }
- mStallDurations.push_back(
- {{hal_format, frame_size[0], frame_size[1], stall_duration}});
- }
- }
-
- // This should be at minimum {mi, ma}, {ma, ma} where mi and ma
- // are min and max frame rates for YUV_420_888. Min should be at most 15.
- // Convert from frame durations measured in ns.
- int32_t min_yuv_fps = 1000000000 / mMaxFrameDuration;
- if (min_yuv_fps > 15) {
- return -ENODEV;
- }
- int32_t max_yuv_fps = 1000000000 / min_yuv_frame_duration;
- mFpsRanges.push_back({{min_yuv_fps, max_yuv_fps}});
- mFpsRanges.push_back({{max_yuv_fps, max_yuv_fps}});
- // Always advertise {30, 30} if max is even higher,
- // since this is what the default video requests use.
- if (max_yuv_fps > 30) {
- mFpsRanges.push_back({{30, 30}});
- }
-
- mCharacteristicsInitialized = true;
- return 0;
+ return metadata_->SetRequestSettings(new_settings);
}
} // namespace v4l2_camera_hal