camera: usb: Add a quirk to favor MJPEG over YUYV
Add a quirk to workaround the problem that Logitech Webcam Pro 9000
might stuck in DQBUF after switching resolutions.
BUG=b:138159048
TEST=Open Hangout with Logitech Webcam Pro 9000
Cq-Depend: chrome-internal:1513379
Change-Id: I2a333eb59bc61e7f230dfb45b85b676b20388083
Reviewed-on: https://chromium-review.googlesource.com/1717852
Tested-by: Shik Chen <shik@chromium.org>
Commit-Ready: Shik Chen <shik@chromium.org>
Legacy-Commit-Queue: Commit Bot <commit-bot@chromium.org>
Reviewed-by: Ricky Liang <jcliang@chromium.org>
(cherry picked from commit 1dee5efe3198f413f0bc32c7d7f4d4410bfd3203)
Reviewed-on: https://chromium-review.googlesource.com/c/chromiumos/platform2/+/1736187
Reviewed-by: Shik Chen <shik@chromium.org>
Commit-Queue: Shik Chen <shik@chromium.org>
diff --git a/camera/hal/usb/camera_characteristics.cc b/camera/hal/usb/camera_characteristics.cc
index e5b26cc..e50f90b 100644
--- a/camera/hal/usb/camera_characteristics.cc
+++ b/camera/hal/usb/camera_characteristics.cc
@@ -20,6 +20,7 @@
#include "cros-camera/common.h"
#include "cros-camera/timezone.h"
+#include "hal/usb/quirks.h"
namespace cros {
@@ -55,6 +56,22 @@
return res;
}
+uint32_t ParseQuirks(const std::string& value) {
+ static const std::map<std::string, uint32_t> kNameMap = {
+ {"monocle", kQuirkMonocle},
+ {"prefer_mjpeg", kQuirkPreferMjpeg},
+ };
+ std::vector<std::string> names = base::SplitString(
+ value, ",", base::TRIM_WHITESPACE, base::SPLIT_WANT_ALL);
+ uint32_t quirks = 0;
+ for (const auto& name : names) {
+ auto it = kNameMap.find(name);
+ CHECK(it != kNameMap.end()) << "Invalid quirk name " << name;
+ quirks |= it->second;
+ }
+ return quirks;
+}
+
void SetEntry(const std::string& key,
const std::string& value,
DeviceInfo* info) {
@@ -67,8 +84,8 @@
} else if (key == "constant_framerate_unsupported") {
std::istringstream(value) >> std::boolalpha >>
info->constant_framerate_unsupported;
- } else if (key == "monocle_quirks") {
- std::istringstream(value) >> std::boolalpha >> info->monocle_quirks;
+ } else if (key == "quirks") {
+ info->quirks = ParseQuirks(value);
} else if (key == "lens_facing") {
info->lens_facing = stoi(value);
} else if (key == "sensor_orientation") {
diff --git a/camera/hal/usb/camera_client.cc b/camera/hal/usb/camera_client.cc
index c0a4e58..47e7190 100644
--- a/camera/hal/usb/camera_client.cc
+++ b/camera/hal/usb/camera_client.cc
@@ -54,7 +54,8 @@
SupportedFormats supported_formats =
device_->GetDeviceSupportedFormats(device_info_.device_path);
- qualified_formats_ = GetQualifiedFormats(supported_formats);
+ qualified_formats_ =
+ GetQualifiedFormats(supported_formats, device_info_.quirks);
metadata_handler_ = std::make_unique<MetadataHandler>(
static_info, device_info, qualified_formats_);
@@ -526,7 +527,8 @@
is_video_recording_(false) {
SupportedFormats supported_formats =
device_->GetDeviceSupportedFormats(device_info_.device_path);
- qualified_formats_ = GetQualifiedFormats(supported_formats);
+ qualified_formats_ =
+ GetQualifiedFormats(supported_formats, device_info_.quirks);
}
CameraClient::RequestHandler::~RequestHandler() {}
diff --git a/camera/hal/usb/camera_hal.cc b/camera/hal/usb/camera_hal.cc
index 4c56d55..7805972 100644
--- a/camera/hal/usb/camera_hal.cc
+++ b/camera/hal/usb/camera_hal.cc
@@ -17,6 +17,7 @@
#include "hal/usb/camera_characteristics.h"
#include "hal/usb/common_types.h"
#include "hal/usb/metadata_handler.h"
+#include "hal/usb/quirks.h"
#include "hal/usb/stream_format.h"
#include "hal/usb/v4l2_camera_device.h"
#include "hal/usb/vendor_tag.h"
@@ -41,7 +42,8 @@
SupportedFormats supported_formats =
V4L2CameraDevice::GetDeviceSupportedFormats(device_info.device_path);
bool is_external = device_info.lens_facing == ANDROID_LENS_FACING_EXTERNAL;
- SupportedFormats qualified_formats = GetQualifiedFormats(supported_formats);
+ SupportedFormats qualified_formats =
+ GetQualifiedFormats(supported_formats, device_info.quirks);
if (MetadataHandler::FillMetadataFromSupportedFormats(
qualified_formats, &metadata, is_external) != 0) {
return nullptr;
@@ -364,6 +366,9 @@
info.usb_pid = pid;
info.is_vivid = is_vivid;
info.power_line_frequency = V4L2CameraDevice::GetPowerLineFrequency(path);
+ if (!is_vivid) {
+ info.quirks |= GetQuirks(vid, pid);
+ }
if (info_ptr == nullptr) {
info.lens_facing = ANDROID_LENS_FACING_EXTERNAL;
diff --git a/camera/hal/usb/common_types.h b/camera/hal/usb/common_types.h
index 1aa684a..665a10a 100644
--- a/camera/hal/usb/common_types.h
+++ b/camera/hal/usb/common_types.h
@@ -49,6 +49,9 @@
uint32_t lens_facing;
int32_t sensor_orientation = 0;
+ // Special settings for device specific quirks.
+ uint32_t quirks = 0;
+
// These fields are not available for external cameras.
std::vector<float> lens_info_available_apertures;
std::vector<float> lens_info_available_focal_lengths;
@@ -58,9 +61,6 @@
int32_t sensor_info_pixel_array_size_height;
float sensor_info_physical_size_width;
float sensor_info_physical_size_height;
-
- // Special setting for specified camera modules.
- bool monocle_quirks = false;
};
typedef std::vector<DeviceInfo> DeviceInfos;
diff --git a/camera/hal/usb/libcamera_hal.gyp b/camera/hal/usb/libcamera_hal.gyp
index e2286f6..5ecbb5f 100644
--- a/camera/hal/usb/libcamera_hal.gyp
+++ b/camera/hal/usb/libcamera_hal.gyp
@@ -56,6 +56,7 @@
'frame_buffer.cc',
'image_processor.cc',
'metadata_handler.cc',
+ 'quirks.cc',
'sensor_handler.cc',
'stream_format.cc',
'test_pattern.cc',
diff --git a/camera/hal/usb/metadata_handler.cc b/camera/hal/usb/metadata_handler.cc
index 0d020ec..984d602 100644
--- a/camera/hal/usb/metadata_handler.cc
+++ b/camera/hal/usb/metadata_handler.cc
@@ -12,6 +12,7 @@
#include "cros-camera/common.h"
#include "cros-camera/utils/camera_config.h"
+#include "hal/usb/quirks.h"
#include "hal/usb/stream_format.h"
#include "hal/usb/v4l2_camera_device.h"
#include "hal/usb/vendor_tag.h"
@@ -634,7 +635,7 @@
UPDATE(ANDROID_CONTROL_AE_ANTIBANDING_MODE, &ae_antibanding_mode, 1);
// Set vendor tags for specified boards.
- if (device_info.monocle_quirks) {
+ if (device_info.quirks & kQuirkMonocle) {
int32_t timestamp_sync =
static_cast<int32_t>(mojom::CameraSensorSyncTimestamp::NEAREST);
UPDATE(kVendorTagTimestampSync, ×tamp_sync, 1);
diff --git a/camera/hal/usb/quirks.cc b/camera/hal/usb/quirks.cc
new file mode 100644
index 0000000..1ce80e8
--- /dev/null
+++ b/camera/hal/usb/quirks.cc
@@ -0,0 +1,38 @@
+/*
+ * Copyright 2019 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/quirks.h"
+
+#include <map>
+#include <utility>
+
+namespace cros {
+
+namespace {
+
+using VidPidPair = std::pair<std::string, std::string>;
+using QuirksMap = std::map<VidPidPair, uint32_t>;
+
+const QuirksMap& GetQuirksMap() {
+ static const QuirksMap kQuirksMap = {
+ // Logitech Webcam Pro 9000 (b/138159048)
+ {{"046d", "0809"}, kQuirkPreferMjpeg},
+ };
+ return kQuirksMap;
+}
+
+} // namespace
+
+uint32_t GetQuirks(const std::string& vid, const std::string& pid) {
+ const QuirksMap& quirks_map = GetQuirksMap();
+ auto it = quirks_map.find({vid, pid});
+ if (it != quirks_map.end()) {
+ return it->second;
+ }
+ return 0;
+}
+
+} // namespace cros
diff --git a/camera/hal/usb/quirks.h b/camera/hal/usb/quirks.h
new file mode 100644
index 0000000..6414c3a
--- /dev/null
+++ b/camera/hal/usb/quirks.h
@@ -0,0 +1,27 @@
+/*
+ * Copyright 2019 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.
+ */
+
+#ifndef CAMERA_HAL_USB_QUIRKS_H_
+#define CAMERA_HAL_USB_QUIRKS_H_
+
+#include <cstdint>
+#include <string>
+
+#include "hal/usb/common_types.h"
+
+namespace cros {
+
+// The bitmask for each quirk.
+enum : uint32_t {
+ kQuirkMonocle = 1 << 0,
+ kQuirkPreferMjpeg = 1 << 1,
+};
+
+uint32_t GetQuirks(const std::string& vid, const std::string& pid);
+
+} // namespace cros
+
+#endif // CAMERA_HAL_USB_QUIRKS_H_
diff --git a/camera/hal/usb/sensor_handler_monocle.cc b/camera/hal/usb/sensor_handler_monocle.cc
index 848d46d..f421c0f 100644
--- a/camera/hal/usb/sensor_handler_monocle.cc
+++ b/camera/hal/usb/sensor_handler_monocle.cc
@@ -11,13 +11,14 @@
#include <rts_read_sensor.h>
#include "cros-camera/common.h"
+#include "hal/usb/quirks.h"
namespace cros {
SensorHandlerMonocle::SensorHandlerMonocle(
const DeviceInfo& device_info, const SupportedFormats& supported_formats)
: handle_(nullptr) {
- if (!device_info.monocle_quirks) {
+ if (!(device_info.quirks & kQuirkMonocle)) {
return;
}
diff --git a/camera/hal/usb/stream_format.cc b/camera/hal/usb/stream_format.cc
index e7e6a92..fec0aec 100644
--- a/camera/hal/usb/stream_format.cc
+++ b/camera/hal/usb/stream_format.cc
@@ -13,22 +13,32 @@
#include <system/graphics.h>
#include "cros-camera/common.h"
+#include "hal/usb/quirks.h"
namespace cros {
-static std::vector<int> kSupportedHalFormats{
+namespace {
+
+constexpr int kSupportedHalFormats[] = {
HAL_PIXEL_FORMAT_BLOB, HAL_PIXEL_FORMAT_YCbCr_420_888,
HAL_PIXEL_FORMAT_IMPLEMENTATION_DEFINED};
-static const std::vector<uint32_t> GetSupportedFourCCs() {
+std::vector<uint32_t> GetSupportedFourCCs(bool prefer_mjpeg) {
// The preference of supported fourccs in the list is from high to low.
- static const std::vector<uint32_t> kSupportedFourCCs = {
+ if (prefer_mjpeg) {
+ return {
+ V4L2_PIX_FMT_MJPEG,
+ V4L2_PIX_FMT_YUYV,
+ };
+ }
+ return {
V4L2_PIX_FMT_YUYV,
V4L2_PIX_FMT_MJPEG,
};
- return kSupportedFourCCs;
}
+} // namespace
+
// Return corresponding format by matching resolution |width|x|height| in
// |formats|.
const SupportedFormat* FindFormatByResolution(const SupportedFormats& formats,
@@ -117,10 +127,12 @@
return ret;
}
-SupportedFormats GetQualifiedFormats(
- const SupportedFormats& supported_formats) {
+SupportedFormats GetQualifiedFormats(const SupportedFormats& supported_formats,
+ uint32_t quirks) {
// The preference of supported fourccs in the list is from high to low.
- const std::vector<uint32_t> supported_fourccs = GetSupportedFourCCs();
+ bool prefer_mjpeg = quirks & kQuirkPreferMjpeg;
+ const std::vector<uint32_t> supported_fourccs =
+ GetSupportedFourCCs(prefer_mjpeg);
SupportedFormats qualified_formats;
for (const auto& supported_fourcc : supported_fourccs) {
for (const auto& supported_format : supported_formats) {
@@ -161,8 +173,9 @@
bool IsFormatSupported(const SupportedFormats& supported_formats,
const camera3_stream_t& stream) {
- if (std::find(kSupportedHalFormats.begin(), kSupportedHalFormats.end(),
- stream.format) == kSupportedHalFormats.end()) {
+ if (std::find(std::begin(kSupportedHalFormats),
+ std::end(kSupportedHalFormats),
+ stream.format) == std::end(kSupportedHalFormats)) {
return false;
}
for (const auto& supported_format : supported_formats) {
diff --git a/camera/hal/usb/stream_format.h b/camera/hal/usb/stream_format.h
index 6c15a7c..97d4314 100644
--- a/camera/hal/usb/stream_format.h
+++ b/camera/hal/usb/stream_format.h
@@ -31,7 +31,8 @@
// Find all formats in preference order.
// The resolutions in returned SupportedFormats vector are unique.
-SupportedFormats GetQualifiedFormats(const SupportedFormats& supported_formats);
+SupportedFormats GetQualifiedFormats(const SupportedFormats& supported_formats,
+ uint32_t quirks);
// Check |stream| is supported in |supported_formats|.
bool IsFormatSupported(const SupportedFormats& supported_formats,