diff options
Diffstat (limited to 'chromium/media/capture/video/chromeos/camera_hal_delegate.cc')
-rw-r--r-- | chromium/media/capture/video/chromeos/camera_hal_delegate.cc | 170 |
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) { |