summaryrefslogtreecommitdiff
path: root/chromium/media/capture/video/chromeos/camera_hal_delegate.cc
diff options
context:
space:
mode:
Diffstat (limited to 'chromium/media/capture/video/chromeos/camera_hal_delegate.cc')
-rw-r--r--chromium/media/capture/video/chromeos/camera_hal_delegate.cc170
1 files changed, 127 insertions, 43 deletions
diff --git a/chromium/media/capture/video/chromeos/camera_hal_delegate.cc b/chromium/media/capture/video/chromeos/camera_hal_delegate.cc
index a0bee569637..3ce1c4c0583 100644
--- a/chromium/media/capture/video/chromeos/camera_hal_delegate.cc
+++ b/chromium/media/capture/video/chromeos/camera_hal_delegate.cc
@@ -19,11 +19,14 @@
#include "base/strings/string_number_conversions.h"
#include "base/strings/string_piece.h"
#include "base/strings/string_split.h"
+#include "base/strings/string_util.h"
#include "base/system/system_monitor.h"
-#include "media/capture/video/chromeos/camera_app_device_bridge_impl.h"
+#include "base/unguessable_token.h"
+#include "components/device_event_log/device_event_log.h"
+#include "media/capture/video/chromeos/ash/camera_hal_dispatcher_impl.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_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"
namespace media {
@@ -31,6 +34,7 @@ namespace media {
namespace {
constexpr int32_t kDefaultFps = 30;
+constexpr char kVirtualPrefix[] = "VIRTUAL_";
constexpr base::TimeDelta kEventWaitTimeoutSecs =
base::TimeDelta::FromSeconds(1);
@@ -38,8 +42,11 @@ constexpr base::TimeDelta kEventWaitTimeoutSecs =
class LocalCameraClientObserver : public CameraClientObserver {
public:
explicit LocalCameraClientObserver(
- scoped_refptr<CameraHalDelegate> camera_hal_delegate)
- : camera_hal_delegate_(std::move(camera_hal_delegate)) {}
+ scoped_refptr<CameraHalDelegate> camera_hal_delegate,
+ cros::mojom::CameraClientType type,
+ base::UnguessableToken auth_token)
+ : CameraClientObserver(type, std::move(auth_token)),
+ camera_hal_delegate_(std::move(camera_hal_delegate)) {}
void OnChannelCreated(
mojo::PendingRemote<cros::mojom::CameraModule> camera_module) override {
@@ -117,7 +124,8 @@ base::flat_set<int32_t> GetAvailableFramerates(
CameraHalDelegate::CameraHalDelegate(
scoped_refptr<base::SingleThreadTaskRunner> ipc_task_runner)
- : camera_module_has_been_set_(
+ : authenticated_(false),
+ camera_module_has_been_set_(
base::WaitableEvent::ResetPolicy::MANUAL,
base::WaitableEvent::InitialState::NOT_SIGNALED),
builtin_camera_info_updated_(
@@ -138,9 +146,27 @@ CameraHalDelegate::CameraHalDelegate(
CameraHalDelegate::~CameraHalDelegate() = default;
-void CameraHalDelegate::RegisterCameraClient() {
- CameraHalDispatcherImpl::GetInstance()->AddClientObserver(
- std::make_unique<LocalCameraClientObserver>(this));
+bool CameraHalDelegate::RegisterCameraClient() {
+ auto* dispatcher = CameraHalDispatcherImpl::GetInstance();
+ auto type = cros::mojom::CameraClientType::CHROME;
+ dispatcher->AddClientObserver(
+ std::make_unique<LocalCameraClientObserver>(
+ this, type, dispatcher->GetTokenForTrustedClient(type)),
+ base::BindOnce(&CameraHalDelegate::OnRegisteredCameraHalClient,
+ base::Unretained(this)));
+ camera_hal_client_registered_.Wait();
+ return authenticated_;
+}
+
+void CameraHalDelegate::OnRegisteredCameraHalClient(int32_t result) {
+ if (result != 0) {
+ LOG(ERROR) << "Failed to register camera HAL client";
+ camera_hal_client_registered_.Signal();
+ return;
+ }
+ CAMERA_LOG(EVENT) << "Registered camera HAL client";
+ authenticated_ = true;
+ camera_hal_client_registered_.Signal();
}
void CameraHalDelegate::SetCameraModule(
@@ -158,8 +184,7 @@ void CameraHalDelegate::Reset() {
std::unique_ptr<VideoCaptureDevice> CameraHalDelegate::CreateDevice(
scoped_refptr<base::SingleThreadTaskRunner> task_runner_for_screen_observer,
- const VideoCaptureDeviceDescriptor& device_descriptor,
- CameraAppDeviceBridgeImpl* camera_app_device_bridge) {
+ const VideoCaptureDeviceDescriptor& device_descriptor) {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
if (!UpdateBuiltInCameraInfo()) {
return nullptr;
@@ -170,35 +195,17 @@ std::unique_ptr<VideoCaptureDevice> CameraHalDelegate::CreateDevice(
return nullptr;
}
- if (camera_app_device_bridge) {
- auto* camera_app_device = camera_app_device_bridge->GetCameraAppDevice(
- device_descriptor.device_id);
- // Since the cleanup callback will be triggered when VideoCaptureDevice died
- // and |camera_app_device_bridge| is actually owned by
- // VideoCaptureServiceImpl, it should be safe to assume
- // |camera_app_device_bridge| is still valid here.
- auto cleanup_callback = base::BindOnce(
- [](const std::string& device_id, CameraAppDeviceBridgeImpl* bridge) {
- bridge->OnDeviceClosed(device_id);
- },
- device_descriptor.device_id, camera_app_device_bridge);
- return std::make_unique<VideoCaptureDeviceChromeOSHalv3>(
- std::move(task_runner_for_screen_observer), device_descriptor, this,
- camera_app_device, std::move(cleanup_callback));
- } else {
- return std::make_unique<VideoCaptureDeviceChromeOSHalv3>(
- std::move(task_runner_for_screen_observer), device_descriptor, this,
- nullptr, base::DoNothing());
- }
+ auto* delegate =
+ GetVCDDelegate(task_runner_for_screen_observer, device_descriptor);
+ return std::make_unique<VideoCaptureDeviceChromeOSHalv3>(delegate,
+ device_descriptor);
}
void CameraHalDelegate::GetSupportedFormats(
- int camera_id,
+ const cros::mojom::CameraInfoPtr& camera_info,
VideoCaptureFormats* supported_formats) {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
- const cros::mojom::CameraInfoPtr& camera_info = camera_info_[camera_id];
-
base::flat_set<int32_t> candidate_fps_set =
GetAvailableFramerates(camera_info);
@@ -244,7 +251,7 @@ void CameraHalDelegate::GetSupportedFormats(
// There's no consumer information here to determine the buffer usage, so
// hard-code the usage that all the clients should be using.
constexpr gfx::BufferUsage kClientBufferUsage =
- gfx::BufferUsage::SCANOUT_VEA_READ_CAMERA_AND_CPU_READ_WRITE;
+ gfx::BufferUsage::VEA_READ_CAMERA_AND_CPU_READ_WRITE;
const ChromiumPixelFormat cr_format =
camera_buffer_factory_->ResolveStreamBufferFormat(hal_format,
kClientBufferUsage);
@@ -257,8 +264,9 @@ void CameraHalDelegate::GetSupportedFormats(
continue;
}
- VLOG(1) << "Supported format: " << width << "x" << height
- << " fps=" << fps << " format=" << cr_format.video_format;
+ CAMERA_LOG(EVENT) << "Supported format: " << width << "x" << height
+ << " fps=" << fps
+ << " format=" << cr_format.video_format;
supported_formats->emplace_back(gfx::Size(width, height), fps,
cr_format.video_format);
}
@@ -287,6 +295,7 @@ void CameraHalDelegate::GetDevicesInfo(
{
base::AutoLock info_lock(camera_info_lock_);
base::AutoLock id_map_lock(device_id_to_camera_id_lock_);
+ base::AutoLock virtual_lock(enable_virtual_device_lock_);
for (const auto& it : camera_info_) {
int camera_id = it.first;
const cros::mojom::CameraInfoPtr& camera_info = it.second;
@@ -334,6 +343,12 @@ void CameraHalDelegate::GetDevicesInfo(
// Mojo validates the input parameters for us so we don't need to
// worry about malformed values.
}
+ case cros::mojom::CameraFacing::CAMERA_FACING_VIRTUAL_BACK:
+ case cros::mojom::CameraFacing::CAMERA_FACING_VIRTUAL_FRONT:
+ case cros::mojom::CameraFacing::CAMERA_FACING_VIRTUAL_EXTERNAL:
+ // |camera_info_| should not have these facing types.
+ LOG(ERROR) << "Invalid facing type: " << camera_info->facing;
+ break;
}
auto* vid = get_vendor_string("com.google.usb.vendorId");
auto* pid = get_vendor_string("com.google.usb.productId");
@@ -343,10 +358,22 @@ void CameraHalDelegate::GetDevicesInfo(
desc.set_control_support(GetControlSupport(camera_info));
device_id_to_camera_id_[desc.device_id] = camera_id;
devices_info.emplace_back(desc);
- GetSupportedFormats(camera_id, &devices_info.back().supported_formats);
+ GetSupportedFormats(camera_info_[camera_id],
+ &devices_info.back().supported_formats);
+
+ // Create a virtual device when multiple streams are enabled.
+ if (enable_virtual_device_[camera_id]) {
+ desc.facing = VideoFacingMode::MEDIA_VIDEO_FACING_NONE;
+ desc.device_id =
+ std::string(kVirtualPrefix) + base::NumberToString(camera_id);
+ desc.set_display_name("Virtual Camera");
+ device_id_to_camera_id_[desc.device_id] = camera_id;
+ devices_info.emplace_back(desc);
+ GetSupportedFormats(camera_info_[camera_id],
+ &devices_info.back().supported_formats);
+ }
}
}
-
// TODO(shik): Report external camera first when lid is closed.
// TODO(jcliang): Remove this after JS API supports query camera facing
// (http://crbug.com/543997).
@@ -404,7 +431,36 @@ cros::mojom::CameraInfoPtr CameraHalDelegate::GetCameraInfoFromDeviceId(
if (it == camera_info_.end()) {
return {};
}
- return it->second.Clone();
+ auto info = it->second.Clone();
+ if (base::StartsWith(device_id, std::string(kVirtualPrefix))) {
+ switch (it->second->facing) {
+ case cros::mojom::CameraFacing::CAMERA_FACING_BACK:
+ info->facing = cros::mojom::CameraFacing::CAMERA_FACING_VIRTUAL_BACK;
+ break;
+ case cros::mojom::CameraFacing::CAMERA_FACING_FRONT:
+ info->facing = cros::mojom::CameraFacing::CAMERA_FACING_VIRTUAL_FRONT;
+ break;
+ case cros::mojom::CameraFacing::CAMERA_FACING_EXTERNAL:
+ info->facing =
+ cros::mojom::CameraFacing::CAMERA_FACING_VIRTUAL_EXTERNAL;
+ break;
+ default:
+ break;
+ }
+ }
+ return info;
+}
+
+void CameraHalDelegate::EnableVirtualDevice(const std::string& device_id,
+ bool enable) {
+ if (base::StartsWith(device_id, std::string(kVirtualPrefix))) {
+ return;
+ }
+ auto camera_id = GetCameraIdFromDeviceId(device_id);
+ if (camera_id != -1) {
+ base::AutoLock lock(enable_virtual_device_lock_);
+ enable_virtual_device_[camera_id] = enable;
+ }
}
const VendorTagInfo* CameraHalDelegate::GetVendorTagInfoByName(
@@ -436,6 +492,27 @@ int CameraHalDelegate::GetCameraIdFromDeviceId(const std::string& device_id) {
return it->second;
}
+VideoCaptureDeviceChromeOSDelegate* CameraHalDelegate::GetVCDDelegate(
+ scoped_refptr<base::SingleThreadTaskRunner> task_runner_for_screen_observer,
+ const VideoCaptureDeviceDescriptor& device_descriptor) {
+ auto camera_id = GetCameraIdFromDeviceId(device_descriptor.device_id);
+ auto it = vcd_delegate_map_.find(camera_id);
+ if (it == vcd_delegate_map_.end() || it->second->HasDeviceClient() == 0) {
+ auto cleanup_callback = base::BindOnce(
+ [](int camera_id,
+ base::flat_map<int,
+ std::unique_ptr<VideoCaptureDeviceChromeOSDelegate>>*
+ vcd_delegate_map) { vcd_delegate_map->erase(camera_id); },
+ camera_id, &vcd_delegate_map_);
+ auto delegate = std::make_unique<VideoCaptureDeviceChromeOSDelegate>(
+ std::move(task_runner_for_screen_observer), device_descriptor, this,
+ std::move(cleanup_callback));
+ vcd_delegate_map_[camera_id] = std::move(delegate);
+ return vcd_delegate_map_[camera_id].get();
+ }
+ return it->second.get();
+}
+
void CameraHalDelegate::SetCameraModuleOnIpcThread(
mojo::PendingRemote<cros::mojom::CameraModule> camera_module) {
DCHECK(ipc_task_runner_->BelongsToCurrentThread());
@@ -462,6 +539,7 @@ void CameraHalDelegate::ResetMojoInterfaceOnIpcThread() {
external_camera_info_updated_.Signal();
// Clear all cached camera info, especially external cameras.
+ base::AutoLock lock(camera_info_lock_);
camera_info_.clear();
pending_external_camera_info_.clear();
}
@@ -495,18 +573,20 @@ void CameraHalDelegate::UpdateBuiltInCameraInfoOnIpcThread() {
void CameraHalDelegate::OnGotNumberOfCamerasOnIpcThread(int32_t num_cameras) {
DCHECK(ipc_task_runner_->BelongsToCurrentThread());
+
+ base::AutoLock lock(camera_info_lock_);
if (num_cameras < 0) {
builtin_camera_info_updated_.Signal();
LOG(ERROR) << "Failed to get number of cameras: " << num_cameras;
return;
}
- VLOG(1) << "Number of built-in cameras: " << num_cameras;
+ CAMERA_LOG(EVENT) << "Number of built-in cameras: " << num_cameras;
num_builtin_cameras_ = num_cameras;
// Per camera HAL v3 specification SetCallbacks() should be called after the
// first time GetNumberOfCameras() is called, and before other CameraModule
// functions are called.
- camera_module_->SetCallbacks(
- camera_module_callbacks_.BindNewPipeAndPassRemote(),
+ camera_module_->SetCallbacksAssociated(
+ camera_module_callbacks_.BindNewEndpointAndPassRemote(),
base::BindOnce(&CameraHalDelegate::OnSetCallbacksOnIpcThread, this));
camera_module_->GetVendorTagOps(
@@ -516,6 +596,8 @@ void CameraHalDelegate::OnGotNumberOfCamerasOnIpcThread(int32_t num_cameras) {
void CameraHalDelegate::OnSetCallbacksOnIpcThread(int32_t result) {
DCHECK(ipc_task_runner_->BelongsToCurrentThread());
+
+ base::AutoLock lock(camera_info_lock_);
if (result) {
num_builtin_cameras_ = 0;
builtin_camera_info_updated_.Signal();
@@ -567,6 +649,7 @@ void CameraHalDelegate::OnGotCameraInfoOnIpcThread(
// |camera_info_| might contain some entries for external cameras as well,
// we should check all built-in cameras explicitly.
bool all_updated = [&]() {
+ camera_info_lock_.AssertAcquired();
for (size_t i = 0; i < num_builtin_cameras_; i++) {
if (camera_info_.find(i) == camera_info_.end()) {
return false;
@@ -606,7 +689,8 @@ void CameraHalDelegate::CameraDeviceStatusChange(
int32_t camera_id,
cros::mojom::CameraDeviceStatus new_status) {
DCHECK(ipc_task_runner_->BelongsToCurrentThread());
- VLOG(1) << "camera_id = " << camera_id << ", new_status = " << new_status;
+ CAMERA_LOG(EVENT) << "camera_id = " << camera_id
+ << ", new_status = " << new_status;
base::AutoLock lock(camera_info_lock_);
auto it = camera_info_.find(camera_id);
switch (new_status) {