camera: usb: read sensor data
Rolling shutter skew and exposure time are from sensor.
We read sensor registers via third-party SDK if the
camera module supports the feature.
BUG=b:123889668
TEST=use flashlight and see the correct values are reported
Change-Id: I407d1003744ede8aa4ee9097b5b6acceec9e6ad7
Reviewed-on: https://chromium-review.googlesource.com/1583570
Tested-by: Heng-ruey Hsu <henryhsu@google.com>
Commit-Ready: ChromeOS CL Exonerator Bot <chromiumos-cl-exonerator@appspot.gserviceaccount.com>
Legacy-Commit-Queue: Commit Bot <commit-bot@chromium.org>
Reviewed-by: Heng-ruey Hsu <henryhsu@google.com>
diff --git a/camera/hal/usb/camera_characteristics.cc b/camera/hal/usb/camera_characteristics.cc
index 011e94a..e5b26cc 100644
--- a/camera/hal/usb/camera_characteristics.cc
+++ b/camera/hal/usb/camera_characteristics.cc
@@ -67,6 +67,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 == "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 1e94428..0885eeb 100644
--- a/camera/hal/usb/camera_client.cc
+++ b/camera/hal/usb/camera_client.cc
@@ -40,7 +40,6 @@
device_info_(device_info),
device_(new V4L2CameraDevice(device_info)),
callback_ops_(nullptr),
- metadata_handler_(new MetadataHandler(static_info)),
request_thread_("Capture request thread") {
memset(&camera3_device_, 0, sizeof(camera3_device_));
camera3_device_.common.tag = HARDWARE_DEVICE_TAG;
@@ -56,6 +55,9 @@
SupportedFormats supported_formats =
device_->GetDeviceSupportedFormats(device_info_.device_path);
qualified_formats_ = GetQualifiedFormats(supported_formats);
+
+ metadata_handler_ = std::make_unique<MetadataHandler>(
+ static_info, device_info, qualified_formats_);
}
CameraClient::~CameraClient() {}
@@ -681,8 +683,9 @@
}
NotifyShutter(capture_result.frame_number);
- ret = metadata_handler_->PostHandleRequest(
- capture_result.frame_number, CurrentBufferTimestamp(), metadata);
+ ret = metadata_handler_->PostHandleRequest(capture_result.frame_number,
+ CurrentBufferTimestamp(), metadata,
+ stream_on_resolution_);
if (ret) {
LOGFID(WARNING, device_id_)
<< "Update metadata in PostHandleRequest failed";
diff --git a/camera/hal/usb/common_types.h b/camera/hal/usb/common_types.h
index 1292cf3..1aa684a 100644
--- a/camera/hal/usb/common_types.h
+++ b/camera/hal/usb/common_types.h
@@ -58,6 +58,9 @@
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 0b8793e..87231ae 100644
--- a/camera/hal/usb/libcamera_hal.gyp
+++ b/camera/hal/usb/libcamera_hal.gyp
@@ -17,6 +17,16 @@
'libyuv',
're2',
],
+ 'conditions': [
+ ['USE_usb_camera_monocle == 1', {
+ 'deps': [
+ 'librealtek-sdk',
+ ],
+ 'defines': [
+ 'MONOCLE_QUIRKS=1',
+ ],
+ }],
+ ],
},
},
'targets': [
@@ -39,11 +49,19 @@
'frame_buffer.cc',
'image_processor.cc',
'metadata_handler.cc',
+ 'sensor_handler.cc',
'stream_format.cc',
'test_pattern.cc',
'v4l2_camera_device.cc',
'vendor_tag.cc',
],
+ 'conditions': [
+ ['USE_usb_camera_monocle == 1', {
+ 'sources': [
+ 'sensor_handler_monocle.cc',
+ ],
+ }],
+ ],
},
],
'conditions': [
diff --git a/camera/hal/usb/metadata_handler.cc b/camera/hal/usb/metadata_handler.cc
index b53735f..2a649d7 100644
--- a/camera/hal/usb/metadata_handler.cc
+++ b/camera/hal/usb/metadata_handler.cc
@@ -26,8 +26,10 @@
namespace cros {
-MetadataHandler::MetadataHandler(const camera_metadata_t& metadata)
- : af_trigger_(false) {
+MetadataHandler::MetadataHandler(const camera_metadata_t& metadata,
+ const DeviceInfo& device_info,
+ const SupportedFormats& supported_formats)
+ : device_info_(device_info), af_trigger_(false) {
// MetadataBase::operator= will make a copy of camera_metadata_t.
metadata_ = &metadata;
@@ -36,6 +38,8 @@
template_settings_[i] = CreateDefaultRequestSettings(i);
}
+ sensor_handler_ = SensorHandler::Create(device_info, supported_formats);
+
thread_checker_.DetachFromThread();
}
@@ -655,7 +659,8 @@
int MetadataHandler::PostHandleRequest(int frame_number,
int64_t timestamp,
- android::CameraMetadata* metadata) {
+ android::CameraMetadata* metadata,
+ const Size& resolution) {
DCHECK(thread_checker_.CalledOnValidThread());
if (current_frame_number_ != frame_number) {
LOGF(ERROR)
@@ -720,11 +725,11 @@
// Rolling shutter skew and exposure time values are fake due to ARCore
// test requirement.
- // TODO(henryhsu): Read the two values from camera.
- const int64_t rolling_shutter_skew = 33'300'000; // 33.3ms
+ const int64_t rolling_shutter_skew =
+ sensor_handler_->GetRollingShutterSkew(resolution);
UPDATE(ANDROID_SENSOR_ROLLING_SHUTTER_SKEW, &rolling_shutter_skew, 1);
- const int64_t exposure_time = 16'600'000; // 16.6ms
+ const int64_t exposure_time = sensor_handler_->GetExposureTime(resolution);
UPDATE(ANDROID_SENSOR_EXPOSURE_TIME, &exposure_time, 1);
// android.statistics
diff --git a/camera/hal/usb/metadata_handler.h b/camera/hal/usb/metadata_handler.h
index 8714052..7f34b73 100644
--- a/camera/hal/usb/metadata_handler.h
+++ b/camera/hal/usb/metadata_handler.h
@@ -13,6 +13,7 @@
#include <hardware/camera3.h>
#include "hal/usb/common_types.h"
+#include "hal/usb/sensor_handler.h"
namespace cros {
@@ -29,7 +30,9 @@
// CameraDevice.
class MetadataHandler {
public:
- explicit MetadataHandler(const camera_metadata_t& metadata);
+ MetadataHandler(const camera_metadata_t& metadata,
+ const DeviceInfo& device_info,
+ const SupportedFormats& supported_formats);
~MetadataHandler();
static int FillDefaultMetadata(android::CameraMetadata* metadata);
@@ -57,7 +60,8 @@
// required metadata which can be gotton from 3A or image processor.
int PostHandleRequest(int frame_number,
int64_t timestamp,
- android::CameraMetadata* metadata);
+ android::CameraMetadata* metadata,
+ const Size& resolution);
private:
// Check |template_type| is valid or not.
@@ -83,9 +87,15 @@
// thread.
base::ThreadChecker thread_checker_;
+ // Camera device information.
+ const DeviceInfo device_info_;
+
int current_frame_number_;
bool af_trigger_;
+
+ // Sensor handler to get sensor related metadata.
+ std::unique_ptr<SensorHandler> sensor_handler_;
};
} // namespace cros
diff --git a/camera/hal/usb/sensor_handler.cc b/camera/hal/usb/sensor_handler.cc
new file mode 100644
index 0000000..4961174
--- /dev/null
+++ b/camera/hal/usb/sensor_handler.cc
@@ -0,0 +1,33 @@
+/* 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/sensor_handler.h"
+
+#include "cros-camera/common.h"
+#if defined(MONOCLE_QUIRKS)
+#include "hal/usb/sensor_handler_monocle.h"
+#endif
+
+namespace cros {
+
+// static
+std::unique_ptr<SensorHandler> SensorHandler::Create(
+ const DeviceInfo& device_info, const SupportedFormats& supported_formats) {
+#if defined(MONOCLE_QUIRKS)
+ return std::make_unique<SensorHandlerMonocle>(device_info, supported_formats);
+#else
+ return std::make_unique<SensorHandlerDefault>();
+#endif
+}
+
+int64_t SensorHandlerDefault::GetRollingShutterSkew(const Size& resolution) {
+ return 33'300'000;
+}
+
+int64_t SensorHandlerDefault::GetExposureTime(const Size& resolution) {
+ return 16'600'000;
+}
+
+} // namespace cros
diff --git a/camera/hal/usb/sensor_handler.h b/camera/hal/usb/sensor_handler.h
new file mode 100644
index 0000000..070e5f3
--- /dev/null
+++ b/camera/hal/usb/sensor_handler.h
@@ -0,0 +1,39 @@
+/* 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_SENSOR_HANDLER_H_
+#define CAMERA_HAL_USB_SENSOR_HANDLER_H_
+
+#include <memory>
+
+#include "hal/usb/common_types.h"
+
+namespace cros {
+
+class SensorHandler {
+ public:
+ static std::unique_ptr<SensorHandler> Create(
+ const DeviceInfo& device_info, const SupportedFormats& supported_formats);
+ virtual ~SensorHandler() {}
+
+ // Get rolling shutter skew value. The return value unit is nano seconds.
+ virtual int64_t GetRollingShutterSkew(const Size& resolution) = 0;
+
+ // Get exposure time. The return value unit is nano seconds.
+ virtual int64_t GetExposureTime(const Size& resolution) = 0;
+};
+
+class SensorHandlerDefault : public SensorHandler {
+ public:
+ SensorHandlerDefault() {}
+ ~SensorHandlerDefault() override = default;
+
+ int64_t GetRollingShutterSkew(const Size& resolution) override;
+ int64_t GetExposureTime(const Size& resolution) override;
+};
+
+} // namespace cros
+
+#endif // CAMERA_HAL_USB_SENSOR_HANDLER_H_
diff --git a/camera/hal/usb/sensor_handler_monocle.cc b/camera/hal/usb/sensor_handler_monocle.cc
new file mode 100644
index 0000000..848d46d
--- /dev/null
+++ b/camera/hal/usb/sensor_handler_monocle.cc
@@ -0,0 +1,99 @@
+/* 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/sensor_handler_monocle.h"
+
+#include <string>
+
+#include <base/files/file_util.h>
+#include <rts_read_sensor.h>
+
+#include "cros-camera/common.h"
+
+namespace cros {
+
+SensorHandlerMonocle::SensorHandlerMonocle(
+ const DeviceInfo& device_info, const SupportedFormats& supported_formats)
+ : handle_(nullptr) {
+ if (!device_info.monocle_quirks) {
+ return;
+ }
+
+ base::FilePath target;
+ std::string device_path;
+ // SDK supposes the device path should be /dev/videoX.
+ if (base::ReadSymbolicLink(base::FilePath(device_info.device_path),
+ &target)) {
+ device_path = "/dev/" + target.BaseName().value();
+ } else {
+ device_path = device_info.device_path;
+ }
+ handle_ = rts_uvc_open(device_path.c_str());
+ if (handle_ == nullptr) {
+ LOGF(ERROR) << "Cannot open device to read sensor data: " << device_path;
+ }
+
+ InitSensorParameters(device_info, supported_formats);
+}
+
+SensorHandlerMonocle::~SensorHandlerMonocle() {
+ if (handle_)
+ rts_uvc_close(handle_);
+}
+
+void SensorHandlerMonocle::InitSensorParameters(
+ const DeviceInfo& device_info, const SupportedFormats& supported_formats) {
+ // TODO(henryhsu): Move to a config file.
+ if (device_info.usb_vid == "0bda" && device_info.usb_pid == "5647") {
+ // These parameters are from OV8856 specification.
+ // Initial exposure time parameters
+ SensorParameters param;
+ for (const auto& supported_format : supported_formats) {
+ if (supported_format.width == 3264 && supported_format.height == 2448) {
+ param.line_pixel_width = 3864;
+ param.line_count = 2452;
+ } else if (supported_format.width == 1920 &&
+ supported_format.height == 1080) {
+ param.line_pixel_width = 3200;
+ param.line_count = 1840;
+ } else {
+ param.line_pixel_width = 3864;
+ param.line_count = 1224;
+ }
+
+ param.readout_time = param.line_pixel_width * param.line_count *
+ 1'000'000'000 / kPixelClock_;
+ param.line_duration =
+ param.line_pixel_width * 1'000'000'000 / kPixelClock_;
+
+ Size resolution(supported_format.width, supported_format.height);
+ sensor_parameters_[resolution] = param;
+ }
+ }
+}
+
+int64_t SensorHandlerMonocle::GetRollingShutterSkew(const Size& resolution) {
+ if (sensor_parameters_.find(resolution) == sensor_parameters_.end()) {
+ return 33'300'000;
+ }
+ return sensor_parameters_[resolution].readout_time;
+}
+
+int64_t SensorHandlerMonocle::GetExposureTime(const Size& resolution) {
+ if (handle_ == nullptr ||
+ sensor_parameters_.find(resolution) == sensor_parameters_.end()) {
+ return 16'600'000;
+ }
+ uint64_t line_count = 0;
+ for (const auto& addr : kExposureTimeRegisters_) {
+ uint16_t value;
+ rts_read_sensor_reg(handle_, addr, &value);
+ line_count = (line_count << 8) | value;
+ }
+ line_count >>= kExposureTimeFractionBits_;
+ return sensor_parameters_[resolution].line_duration * line_count;
+}
+
+} // namespace cros
diff --git a/camera/hal/usb/sensor_handler_monocle.h b/camera/hal/usb/sensor_handler_monocle.h
new file mode 100644
index 0000000..827316c4
--- /dev/null
+++ b/camera/hal/usb/sensor_handler_monocle.h
@@ -0,0 +1,64 @@
+/* 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_SENSOR_HANDLER_MONOCLE_H_
+#define CAMERA_HAL_USB_SENSOR_HANDLER_MONOCLE_H_
+
+#include <map>
+#include <vector>
+
+#include "hal/usb/common_types.h"
+#include "hal/usb/sensor_handler.h"
+
+namespace cros {
+
+class SensorHandlerMonocle : public SensorHandler {
+ public:
+ // We need some information from sensor to calculate rolling shutter skew
+ // metadata. The metadata is different for each resolution.
+ struct SensorParameters {
+ // The number of pixels horizontally.
+ int64_t line_pixel_width;
+ // The line number vertically.
+ int64_t line_count;
+
+ // Cache calculated rolling shutter skew.
+ int64_t readout_time;
+ // Cache calculated line duration for exposure time.
+ int64_t line_duration;
+ };
+
+ SensorHandlerMonocle(const DeviceInfo& device_info,
+ const SupportedFormats& supported_formats);
+ ~SensorHandlerMonocle() override;
+
+ int64_t GetRollingShutterSkew(const Size& resolution) override;
+ int64_t GetExposureTime(const Size& resolution) override;
+
+ private:
+ // Initial sensor parameters for all resolutions by device info.
+ void InitSensorParameters(const DeviceInfo& device_info,
+ const SupportedFormats& supported_formats);
+
+ // Clock rate used in camera sensor. The unit is HZ.
+ static constexpr int64_t kPixelClock_ = 144'000'000;
+
+ // The sensor registers to export exposure time.
+ static constexpr uint32_t kExposureTimeRegisters_[] = {0x3500, 0x3501,
+ 0x3502};
+
+ // Exposure time parameters.
+ static constexpr uint32_t kExposureTimeFractionBits_ = 4;
+
+ // Sensor parameters for each resolution.
+ std::map<Size, SensorParameters> sensor_parameters_;
+
+ // file handle for third_party SDK to read sensor data.
+ void* handle_;
+};
+
+} // namespace cros
+
+#endif // CAMERA_HAL_USB_SENSOR_HANDLER_MONOCLE_H_
diff --git a/common-mk/common.gypi b/common-mk/common.gypi
index 96fcc10..1a64175 100644
--- a/common-mk/common.gypi
+++ b/common-mk/common.gypi
@@ -67,6 +67,7 @@
'USE_tpm2_simulator%': 0,
'USE_ubsan%': 0,
'USE_udev%': 0,
+ 'USE_usb_camera_monocle%': 0,
'USE_vpn%': 0,
'USE_wake_on_wifi%': 0,
'USE_wifi%': 0,
diff --git a/common-mk/platform2.py b/common-mk/platform2.py
index 4e542e1..489c485 100755
--- a/common-mk/platform2.py
+++ b/common-mk/platform2.py
@@ -76,6 +76,7 @@
'tpm2_simulator',
'ubsan',
'udev',
+ 'usb_camera_monocle',
'vpn',
'wake_on_wifi',
'wifi',