blob: 92e25d9b05e32bbac436c3695620d361aea8e8e7 [file] [log] [blame]
// Copyright 2019 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/camera_app_device_bridge_impl.h"
#include <string>
#include "base/callback_helpers.h"
#include "base/command_line.h"
#include "media/base/bind_to_current_loop.h"
#include "media/base/media_switches.h"
#include "media/capture/video/chromeos/public/cros_features.h"
#include "media/capture/video/chromeos/video_capture_device_chromeos_halv3.h"
namespace media {
CameraAppDeviceBridgeImpl::CameraAppDeviceBridgeImpl() {
const base::CommandLine* command_line =
base::CommandLine::ForCurrentProcess();
bool use_fake_camera =
command_line->HasSwitch(switches::kUseFakeDeviceForMediaStream);
bool use_file_camera =
command_line->HasSwitch(switches::kUseFileForFakeVideoCapture);
is_supported_ =
ShouldUseCrosCameraService() && !use_fake_camera && !use_file_camera;
}
CameraAppDeviceBridgeImpl::~CameraAppDeviceBridgeImpl() = default;
// static
CameraAppDeviceBridgeImpl* CameraAppDeviceBridgeImpl::GetInstance() {
return base::Singleton<CameraAppDeviceBridgeImpl>::get();
}
void CameraAppDeviceBridgeImpl::BindReceiver(
mojo::PendingReceiver<cros::mojom::CameraAppDeviceBridge> receiver) {
receivers_.Add(this, std::move(receiver));
}
void CameraAppDeviceBridgeImpl::OnVideoCaptureDeviceCreated(
const std::string& device_id,
scoped_refptr<base::SingleThreadTaskRunner> ipc_task_runner) {
base::AutoLock lock(task_runner_map_lock_);
DCHECK_EQ(ipc_task_runners_.count(device_id), 0u);
ipc_task_runners_.emplace(device_id, ipc_task_runner);
}
void CameraAppDeviceBridgeImpl::OnVideoCaptureDeviceClosing(
const std::string& device_id) {
auto remove_ipc_task_runner =
base::BindOnce(&CameraAppDeviceBridgeImpl::RemoveIpcTaskRunner,
base::Unretained(this), device_id);
base::AutoLock lock(task_runner_map_lock_);
DCHECK_EQ(ipc_task_runners_.count(device_id), 1u);
// Since the IPC thread is owned by VCD and the CameraAppBridgeImpl is a
// singleton which has longer lifetime than VCD, it is safe to use
// base::Unretained(this) here.
ipc_task_runners_[device_id]->PostTask(
FROM_HERE,
base::BindOnce(
&CameraAppDeviceBridgeImpl::InvalidateDevicePtrsOnDeviceIpcThread,
base::Unretained(this), device_id,
/* should_disable_new_ptrs */ false,
std::move(remove_ipc_task_runner)));
}
void CameraAppDeviceBridgeImpl::OnDeviceMojoDisconnected(
const std::string& device_id) {
auto remove_device = media::BindToCurrentLoop(
base::BindOnce(&CameraAppDeviceBridgeImpl::RemoveCameraAppDevice,
base::Unretained(this), device_id));
{
base::AutoLock lock(task_runner_map_lock_);
auto it = ipc_task_runners_.find(device_id);
if (it != ipc_task_runners_.end()) {
// Since the IPC thread is owned by VCD and the CameraAppBridgeImpl is a
// singleton which has longer lifetime than VCD, it is safe to use
// base::Unretained(this) here.
it->second->PostTask(
FROM_HERE,
base::BindOnce(
&CameraAppDeviceBridgeImpl::InvalidateDevicePtrsOnDeviceIpcThread,
base::Unretained(this), device_id,
/* should_disable_new_ptrs */ true, std::move(remove_device)));
return;
}
}
std::move(remove_device).Run();
}
void CameraAppDeviceBridgeImpl::InvalidateDevicePtrsOnDeviceIpcThread(
const std::string& device_id,
bool should_disable_new_ptrs,
base::OnceClosure callback) {
auto device = GetWeakCameraAppDevice(device_id);
if (device) {
device->ResetOnDeviceIpcThread(std::move(callback),
should_disable_new_ptrs);
} else {
std::move(callback).Run();
}
}
void CameraAppDeviceBridgeImpl::SetCameraInfoGetter(
CameraInfoGetter camera_info_getter) {
base::AutoLock lock(camera_info_getter_lock_);
camera_info_getter_ = std::move(camera_info_getter);
}
void CameraAppDeviceBridgeImpl::UnsetCameraInfoGetter() {
base::AutoLock lock(camera_info_getter_lock_);
camera_info_getter_ = base::NullCallback();
}
void CameraAppDeviceBridgeImpl::SetVirtualDeviceController(
VirtualDeviceController virtual_device_controller) {
base::AutoLock lock(virtual_device_controller_lock_);
virtual_device_controller_ = std::move(virtual_device_controller);
}
void CameraAppDeviceBridgeImpl::UnsetVirtualDeviceController() {
base::AutoLock lock(virtual_device_controller_lock_);
virtual_device_controller_ = base::NullCallback();
}
base::WeakPtr<CameraAppDeviceImpl>
CameraAppDeviceBridgeImpl::GetWeakCameraAppDevice(
const std::string& device_id) {
base::AutoLock lock(device_map_lock_);
auto it = camera_app_devices_.find(device_id);
if (it == camera_app_devices_.end()) {
return nullptr;
}
return it->second->GetWeakPtr();
}
void CameraAppDeviceBridgeImpl::RemoveCameraAppDevice(
const std::string& device_id) {
base::AutoLock lock(device_map_lock_);
auto it = camera_app_devices_.find(device_id);
if (it == camera_app_devices_.end()) {
return;
}
camera_app_devices_.erase(it);
}
void CameraAppDeviceBridgeImpl::RemoveIpcTaskRunner(
const std::string& device_id) {
base::AutoLock lock(task_runner_map_lock_);
ipc_task_runners_.erase(device_id);
}
void CameraAppDeviceBridgeImpl::GetCameraAppDevice(
const std::string& device_id,
GetCameraAppDeviceCallback callback) {
DCHECK(is_supported_);
mojo::PendingRemote<cros::mojom::CameraAppDevice> device_remote;
auto* device = GetOrCreateCameraAppDevice(device_id);
DCHECK(device);
device->BindReceiver(device_remote.InitWithNewPipeAndPassReceiver());
std::move(callback).Run(cros::mojom::GetCameraAppDeviceStatus::SUCCESS,
std::move(device_remote));
}
media::CameraAppDeviceImpl*
CameraAppDeviceBridgeImpl::GetOrCreateCameraAppDevice(
const std::string& device_id) {
base::AutoLock lock(device_map_lock_);
auto it = camera_app_devices_.find(device_id);
if (it != camera_app_devices_.end()) {
return it->second.get();
}
base::AutoLock camera_info_lock(camera_info_getter_lock_);
// Since we ensure that VideoCaptureDeviceFactory is created before binding
// CameraAppDeviceBridge and VideoCaptureDeviceFactory is only destroyed when
// the video capture service dies, we can guarantee that |camera_info_getter_|
// is always valid here.
DCHECK(camera_info_getter_);
auto device_info = camera_info_getter_.Run(device_id);
auto device_impl = std::make_unique<media::CameraAppDeviceImpl>(
device_id, std::move(device_info));
auto result = camera_app_devices_.emplace(device_id, std::move(device_impl));
return result.first->second.get();
}
void CameraAppDeviceBridgeImpl::IsSupported(IsSupportedCallback callback) {
std::move(callback).Run(is_supported_);
}
void CameraAppDeviceBridgeImpl::SetMultipleStreamsEnabled(
const std::string& device_id,
bool enabled,
SetMultipleStreamsEnabledCallback callback) {
base::AutoLock lock(virtual_device_controller_lock_);
if (!virtual_device_controller_) {
std::move(callback).Run(false);
return;
}
virtual_device_controller_.Run(device_id, enabled);
std::move(callback).Run(true);
}
} // namespace media