Commit 3bd31fd1 authored by Francois Beaufort's avatar Francois Beaufort Committed by Commit Bot

[PTZ] Cache list of zooms when enumerating cameras

VideoCaptureDeviceFactoryAndroid was getting zoom support for each
device every time when enumerating devices. This was problematic on some
devices where opening a camera breaks existing stream for that camera.
This CL adds cache of zooms in VideoCaptureDeviceFactoryAndroid. This
allows to workaround the bug by getting zoom support only once for each
device.

Bug: 1138608, 934063
Change-Id: I52895ee5a538c44ce2ff53bc27714da88b9be54b
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2517465
Commit-Queue: François Beaufort <beaufort.francois@gmail.com>
Reviewed-by: default avatarMiguel Casas <mcasas@chromium.org>
Reviewed-by: default avatarReilly Grant <reillyg@chromium.org>
Cr-Commit-Position: refs/heads/master@{#824587}
parent 01dd39f8
......@@ -190,10 +190,22 @@ public class VideoCaptureCamera
}
static boolean isZoomSupported(int id) {
// Workaround for https://crbug.com/1138608: Detecting zoom support requires opening the
// camera which can conflict with calls to allocate() and cause the "real" camera open to
// fail.
return false;
android.hardware.Camera camera;
try {
camera = android.hardware.Camera.open(id);
} catch (RuntimeException ex) {
Log.e(TAG, "Camera.open: ", ex);
return false;
}
android.hardware.Camera.Parameters parameters = getCameraParameters(camera);
if (parameters == null) {
camera.release();
return false;
}
final boolean isZoomSupported = parameters.isZoomSupported();
camera.release();
return isZoomSupported;
}
static int getFacingMode(int id) {
......
......@@ -85,11 +85,18 @@ void VideoCaptureDeviceFactoryAndroid::GetDevicesInfo(
const int capture_api_type =
Java_VideoCaptureFactory_getCaptureApiType(env, camera_index);
VideoCaptureControlSupport control_support;
control_support.zoom =
Java_VideoCaptureFactory_isZoomSupported(env, camera_index);
const int facing_mode =
Java_VideoCaptureFactory_getFacingMode(env, camera_index);
auto zoom_it = zooms_cache_.find(device_id);
if (zoom_it != zooms_cache_.end()) {
control_support.zoom = zoom_it->second;
} else {
control_support.zoom =
Java_VideoCaptureFactory_isZoomSupported(env, camera_index);
zooms_cache_.emplace(device_id, control_support.zoom);
}
// Android cameras are not typically USB devices, and the model_id is
// currently only used for USB model identifiers, so this implementation
// just indicates an unknown device model (by not providing one).
......@@ -132,6 +139,16 @@ void VideoCaptureDeviceFactoryAndroid::GetDevicesInfo(
});
}
// Remove old entries from |zooms_cache_| if necessary.
if (zooms_cache_.size() > devices_info.size()) {
base::EraseIf(zooms_cache_, [&devices_info](const auto& entry) {
return base::ranges::none_of(
devices_info, [&entry](const VideoCaptureDeviceInfo& info) {
return entry.first == info.descriptor.device_id;
});
});
}
std::move(callback).Run(std::move(devices_info));
}
......
......@@ -44,11 +44,13 @@ class CAPTURE_EXPORT VideoCaptureDeviceFactoryAndroid
// Switch to indicate that all created Java capturers will be in test mode.
bool test_mode_ = false;
// VideoCaptureFormats are cached, so GetSupportedFormats() doesn't need to be
// VideoCaptureFormats and zooms are cached, so GetSupportedFormats() and
// Java_VideoCaptureFactory_isZoomSupported() respectively don't need to be
// called for every device every time GetDevicesInfo() is called. It also
// allows to workaround bugs on some devices that don't handle the case when
// an actively used camera is opened again (see https://crbug.com/1138608).
base::flat_map<std::string, VideoCaptureFormats> supported_formats_cache_;
base::flat_map<std::string, bool> zooms_cache_;
DISALLOW_COPY_AND_ASSIGN(VideoCaptureDeviceFactoryAndroid);
};
......
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