Commit 135a698d authored by Moja Hsu's avatar Moja Hsu Committed by Chromium LUCI CQ

camera: Support focus distance control

This CL adds focusMode(continuous/manual) and focusDistance
MediaTrackCapabilities.

Bug: b:151048287, 1068176
Test: Tested logitech camera on eve. Test WFC of kukui.
Change-Id: I85fa31b8b4f147b8cc054eac3f94974595545c05
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2371843
Commit-Queue: Hsu Wei-Cheng <mojahsu@chromium.org>
Reviewed-by: default avatarWei Lee <wtlee@chromium.org>
Cr-Commit-Position: refs/heads/master@{#836565}
parent 2b80fa7d
......@@ -427,6 +427,36 @@ void Camera3AController::SetExposureTime(bool enable_auto,
DVLOG(1) << "Setting AE mode to: " << ae_mode_;
}
void Camera3AController::SetFocusDistance(bool enable_auto,
float focus_distance_diopters) {
DCHECK(task_runner_->BelongsToCurrentThread());
if (enable_auto) {
if (!available_af_modes_.count(
cros::mojom::AndroidControlAfMode::ANDROID_CONTROL_AF_MODE_AUTO)) {
LOG(WARNING) << "Don't support ANDROID_CONTROL_AF_MODE_AUTO";
return;
}
af_mode_ = cros::mojom::AndroidControlAfMode::ANDROID_CONTROL_AF_MODE_AUTO;
capture_metadata_dispatcher_->UnsetRepeatingCaptureMetadata(
cros::mojom::CameraMetadataTag::ANDROID_LENS_FOCUS_DISTANCE);
} else {
if (!available_af_modes_.count(
cros::mojom::AndroidControlAfMode::ANDROID_CONTROL_AF_MODE_OFF)) {
LOG(WARNING) << "Don't support ANDROID_CONTROL_AE_MODE_OFF";
return;
}
af_mode_ = cros::mojom::AndroidControlAfMode::ANDROID_CONTROL_AF_MODE_OFF;
SetRepeatingCaptureMetadata(
cros::mojom::CameraMetadataTag::ANDROID_LENS_FOCUS_DISTANCE,
focus_distance_diopters);
}
Set3AMode(cros::mojom::CameraMetadataTag::ANDROID_CONTROL_AF_MODE,
base::checked_cast<uint8_t>(af_mode_));
DVLOG(1) << "Setting AF mode to: " << af_mode_;
}
bool Camera3AController::IsPointOfInterestSupported() {
return point_of_interest_supported_;
}
......
......@@ -50,6 +50,11 @@ class CAPTURE_EXPORT Camera3AController final
// only effective if |enable_auto| is set to false
void SetExposureTime(bool enable_auto, int64_t exposure_time_nanoseconds);
// Set focus distance.
// |enable_auto| enables auto focus mode. |focus_distance_diopters| is only
// effective if |enable_auto| is set to false
void SetFocusDistance(bool enable_auto, float focus_distance_diopters);
bool IsPointOfInterestSupported();
// Set point of interest. The coordinate system is based on the active
......
......@@ -294,6 +294,7 @@ void CameraDeviceDelegate::AllocateAndStart(
is_set_brightness_ = false;
is_set_contrast_ = false;
is_set_exposure_time_ = false;
is_set_focus_distance_ = false;
is_set_pan_ = false;
is_set_saturation_ = false;
is_set_sharpness_ = false;
......@@ -526,6 +527,18 @@ void CameraDeviceDelegate::SetPhotoOptions(
is_set_exposure_time_ = false;
}
if (settings->has_focus_mode &&
settings->focus_mode == mojom::MeteringMode::MANUAL &&
settings->has_focus_distance) {
// The unit of settings is meter but it is diopter of android metadata.
float focus_distance_diopters_ = 1.0 / settings->focus_distance;
camera_3a_controller_->SetFocusDistance(false, focus_distance_diopters_);
is_set_focus_distance_ = true;
} else if (is_set_focus_distance_) {
camera_3a_controller_->SetFocusDistance(true, 0);
is_set_focus_distance_ = false;
}
// If there is callback of SetPhotoOptions(), the streams might being
// reconfigured and we should notify them once the reconfiguration is done.
auto on_reconfigured_callback = base::BindOnce(
......@@ -1321,6 +1334,19 @@ void CameraDeviceDelegate::OnResultMetadataAvailable(
if (awb_mode.size() == 1)
result_metadata_.awb_mode = awb_mode[0];
result_metadata_.af_mode.reset();
auto af_mode = GetMetadataEntryAsSpan<uint8_t>(
result_metadata, cros::mojom::CameraMetadataTag::ANDROID_CONTROL_AF_MODE);
if (af_mode.size() == 1)
result_metadata_.af_mode = af_mode[0];
result_metadata_.focus_distance.reset();
auto focus_distance = GetMetadataEntryAsSpan<float>(
result_metadata,
cros::mojom::CameraMetadataTag::ANDROID_LENS_FOCUS_DISTANCE);
if (focus_distance.size() == 1)
result_metadata_.focus_distance = focus_distance[0];
result_metadata_frame_number_ = frame_number;
// We need to wait the new result metadata for new settings.
if (result_metadata_frame_number_ >
......@@ -1492,6 +1518,51 @@ void CameraDeviceDelegate::DoGetPhotoState(
result_metadata_.exposure_time.value() / (100 * kMicroToNano);
}
auto af_available_modes = GetMetadataEntryAsSpan<uint8_t>(
static_metadata_,
cros::mojom::CameraMetadataTag::ANDROID_CONTROL_AF_AVAILABLE_MODES);
bool support_manual_focus_distance = false;
if (af_available_modes.size() > 1 && result_metadata_.af_mode) {
support_manual_focus_distance = base::Contains(
af_available_modes,
static_cast<uint8_t>(
cros::mojom::AndroidControlAfMode::ANDROID_CONTROL_AF_MODE_OFF));
}
auto minimum_focus_distance = GetMetadataEntryAsSpan<float>(
static_metadata_,
cros::mojom::CameraMetadataTag::ANDROID_LENS_INFO_MINIMUM_FOCUS_DISTANCE);
// If the lens is fixed-focus, minimum_focus_distance will be 0.
if (support_manual_focus_distance && minimum_focus_distance[0] != 0 &&
result_metadata_.focus_distance) {
photo_state->supported_focus_modes.push_back(mojom::MeteringMode::MANUAL);
photo_state->supported_focus_modes.push_back(
mojom::MeteringMode::CONTINUOUS);
if (result_metadata_.af_mode ==
static_cast<uint8_t>(
cros::mojom::AndroidControlAfMode::ANDROID_CONTROL_AF_MODE_OFF))
photo_state->current_focus_mode = mojom::MeteringMode::MANUAL;
else
photo_state->current_focus_mode = mojom::MeteringMode::CONTINUOUS;
// The unit of photo_state->focus_distance is meter and from metadata is
// diopter.
photo_state->focus_distance->min =
std::roundf(100.0 / minimum_focus_distance[0]) / 100.0;
photo_state->focus_distance->max = std::numeric_limits<double>::infinity();
photo_state->focus_distance->step = 0.01;
if (result_metadata_.focus_distance.value() == 0) {
photo_state->focus_distance->current =
std::numeric_limits<double>::infinity();
} else {
// We want to make sure |current| is a possible value of
// |min| + |steps(0.01)|*X. The minimum can be divided by step(0.01). So
// we only need to round the value less than 0.01.
double meters = 1.0 / result_metadata_.focus_distance.value();
photo_state->focus_distance->current = std::roundf(meters * 100) / 100.0;
}
}
std::move(callback).Run(std::move(photo_state));
}
......
......@@ -57,10 +57,12 @@ struct ResultMetadata {
~ResultMetadata();
base::Optional<uint8_t> ae_mode;
base::Optional<uint8_t> af_mode;
base::Optional<uint8_t> awb_mode;
base::Optional<int32_t> brightness;
base::Optional<int32_t> contrast;
base::Optional<int64_t> exposure_time;
base::Optional<float> focus_distance;
base::Optional<int32_t> pan;
base::Optional<int32_t> saturation;
base::Optional<int32_t> sharpness;
......@@ -278,6 +280,7 @@ class CAPTURE_EXPORT CameraDeviceDelegate final
bool is_set_brightness_;
bool is_set_contrast_;
bool is_set_exposure_time_;
bool is_set_focus_distance_;
bool is_set_pan_;
bool is_set_saturation_;
bool is_set_sharpness_;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment