Commit 6c05239c authored by Heng-Ruey Hsu's avatar Heng-Ruey Hsu Committed by Chromium LUCI CQ

Add video capture device chromeos delegate

Simply rename *_halv3 to *_delegate to keep git history.
Add an intermediate layer to prepare further refactor to support
multiple streams.

Bug: b:151047537
Test: Manually
Change-Id: Ic2db36b003206972aabd70a5ceafd00e9f8f1c3e
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2351931
Commit-Queue: Heng-ruey Hsu <henryhsu@chromium.org>
Reviewed-by: default avatarMiguel Casas <mcasas@chromium.org>
Reviewed-by: default avatarWei Lee <wtlee@chromium.org>
Auto-Submit: Heng-ruey Hsu <henryhsu@chromium.org>
Cr-Commit-Position: refs/heads/master@{#834638}
parent 8898e9b2
...@@ -310,6 +310,8 @@ component("capture_lib") { ...@@ -310,6 +310,8 @@ component("capture_lib") {
"video/chromeos/token_manager.h", "video/chromeos/token_manager.h",
"video/chromeos/vendor_tag_ops_delegate.cc", "video/chromeos/vendor_tag_ops_delegate.cc",
"video/chromeos/vendor_tag_ops_delegate.h", "video/chromeos/vendor_tag_ops_delegate.h",
"video/chromeos/video_capture_device_chromeos_delegate.cc",
"video/chromeos/video_capture_device_chromeos_delegate.h",
"video/chromeos/video_capture_device_chromeos_halv3.cc", "video/chromeos/video_capture_device_chromeos_halv3.cc",
"video/chromeos/video_capture_device_chromeos_halv3.h", "video/chromeos/video_capture_device_chromeos_halv3.h",
"video/chromeos/video_capture_device_factory_chromeos.cc", "video/chromeos/video_capture_device_factory_chromeos.cc",
......
...@@ -25,6 +25,7 @@ ...@@ -25,6 +25,7 @@
#include "media/capture/video/chromeos/camera_buffer_factory.h" #include "media/capture/video/chromeos/camera_buffer_factory.h"
#include "media/capture/video/chromeos/camera_hal_dispatcher_impl.h" #include "media/capture/video/chromeos/camera_hal_dispatcher_impl.h"
#include "media/capture/video/chromeos/camera_metadata_utils.h" #include "media/capture/video/chromeos/camera_metadata_utils.h"
#include "media/capture/video/chromeos/video_capture_device_chromeos_delegate.h"
#include "media/capture/video/chromeos/video_capture_device_chromeos_halv3.h" #include "media/capture/video/chromeos/video_capture_device_chromeos_halv3.h"
namespace media { namespace media {
...@@ -205,13 +206,17 @@ std::unique_ptr<VideoCaptureDevice> CameraHalDelegate::CreateDevice( ...@@ -205,13 +206,17 @@ std::unique_ptr<VideoCaptureDevice> CameraHalDelegate::CreateDevice(
bridge->OnDeviceClosed(device_id); bridge->OnDeviceClosed(device_id);
}, },
device_descriptor.device_id, camera_app_device_bridge); device_descriptor.device_id, camera_app_device_bridge);
return std::make_unique<VideoCaptureDeviceChromeOSHalv3>( auto delegate = std::make_unique<VideoCaptureDeviceChromeOSDelegate>(
std::move(task_runner_for_screen_observer), device_descriptor, this, std::move(task_runner_for_screen_observer), device_descriptor, this,
camera_app_device, std::move(cleanup_callback)); camera_app_device, std::move(cleanup_callback));
} else {
return std::make_unique<VideoCaptureDeviceChromeOSHalv3>( return std::make_unique<VideoCaptureDeviceChromeOSHalv3>(
std::move(delegate));
} else {
auto delegate = std::make_unique<VideoCaptureDeviceChromeOSDelegate>(
std::move(task_runner_for_screen_observer), device_descriptor, this, std::move(task_runner_for_screen_observer), device_descriptor, this,
nullptr, base::DoNothing()); nullptr, base::DoNothing());
return std::make_unique<VideoCaptureDeviceChromeOSHalv3>(
std::move(delegate));
} }
} }
......
// Copyright 2017 The Chromium 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 "media/capture/video/chromeos/video_capture_device_chromeos_delegate.h"
#include <memory>
#include <string>
#include <utility>
#include "base/bind.h"
#include "base/callback_helpers.h"
#include "base/location.h"
#include "base/synchronization/waitable_event.h"
#include "base/threading/platform_thread.h"
#include "base/trace_event/trace_event.h"
#include "chromeos/dbus/power/power_manager_client.h"
#include "media/base/bind_to_current_loop.h"
#include "media/capture/video/chromeos/camera_device_delegate.h"
#include "media/capture/video/chromeos/camera_hal_delegate.h"
#include "ui/display/display.h"
#include "ui/display/display_observer.h"
#include "ui/display/screen.h"
namespace media {
class VideoCaptureDeviceChromeOSDelegate::PowerManagerClientProxy
: public base::RefCountedThreadSafe<PowerManagerClientProxy>,
public chromeos::PowerManagerClient::Observer {
public:
PowerManagerClientProxy() = default;
void Init(base::WeakPtr<VideoCaptureDeviceChromeOSDelegate> device,
scoped_refptr<base::SingleThreadTaskRunner> device_task_runner,
scoped_refptr<base::SingleThreadTaskRunner> dbus_task_runner) {
device_ = std::move(device);
device_task_runner_ = std::move(device_task_runner);
dbus_task_runner_ = std::move(dbus_task_runner);
dbus_task_runner_->PostTask(
FROM_HERE,
base::BindOnce(&PowerManagerClientProxy::InitOnDBusThread, this));
}
void Shutdown() {
dbus_task_runner_->PostTask(
FROM_HERE,
base::BindOnce(&PowerManagerClientProxy::ShutdownOnDBusThread, this));
}
void UnblockSuspend(const base::UnguessableToken& unblock_suspend_token) {
dbus_task_runner_->PostTask(
FROM_HERE,
base::BindOnce(&PowerManagerClientProxy::UnblockSuspendOnDBusThread,
this, unblock_suspend_token));
}
private:
friend class base::RefCountedThreadSafe<PowerManagerClientProxy>;
~PowerManagerClientProxy() override = default;
void InitOnDBusThread() {
DCHECK(dbus_task_runner_->RunsTasksInCurrentSequence());
chromeos::PowerManagerClient::Get()->AddObserver(this);
}
void ShutdownOnDBusThread() {
DCHECK(dbus_task_runner_->RunsTasksInCurrentSequence());
chromeos::PowerManagerClient::Get()->RemoveObserver(this);
}
void UnblockSuspendOnDBusThread(
const base::UnguessableToken& unblock_suspend_token) {
DCHECK(dbus_task_runner_->RunsTasksInCurrentSequence());
chromeos::PowerManagerClient::Get()->UnblockSuspend(unblock_suspend_token);
}
// chromeos::PowerManagerClient::Observer:
void SuspendImminent(power_manager::SuspendImminent::Reason reason) final {
auto token = base::UnguessableToken::Create();
chromeos::PowerManagerClient::Get()->BlockSuspend(
token, "VideoCaptureDeviceChromeOSDelegate");
device_task_runner_->PostTask(
FROM_HERE,
base::BindOnce(&VideoCaptureDeviceChromeOSDelegate::CloseDevice,
device_, token));
}
void SuspendDone(base::TimeDelta sleep_duration) final {
device_task_runner_->PostTask(
FROM_HERE,
base::BindOnce(&VideoCaptureDeviceChromeOSDelegate::OpenDevice,
device_));
}
base::WeakPtr<VideoCaptureDeviceChromeOSDelegate> device_;
scoped_refptr<base::SingleThreadTaskRunner> device_task_runner_;
scoped_refptr<base::SingleThreadTaskRunner> dbus_task_runner_;
DISALLOW_COPY_AND_ASSIGN(PowerManagerClientProxy);
};
VideoCaptureDeviceChromeOSDelegate::VideoCaptureDeviceChromeOSDelegate(
scoped_refptr<base::SingleThreadTaskRunner> ui_task_runner,
const VideoCaptureDeviceDescriptor& device_descriptor,
scoped_refptr<CameraHalDelegate> camera_hal_delegate,
CameraAppDeviceImpl* camera_app_device,
base::OnceClosure cleanup_callback)
: device_descriptor_(device_descriptor),
camera_hal_delegate_(std::move(camera_hal_delegate)),
capture_task_runner_(base::ThreadTaskRunnerHandle::Get()),
camera_device_ipc_thread_(std::string("CameraDeviceIpcThread") +
device_descriptor.device_id),
screen_observer_delegate_(
ScreenObserverDelegate::Create(this, ui_task_runner)),
lens_facing_(device_descriptor.facing),
// External cameras have lens_facing as MEDIA_VIDEO_FACING_NONE.
// We don't want to rotate the frame even if the device rotates.
rotates_with_device_(lens_facing_ !=
VideoFacingMode::MEDIA_VIDEO_FACING_NONE),
rotation_(0),
camera_app_device_(camera_app_device),
cleanup_callback_(std::move(cleanup_callback)),
power_manager_client_proxy_(
base::MakeRefCounted<PowerManagerClientProxy>()),
client_type_(ClientType::kPreviewClient) {
power_manager_client_proxy_->Init(weak_ptr_factory_.GetWeakPtr(),
capture_task_runner_,
std::move(ui_task_runner));
}
VideoCaptureDeviceChromeOSDelegate::~VideoCaptureDeviceChromeOSDelegate() {
DCHECK(capture_task_runner_->BelongsToCurrentThread());
DCHECK(!camera_device_ipc_thread_.IsRunning());
screen_observer_delegate_->RemoveObserver();
power_manager_client_proxy_->Shutdown();
std::move(cleanup_callback_).Run();
}
// VideoCaptureDevice implementation.
void VideoCaptureDeviceChromeOSDelegate::AllocateAndStart(
const VideoCaptureParams& params,
std::unique_ptr<Client> client) {
DCHECK(capture_task_runner_->BelongsToCurrentThread());
DCHECK(!camera_device_delegate_);
TRACE_EVENT0("camera", "Start Device");
if (!camera_device_ipc_thread_.Start()) {
std::string error_msg = "Failed to start device thread";
LOG(ERROR) << error_msg;
client->OnError(
media::VideoCaptureError::kCrosHalV3FailedToStartDeviceThread,
FROM_HERE, error_msg);
return;
}
capture_params_ = params;
device_context_ = std::make_unique<CameraDeviceContext>();
if (device_context_->AddClient(client_type_, std::move(client))) {
camera_device_delegate_ = std::make_unique<CameraDeviceDelegate>(
device_descriptor_, camera_hal_delegate_,
camera_device_ipc_thread_.task_runner(), camera_app_device_,
client_type_);
OpenDevice();
}
}
void VideoCaptureDeviceChromeOSDelegate::StopAndDeAllocate() {
DCHECK(capture_task_runner_->BelongsToCurrentThread());
if (!camera_device_delegate_) {
return;
}
CloseDevice(base::UnguessableToken());
camera_device_ipc_thread_.Stop();
camera_device_delegate_.reset();
device_context_->RemoveClient(client_type_);
device_context_.reset();
}
void VideoCaptureDeviceChromeOSDelegate::TakePhoto(TakePhotoCallback callback) {
DCHECK(capture_task_runner_->BelongsToCurrentThread());
DCHECK(camera_device_delegate_);
camera_device_ipc_thread_.task_runner()->PostTask(
FROM_HERE, base::BindOnce(&CameraDeviceDelegate::TakePhoto,
camera_device_delegate_->GetWeakPtr(),
std::move(callback)));
}
void VideoCaptureDeviceChromeOSDelegate::GetPhotoState(
GetPhotoStateCallback callback) {
DCHECK(capture_task_runner_->BelongsToCurrentThread());
camera_device_ipc_thread_.task_runner()->PostTask(
FROM_HERE, base::BindOnce(&CameraDeviceDelegate::GetPhotoState,
camera_device_delegate_->GetWeakPtr(),
std::move(callback)));
}
void VideoCaptureDeviceChromeOSDelegate::SetPhotoOptions(
mojom::PhotoSettingsPtr settings,
SetPhotoOptionsCallback callback) {
DCHECK(capture_task_runner_->BelongsToCurrentThread());
camera_device_ipc_thread_.task_runner()->PostTask(
FROM_HERE, base::BindOnce(&CameraDeviceDelegate::SetPhotoOptions,
camera_device_delegate_->GetWeakPtr(),
std::move(settings), std::move(callback)));
}
void VideoCaptureDeviceChromeOSDelegate::OpenDevice() {
DCHECK(capture_task_runner_->BelongsToCurrentThread());
if (!camera_device_delegate_) {
return;
}
// It's safe to pass unretained |device_context_| here since
// VideoCaptureDeviceChromeOSDelegate owns |camera_device_delegate_| and makes
// sure |device_context_| outlives |camera_device_delegate_|.
camera_device_ipc_thread_.task_runner()->PostTask(
FROM_HERE,
base::BindOnce(&CameraDeviceDelegate::AllocateAndStart,
camera_device_delegate_->GetWeakPtr(), capture_params_,
base::Unretained(device_context_.get())));
camera_device_ipc_thread_.task_runner()->PostTask(
FROM_HERE,
base::BindOnce(&CameraDeviceDelegate::SetRotation,
camera_device_delegate_->GetWeakPtr(), rotation_));
}
void VideoCaptureDeviceChromeOSDelegate::CloseDevice(
base::UnguessableToken unblock_suspend_token) {
DCHECK(capture_task_runner_->BelongsToCurrentThread());
if (!camera_device_delegate_) {
return;
}
// We do our best to allow the camera HAL cleanly shut down the device. In
// general we don't trust the camera HAL so if the device does not close in
// time we simply terminate the Mojo channel by resetting
// |camera_device_delegate_|.
base::WaitableEvent device_closed(
base::WaitableEvent::ResetPolicy::MANUAL,
base::WaitableEvent::InitialState::NOT_SIGNALED);
camera_device_ipc_thread_.task_runner()->PostTask(
FROM_HERE, base::BindOnce(&CameraDeviceDelegate::StopAndDeAllocate,
camera_device_delegate_->GetWeakPtr(),
base::BindOnce(
[](base::WaitableEvent* device_closed) {
device_closed->Signal();
},
base::Unretained(&device_closed))));
base::TimeDelta kWaitTimeoutSecs = base::TimeDelta::FromSeconds(3);
device_closed.TimedWait(kWaitTimeoutSecs);
if (!unblock_suspend_token.is_empty())
power_manager_client_proxy_->UnblockSuspend(unblock_suspend_token);
}
void VideoCaptureDeviceChromeOSDelegate::SetDisplayRotation(
const display::Display& display) {
DCHECK(capture_task_runner_->BelongsToCurrentThread());
if (display.IsInternal())
SetRotation(display.rotation() * 90);
}
void VideoCaptureDeviceChromeOSDelegate::SetRotation(int rotation) {
DCHECK(capture_task_runner_->BelongsToCurrentThread());
if (!rotates_with_device_) {
rotation = 0;
} else if (lens_facing_ == VideoFacingMode::MEDIA_VIDEO_FACING_ENVIRONMENT) {
// Original frame when |rotation| = 0
// -----------------------
// | * |
// | * * |
// | * * |
// | ******* |
// | * * |
// | * * |
// -----------------------
//
// |rotation| = 90, this is what back camera sees
// -----------------------
// | ******** |
// | * **** |
// | * *** |
// | * *** |
// | * **** |
// | ******** |
// -----------------------
//
// |rotation| = 90, this is what front camera sees
// -----------------------
// | ******** |
// | **** * |
// | *** * |
// | *** * |
// | **** * |
// | ******** |
// -----------------------
//
// Therefore, for back camera, we need to rotate (360 - |rotation|).
rotation = (360 - rotation) % 360;
}
rotation_ = rotation;
if (camera_device_ipc_thread_.IsRunning()) {
camera_device_ipc_thread_.task_runner()->PostTask(
FROM_HERE,
base::BindOnce(&CameraDeviceDelegate::SetRotation,
camera_device_delegate_->GetWeakPtr(), rotation_));
}
}
} // namespace media
// Copyright 2017 The Chromium 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 MEDIA_CAPTURE_VIDEO_CHROMEOS_VIDEO_CAPTURE_DEVICE_CHROMEOS_DELEGATE_H_
#define MEDIA_CAPTURE_VIDEO_CHROMEOS_VIDEO_CAPTURE_DEVICE_CHROMEOS_DELEGATE_H_
#include <memory>
#include "base/macros.h"
#include "base/memory/weak_ptr.h"
#include "base/single_thread_task_runner.h"
#include "base/threading/thread.h"
#include "media/capture/video/chromeos/camera_device_context.h"
#include "media/capture/video/chromeos/display_rotation_observer.h"
#include "media/capture/video/video_capture_device.h"
#include "media/capture/video/video_capture_device_descriptor.h"
#include "media/capture/video_capture_types.h"
namespace display {
class Display;
} // namespace display
namespace media {
class CameraAppDeviceImpl;
class CameraHalDelegate;
class CameraDeviceDelegate;
// Implementation of VideoCaptureDevice for ChromeOS with CrOS camera HALv3.
class CAPTURE_EXPORT VideoCaptureDeviceChromeOSDelegate final
: public VideoCaptureDevice,
public DisplayRotationObserver {
public:
VideoCaptureDeviceChromeOSDelegate(
scoped_refptr<base::SingleThreadTaskRunner> ui_task_runner,
const VideoCaptureDeviceDescriptor& device_descriptor,
scoped_refptr<CameraHalDelegate> camera_hal_delegate,
CameraAppDeviceImpl* camera_app_device,
base::OnceClosure cleanup_callback);
~VideoCaptureDeviceChromeOSDelegate() final;
// VideoCaptureDevice implementation.
void AllocateAndStart(const VideoCaptureParams& params,
std::unique_ptr<Client> client) final;
void StopAndDeAllocate() final;
void TakePhoto(TakePhotoCallback callback) final;
void GetPhotoState(GetPhotoStateCallback callback) final;
void SetPhotoOptions(mojom::PhotoSettingsPtr settings,
SetPhotoOptionsCallback callback) final;
private:
// Helper to interact with PowerManagerClient on DBus original thread.
class PowerManagerClientProxy;
void OpenDevice();
void CloseDevice(base::UnguessableToken unblock_suspend_token);
// DisplayRotationDelegate implementation.
void SetDisplayRotation(const display::Display& display) final;
void SetRotation(int rotation);
const VideoCaptureDeviceDescriptor device_descriptor_;
// A reference to the CameraHalDelegate instance in the VCD factory. This is
// used by AllocateAndStart to query camera info and create the camera device.
const scoped_refptr<CameraHalDelegate> camera_hal_delegate_;
// A reference to the thread that all the VideoCaptureDevice interface methods
// are expected to be called on.
const scoped_refptr<base::SingleThreadTaskRunner> capture_task_runner_;
// The thread that all the Mojo operations of |camera_device_delegate_| take
// place. Started in AllocateAndStart and stopped in StopAndDeAllocate, where
// the access to the base::Thread methods are sequenced on
// |capture_task_runner_|.
base::Thread camera_device_ipc_thread_;
VideoCaptureParams capture_params_;
// |device_context_| is created and owned by
// VideoCaptureDeviceChromeOSDelegate and is only accessed by
// |camera_device_delegate_|.
std::unique_ptr<CameraDeviceContext> device_context_;
// Internal delegate doing the actual capture setting, buffer allocation and
// circulation with the camera HAL. Created in AllocateAndStart and deleted in
// StopAndDeAllocate on |capture_task_runner_|. All methods of
// |camera_device_delegate_| operate on |camera_device_ipc_thread_|.
std::unique_ptr<CameraDeviceDelegate> camera_device_delegate_;
scoped_refptr<ScreenObserverDelegate> screen_observer_delegate_;
const VideoFacingMode lens_facing_;
// Whether the incoming frames should rotate when the device rotates.
const bool rotates_with_device_;
int rotation_;
CameraAppDeviceImpl* camera_app_device_; // Weak.
base::OnceClosure cleanup_callback_;
scoped_refptr<PowerManagerClientProxy> power_manager_client_proxy_;
// The client type in CameraDeviceContext.
ClientType client_type_;
base::WeakPtrFactory<VideoCaptureDeviceChromeOSDelegate> weak_ptr_factory_{
this};
DISALLOW_IMPLICIT_CONSTRUCTORS(VideoCaptureDeviceChromeOSDelegate);
};
} // namespace media
#endif // MEDIA_CAPTURE_VIDEO_CHROMEOS_VIDEO_CAPTURE_DEVICE_CHROMEOS_DELEGATE_H_
// Copyright 2017 The Chromium Authors. All rights reserved. // Copyright 2020 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be // Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file. // found in the LICENSE file.
#include "media/capture/video/chromeos/video_capture_device_chromeos_halv3.h" #include "media/capture/video/chromeos/video_capture_device_chromeos_halv3.h"
#include <memory> #include "media/capture/video/chromeos/video_capture_device_chromeos_delegate.h"
#include <string>
#include <utility>
#include "base/bind.h"
#include "base/callback_helpers.h"
#include "base/location.h"
#include "base/synchronization/waitable_event.h"
#include "base/threading/platform_thread.h"
#include "base/trace_event/trace_event.h"
#include "chromeos/dbus/power/power_manager_client.h"
#include "media/base/bind_to_current_loop.h"
#include "media/capture/video/chromeos/camera_device_context.h"
#include "media/capture/video/chromeos/camera_device_delegate.h"
#include "media/capture/video/chromeos/camera_hal_delegate.h"
#include "ui/display/display.h"
#include "ui/display/display_observer.h"
#include "ui/display/screen.h"
namespace media { namespace media {
class VideoCaptureDeviceChromeOSHalv3::PowerManagerClientProxy
: public base::RefCountedThreadSafe<PowerManagerClientProxy>,
public chromeos::PowerManagerClient::Observer {
public:
PowerManagerClientProxy() = default;
void Init(base::WeakPtr<VideoCaptureDeviceChromeOSHalv3> device,
scoped_refptr<base::SingleThreadTaskRunner> device_task_runner,
scoped_refptr<base::SingleThreadTaskRunner> dbus_task_runner) {
device_ = std::move(device);
device_task_runner_ = std::move(device_task_runner);
dbus_task_runner_ = std::move(dbus_task_runner);
dbus_task_runner_->PostTask(
FROM_HERE,
base::BindOnce(&PowerManagerClientProxy::InitOnDBusThread, this));
}
void Shutdown() {
dbus_task_runner_->PostTask(
FROM_HERE,
base::BindOnce(&PowerManagerClientProxy::ShutdownOnDBusThread, this));
}
void UnblockSuspend(const base::UnguessableToken& unblock_suspend_token) {
dbus_task_runner_->PostTask(
FROM_HERE,
base::BindOnce(&PowerManagerClientProxy::UnblockSuspendOnDBusThread,
this, unblock_suspend_token));
}
private:
friend class base::RefCountedThreadSafe<PowerManagerClientProxy>;
~PowerManagerClientProxy() override = default;
void InitOnDBusThread() {
DCHECK(dbus_task_runner_->RunsTasksInCurrentSequence());
chromeos::PowerManagerClient::Get()->AddObserver(this);
}
void ShutdownOnDBusThread() {
DCHECK(dbus_task_runner_->RunsTasksInCurrentSequence());
chromeos::PowerManagerClient::Get()->RemoveObserver(this);
}
void UnblockSuspendOnDBusThread(
const base::UnguessableToken& unblock_suspend_token) {
DCHECK(dbus_task_runner_->RunsTasksInCurrentSequence());
chromeos::PowerManagerClient::Get()->UnblockSuspend(unblock_suspend_token);
}
// chromeos::PowerManagerClient::Observer:
void SuspendImminent(power_manager::SuspendImminent::Reason reason) final {
auto token = base::UnguessableToken::Create();
chromeos::PowerManagerClient::Get()->BlockSuspend(
token, "VideoCaptureDeviceChromeOSHalv3");
device_task_runner_->PostTask(
FROM_HERE, base::BindOnce(&VideoCaptureDeviceChromeOSHalv3::CloseDevice,
device_, token));
}
void SuspendDone(base::TimeDelta sleep_duration) final {
device_task_runner_->PostTask(
FROM_HERE,
base::BindOnce(&VideoCaptureDeviceChromeOSHalv3::OpenDevice, device_));
}
base::WeakPtr<VideoCaptureDeviceChromeOSHalv3> device_;
scoped_refptr<base::SingleThreadTaskRunner> device_task_runner_;
scoped_refptr<base::SingleThreadTaskRunner> dbus_task_runner_;
DISALLOW_COPY_AND_ASSIGN(PowerManagerClientProxy);
};
VideoCaptureDeviceChromeOSHalv3::VideoCaptureDeviceChromeOSHalv3( VideoCaptureDeviceChromeOSHalv3::VideoCaptureDeviceChromeOSHalv3(
scoped_refptr<base::SingleThreadTaskRunner> ui_task_runner, std::unique_ptr<VideoCaptureDeviceChromeOSDelegate> delegate)
const VideoCaptureDeviceDescriptor& device_descriptor, : vcd_delegate_(std::move(delegate)) {}
scoped_refptr<CameraHalDelegate> camera_hal_delegate,
CameraAppDeviceImpl* camera_app_device,
base::OnceClosure cleanup_callback)
: device_descriptor_(device_descriptor),
camera_hal_delegate_(std::move(camera_hal_delegate)),
capture_task_runner_(base::ThreadTaskRunnerHandle::Get()),
camera_device_ipc_thread_(std::string("CameraDeviceIpcThread") +
device_descriptor.device_id),
screen_observer_delegate_(
ScreenObserverDelegate::Create(this, ui_task_runner)),
lens_facing_(device_descriptor.facing),
// External cameras have lens_facing as MEDIA_VIDEO_FACING_NONE.
// We don't want to rotate the frame even if the device rotates.
rotates_with_device_(lens_facing_ !=
VideoFacingMode::MEDIA_VIDEO_FACING_NONE),
rotation_(0),
camera_app_device_(camera_app_device),
cleanup_callback_(std::move(cleanup_callback)),
power_manager_client_proxy_(
base::MakeRefCounted<PowerManagerClientProxy>()),
client_type_(ClientType::kPreviewClient) {
power_manager_client_proxy_->Init(weak_ptr_factory_.GetWeakPtr(),
capture_task_runner_,
std::move(ui_task_runner));
}
VideoCaptureDeviceChromeOSHalv3::~VideoCaptureDeviceChromeOSHalv3() { VideoCaptureDeviceChromeOSHalv3::~VideoCaptureDeviceChromeOSHalv3() {
DCHECK(capture_task_runner_->BelongsToCurrentThread());
DCHECK(!camera_device_ipc_thread_.IsRunning());
screen_observer_delegate_->RemoveObserver();
power_manager_client_proxy_->Shutdown();
std::move(cleanup_callback_).Run();
} }
// VideoCaptureDevice implementation. // VideoCaptureDevice implementation.
void VideoCaptureDeviceChromeOSHalv3::AllocateAndStart( void VideoCaptureDeviceChromeOSHalv3::AllocateAndStart(
const VideoCaptureParams& params, const VideoCaptureParams& params,
std::unique_ptr<Client> client) { std::unique_ptr<Client> client) {
DCHECK(capture_task_runner_->BelongsToCurrentThread()); vcd_delegate_->AllocateAndStart(params, std::move(client));
DCHECK(!camera_device_delegate_);
TRACE_EVENT0("camera", "Start Device");
if (!camera_device_ipc_thread_.Start()) {
std::string error_msg = "Failed to start device thread";
LOG(ERROR) << error_msg;
client->OnError(
media::VideoCaptureError::kCrosHalV3FailedToStartDeviceThread,
FROM_HERE, error_msg);
return;
}
capture_params_ = params;
device_context_ = std::make_unique<CameraDeviceContext>();
if (device_context_->AddClient(client_type_, std::move(client))) {
camera_device_delegate_ = std::make_unique<CameraDeviceDelegate>(
device_descriptor_, camera_hal_delegate_,
camera_device_ipc_thread_.task_runner(), camera_app_device_,
client_type_);
OpenDevice();
}
} }
void VideoCaptureDeviceChromeOSHalv3::StopAndDeAllocate() { void VideoCaptureDeviceChromeOSHalv3::StopAndDeAllocate() {
DCHECK(capture_task_runner_->BelongsToCurrentThread()); vcd_delegate_->StopAndDeAllocate();
if (!camera_device_delegate_) {
return;
}
CloseDevice(base::UnguessableToken());
camera_device_ipc_thread_.Stop();
camera_device_delegate_.reset();
device_context_->RemoveClient(client_type_);
device_context_.reset();
} }
void VideoCaptureDeviceChromeOSHalv3::TakePhoto(TakePhotoCallback callback) { void VideoCaptureDeviceChromeOSHalv3::TakePhoto(TakePhotoCallback callback) {
DCHECK(capture_task_runner_->BelongsToCurrentThread()); vcd_delegate_->TakePhoto(std::move(callback));
DCHECK(camera_device_delegate_);
camera_device_ipc_thread_.task_runner()->PostTask(
FROM_HERE, base::BindOnce(&CameraDeviceDelegate::TakePhoto,
camera_device_delegate_->GetWeakPtr(),
std::move(callback)));
} }
void VideoCaptureDeviceChromeOSHalv3::GetPhotoState( void VideoCaptureDeviceChromeOSHalv3::GetPhotoState(
GetPhotoStateCallback callback) { GetPhotoStateCallback callback) {
DCHECK(capture_task_runner_->BelongsToCurrentThread()); vcd_delegate_->GetPhotoState(std::move(callback));
camera_device_ipc_thread_.task_runner()->PostTask(
FROM_HERE, base::BindOnce(&CameraDeviceDelegate::GetPhotoState,
camera_device_delegate_->GetWeakPtr(),
std::move(callback)));
} }
void VideoCaptureDeviceChromeOSHalv3::SetPhotoOptions( void VideoCaptureDeviceChromeOSHalv3::SetPhotoOptions(
mojom::PhotoSettingsPtr settings, mojom::PhotoSettingsPtr settings,
SetPhotoOptionsCallback callback) { SetPhotoOptionsCallback callback) {
DCHECK(capture_task_runner_->BelongsToCurrentThread()); vcd_delegate_->SetPhotoOptions(std::move(settings), std::move(callback));
camera_device_ipc_thread_.task_runner()->PostTask(
FROM_HERE, base::BindOnce(&CameraDeviceDelegate::SetPhotoOptions,
camera_device_delegate_->GetWeakPtr(),
std::move(settings), std::move(callback)));
}
void VideoCaptureDeviceChromeOSHalv3::OpenDevice() {
DCHECK(capture_task_runner_->BelongsToCurrentThread());
if (!camera_device_delegate_) {
return;
}
// It's safe to pass unretained |device_context_| here since
// VideoCaptureDeviceChromeOSHalv3 owns |camera_device_delegate_| and makes
// sure |device_context_| outlives |camera_device_delegate_|.
camera_device_ipc_thread_.task_runner()->PostTask(
FROM_HERE,
base::BindOnce(&CameraDeviceDelegate::AllocateAndStart,
camera_device_delegate_->GetWeakPtr(), capture_params_,
base::Unretained(device_context_.get())));
camera_device_ipc_thread_.task_runner()->PostTask(
FROM_HERE,
base::BindOnce(&CameraDeviceDelegate::SetRotation,
camera_device_delegate_->GetWeakPtr(), rotation_));
}
void VideoCaptureDeviceChromeOSHalv3::CloseDevice(
base::UnguessableToken unblock_suspend_token) {
DCHECK(capture_task_runner_->BelongsToCurrentThread());
if (!camera_device_delegate_) {
return;
}
// We do our best to allow the camera HAL cleanly shut down the device. In
// general we don't trust the camera HAL so if the device does not close in
// time we simply terminate the Mojo channel by resetting
// |camera_device_delegate_|.
base::WaitableEvent device_closed(
base::WaitableEvent::ResetPolicy::MANUAL,
base::WaitableEvent::InitialState::NOT_SIGNALED);
camera_device_ipc_thread_.task_runner()->PostTask(
FROM_HERE, base::BindOnce(&CameraDeviceDelegate::StopAndDeAllocate,
camera_device_delegate_->GetWeakPtr(),
base::BindOnce(
[](base::WaitableEvent* device_closed) {
device_closed->Signal();
},
base::Unretained(&device_closed))));
base::TimeDelta kWaitTimeoutSecs = base::TimeDelta::FromSeconds(3);
device_closed.TimedWait(kWaitTimeoutSecs);
if (!unblock_suspend_token.is_empty())
power_manager_client_proxy_->UnblockSuspend(unblock_suspend_token);
}
void VideoCaptureDeviceChromeOSHalv3::SetDisplayRotation(
const display::Display& display) {
DCHECK(capture_task_runner_->BelongsToCurrentThread());
if (display.IsInternal())
SetRotation(display.rotation() * 90);
}
void VideoCaptureDeviceChromeOSHalv3::SetRotation(int rotation) {
DCHECK(capture_task_runner_->BelongsToCurrentThread());
if (!rotates_with_device_) {
rotation = 0;
} else if (lens_facing_ == VideoFacingMode::MEDIA_VIDEO_FACING_ENVIRONMENT) {
// Original frame when |rotation| = 0
// -----------------------
// | * |
// | * * |
// | * * |
// | ******* |
// | * * |
// | * * |
// -----------------------
//
// |rotation| = 90, this is what back camera sees
// -----------------------
// | ******** |
// | * **** |
// | * *** |
// | * *** |
// | * **** |
// | ******** |
// -----------------------
//
// |rotation| = 90, this is what front camera sees
// -----------------------
// | ******** |
// | **** * |
// | *** * |
// | *** * |
// | **** * |
// | ******** |
// -----------------------
//
// Therefore, for back camera, we need to rotate (360 - |rotation|).
rotation = (360 - rotation) % 360;
}
rotation_ = rotation;
if (camera_device_ipc_thread_.IsRunning()) {
camera_device_ipc_thread_.task_runner()->PostTask(
FROM_HERE,
base::BindOnce(&CameraDeviceDelegate::SetRotation,
camera_device_delegate_->GetWeakPtr(), rotation_));
}
} }
} // namespace media } // namespace media
// Copyright 2017 The Chromium Authors. All rights reserved. // Copyright 2020 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be // Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file. // found in the LICENSE file.
...@@ -7,39 +7,18 @@ ...@@ -7,39 +7,18 @@
#include <memory> #include <memory>
#include "base/macros.h"
#include "base/memory/weak_ptr.h"
#include "base/single_thread_task_runner.h"
#include "base/threading/thread.h"
#include "media/capture/video/chromeos/camera_device_context.h"
#include "media/capture/video/chromeos/display_rotation_observer.h"
#include "media/capture/video/video_capture_device.h" #include "media/capture/video/video_capture_device.h"
#include "media/capture/video/video_capture_device_descriptor.h"
#include "media/capture/video_capture_types.h"
namespace display {
class Display;
} // namespace display
namespace media { namespace media {
class CameraAppDeviceImpl; class VideoCaptureDeviceChromeOSDelegate;
class CameraHalDelegate;
class CameraDeviceDelegate;
// Implementation of VideoCaptureDevice for ChromeOS with CrOS camera HALv3. // Implementation of VideoCaptureDevice for ChromeOS with CrOS camera HALv3.
class CAPTURE_EXPORT VideoCaptureDeviceChromeOSHalv3 final class CAPTURE_EXPORT VideoCaptureDeviceChromeOSHalv3 final
: public VideoCaptureDevice, : public VideoCaptureDevice {
public DisplayRotationObserver {
public: public:
VideoCaptureDeviceChromeOSHalv3( explicit VideoCaptureDeviceChromeOSHalv3(
scoped_refptr<base::SingleThreadTaskRunner> ui_task_runner, std::unique_ptr<VideoCaptureDeviceChromeOSDelegate> delegate);
const VideoCaptureDeviceDescriptor& device_descriptor,
scoped_refptr<CameraHalDelegate> camera_hal_delegate,
CameraAppDeviceImpl* camera_app_device,
base::OnceClosure cleanup_callback);
~VideoCaptureDeviceChromeOSHalv3() final; ~VideoCaptureDeviceChromeOSHalv3() final;
...@@ -53,59 +32,7 @@ class CAPTURE_EXPORT VideoCaptureDeviceChromeOSHalv3 final ...@@ -53,59 +32,7 @@ class CAPTURE_EXPORT VideoCaptureDeviceChromeOSHalv3 final
SetPhotoOptionsCallback callback) final; SetPhotoOptionsCallback callback) final;
private: private:
// Helper to interact with PowerManagerClient on DBus original thread. std::unique_ptr<VideoCaptureDeviceChromeOSDelegate> vcd_delegate_;
class PowerManagerClientProxy;
void OpenDevice();
void CloseDevice(base::UnguessableToken unblock_suspend_token);
// DisplayRotationDelegate implementation.
void SetDisplayRotation(const display::Display& display) final;
void SetRotation(int rotation);
const VideoCaptureDeviceDescriptor device_descriptor_;
// A reference to the CameraHalDelegate instance in the VCD factory. This is
// used by AllocateAndStart to query camera info and create the camera device.
const scoped_refptr<CameraHalDelegate> camera_hal_delegate_;
// A reference to the thread that all the VideoCaptureDevice interface methods
// are expected to be called on.
const scoped_refptr<base::SingleThreadTaskRunner> capture_task_runner_;
// The thread that all the Mojo operations of |camera_device_delegate_| take
// place. Started in AllocateAndStart and stopped in StopAndDeAllocate, where
// the access to the base::Thread methods are sequenced on
// |capture_task_runner_|.
base::Thread camera_device_ipc_thread_;
VideoCaptureParams capture_params_;
// |device_context_| is created and owned by VideoCaptureDeviceChromeOSHalv3
// and is only accessed by |camera_device_delegate_|.
std::unique_ptr<CameraDeviceContext> device_context_;
// Internal delegate doing the actual capture setting, buffer allocation and
// circulation with the camera HAL. Created in AllocateAndStart and deleted in
// StopAndDeAllocate on |capture_task_runner_|. All methods of
// |camera_device_delegate_| operate on |camera_device_ipc_thread_|.
std::unique_ptr<CameraDeviceDelegate> camera_device_delegate_;
scoped_refptr<ScreenObserverDelegate> screen_observer_delegate_;
const VideoFacingMode lens_facing_;
// Whether the incoming frames should rotate when the device rotates.
const bool rotates_with_device_;
int rotation_;
CameraAppDeviceImpl* camera_app_device_; // Weak.
base::OnceClosure cleanup_callback_;
scoped_refptr<PowerManagerClientProxy> power_manager_client_proxy_;
// The client type in CameraDeviceContext.
ClientType client_type_;
base::WeakPtrFactory<VideoCaptureDeviceChromeOSHalv3> weak_ptr_factory_{this};
DISALLOW_IMPLICIT_CONSTRUCTORS(VideoCaptureDeviceChromeOSHalv3); DISALLOW_IMPLICIT_CONSTRUCTORS(VideoCaptureDeviceChromeOSHalv3);
}; };
......
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