1 // Copyright (c) 2012 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.
5 // Implementation notes about interactions with VideoCaptureImpl.
7 // How is VideoCaptureImpl used:
9 // VideoCaptureImpl is an IO thread object while VideoCaptureImplManager
10 // lives only on the render thread. It is only possible to access an
11 // object of VideoCaptureImpl via a task on the IO thread.
13 // How is VideoCaptureImpl deleted:
15 // A task is posted to the IO thread to delete a VideoCaptureImpl.
16 // Immediately after that the pointer to it is dropped. This means no
17 // access to this VideoCaptureImpl object is possible on the render
18 // thread. Also note that VideoCaptureImpl does not post task to itself.
20 // The use of Unretained:
22 // We make sure deletion is the last task on the IO thread for a
23 // VideoCaptureImpl object. This allows the use of Unretained() binding.
25 #include "content/renderer/media/video_capture_impl_manager.h"
27 #include "base/bind.h"
28 #include "base/bind_helpers.h"
29 #include "base/location.h"
30 #include "base/thread_task_runner_handle.h"
31 #include "content/child/child_process.h"
32 #include "content/renderer/media/video_capture_impl.h"
33 #include "content/renderer/media/video_capture_message_filter.h"
34 #include "media/base/bind_to_current_loop.h"
38 VideoCaptureImplManager::VideoCaptureImplManager()
39 : filter_(new VideoCaptureMessageFilter()),
40 render_main_task_runner_(base::ThreadTaskRunnerHandle::Get()),
41 weak_factory_(this) {}
43 VideoCaptureImplManager::~VideoCaptureImplManager() {
44 DCHECK(render_main_task_runner_
->BelongsToCurrentThread());
47 // Forcibly release all video capture resources.
48 for (const auto& device
: devices_
) {
49 VideoCaptureImpl
* const impl
= device
.second
;
50 ChildProcess::current()->io_task_runner()->PostTask(
52 base::Bind(&VideoCaptureImpl::DeInit
, base::Unretained(impl
)));
53 ChildProcess::current()->io_task_runner()->DeleteSoon(FROM_HERE
, impl
);
58 base::Closure
VideoCaptureImplManager::UseDevice(
59 media::VideoCaptureSessionId id
) {
60 DCHECK(render_main_task_runner_
->BelongsToCurrentThread());
61 VideoCaptureDeviceMap::const_iterator it
= devices_
.find(id
);
62 DCHECK(it
== devices_
.end())
63 << "UseDevice: This VideoCaptureSessionId is already in use.";
64 if (it
!= devices_
.end())
65 return base::Closure();
67 VideoCaptureImpl
* impl
= CreateVideoCaptureImplForTesting(id
, filter_
.get());
69 impl
= new VideoCaptureImpl(id
, filter_
.get());
71 ChildProcess::current()->io_task_runner()->PostTask(
72 FROM_HERE
, base::Bind(&VideoCaptureImpl::Init
, base::Unretained(impl
)));
74 return base::Bind(&VideoCaptureImplManager::UnrefDevice
,
75 weak_factory_
.GetWeakPtr(), id
);
78 base::Closure
VideoCaptureImplManager::StartCapture(
79 media::VideoCaptureSessionId id
,
80 const media::VideoCaptureParams
& params
,
81 const VideoCaptureStateUpdateCB
& state_update_cb
,
82 const VideoCaptureDeliverFrameCB
& deliver_frame_cb
) {
83 DCHECK(render_main_task_runner_
->BelongsToCurrentThread());
84 const VideoCaptureDeviceMap::const_iterator it
= devices_
.find(id
);
85 DCHECK(it
!= devices_
.end());
86 VideoCaptureImpl
* const impl
= it
->second
;
88 ChildProcess::current()->io_task_runner()->PostTask(
90 base::Bind(&VideoCaptureImpl::StartCapture
, base::Unretained(impl
),
91 params
, state_update_cb
, deliver_frame_cb
));
92 return base::Bind(&VideoCaptureImplManager::StopCapture
,
93 weak_factory_
.GetWeakPtr(), id
);
96 void VideoCaptureImplManager::GetDeviceSupportedFormats(
97 media::VideoCaptureSessionId id
,
98 const VideoCaptureDeviceFormatsCB
& callback
) {
99 DCHECK(render_main_task_runner_
->BelongsToCurrentThread());
100 const VideoCaptureDeviceMap::const_iterator it
= devices_
.find(id
);
101 DCHECK(it
!= devices_
.end());
102 VideoCaptureImpl
* const impl
= it
->second
;
103 ChildProcess::current()->io_task_runner()->PostTask(
104 FROM_HERE
, base::Bind(&VideoCaptureImpl::GetDeviceSupportedFormats
,
105 base::Unretained(impl
), callback
));
108 void VideoCaptureImplManager::GetDeviceFormatsInUse(
109 media::VideoCaptureSessionId id
,
110 const VideoCaptureDeviceFormatsCB
& callback
) {
111 DCHECK(render_main_task_runner_
->BelongsToCurrentThread());
112 const VideoCaptureDeviceMap::const_iterator it
= devices_
.find(id
);
113 DCHECK(it
!= devices_
.end());
114 VideoCaptureImpl
* const impl
= it
->second
;
115 ChildProcess::current()->io_task_runner()->PostTask(
116 FROM_HERE
, base::Bind(&VideoCaptureImpl::GetDeviceFormatsInUse
,
117 base::Unretained(impl
), callback
));
121 VideoCaptureImplManager::CreateVideoCaptureImplForTesting(
122 media::VideoCaptureSessionId id
,
123 VideoCaptureMessageFilter
* filter
) const {
127 void VideoCaptureImplManager::StopCapture(media::VideoCaptureSessionId id
) {
128 DCHECK(render_main_task_runner_
->BelongsToCurrentThread());
129 const VideoCaptureDeviceMap::const_iterator it
= devices_
.find(id
);
130 DCHECK(it
!= devices_
.end());
131 VideoCaptureImpl
* const impl
= it
->second
;
132 ChildProcess::current()->io_task_runner()->PostTask(
134 base::Bind(&VideoCaptureImpl::StopCapture
, base::Unretained(impl
)));
137 void VideoCaptureImplManager::UnrefDevice(
138 media::VideoCaptureSessionId id
) {
139 DCHECK(render_main_task_runner_
->BelongsToCurrentThread());
140 const VideoCaptureDeviceMap::iterator it
= devices_
.find(id
);
141 DCHECK(it
!= devices_
.end());
142 VideoCaptureImpl
* const impl
= it
->second
;
144 // Unref and destroy on the IO thread if there's no more client.
146 ChildProcess::current()->io_task_runner()->PostTask(
147 FROM_HERE
, base::Bind(&VideoCaptureImpl::DeInit
, base::Unretained(impl
)));
148 ChildProcess::current()->io_task_runner()->DeleteSoon(FROM_HERE
, impl
);
151 void VideoCaptureImplManager::SuspendDevices(bool suspend
) {
152 DCHECK(render_main_task_runner_
->BelongsToCurrentThread());
153 for (const auto& device
: devices_
) {
154 VideoCaptureImpl
* const impl
= device
.second
;
155 ChildProcess::current()->io_task_runner()->PostTask(
156 FROM_HERE
, base::Bind(&VideoCaptureImpl::SuspendCapture
,
157 base::Unretained(impl
), suspend
));
161 } // namespace content