1 // Copyright 2017 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 #include "services/video_capture/video_capture_service_impl.h"
6
7 #include <utility>
8
9 #include "base/bind.h"
10 #include "base/feature_list.h"
11 #include "base/task/post_task.h"
12 #include "base/task/thread_pool.h"
13 #include "build/build_config.h"
14 #include "build/chromeos_buildflags.h"
15 #include "gpu/command_buffer/client/gpu_memory_buffer_manager.h"
16 #include "media/capture/video/create_video_capture_device_factory.h"
17 #include "media/capture/video/fake_video_capture_device_factory.h"
18 #include "media/capture/video/video_capture_buffer_pool.h"
19 #include "media/capture/video/video_capture_buffer_tracker.h"
20 #include "media/capture/video/video_capture_system_impl.h"
21 #include "mojo/public/cpp/bindings/pending_receiver.h"
22 #include "mojo/public/cpp/bindings/pending_remote.h"
23 #include "mojo/public/cpp/bindings/remote.h"
24 #include "mojo/public/cpp/bindings/self_owned_receiver.h"
25 #include "services/video_capture/device_factory_media_to_mojo_adapter.h"
26 #include "services/video_capture/testing_controls_impl.h"
27 #include "services/video_capture/video_source_provider_impl.h"
28 #include "services/video_capture/virtual_device_enabled_device_factory.h"
29 #include "services/viz/public/cpp/gpu/gpu.h"
30
31 #if defined(OS_MAC)
32 #include "media/capture/video/mac/video_capture_device_factory_mac.h"
33 #endif
34
35 namespace video_capture {
36
37 // Intended usage of this class is to instantiate on any sequence, and then
38 // operate and release the instance on the task runner exposed via
39 // GetTaskRunner() via WeakPtrs provided via GetWeakPtr(). To this end,
40 // GetTaskRunner() and GetWeakPtr() can be called from any sequence, typically
41 // the same as the one calling the constructor.
42 class VideoCaptureServiceImpl::GpuDependenciesContext {
43 public:
GpuDependenciesContext()44 GpuDependenciesContext() {
45 gpu_io_task_runner_ = base::ThreadPool::CreateSequencedTaskRunner(
46 {base::TaskPriority::USER_BLOCKING, base::MayBlock()});
47 }
48
~GpuDependenciesContext()49 ~GpuDependenciesContext() {
50 DCHECK(gpu_io_task_runner_->RunsTasksInCurrentSequence());
51 }
52
GetWeakPtr()53 base::WeakPtr<GpuDependenciesContext> GetWeakPtr() {
54 return weak_factory_for_gpu_io_thread_.GetWeakPtr();
55 }
56
GetTaskRunner()57 scoped_refptr<base::SequencedTaskRunner> GetTaskRunner() {
58 return gpu_io_task_runner_;
59 }
60
61 #if BUILDFLAG(IS_ASH)
InjectGpuDependencies(mojo::PendingRemote<mojom::AcceleratorFactory> accelerator_factory_info)62 void InjectGpuDependencies(
63 mojo::PendingRemote<mojom::AcceleratorFactory> accelerator_factory_info) {
64 DCHECK(gpu_io_task_runner_->RunsTasksInCurrentSequence());
65 accelerator_factory_.reset();
66 accelerator_factory_.Bind(std::move(accelerator_factory_info));
67 }
68
CreateJpegDecodeAccelerator(mojo::PendingReceiver<chromeos_camera::mojom::MjpegDecodeAccelerator> receiver)69 void CreateJpegDecodeAccelerator(
70 mojo::PendingReceiver<chromeos_camera::mojom::MjpegDecodeAccelerator>
71 receiver) {
72 DCHECK(gpu_io_task_runner_->RunsTasksInCurrentSequence());
73 if (!accelerator_factory_)
74 return;
75 accelerator_factory_->CreateJpegDecodeAccelerator(std::move(receiver));
76 }
77 #endif // BUILDFLAG(IS_ASH)
78
79 private:
80 // Task runner for operating |accelerator_factory_| and
81 // |gpu_memory_buffer_manager_| on. This must be a different thread from the
82 // main service thread in order to avoid a deadlock during shutdown where
83 // the main service thread joins a video capture device thread that, in turn,
84 // will try to post the release of the jpeg decoder to the thread it is
85 // operated on.
86 scoped_refptr<base::SequencedTaskRunner> gpu_io_task_runner_;
87
88 #if BUILDFLAG(IS_ASH)
89 mojo::Remote<mojom::AcceleratorFactory> accelerator_factory_;
90 #endif // BUILDFLAG(IS_ASH)
91
92 base::WeakPtrFactory<GpuDependenciesContext> weak_factory_for_gpu_io_thread_{
93 this};
94 };
95
VideoCaptureServiceImpl(mojo::PendingReceiver<mojom::VideoCaptureService> receiver,scoped_refptr<base::SingleThreadTaskRunner> ui_task_runner)96 VideoCaptureServiceImpl::VideoCaptureServiceImpl(
97 mojo::PendingReceiver<mojom::VideoCaptureService> receiver,
98 scoped_refptr<base::SingleThreadTaskRunner> ui_task_runner)
99 : receiver_(this, std::move(receiver)),
100 ui_task_runner_(std::move(ui_task_runner)) {}
101
~VideoCaptureServiceImpl()102 VideoCaptureServiceImpl::~VideoCaptureServiceImpl() {
103 factory_receivers_.Clear();
104 device_factory_.reset();
105
106 #if BUILDFLAG(IS_ASH)
107 camera_app_device_bridge_.reset();
108 #endif // defined (OS_CHROMEOS)
109
110 if (gpu_dependencies_context_) {
111 gpu_dependencies_context_->GetTaskRunner()->DeleteSoon(
112 FROM_HERE, std::move(gpu_dependencies_context_));
113 }
114 }
115
116 #if BUILDFLAG(IS_ASH)
InjectGpuDependencies(mojo::PendingRemote<mojom::AcceleratorFactory> accelerator_factory)117 void VideoCaptureServiceImpl::InjectGpuDependencies(
118 mojo::PendingRemote<mojom::AcceleratorFactory> accelerator_factory) {
119 LazyInitializeGpuDependenciesContext();
120 gpu_dependencies_context_->GetTaskRunner()->PostTask(
121 FROM_HERE, base::BindOnce(&GpuDependenciesContext::InjectGpuDependencies,
122 gpu_dependencies_context_->GetWeakPtr(),
123 std::move(accelerator_factory)));
124 }
125
ConnectToCameraAppDeviceBridge(mojo::PendingReceiver<cros::mojom::CameraAppDeviceBridge> receiver)126 void VideoCaptureServiceImpl::ConnectToCameraAppDeviceBridge(
127 mojo::PendingReceiver<cros::mojom::CameraAppDeviceBridge> receiver) {
128 DCHECK(camera_app_device_bridge_);
129 camera_app_device_bridge_->BindReceiver(std::move(receiver));
130 }
131 #endif // BUILDFLAG(IS_ASH)
132
ConnectToDeviceFactory(mojo::PendingReceiver<mojom::DeviceFactory> receiver)133 void VideoCaptureServiceImpl::ConnectToDeviceFactory(
134 mojo::PendingReceiver<mojom::DeviceFactory> receiver) {
135 LazyInitializeDeviceFactory();
136 factory_receivers_.Add(device_factory_.get(), std::move(receiver));
137 }
138
ConnectToVideoSourceProvider(mojo::PendingReceiver<mojom::VideoSourceProvider> receiver)139 void VideoCaptureServiceImpl::ConnectToVideoSourceProvider(
140 mojo::PendingReceiver<mojom::VideoSourceProvider> receiver) {
141 LazyInitializeVideoSourceProvider();
142 video_source_provider_->AddClient(std::move(receiver));
143 }
144
SetRetryCount(int32_t count)145 void VideoCaptureServiceImpl::SetRetryCount(int32_t count) {
146 #if defined(OS_MAC)
147 media::VideoCaptureDeviceFactoryMac::SetGetDevicesInfoRetryCount(count);
148 #endif
149 }
150
BindControlsForTesting(mojo::PendingReceiver<mojom::TestingControls> receiver)151 void VideoCaptureServiceImpl::BindControlsForTesting(
152 mojo::PendingReceiver<mojom::TestingControls> receiver) {
153 mojo::MakeSelfOwnedReceiver(std::make_unique<TestingControlsImpl>(),
154 std::move(receiver));
155 }
156
LazyInitializeGpuDependenciesContext()157 void VideoCaptureServiceImpl::LazyInitializeGpuDependenciesContext() {
158 if (!gpu_dependencies_context_)
159 gpu_dependencies_context_ = std::make_unique<GpuDependenciesContext>();
160 }
161
LazyInitializeDeviceFactory()162 void VideoCaptureServiceImpl::LazyInitializeDeviceFactory() {
163 if (device_factory_)
164 return;
165
166 LazyInitializeGpuDependenciesContext();
167
168 // Create the platform-specific device factory.
169 // The task runner passed to CreateFactory is used for things that need to
170 // happen on a "UI thread equivalent", e.g. obtaining screen rotation on
171 // Chrome OS.
172 #if BUILDFLAG(IS_ASH)
173 camera_app_device_bridge_ =
174 std::make_unique<media::CameraAppDeviceBridgeImpl>();
175 std::unique_ptr<media::VideoCaptureDeviceFactory> media_device_factory =
176 media::CreateVideoCaptureDeviceFactory(ui_task_runner_,
177 camera_app_device_bridge_.get());
178 camera_app_device_bridge_->SetIsSupported(
179 media_device_factory->IsSupportedCameraAppDeviceBridge());
180 #else
181 std::unique_ptr<media::VideoCaptureDeviceFactory> media_device_factory =
182 media::CreateVideoCaptureDeviceFactory(ui_task_runner_);
183 #endif // BUILDFLAG(IS_ASH)
184
185 auto video_capture_system = std::make_unique<media::VideoCaptureSystemImpl>(
186 std::move(media_device_factory));
187
188 #if BUILDFLAG(IS_ASH)
189 device_factory_ = std::make_unique<VirtualDeviceEnabledDeviceFactory>(
190 std::make_unique<DeviceFactoryMediaToMojoAdapter>(
191 std::move(video_capture_system),
192 base::BindRepeating(
193 &GpuDependenciesContext::CreateJpegDecodeAccelerator,
194 gpu_dependencies_context_->GetWeakPtr()),
195 gpu_dependencies_context_->GetTaskRunner()));
196 #else
197 device_factory_ = std::make_unique<VirtualDeviceEnabledDeviceFactory>(
198 std::make_unique<DeviceFactoryMediaToMojoAdapter>(
199 std::move(video_capture_system)));
200 #endif // BUILDFLAG(IS_ASH)
201 }
202
LazyInitializeVideoSourceProvider()203 void VideoCaptureServiceImpl::LazyInitializeVideoSourceProvider() {
204 if (video_source_provider_)
205 return;
206 LazyInitializeDeviceFactory();
207 video_source_provider_ = std::make_unique<VideoSourceProviderImpl>(
208 device_factory_.get(),
209 // Unretained(this) is safe, because |this| owns |video_source_provider_|.
210 base::BindRepeating(
211 &VideoCaptureServiceImpl::OnLastSourceProviderClientDisconnected,
212 base::Unretained(this)));
213 }
214
OnLastSourceProviderClientDisconnected()215 void VideoCaptureServiceImpl::OnLastSourceProviderClientDisconnected() {
216 video_source_provider_.reset();
217 }
218
219 } // namespace video_capture
220