Commit 74a6f7fb authored by Christian Fremerey's avatar Christian Fremerey Committed by Commit Bot

[Video Capture, ChromeOS] Fix wrong rotation when starting capture with non-zero rotation

When starting video capture with a device that is rotated, e.g. a
convertible in portrait orientation, the rotation of the captured video
intermittently (most of the time) comes out wrong.

The root cause is that rotation events are ignored before capturing is
started but may end up arriving before.

This CL fixes this by storing the rotation in case rotation events are
received while capturing is not started.

Bug: 944215
Change-Id: I1346772341044c92be754d11d17a519397598df9
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/1540459Reviewed-by: default avatarRicky Liang <jcliang@chromium.org>
Reviewed-by: default avatarSheng-hao Tsao <shenghao@chromium.org>
Commit-Queue: Christian Fremerey <chfremer@chromium.org>
Cr-Commit-Position: refs/heads/master@{#644783}
parent f8a75eb0
...@@ -234,7 +234,8 @@ V4L2CaptureDelegate::V4L2CaptureDelegate( ...@@ -234,7 +234,8 @@ V4L2CaptureDelegate::V4L2CaptureDelegate(
V4L2CaptureDevice* v4l2, V4L2CaptureDevice* v4l2,
const VideoCaptureDeviceDescriptor& device_descriptor, const VideoCaptureDeviceDescriptor& device_descriptor,
const scoped_refptr<base::SingleThreadTaskRunner>& v4l2_task_runner, const scoped_refptr<base::SingleThreadTaskRunner>& v4l2_task_runner,
int power_line_frequency) int power_line_frequency,
int rotation)
: v4l2_(v4l2), : v4l2_(v4l2),
v4l2_task_runner_(v4l2_task_runner), v4l2_task_runner_(v4l2_task_runner),
device_descriptor_(device_descriptor), device_descriptor_(device_descriptor),
...@@ -242,7 +243,7 @@ V4L2CaptureDelegate::V4L2CaptureDelegate( ...@@ -242,7 +243,7 @@ V4L2CaptureDelegate::V4L2CaptureDelegate(
device_fd_(v4l2), device_fd_(v4l2),
is_capturing_(false), is_capturing_(false),
timeout_count_(0), timeout_count_(0),
rotation_(0), rotation_(rotation),
weak_factory_(this) {} weak_factory_(this) {}
void V4L2CaptureDelegate::AllocateAndStart( void V4L2CaptureDelegate::AllocateAndStart(
......
...@@ -51,7 +51,8 @@ class CAPTURE_EXPORT V4L2CaptureDelegate final { ...@@ -51,7 +51,8 @@ class CAPTURE_EXPORT V4L2CaptureDelegate final {
V4L2CaptureDevice* v4l2, V4L2CaptureDevice* v4l2,
const VideoCaptureDeviceDescriptor& device_descriptor, const VideoCaptureDeviceDescriptor& device_descriptor,
const scoped_refptr<base::SingleThreadTaskRunner>& v4l2_task_runner, const scoped_refptr<base::SingleThreadTaskRunner>& v4l2_task_runner,
int power_line_frequency); int power_line_frequency,
int rotation);
~V4L2CaptureDelegate(); ~V4L2CaptureDelegate();
// Forward-to versions of VideoCaptureDevice virtual methods. // Forward-to versions of VideoCaptureDevice virtual methods.
......
...@@ -182,7 +182,8 @@ class V4L2CaptureDelegateTest : public ::testing::Test { ...@@ -182,7 +182,8 @@ class V4L2CaptureDelegateTest : public ::testing::Test {
v4l2_.get(), v4l2_.get(),
device_descriptor_, device_descriptor_,
base::ThreadTaskRunnerHandle::Get(), base::ThreadTaskRunnerHandle::Get(),
50)) {} 50,
0)) {}
~V4L2CaptureDelegateTest() override = default; ~V4L2CaptureDelegateTest() override = default;
base::test::ScopedTaskEnvironment scoped_task_environment_; base::test::ScopedTaskEnvironment scoped_task_environment_;
......
...@@ -28,10 +28,12 @@ VideoCaptureDeviceChromeOS::VideoCaptureDeviceChromeOS( ...@@ -28,10 +28,12 @@ VideoCaptureDeviceChromeOS::VideoCaptureDeviceChromeOS(
ScreenObserverDelegate::Create(this, ui_task_runner)) {} ScreenObserverDelegate::Create(this, ui_task_runner)) {}
VideoCaptureDeviceChromeOS::~VideoCaptureDeviceChromeOS() { VideoCaptureDeviceChromeOS::~VideoCaptureDeviceChromeOS() {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
screen_observer_delegate_->RemoveObserver(); screen_observer_delegate_->RemoveObserver();
} }
void VideoCaptureDeviceChromeOS::SetRotation(int rotation) { void VideoCaptureDeviceChromeOS::SetRotation(int rotation) {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
if (!camera_config_.rotates_with_device) { if (!camera_config_.rotates_with_device) {
rotation = 0; rotation = 0;
} else if (camera_config_.lens_facing == } else if (camera_config_.lens_facing ==
...@@ -77,6 +79,7 @@ void VideoCaptureDeviceChromeOS::SetRotation(int rotation) { ...@@ -77,6 +79,7 @@ void VideoCaptureDeviceChromeOS::SetRotation(int rotation) {
void VideoCaptureDeviceChromeOS::SetDisplayRotation( void VideoCaptureDeviceChromeOS::SetDisplayRotation(
const display::Display& display) { const display::Display& display) {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
if (display.IsInternal()) if (display.IsInternal())
SetRotation(display.rotation() * 90); SetRotation(display.rotation() * 90);
} }
......
...@@ -51,8 +51,12 @@ class VideoCaptureDeviceChromeOS : public VideoCaptureDeviceLinux, ...@@ -51,8 +51,12 @@ class VideoCaptureDeviceChromeOS : public VideoCaptureDeviceLinux,
private: private:
// DisplayRotationObserver implementation. // DisplayRotationObserver implementation.
void SetDisplayRotation(const display::Display& display) override; void SetDisplayRotation(const display::Display& display) override;
const ChromeOSDeviceCameraConfig camera_config_; const ChromeOSDeviceCameraConfig camera_config_;
scoped_refptr<ScreenObserverDelegate> screen_observer_delegate_; scoped_refptr<ScreenObserverDelegate> screen_observer_delegate_;
SEQUENCE_CHECKER(sequence_checker_);
DISALLOW_IMPLICIT_CONSTRUCTORS(VideoCaptureDeviceChromeOS); DISALLOW_IMPLICIT_CONSTRUCTORS(VideoCaptureDeviceChromeOS);
}; };
......
...@@ -56,9 +56,11 @@ VideoCaptureDeviceLinux::VideoCaptureDeviceLinux( ...@@ -56,9 +56,11 @@ VideoCaptureDeviceLinux::VideoCaptureDeviceLinux(
const VideoCaptureDeviceDescriptor& device_descriptor) const VideoCaptureDeviceDescriptor& device_descriptor)
: device_descriptor_(device_descriptor), : device_descriptor_(device_descriptor),
v4l2_(std::move(v4l2)), v4l2_(std::move(v4l2)),
v4l2_thread_("V4L2CaptureThread") {} v4l2_thread_("V4L2CaptureThread"),
rotation_(0) {}
VideoCaptureDeviceLinux::~VideoCaptureDeviceLinux() { VideoCaptureDeviceLinux::~VideoCaptureDeviceLinux() {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
// Check if the thread is running. // Check if the thread is running.
// This means that the device has not been StopAndDeAllocate()d properly. // This means that the device has not been StopAndDeAllocate()d properly.
DCHECK(!v4l2_thread_.IsRunning()); DCHECK(!v4l2_thread_.IsRunning());
...@@ -68,6 +70,7 @@ VideoCaptureDeviceLinux::~VideoCaptureDeviceLinux() { ...@@ -68,6 +70,7 @@ VideoCaptureDeviceLinux::~VideoCaptureDeviceLinux() {
void VideoCaptureDeviceLinux::AllocateAndStart( void VideoCaptureDeviceLinux::AllocateAndStart(
const VideoCaptureParams& params, const VideoCaptureParams& params,
std::unique_ptr<VideoCaptureDevice::Client> client) { std::unique_ptr<VideoCaptureDevice::Client> client) {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
DCHECK(!capture_impl_); DCHECK(!capture_impl_);
if (v4l2_thread_.IsRunning()) if (v4l2_thread_.IsRunning())
return; // Wrong state. return; // Wrong state.
...@@ -77,7 +80,7 @@ void VideoCaptureDeviceLinux::AllocateAndStart( ...@@ -77,7 +80,7 @@ void VideoCaptureDeviceLinux::AllocateAndStart(
TranslatePowerLineFrequencyToV4L2(GetPowerLineFrequency(params)); TranslatePowerLineFrequencyToV4L2(GetPowerLineFrequency(params));
capture_impl_ = std::make_unique<V4L2CaptureDelegate>( capture_impl_ = std::make_unique<V4L2CaptureDelegate>(
v4l2_.get(), device_descriptor_, v4l2_thread_.task_runner(), v4l2_.get(), device_descriptor_, v4l2_thread_.task_runner(),
line_frequency); line_frequency, rotation_);
if (!capture_impl_) { if (!capture_impl_) {
client->OnError(VideoCaptureError:: client->OnError(VideoCaptureError::
kDeviceCaptureLinuxFailedToCreateVideoCaptureDelegate, kDeviceCaptureLinuxFailedToCreateVideoCaptureDelegate,
...@@ -98,6 +101,7 @@ void VideoCaptureDeviceLinux::AllocateAndStart( ...@@ -98,6 +101,7 @@ void VideoCaptureDeviceLinux::AllocateAndStart(
} }
void VideoCaptureDeviceLinux::StopAndDeAllocate() { void VideoCaptureDeviceLinux::StopAndDeAllocate() {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
if (!v4l2_thread_.IsRunning()) if (!v4l2_thread_.IsRunning())
return; // Wrong state. return; // Wrong state.
v4l2_thread_.task_runner()->PostTask( v4l2_thread_.task_runner()->PostTask(
...@@ -110,6 +114,7 @@ void VideoCaptureDeviceLinux::StopAndDeAllocate() { ...@@ -110,6 +114,7 @@ void VideoCaptureDeviceLinux::StopAndDeAllocate() {
} }
void VideoCaptureDeviceLinux::TakePhoto(TakePhotoCallback callback) { void VideoCaptureDeviceLinux::TakePhoto(TakePhotoCallback callback) {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
DCHECK(capture_impl_); DCHECK(capture_impl_);
auto functor = auto functor =
base::BindOnce(&V4L2CaptureDelegate::TakePhoto, base::BindOnce(&V4L2CaptureDelegate::TakePhoto,
...@@ -123,6 +128,7 @@ void VideoCaptureDeviceLinux::TakePhoto(TakePhotoCallback callback) { ...@@ -123,6 +128,7 @@ void VideoCaptureDeviceLinux::TakePhoto(TakePhotoCallback callback) {
} }
void VideoCaptureDeviceLinux::GetPhotoState(GetPhotoStateCallback callback) { void VideoCaptureDeviceLinux::GetPhotoState(GetPhotoStateCallback callback) {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
auto functor = auto functor =
base::BindOnce(&V4L2CaptureDelegate::GetPhotoState, base::BindOnce(&V4L2CaptureDelegate::GetPhotoState,
capture_impl_->GetWeakPtr(), std::move(callback)); capture_impl_->GetWeakPtr(), std::move(callback));
...@@ -137,6 +143,7 @@ void VideoCaptureDeviceLinux::GetPhotoState(GetPhotoStateCallback callback) { ...@@ -137,6 +143,7 @@ void VideoCaptureDeviceLinux::GetPhotoState(GetPhotoStateCallback callback) {
void VideoCaptureDeviceLinux::SetPhotoOptions( void VideoCaptureDeviceLinux::SetPhotoOptions(
mojom::PhotoSettingsPtr settings, mojom::PhotoSettingsPtr settings,
SetPhotoOptionsCallback callback) { SetPhotoOptionsCallback callback) {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
auto functor = base::BindOnce(&V4L2CaptureDelegate::SetPhotoOptions, auto functor = base::BindOnce(&V4L2CaptureDelegate::SetPhotoOptions,
capture_impl_->GetWeakPtr(), capture_impl_->GetWeakPtr(),
std::move(settings), std::move(callback)); std::move(settings), std::move(callback));
...@@ -149,6 +156,8 @@ void VideoCaptureDeviceLinux::SetPhotoOptions( ...@@ -149,6 +156,8 @@ void VideoCaptureDeviceLinux::SetPhotoOptions(
} }
void VideoCaptureDeviceLinux::SetRotation(int rotation) { void VideoCaptureDeviceLinux::SetRotation(int rotation) {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
rotation_ = rotation;
if (v4l2_thread_.IsRunning()) { if (v4l2_thread_.IsRunning()) {
v4l2_thread_.task_runner()->PostTask( v4l2_thread_.task_runner()->PostTask(
FROM_HERE, base::BindOnce(&V4L2CaptureDelegate::SetRotation, FROM_HERE, base::BindOnce(&V4L2CaptureDelegate::SetRotation,
......
...@@ -67,6 +67,13 @@ class VideoCaptureDeviceLinux : public VideoCaptureDevice { ...@@ -67,6 +67,13 @@ class VideoCaptureDeviceLinux : public VideoCaptureDevice {
base::Thread v4l2_thread_; // Thread used for reading data from the device. base::Thread v4l2_thread_; // Thread used for reading data from the device.
// SetRotation() may get called even when the device is not started. When that
// is the case we remember the value here and use it as soon as the device
// gets started.
int rotation_;
SEQUENCE_CHECKER(sequence_checker_);
DISALLOW_IMPLICIT_CONSTRUCTORS(VideoCaptureDeviceLinux); DISALLOW_IMPLICIT_CONSTRUCTORS(VideoCaptureDeviceLinux);
}; };
......
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