Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(596)

Side by Side Diff: content/browser/renderer_host/media/video_capture_manager.cc

Issue 2738763002: [Mojo Video Capture] Introduce abstraction BuildableVideoCaptureDevice (Closed)
Patch Set: Incorporated miu@'s suggestions from PatchSet 2 Created 3 years, 9 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. 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 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "content/browser/renderer_host/media/video_capture_manager.h" 5 #include "content/browser/renderer_host/media/video_capture_manager.h"
6 6
7 #include <algorithm> 7 #include <algorithm>
8 #include <set> 8 #include <set>
9 #include <utility> 9 #include <utility>
10 10
11 #include "base/bind.h" 11 #include "base/bind.h"
12 #include "base/bind_helpers.h" 12 #include "base/bind_helpers.h"
13 #include "base/command_line.h" 13 #include "base/command_line.h"
14 #include "base/location.h" 14 #include "base/location.h"
15 #include "base/logging.h" 15 #include "base/logging.h"
16 #include "base/memory/ptr_util.h" 16 #include "base/memory/ptr_util.h"
17 #include "base/metrics/histogram_macros.h" 17 #include "base/metrics/histogram_macros.h"
18 #include "base/single_thread_task_runner.h" 18 #include "base/single_thread_task_runner.h"
19 #include "base/stl_util.h" 19 #include "base/stl_util.h"
20 #include "base/strings/stringprintf.h" 20 #include "base/strings/stringprintf.h"
21 #include "base/task_runner_util.h" 21 #include "base/task_runner_util.h"
22 #include "base/threading/sequenced_worker_pool.h" 22 #include "base/threading/sequenced_worker_pool.h"
23 #include "base/threading/thread_task_runner_handle.h" 23 #include "base/threading/thread_task_runner_handle.h"
24 #include "build/build_config.h" 24 #include "build/build_config.h"
25 #include "content/browser/media/capture/desktop_capture_device_uma_types.h" 25 #include "content/browser/media/capture/desktop_capture_device_uma_types.h"
26 #include "content/browser/media/capture/web_contents_video_capture_device.h" 26 #include "content/browser/media/capture/web_contents_video_capture_device.h"
27 #include "content/browser/media/media_internals.h" 27 #include "content/browser/media/media_internals.h"
28 #include "content/browser/renderer_host/media/in_process_buildable_video_capture _device.h"
28 #include "content/browser/renderer_host/media/video_capture_controller.h" 29 #include "content/browser/renderer_host/media/video_capture_controller.h"
29 #include "content/browser/renderer_host/media/video_capture_controller_event_han dler.h" 30 #include "content/browser/renderer_host/media/video_capture_controller_event_han dler.h"
30 #include "content/browser/renderer_host/media/video_capture_gpu_jpeg_decoder.h"
31 #include "content/browser/renderer_host/media/video_frame_receiver_on_io_thread. h"
32 #include "content/public/browser/browser_thread.h" 31 #include "content/public/browser/browser_thread.h"
33 #include "content/public/browser/desktop_media_id.h" 32 #include "content/public/browser/desktop_media_id.h"
34 #include "content/public/common/media_stream_request.h" 33 #include "content/public/common/media_stream_request.h"
35 #include "media/base/bind_to_current_loop.h" 34 #include "media/base/bind_to_current_loop.h"
36 #include "media/base/media_switches.h" 35 #include "media/base/media_switches.h"
37 #include "media/base/video_facing.h" 36 #include "media/base/video_facing.h"
38 #include "media/capture/video/video_capture_buffer_pool_impl.h" 37 #include "media/capture/video/video_capture_buffer_pool_impl.h"
39 #include "media/capture/video/video_capture_buffer_tracker_factory_impl.h" 38 #include "media/capture/video/video_capture_buffer_tracker_factory_impl.h"
40 #include "media/capture/video/video_capture_device.h" 39 #include "media/capture/video/video_capture_device.h"
41 #include "media/capture/video/video_capture_device_client.h" 40 #include "media/capture/video/video_capture_device_client.h"
(...skipping 10 matching lines...) Expand all
52 #endif 51 #endif
53 52
54 #if defined(OS_ANDROID) 53 #if defined(OS_ANDROID)
55 #include "content/browser/media/capture/screen_capture_device_android.h" 54 #include "content/browser/media/capture/screen_capture_device_android.h"
56 #endif 55 #endif
57 56
58 #endif // defined(ENABLE_SCREEN_CAPTURE) 57 #endif // defined(ENABLE_SCREEN_CAPTURE)
59 58
60 namespace { 59 namespace {
61 60
62 class VideoFrameConsumerFeedbackObserverOnTaskRunner
63 : public media::VideoFrameConsumerFeedbackObserver {
64 public:
65 VideoFrameConsumerFeedbackObserverOnTaskRunner(
66 media::VideoFrameConsumerFeedbackObserver* observer,
67 scoped_refptr<base::SingleThreadTaskRunner> task_runner)
68 : observer_(observer), task_runner_(std::move(task_runner)) {}
69
70 void OnUtilizationReport(int frame_feedback_id, double utilization) override {
71 task_runner_->PostTask(
72 FROM_HERE,
73 base::Bind(
74 &media::VideoFrameConsumerFeedbackObserver::OnUtilizationReport,
75 base::Unretained(observer_), frame_feedback_id, utilization));
76 }
77
78 private:
79 media::VideoFrameConsumerFeedbackObserver* const observer_;
80 const scoped_refptr<base::SingleThreadTaskRunner> task_runner_;
81 };
82
83 // Compares two VideoCaptureFormat by checking smallest frame_size area, then 61 // Compares two VideoCaptureFormat by checking smallest frame_size area, then
84 // by _largest_ frame_rate. Used to order a VideoCaptureFormats vector so that 62 // by _largest_ frame_rate. Used to order a VideoCaptureFormats vector so that
85 // the first entry for a given resolution has the largest frame rate, as needed 63 // the first entry for a given resolution has the largest frame rate, as needed
86 // by the ConsolidateCaptureFormats() method. 64 // by the ConsolidateCaptureFormats() method.
87 bool IsCaptureFormatSmaller(const media::VideoCaptureFormat& format1, 65 bool IsCaptureFormatSmaller(const media::VideoCaptureFormat& format1,
88 const media::VideoCaptureFormat& format2) { 66 const media::VideoCaptureFormat& format2) {
89 DCHECK(format1.frame_size.GetCheckedArea().IsValid()); 67 DCHECK(format1.frame_size.GetCheckedArea().IsValid());
90 DCHECK(format2.frame_size.GetCheckedArea().IsValid()); 68 DCHECK(format2.frame_size.GetCheckedArea().IsValid());
91 if (format1.frame_size.GetCheckedArea().ValueOrDefault(0) == 69 if (format1.frame_size.GetCheckedArea().ValueOrDefault(0) ==
92 format2.frame_size.GetCheckedArea().ValueOrDefault(0)) { 70 format2.frame_size.GetCheckedArea().ValueOrDefault(0)) {
(...skipping 25 matching lines...) Expand all
118 formats->erase(last, formats->end()); 96 formats->erase(last, formats->end());
119 // Mark all formats as I420, since this is what the renderer side will get 97 // Mark all formats as I420, since this is what the renderer side will get
120 // anyhow: the actual pixel format is decided at the device level. 98 // anyhow: the actual pixel format is decided at the device level.
121 // Don't do this for Y16 format as it is handled separatelly. 99 // Don't do this for Y16 format as it is handled separatelly.
122 for (auto& format : *formats) { 100 for (auto& format : *formats) {
123 if (format.pixel_format != media::PIXEL_FORMAT_Y16) 101 if (format.pixel_format != media::PIXEL_FORMAT_Y16)
124 format.pixel_format = media::PIXEL_FORMAT_I420; 102 format.pixel_format = media::PIXEL_FORMAT_I420;
125 } 103 }
126 } 104 }
127 105
128 // The maximum number of video frame buffers in-flight at any one time. This
129 // value should be based on the logical capacity of the capture pipeline, and
130 // not on hardware performance. For example, tab capture requires more buffers
131 // than webcam capture because the pipeline is longer (it includes read-backs
132 // pending in the GPU pipeline).
133 const int kMaxNumberOfBuffers = 3;
134 // TODO(miu): The value for tab capture should be determined programmatically.
135 // http://crbug.com/460318
136 const int kMaxNumberOfBuffersForTabCapture = 10;
137
138 // Used for logging capture events. 106 // Used for logging capture events.
139 // Elements in this enum should not be deleted or rearranged; the only 107 // Elements in this enum should not be deleted or rearranged; the only
140 // permitted operation is to add new elements before NUM_VIDEO_CAPTURE_EVENT. 108 // permitted operation is to add new elements before NUM_VIDEO_CAPTURE_EVENT.
141 enum VideoCaptureEvent { 109 enum VideoCaptureEvent {
142 VIDEO_CAPTURE_START_CAPTURE = 0, 110 VIDEO_CAPTURE_START_CAPTURE = 0,
143 VIDEO_CAPTURE_STOP_CAPTURE_OK = 1, 111 VIDEO_CAPTURE_STOP_CAPTURE_OK = 1,
144 VIDEO_CAPTURE_STOP_CAPTURE_DUE_TO_ERROR = 2, 112 VIDEO_CAPTURE_STOP_CAPTURE_DUE_TO_ERROR = 2,
145 VIDEO_CAPTURE_STOP_CAPTURE_OK_NO_FRAMES_PRODUCED_BY_DEVICE = 3, 113 VIDEO_CAPTURE_STOP_CAPTURE_OK_NO_FRAMES_PRODUCED_BY_DEVICE = 3,
146 VIDEO_CAPTURE_STOP_CAPTURE_OK_NO_FRAMES_PRODUCED_BY_DESKTOP_OR_TAB = 4, 114 VIDEO_CAPTURE_STOP_CAPTURE_OK_NO_FRAMES_PRODUCED_BY_DESKTOP_OR_TAB = 4,
147 NUM_VIDEO_CAPTURE_EVENT 115 NUM_VIDEO_CAPTURE_EVENT
148 }; 116 };
149 117
150 void LogVideoCaptureEvent(VideoCaptureEvent event) { 118 void LogVideoCaptureEvent(VideoCaptureEvent event) {
151 UMA_HISTOGRAM_ENUMERATION("Media.VideoCaptureManager.Event", 119 UMA_HISTOGRAM_ENUMERATION("Media.VideoCaptureManager.Event", event,
152 event,
153 NUM_VIDEO_CAPTURE_EVENT); 120 NUM_VIDEO_CAPTURE_EVENT);
154 } 121 }
155 122
156 // Counter used for identifying a DeviceRequest to start a capture device.
157 static int g_device_start_id = 0;
158
159 const media::VideoCaptureSessionId kFakeSessionId = -1; 123 const media::VideoCaptureSessionId kFakeSessionId = -1;
160 124
161 std::unique_ptr<media::VideoCaptureJpegDecoder> CreateGpuJpegDecoder(
162 const media::VideoCaptureJpegDecoder::DecodeDoneCB& decode_done_cb) {
163 return base::MakeUnique<content::VideoCaptureGpuJpegDecoder>(decode_done_cb);
164 }
165
166 } // namespace 125 } // namespace
167 126
168 namespace content { 127 namespace content {
169 128
170 // Instances of this struct go through several different phases during their
171 // lifetime.
172 // Phase 1: When first created (in GetOrCreateDeviceEntry()), this consists of
173 // only the |video_capture_controller|. Clients can already connect to the
174 // controller, but there is no |video_capture_device| present.
175 // Phase 2: When a request to "start" the entry comes in (via
176 // HandleQueuedStartRequest()), creation of |video_capture_device| is scheduled
177 // to run asynchronously on the Device Thread.
178 // Phase 3: As soon as the creation of the VideoCaptureDevice is complete, this
179 // newly created VideoCaptureDevice instance is connected to the
180 // VideoCaptureController via SetConsumerFeedbackObserver().
181 // Phase 4: This phase can only be reached on Android. When the application goes
182 // to the background, the |video_capture_device| is asynchronously stopped and
183 // released on the Device Thread. When the application is resumed, we
184 // transition to Phase 2.
185 struct VideoCaptureManager::DeviceEntry {
186 public:
187 DeviceEntry(MediaStreamType stream_type,
188 const std::string& id,
189 const media::VideoCaptureParams& params);
190 ~DeviceEntry();
191 std::unique_ptr<media::VideoCaptureDevice::Client> CreateDeviceClient();
192
193 const int serial_id;
194 const MediaStreamType stream_type;
195 const std::string id;
196 const media::VideoCaptureParams parameters;
197 VideoCaptureController video_capture_controller;
198 std::unique_ptr<media::VideoCaptureDevice> video_capture_device;
199 };
200
201 // Bundles a media::VideoCaptureDeviceDescriptor with corresponding supported 129 // Bundles a media::VideoCaptureDeviceDescriptor with corresponding supported
202 // video formats. 130 // video formats.
203 struct VideoCaptureManager::DeviceInfo { 131 struct VideoCaptureManager::DeviceInfo {
204 DeviceInfo(); 132 DeviceInfo();
205 DeviceInfo(media::VideoCaptureDeviceDescriptor descriptor); 133 DeviceInfo(media::VideoCaptureDeviceDescriptor descriptor);
206 DeviceInfo(const DeviceInfo& other); 134 DeviceInfo(const DeviceInfo& other);
207 ~DeviceInfo(); 135 ~DeviceInfo();
208 DeviceInfo& operator=(const DeviceInfo& other); 136 DeviceInfo& operator=(const DeviceInfo& other);
209 137
210 media::VideoCaptureDeviceDescriptor descriptor; 138 media::VideoCaptureDeviceDescriptor descriptor;
(...skipping 17 matching lines...) Expand all
228 156
229 private: 157 private:
230 const int serial_id_; 158 const int serial_id_;
231 const media::VideoCaptureSessionId session_id_; 159 const media::VideoCaptureSessionId session_id_;
232 const media::VideoCaptureParams params_; 160 const media::VideoCaptureParams params_;
233 // Set to true if the device should be stopped before it has successfully 161 // Set to true if the device should be stopped before it has successfully
234 // been started. 162 // been started.
235 bool abort_start_; 163 bool abort_start_;
236 }; 164 };
237 165
238 VideoCaptureManager::DeviceEntry::DeviceEntry(
239 MediaStreamType stream_type,
240 const std::string& id,
241 const media::VideoCaptureParams& params)
242 : serial_id(g_device_start_id++),
243 stream_type(stream_type),
244 id(id),
245 parameters(params) {}
246
247 VideoCaptureManager::DeviceEntry::~DeviceEntry() {
248 DCHECK_CURRENTLY_ON(BrowserThread::IO);
249 // DCHECK that this DeviceEntry does not still own a
250 // media::VideoCaptureDevice. media::VideoCaptureDevice must be deleted on
251 // the device thread.
252 DCHECK(video_capture_device == nullptr);
253 }
254
255 std::unique_ptr<media::VideoCaptureDevice::Client>
256 VideoCaptureManager::DeviceEntry::CreateDeviceClient() {
257 DCHECK_CURRENTLY_ON(BrowserThread::IO);
258
259 const int max_buffers = stream_type == MEDIA_TAB_VIDEO_CAPTURE
260 ? kMaxNumberOfBuffersForTabCapture
261 : kMaxNumberOfBuffers;
262 scoped_refptr<media::VideoCaptureBufferPool> buffer_pool =
263 new media::VideoCaptureBufferPoolImpl(
264 base::MakeUnique<media::VideoCaptureBufferTrackerFactoryImpl>(),
265 max_buffers);
266
267 return base::MakeUnique<media::VideoCaptureDeviceClient>(
268 base::MakeUnique<VideoFrameReceiverOnIOThread>(
269 video_capture_controller.GetWeakPtrForIOThread()),
270 std::move(buffer_pool),
271 base::Bind(&CreateGpuJpegDecoder,
272 base::Bind(&media::VideoFrameReceiver::OnFrameReadyInBuffer,
273 video_capture_controller.GetWeakPtrForIOThread())));
274 }
275
276 VideoCaptureManager::DeviceInfo::DeviceInfo() = default; 166 VideoCaptureManager::DeviceInfo::DeviceInfo() = default;
277 167
278 VideoCaptureManager::DeviceInfo::DeviceInfo( 168 VideoCaptureManager::DeviceInfo::DeviceInfo(
279 media::VideoCaptureDeviceDescriptor descriptor) 169 media::VideoCaptureDeviceDescriptor descriptor)
280 : descriptor(descriptor) {} 170 : descriptor(descriptor) {}
281 171
282 VideoCaptureManager::DeviceInfo::DeviceInfo( 172 VideoCaptureManager::DeviceInfo::DeviceInfo(
283 const VideoCaptureManager::DeviceInfo& other) = default; 173 const VideoCaptureManager::DeviceInfo& other) = default;
284 174
285 VideoCaptureManager::DeviceInfo::~DeviceInfo() = default; 175 VideoCaptureManager::DeviceInfo::~DeviceInfo() = default;
286 176
287 VideoCaptureManager::DeviceInfo& VideoCaptureManager::DeviceInfo::operator=( 177 VideoCaptureManager::DeviceInfo& VideoCaptureManager::DeviceInfo::operator=(
288 const VideoCaptureManager::DeviceInfo& other) = default; 178 const VideoCaptureManager::DeviceInfo& other) = default;
289 179
290 VideoCaptureManager::CaptureDeviceStartRequest::CaptureDeviceStartRequest( 180 VideoCaptureManager::CaptureDeviceStartRequest::CaptureDeviceStartRequest(
291 int serial_id, 181 int serial_id,
292 media::VideoCaptureSessionId session_id, 182 media::VideoCaptureSessionId session_id,
293 const media::VideoCaptureParams& params) 183 const media::VideoCaptureParams& params)
294 : serial_id_(serial_id), 184 : serial_id_(serial_id),
295 session_id_(session_id), 185 session_id_(session_id),
296 params_(params), 186 params_(params),
297 abort_start_(false) { 187 abort_start_(false) {}
298 }
299 188
300 VideoCaptureManager::VideoCaptureManager( 189 VideoCaptureManager::VideoCaptureManager(
301 std::unique_ptr<media::VideoCaptureDeviceFactory> factory, 190 std::unique_ptr<media::VideoCaptureDeviceFactory> factory,
302 scoped_refptr<base::SingleThreadTaskRunner> device_task_runner) 191 scoped_refptr<base::SingleThreadTaskRunner> device_task_runner)
303 : device_task_runner_(std::move(device_task_runner)), 192 : device_task_runner_(std::move(device_task_runner)),
304 new_capture_session_id_(1), 193 new_capture_session_id_(1),
305 video_capture_device_factory_(std::move(factory)) {} 194 video_capture_device_factory_(std::move(factory)) {}
306 195
307 VideoCaptureManager::~VideoCaptureManager() { 196 VideoCaptureManager::~VideoCaptureManager() {
308 DCHECK(devices_.empty()); 197 DCHECK(controllers_.empty());
309 DCHECK(device_start_queue_.empty()); 198 DCHECK(device_start_queue_.empty());
310 } 199 }
311 200
312 void VideoCaptureManager::AddVideoCaptureObserver( 201 void VideoCaptureManager::AddVideoCaptureObserver(
313 media::VideoCaptureObserver* observer) { 202 media::VideoCaptureObserver* observer) {
314 DCHECK(observer); 203 DCHECK(observer);
315 DCHECK_CURRENTLY_ON(BrowserThread::IO); 204 DCHECK_CURRENTLY_ON(BrowserThread::IO);
316 capture_observers_.AddObserver(observer); 205 capture_observers_.AddObserver(observer);
317 } 206 }
318 207
(...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after
358 devices_info_cache_); 247 devices_info_cache_);
359 // OK to use base::Unretained() since we own the VCDFactory and |this| is 248 // OK to use base::Unretained() since we own the VCDFactory and |this| is
360 // bound in |devices_enumerated_callback|. 249 // bound in |devices_enumerated_callback|.
361 device_task_runner_->PostTask( 250 device_task_runner_->PostTask(
362 FROM_HERE, 251 FROM_HERE,
363 base::Bind(&media::VideoCaptureDeviceFactory::EnumerateDeviceDescriptors, 252 base::Bind(&media::VideoCaptureDeviceFactory::EnumerateDeviceDescriptors,
364 base::Unretained(video_capture_device_factory_.get()), 253 base::Unretained(video_capture_device_factory_.get()),
365 devices_enumerated_callback)); 254 devices_enumerated_callback));
366 } 255 }
367 256
257 const media::VideoCaptureDeviceDescriptor*
258 VideoCaptureManager::LookupDeviceDescriptor(const std::string& id) {
259 const DeviceInfo* info = GetDeviceInfoById(id);
260 return info ? (&info->descriptor) : nullptr;
261 }
262
368 int VideoCaptureManager::Open(const MediaStreamDevice& device) { 263 int VideoCaptureManager::Open(const MediaStreamDevice& device) {
369 DCHECK_CURRENTLY_ON(BrowserThread::IO); 264 DCHECK_CURRENTLY_ON(BrowserThread::IO);
370 265
371 // Generate a new id for the session being opened. 266 // Generate a new id for the session being opened.
372 const media::VideoCaptureSessionId capture_session_id = 267 const media::VideoCaptureSessionId capture_session_id =
373 new_capture_session_id_++; 268 new_capture_session_id_++;
374 269
375 DCHECK(sessions_.find(capture_session_id) == sessions_.end()); 270 DCHECK(sessions_.find(capture_session_id) == sessions_.end());
376 DVLOG(1) << "VideoCaptureManager::Open, id " << capture_session_id; 271 DVLOG(1) << "VideoCaptureManager::Open, id " << capture_session_id;
377 272
(...skipping 12 matching lines...) Expand all
390 void VideoCaptureManager::Close(int capture_session_id) { 285 void VideoCaptureManager::Close(int capture_session_id) {
391 DCHECK_CURRENTLY_ON(BrowserThread::IO); 286 DCHECK_CURRENTLY_ON(BrowserThread::IO);
392 DVLOG(1) << "VideoCaptureManager::Close, id " << capture_session_id; 287 DVLOG(1) << "VideoCaptureManager::Close, id " << capture_session_id;
393 288
394 SessionMap::iterator session_it = sessions_.find(capture_session_id); 289 SessionMap::iterator session_it = sessions_.find(capture_session_id);
395 if (session_it == sessions_.end()) { 290 if (session_it == sessions_.end()) {
396 NOTREACHED(); 291 NOTREACHED();
397 return; 292 return;
398 } 293 }
399 294
400 DeviceEntry* const existing_device = 295 VideoCaptureController* const existing_device = LookupControllerByTypeAndId(
401 GetDeviceEntryByTypeAndId(session_it->second.type, session_it->second.id); 296 session_it->second.type, session_it->second.id);
402 if (existing_device) { 297 if (existing_device) {
403 // Remove any client that is still using the session. This is safe to call 298 // Remove any client that is still using the session. This is safe to call
404 // even if there are no clients using the session. 299 // even if there are no clients using the session.
405 existing_device->video_capture_controller.StopSession(capture_session_id); 300 existing_device->StopSession(capture_session_id);
406 301
407 // StopSession() may have removed the last client, so we might need to 302 // StopSession() may have removed the last client, so we might need to
408 // close the device. 303 // close the device.
409 DestroyDeviceEntryIfNoClients(existing_device); 304 DestroyDeviceEntryIfNoClients(existing_device);
410 } 305 }
411 306
412 // Notify listeners asynchronously, and forget the session. 307 // Notify listeners asynchronously, and forget the session.
413 base::ThreadTaskRunnerHandle::Get()->PostTask( 308 base::ThreadTaskRunnerHandle::Get()->PostTask(
414 FROM_HERE, base::Bind(&VideoCaptureManager::OnClosed, this, 309 FROM_HERE, base::Bind(&VideoCaptureManager::OnClosed, this,
415 session_it->second.type, capture_session_id)); 310 session_it->second.type, capture_session_id));
416 sessions_.erase(session_it); 311 sessions_.erase(session_it);
417 } 312 }
418 313
419 void VideoCaptureManager::QueueStartDevice( 314 void VideoCaptureManager::QueueStartDevice(
420 media::VideoCaptureSessionId session_id, 315 media::VideoCaptureSessionId session_id,
421 DeviceEntry* entry, 316 VideoCaptureController* controller,
422 const media::VideoCaptureParams& params) { 317 const media::VideoCaptureParams& params) {
423 DCHECK_CURRENTLY_ON(BrowserThread::IO); 318 DCHECK_CURRENTLY_ON(BrowserThread::IO);
424 device_start_queue_.push_back( 319 device_start_queue_.push_back(
425 CaptureDeviceStartRequest(entry->serial_id, session_id, params)); 320 CaptureDeviceStartRequest(controller->serial_id(), session_id, params));
426 if (device_start_queue_.size() == 1) 321 if (device_start_queue_.size() == 1)
427 HandleQueuedStartRequest(); 322 HandleQueuedStartRequest();
428 } 323 }
429 324
430 void VideoCaptureManager::DoStopDevice(DeviceEntry* entry) { 325 void VideoCaptureManager::DoStopDevice(VideoCaptureController* controller) {
431 DCHECK_CURRENTLY_ON(BrowserThread::IO); 326 DCHECK_CURRENTLY_ON(BrowserThread::IO);
432 // TODO(mcasas): use a helper function https://crbug.com/624854. 327 // TODO(mcasas): use a helper function https://crbug.com/624854.
433 DCHECK( 328 DCHECK(std::find_if(
434 std::find_if(devices_.begin(), devices_.end(), 329 controllers_.begin(), controllers_.end(),
435 [entry](const std::unique_ptr<DeviceEntry>& device_entry) { 330 [controller](
436 return device_entry.get() == entry; 331 const scoped_refptr<VideoCaptureController>& device_entry) {
437 }) != devices_.end()); 332 return device_entry.get() == controller;
333 }) != controllers_.end());
438 334
439 // Find the matching start request. 335 // Find the matching start request.
440 for (DeviceStartQueue::reverse_iterator request = 336 for (DeviceStartQueue::reverse_iterator request =
441 device_start_queue_.rbegin(); 337 device_start_queue_.rbegin();
442 request != device_start_queue_.rend(); ++request) { 338 request != device_start_queue_.rend(); ++request) {
443 if (request->serial_id() == entry->serial_id) { 339 if (request->serial_id() == controller->serial_id()) {
444 request->set_abort_start(); 340 request->set_abort_start();
445 DVLOG(3) << "DoStopDevice, aborting start request for device " 341 DVLOG(3) << "DoStopDevice, aborting start request for device "
446 << entry->id << " serial_id = " << entry->serial_id; 342 << controller->device_id()
343 << " serial_id = " << controller->serial_id();
447 return; 344 return;
448 } 345 }
449 } 346 }
450 347
451 const DeviceInfo* device_info = GetDeviceInfoById(entry->id); 348 const DeviceInfo* device_info = GetDeviceInfoById(controller->device_id());
452 if (device_info != nullptr) { 349 if (device_info != nullptr) {
453 for (auto& observer : capture_observers_) 350 for (auto& observer : capture_observers_)
454 observer.OnVideoCaptureStopped(device_info->descriptor.facing); 351 observer.OnVideoCaptureStopped(device_info->descriptor.facing);
455 } 352 }
456 353
457 DVLOG(3) << "DoStopDevice. Send stop request for device = " << entry->id 354 DVLOG(3) << "DoStopDevice. Send stop request for device = "
458 << " serial_id = " << entry->serial_id << "."; 355 << controller->device_id()
459 entry->video_capture_controller.OnLog( 356 << " serial_id = " << controller->serial_id() << ".";
460 base::StringPrintf("Stopping device: id: %s", entry->id.c_str())); 357 controller->OnLog(base::StringPrintf("Stopping device: id: %s",
461 entry->video_capture_controller.SetConsumerFeedbackObserver(nullptr); 358 controller->device_id().c_str()));
462 359
463 // |entry->video_capture_device| can be null if creating the device has 360 if (controller->IsDeviceAlive()) {
464 // failed. 361 // Since we may be removing |controller| from |controllers_| while
465 if (entry->video_capture_device) { 362 // ReleaseDeviceAsnyc() is executing, we pass it shared ownership to
466 device_task_runner_->PostTask( 363 // |controller|.
467 FROM_HERE, 364 controller->ReleaseDeviceAsync(MakeScopedRefptrOwnership(
468 base::Bind(&VideoCaptureManager::DoStopDeviceOnDeviceThread, this, 365 GetControllerSharedRefFromSerialId(controller->serial_id())));
469 base::Passed(&entry->video_capture_device)));
470 } 366 }
471 } 367 }
472 368
473 void VideoCaptureManager::HandleQueuedStartRequest() { 369 void VideoCaptureManager::HandleQueuedStartRequest() {
474 DCHECK_CURRENTLY_ON(BrowserThread::IO); 370 DCHECK_CURRENTLY_ON(BrowserThread::IO);
475 // Remove all start requests that have been aborted. 371 // Remove all start requests that have been aborted.
476 while (device_start_queue_.begin() != device_start_queue_.end() && 372 while (device_start_queue_.begin() != device_start_queue_.end() &&
477 device_start_queue_.begin()->abort_start()) { 373 device_start_queue_.begin()->abort_start()) {
478 device_start_queue_.pop_front(); 374 device_start_queue_.pop_front();
479 } 375 }
480 DeviceStartQueue::iterator request = device_start_queue_.begin(); 376 DeviceStartQueue::iterator request = device_start_queue_.begin();
481 if (request == device_start_queue_.end()) 377 if (request == device_start_queue_.end())
482 return; 378 return;
483 379
484 const int serial_id = request->serial_id(); 380 const int serial_id = request->serial_id();
485 DeviceEntry* const entry = GetDeviceEntryBySerialId(serial_id); 381 VideoCaptureController* const controller =
486 DCHECK(entry); 382 LookupControllerBySerialId(serial_id);
383 DCHECK(controller);
487 384
488 DVLOG(3) << "HandleQueuedStartRequest, Post start to device thread, device = " 385 DVLOG(3) << "HandleQueuedStartRequest, Post start to device thread, device = "
489 << entry->id << " start id = " << entry->serial_id; 386 << controller->device_id()
387 << " start id = " << controller->serial_id();
490 388
491 std::unique_ptr<media::VideoCaptureDevice::Client> device_client = 389 // The method CreateAndStartDeviceAsync() is going to run asynchronously.
492 entry->CreateDeviceClient(); 390 // Since we may be removing the controller while it is executing, we need to
493 391 // pass it shared ownership to itself so that it stays alive while executing.
494 base::Callback<std::unique_ptr<VideoCaptureDevice>(void)> 392 // And since the execution may make callbacks into |this|, we also need
495 start_capture_function; 393 // to pass it shared ownership to |this|.
496 394 auto context_reference = base::MakeUnique<OwnershipCollection>();
497 switch (entry->stream_type) { 395 context_reference->AttachOwnership(
498 case MEDIA_DEVICE_VIDEO_CAPTURE: { 396 MakeScopedRefptrOwnership(scoped_refptr<VideoCaptureManager>(this)));
499 // We look up the device id from the renderer in our local enumeration 397 context_reference->AttachOwnership(
500 // since the renderer does not have all the information that might be 398 MakeScopedRefptrOwnership(GetControllerSharedRefFromSerialId(serial_id)));
501 // held in the browser-side VideoCaptureDevice::Name structure. 399 // TODO(chfremer): Check if request->params() can actually be different from
502 const DeviceInfo* found = GetDeviceInfoById(entry->id); 400 // controller->parameters, and simplify if this is not the case.
503 if (found) { 401 controller->CreateAndStartDeviceAsync(
504 entry->video_capture_controller.OnLog( 402 request->params(), static_cast<BuildableDeviceCallbacks*>(this),
505 base::StringPrintf("Starting device: id: %s, name: %s, api: %s", 403 std::move(context_reference));
506 found->descriptor.device_id.c_str(),
507 found->descriptor.GetNameAndModel().c_str(),
508 found->descriptor.GetCaptureApiTypeString()));
509
510 for (auto& observer : capture_observers_)
511 observer.OnVideoCaptureStarted(found->descriptor.facing);
512
513 start_capture_function =
514 base::Bind(&VideoCaptureManager::DoStartDeviceCaptureOnDeviceThread,
515 this, found->descriptor, request->params(),
516 base::Passed(std::move(device_client)));
517 } else {
518 // Errors from DoStartDeviceCaptureOnDeviceThread go via
519 // VideoCaptureDeviceClient::OnError, which needs some thread
520 // dancing to get errors processed on the IO thread. But since
521 // we're on that thread, we call VideoCaptureController
522 // methods directly.
523 const std::string log_message = base::StringPrintf(
524 "Error on %s:%d: device %s unknown. Maybe recently disconnected?",
525 __FILE__, __LINE__, entry->id.c_str());
526 DLOG(ERROR) << log_message;
527 entry->video_capture_controller.OnLog(log_message);
528 entry->video_capture_controller.OnError();
529 // Drop the failed start request.
530 device_start_queue_.pop_front();
531
532 return;
533 }
534 break;
535 }
536 case MEDIA_TAB_VIDEO_CAPTURE:
537 start_capture_function = base::Bind(
538 &VideoCaptureManager::DoStartTabCaptureOnDeviceThread, this,
539 entry->id, request->params(), base::Passed(std::move(device_client)));
540 break;
541
542 case MEDIA_DESKTOP_VIDEO_CAPTURE:
543 start_capture_function = base::Bind(
544 &VideoCaptureManager::DoStartDesktopCaptureOnDeviceThread, this,
545 entry->id, request->params(), base::Passed(std::move(device_client)));
546 break;
547
548 default: {
549 NOTIMPLEMENTED();
550 return;
551 }
552 }
553 base::PostTaskAndReplyWithResult(
554 device_task_runner_.get(), FROM_HERE, start_capture_function,
555 base::Bind(&VideoCaptureManager::OnDeviceStarted, this,
556 request->serial_id()));
557 } 404 }
558 405
559 void VideoCaptureManager::OnDeviceStarted( 406 void VideoCaptureManager::WillStartDevice(media::VideoFacingMode facing_mode) {
560 int serial_id, 407 for (auto& observer : capture_observers_)
561 std::unique_ptr<VideoCaptureDevice> device) { 408 observer.OnVideoCaptureStarted(facing_mode);
409 }
410
411 void VideoCaptureManager::DidStartDevice(VideoCaptureController* controller) {
562 DVLOG(3) << __func__; 412 DVLOG(3) << __func__;
563 DCHECK_CURRENTLY_ON(BrowserThread::IO); 413 DCHECK_CURRENTLY_ON(BrowserThread::IO);
564 DCHECK_EQ(serial_id, device_start_queue_.begin()->serial_id()); 414 DCHECK(controller);
565 // |device| can be null if creation failed in 415 DCHECK_EQ(controller->serial_id(), device_start_queue_.begin()->serial_id());
566 // DoStartDeviceCaptureOnDeviceThread.
567 if (device_start_queue_.front().abort_start()) { 416 if (device_start_queue_.front().abort_start()) {
568 // The device is no longer wanted. Stop the device again. 417 // A request to release the device may have arrived during the asynchronous
569 DVLOG(3) << "OnDeviceStarted but start request have been aborted."; 418 // device startup.
570 media::VideoCaptureDevice* device_ptr = device.get(); 419 DVLOG(3) << "Device release request has been issued while device was "
571 base::Closure closure = 420 << "starting up asynchronously.";
572 base::Bind(&VideoCaptureManager::DoStopDeviceOnDeviceThread, this, 421 controller->ReleaseDeviceAsync(MakeScopedRefptrOwnership(
573 base::Passed(&device)); 422 GetControllerSharedRefFromSerialId(controller->serial_id())));
574 if (device_ptr && !device_task_runner_->PostTask(FROM_HERE, closure)) {
575 // PostTask failed. The device must be stopped anyway.
576 device_ptr->StopAndDeAllocate();
577 }
578 } else { 423 } else {
579 DeviceEntry* const entry = GetDeviceEntryBySerialId(serial_id); 424 if (controller->stream_type() == MEDIA_DESKTOP_VIDEO_CAPTURE) {
580 DCHECK(entry);
581 DCHECK(!entry->video_capture_device);
582 if (device) {
583 // Passing raw pointer |device.get()| to the controller is safe,
584 // because we transfer ownership of it to |entry|. We are calling
585 // SetConsumerFeedbackObserver(nullptr) before releasing
586 // |entry->video_capture_device_| on the |device_task_runner_|.
587 entry->video_capture_controller.SetConsumerFeedbackObserver(
588 base::MakeUnique<VideoFrameConsumerFeedbackObserverOnTaskRunner>(
589 device.get(), device_task_runner_));
590 }
591 entry->video_capture_device = std::move(device);
592
593 if (entry->stream_type == MEDIA_DESKTOP_VIDEO_CAPTURE) {
594 const media::VideoCaptureSessionId session_id = 425 const media::VideoCaptureSessionId session_id =
595 device_start_queue_.front().session_id(); 426 device_start_queue_.front().session_id();
596 DCHECK(session_id != kFakeSessionId); 427 DCHECK(session_id != kFakeSessionId);
597 MaybePostDesktopCaptureWindowId(session_id); 428 MaybePostDesktopCaptureWindowId(session_id);
598 } 429 }
599 430
600 auto it = photo_request_queue_.begin(); 431 auto it = photo_request_queue_.begin();
601 while (it != photo_request_queue_.end()) { 432 while (it != photo_request_queue_.end()) {
602 auto request = it++; 433 auto request = it++;
603 DeviceEntry* maybe_entry = GetDeviceEntryBySessionId(request->first); 434 VideoCaptureController* maybe_entry =
604 if (maybe_entry && maybe_entry->video_capture_device) { 435 LookupControllerBySessionId(request->first);
605 request->second.Run(maybe_entry->video_capture_device.get()); 436 if (maybe_entry && maybe_entry->IsDeviceAlive()) {
437 request->second.Run();
606 photo_request_queue_.erase(request); 438 photo_request_queue_.erase(request);
607 } 439 }
608 } 440 }
609 } 441 }
610 442
611 device_start_queue_.pop_front(); 443 device_start_queue_.pop_front();
612 HandleQueuedStartRequest(); 444 HandleQueuedStartRequest();
613 } 445 }
614 446
615 std::unique_ptr<media::VideoCaptureDevice> 447 void VideoCaptureManager::OnDeviceStartFailed(
616 VideoCaptureManager::DoStartDeviceCaptureOnDeviceThread( 448 VideoCaptureController* controller) {
617 const VideoCaptureDeviceDescriptor& descriptor, 449 const std::string log_message = base::StringPrintf(
618 const media::VideoCaptureParams& params, 450 "Starting device %s has failed. Maybe recently disconnected?",
619 std::unique_ptr<VideoCaptureDevice::Client> device_client) { 451 controller->device_id().c_str());
620 SCOPED_UMA_HISTOGRAM_TIMER("Media.VideoCaptureManager.StartDeviceTime"); 452 DLOG(ERROR) << log_message;
621 DCHECK(IsOnDeviceThread()); 453 controller->OnLog(log_message);
454 controller->OnError();
622 455
623 std::unique_ptr<VideoCaptureDevice> video_capture_device; 456 device_start_queue_.pop_front();
624 video_capture_device = 457 HandleQueuedStartRequest();
625 video_capture_device_factory_->CreateDevice(descriptor);
626
627 if (!video_capture_device) {
628 device_client->OnError(FROM_HERE, "Could not create capture device");
629 return nullptr;
630 }
631
632 video_capture_device->AllocateAndStart(params, std::move(device_client));
633 return video_capture_device;
634 }
635
636 std::unique_ptr<media::VideoCaptureDevice>
637 VideoCaptureManager::DoStartTabCaptureOnDeviceThread(
638 const std::string& id,
639 const media::VideoCaptureParams& params,
640 std::unique_ptr<VideoCaptureDevice::Client> device_client) {
641 SCOPED_UMA_HISTOGRAM_TIMER("Media.VideoCaptureManager.StartDeviceTime");
642 DCHECK(IsOnDeviceThread());
643
644 std::unique_ptr<VideoCaptureDevice> video_capture_device;
645 #if defined(OS_LINUX) || defined(OS_MACOSX) || defined(OS_WIN)
646 video_capture_device = WebContentsVideoCaptureDevice::Create(id);
647 #endif
648
649 if (!video_capture_device) {
650 device_client->OnError(FROM_HERE, "Could not create capture device");
651 return nullptr;
652 }
653
654 video_capture_device->AllocateAndStart(params, std::move(device_client));
655 return video_capture_device;
656 }
657
658 std::unique_ptr<media::VideoCaptureDevice>
659 VideoCaptureManager::DoStartDesktopCaptureOnDeviceThread(
660 const std::string& id,
661 const media::VideoCaptureParams& params,
662 std::unique_ptr<VideoCaptureDevice::Client> device_client) {
663 SCOPED_UMA_HISTOGRAM_TIMER("Media.VideoCaptureManager.StartDeviceTime");
664 DCHECK(IsOnDeviceThread());
665
666 std::unique_ptr<VideoCaptureDevice> video_capture_device;
667 #if defined(ENABLE_SCREEN_CAPTURE)
668 DesktopMediaID desktop_id = DesktopMediaID::Parse(id);
669 if (desktop_id.is_null()) {
670 device_client->OnError(FROM_HERE, "Desktop media ID is null");
671 return nullptr;
672 }
673
674 if (desktop_id.type == DesktopMediaID::TYPE_WEB_CONTENTS) {
675 #if defined(OS_LINUX) || defined(OS_MACOSX) || defined(OS_WIN)
676 video_capture_device = WebContentsVideoCaptureDevice::Create(id);
677 IncrementDesktopCaptureCounter(TAB_VIDEO_CAPTURER_CREATED);
678 if (desktop_id.audio_share) {
679 IncrementDesktopCaptureCounter(TAB_VIDEO_CAPTURER_CREATED_WITH_AUDIO);
680 } else {
681 IncrementDesktopCaptureCounter(TAB_VIDEO_CAPTURER_CREATED_WITHOUT_AUDIO);
682 }
683 #endif
684 } else {
685 #if defined(OS_ANDROID)
686 video_capture_device = base::MakeUnique<ScreenCaptureDeviceAndroid>();
687 #else
688 #if defined(USE_AURA)
689 video_capture_device = DesktopCaptureDeviceAura::Create(desktop_id);
690 #endif // defined(USE_AURA)
691 #if BUILDFLAG(ENABLE_WEBRTC)
692 if (!video_capture_device)
693 video_capture_device = DesktopCaptureDevice::Create(desktop_id);
694 #endif // BUILDFLAG(ENABLE_WEBRTC)
695 #endif // defined (OS_ANDROID)
696 }
697 #endif // defined(ENABLE_SCREEN_CAPTURE)
698
699 if (!video_capture_device) {
700 device_client->OnError(FROM_HERE, "Could not create capture device");
701 return nullptr;
702 }
703
704 video_capture_device->AllocateAndStart(params, std::move(device_client));
705 return video_capture_device;
706 } 458 }
707 459
708 void VideoCaptureManager::StartCaptureForClient( 460 void VideoCaptureManager::StartCaptureForClient(
709 media::VideoCaptureSessionId session_id, 461 media::VideoCaptureSessionId session_id,
710 const media::VideoCaptureParams& params, 462 const media::VideoCaptureParams& params,
711 VideoCaptureControllerID client_id, 463 VideoCaptureControllerID client_id,
712 VideoCaptureControllerEventHandler* client_handler, 464 VideoCaptureControllerEventHandler* client_handler,
713 const DoneCB& done_cb) { 465 const DoneCB& done_cb) {
714 DCHECK_CURRENTLY_ON(BrowserThread::IO); 466 DCHECK_CURRENTLY_ON(BrowserThread::IO);
715 DVLOG(1) << __func__ << ", session_id = " << session_id << ", request: " 467 DVLOG(1) << __func__ << ", session_id = " << session_id << ", request: "
716 << media::VideoCaptureFormat::ToString(params.requested_format); 468 << media::VideoCaptureFormat::ToString(params.requested_format);
717 469
718 DeviceEntry* entry = GetOrCreateDeviceEntry(session_id, params); 470 VideoCaptureController* controller =
719 if (!entry) { 471 GetOrCreateController(session_id, params);
472 if (!controller) {
720 done_cb.Run(base::WeakPtr<VideoCaptureController>()); 473 done_cb.Run(base::WeakPtr<VideoCaptureController>());
721 return; 474 return;
722 } 475 }
723 476
724 LogVideoCaptureEvent(VIDEO_CAPTURE_START_CAPTURE); 477 LogVideoCaptureEvent(VIDEO_CAPTURE_START_CAPTURE);
725 478
726 // First client starts the device. 479 // First client starts the device.
727 if (!entry->video_capture_controller.HasActiveClient() && 480 if (!controller->HasActiveClient() && !controller->HasPausedClient()) {
728 !entry->video_capture_controller.HasPausedClient()) { 481 DVLOG(1) << "VideoCaptureManager starting device (id = "
729 DVLOG(1) << "VideoCaptureManager starting device (type = " 482 << controller->device_id() << ")";
730 << entry->stream_type << ", id = " << entry->id << ")"; 483 QueueStartDevice(session_id, controller, params);
731 QueueStartDevice(session_id, entry, params);
732 } 484 }
733 // Run the callback first, as AddClient() may trigger OnFrameInfo(). 485 // Run the callback first, as AddClient() may trigger OnFrameInfo().
734 done_cb.Run(entry->video_capture_controller.GetWeakPtrForIOThread()); 486 done_cb.Run(controller->GetWeakPtrForIOThread());
735 entry->video_capture_controller.AddClient(client_id, client_handler, 487 controller->AddClient(client_id, client_handler, session_id, params);
736 session_id, params);
737 } 488 }
738 489
739 void VideoCaptureManager::StopCaptureForClient( 490 void VideoCaptureManager::StopCaptureForClient(
740 VideoCaptureController* controller, 491 VideoCaptureController* controller,
741 VideoCaptureControllerID client_id, 492 VideoCaptureControllerID client_id,
742 VideoCaptureControllerEventHandler* client_handler, 493 VideoCaptureControllerEventHandler* client_handler,
743 bool aborted_due_to_error) { 494 bool aborted_due_to_error) {
744 DCHECK_CURRENTLY_ON(BrowserThread::IO); 495 DCHECK_CURRENTLY_ON(BrowserThread::IO);
745 DCHECK(controller); 496 DCHECK(controller);
746 DCHECK(client_handler); 497 DCHECK(client_handler);
747 498
748 DeviceEntry* entry = GetDeviceEntryByController(controller); 499 if (!IsControllerPointerValid(controller)) {
749 if (!entry) {
750 NOTREACHED(); 500 NOTREACHED();
751 return; 501 return;
752 } 502 }
753 if (!aborted_due_to_error) { 503 if (!aborted_due_to_error) {
754 if (controller->has_received_frames()) { 504 if (controller->has_received_frames()) {
755 LogVideoCaptureEvent(VIDEO_CAPTURE_STOP_CAPTURE_OK); 505 LogVideoCaptureEvent(VIDEO_CAPTURE_STOP_CAPTURE_OK);
756 } else if (entry->stream_type == MEDIA_DEVICE_VIDEO_CAPTURE) { 506 } else if (controller->stream_type() == MEDIA_DEVICE_VIDEO_CAPTURE) {
757 LogVideoCaptureEvent( 507 LogVideoCaptureEvent(
758 VIDEO_CAPTURE_STOP_CAPTURE_OK_NO_FRAMES_PRODUCED_BY_DEVICE); 508 VIDEO_CAPTURE_STOP_CAPTURE_OK_NO_FRAMES_PRODUCED_BY_DEVICE);
759 } else { 509 } else {
760 LogVideoCaptureEvent( 510 LogVideoCaptureEvent(
761 VIDEO_CAPTURE_STOP_CAPTURE_OK_NO_FRAMES_PRODUCED_BY_DESKTOP_OR_TAB); 511 VIDEO_CAPTURE_STOP_CAPTURE_OK_NO_FRAMES_PRODUCED_BY_DESKTOP_OR_TAB);
762 } 512 }
763 } else { 513 } else {
764 LogVideoCaptureEvent(VIDEO_CAPTURE_STOP_CAPTURE_DUE_TO_ERROR); 514 LogVideoCaptureEvent(VIDEO_CAPTURE_STOP_CAPTURE_DUE_TO_ERROR);
765 for (auto it : sessions_) { 515 for (auto it : sessions_) {
766 if (it.second.type == entry->stream_type && it.second.id == entry->id) { 516 if (it.second.type == controller->stream_type() &&
517 it.second.id == controller->device_id()) {
767 for (auto& listener : listeners_) 518 for (auto& listener : listeners_)
768 listener.Aborted(it.second.type, it.first); 519 listener.Aborted(it.second.type, it.first);
769 // Aborted() call might synchronously destroy |entry|, recheck. 520 // Aborted() call might synchronously destroy |controller|, recheck.
770 entry = GetDeviceEntryByController(controller); 521 if (!IsControllerPointerValid(controller))
771 if (!entry)
772 return; 522 return;
773 break; 523 break;
774 } 524 }
775 } 525 }
776 } 526 }
777 527
778 // Detach client from controller. 528 // Detach client from controller.
779 const media::VideoCaptureSessionId session_id = 529 const media::VideoCaptureSessionId session_id =
780 controller->RemoveClient(client_id, client_handler); 530 controller->RemoveClient(client_id, client_handler);
781 DVLOG(1) << __func__ << ", session_id = " << session_id; 531 DVLOG(1) << __func__ << ", session_id = " << session_id;
782 532
783 // If controller has no more clients, delete controller and device. 533 // If controller has no more clients, delete controller and device.
784 DestroyDeviceEntryIfNoClients(entry); 534 DestroyDeviceEntryIfNoClients(controller);
785 } 535 }
786 536
787 void VideoCaptureManager::PauseCaptureForClient( 537 void VideoCaptureManager::PauseCaptureForClient(
788 VideoCaptureController* controller, 538 VideoCaptureController* controller,
789 VideoCaptureControllerID client_id, 539 VideoCaptureControllerID client_id,
790 VideoCaptureControllerEventHandler* client_handler) { 540 VideoCaptureControllerEventHandler* client_handler) {
791 DCHECK_CURRENTLY_ON(BrowserThread::IO); 541 DCHECK_CURRENTLY_ON(BrowserThread::IO);
792 DCHECK(controller); 542 DCHECK(controller);
793 DCHECK(client_handler); 543 DCHECK(client_handler);
794 DeviceEntry* entry = GetDeviceEntryByController(controller); 544 if (!IsControllerPointerValid(controller))
795 if (!entry) 545 NOTREACHED() << "Got Null controller while pausing capture";
796 NOTREACHED() << "Got Null entry while pausing capture";
797 546
798 const bool had_active_client = controller->HasActiveClient(); 547 const bool had_active_client = controller->HasActiveClient();
799 controller->PauseClient(client_id, client_handler); 548 controller->PauseClient(client_id, client_handler);
800 if (!had_active_client || controller->HasActiveClient()) 549 if (!had_active_client || controller->HasActiveClient())
801 return; 550 return;
802 if (media::VideoCaptureDevice* device = entry->video_capture_device.get()) { 551 if (!controller->IsDeviceAlive())
803 device_task_runner_->PostTask( 552 return;
804 FROM_HERE, 553 controller->MaybeSuspend();
805 base::Bind(&VideoCaptureDevice::MaybeSuspend,
806 // Unretained is safe to use here because |device| would be
807 // null if it was scheduled for shutdown and destruction, and
808 // because this task is guaranteed to run before the task
809 // that destroys the |device|.
810 base::Unretained(device)));
811 }
812 } 554 }
813 555
814 void VideoCaptureManager::ResumeCaptureForClient( 556 void VideoCaptureManager::ResumeCaptureForClient(
815 media::VideoCaptureSessionId session_id, 557 media::VideoCaptureSessionId session_id,
816 const media::VideoCaptureParams& params, 558 const media::VideoCaptureParams& params,
817 VideoCaptureController* controller, 559 VideoCaptureController* controller,
818 VideoCaptureControllerID client_id, 560 VideoCaptureControllerID client_id,
819 VideoCaptureControllerEventHandler* client_handler) { 561 VideoCaptureControllerEventHandler* client_handler) {
820 DCHECK_CURRENTLY_ON(BrowserThread::IO); 562 DCHECK_CURRENTLY_ON(BrowserThread::IO);
821 DCHECK(controller); 563 DCHECK(controller);
822 DCHECK(client_handler); 564 DCHECK(client_handler);
823 565
824 DeviceEntry* entry = GetDeviceEntryByController(controller); 566 if (!IsControllerPointerValid(controller))
825 if (!entry) 567 NOTREACHED() << "Got Null controller while resuming capture";
826 NOTREACHED() << "Got Null entry while resuming capture";
827 568
828 const bool had_active_client = controller->HasActiveClient(); 569 const bool had_active_client = controller->HasActiveClient();
829 controller->ResumeClient(client_id, client_handler); 570 controller->ResumeClient(client_id, client_handler);
830 if (had_active_client || !controller->HasActiveClient()) 571 if (had_active_client || !controller->HasActiveClient())
831 return; 572 return;
832 if (media::VideoCaptureDevice* device = entry->video_capture_device.get()) { 573 if (!controller->IsDeviceAlive())
833 device_task_runner_->PostTask( 574 return;
834 FROM_HERE, 575 controller->Resume();
835 base::Bind(&VideoCaptureDevice::Resume,
836 // Unretained is safe to use here because |device| would be
837 // null if it was scheduled for shutdown and destruction, and
838 // because this task is guaranteed to run before the task
839 // that destroys the |device|.
840 base::Unretained(device)));
841 }
842 } 576 }
843 577
844 void VideoCaptureManager::RequestRefreshFrameForClient( 578 void VideoCaptureManager::RequestRefreshFrameForClient(
845 VideoCaptureController* controller) { 579 VideoCaptureController* controller) {
846 DCHECK_CURRENTLY_ON(BrowserThread::IO); 580 DCHECK_CURRENTLY_ON(BrowserThread::IO);
847 581
848 if (DeviceEntry* entry = GetDeviceEntryByController(controller)) { 582 if (IsControllerPointerValid(controller)) {
849 if (media::VideoCaptureDevice* device = entry->video_capture_device.get()) { 583 if (!controller->IsDeviceAlive())
850 device_task_runner_->PostTask( 584 return;
851 FROM_HERE, 585 controller->RequestRefreshFrame();
852 base::Bind(&VideoCaptureDevice::RequestRefreshFrame,
853 // Unretained is safe to use here because |device| would be
854 // null if it was scheduled for shutdown and destruction,
855 // and because this task is guaranteed to run before the
856 // task that destroys the |device|.
857 base::Unretained(device)));
858 }
859 } 586 }
860 } 587 }
861 588
862 bool VideoCaptureManager::GetDeviceSupportedFormats( 589 bool VideoCaptureManager::GetDeviceSupportedFormats(
863 media::VideoCaptureSessionId capture_session_id, 590 media::VideoCaptureSessionId capture_session_id,
864 media::VideoCaptureFormats* supported_formats) { 591 media::VideoCaptureFormats* supported_formats) {
865 DCHECK_CURRENTLY_ON(BrowserThread::IO); 592 DCHECK_CURRENTLY_ON(BrowserThread::IO);
866 DCHECK(supported_formats->empty()); 593 DCHECK(supported_formats->empty());
867 594
868 SessionMap::iterator it = sessions_.find(capture_session_id); 595 SessionMap::iterator it = sessions_.find(capture_session_id);
(...skipping 24 matching lines...) Expand all
893 DCHECK(formats_in_use->empty()); 620 DCHECK(formats_in_use->empty());
894 621
895 SessionMap::iterator it = sessions_.find(capture_session_id); 622 SessionMap::iterator it = sessions_.find(capture_session_id);
896 if (it == sessions_.end()) 623 if (it == sessions_.end())
897 return false; 624 return false;
898 DVLOG(1) << "GetDeviceFormatsInUse for device: " << it->second.name; 625 DVLOG(1) << "GetDeviceFormatsInUse for device: " << it->second.name;
899 626
900 return GetDeviceFormatsInUse(it->second.type, it->second.id, formats_in_use); 627 return GetDeviceFormatsInUse(it->second.type, it->second.id, formats_in_use);
901 } 628 }
902 629
903 bool VideoCaptureManager::GetDeviceFormatsInUse( 630 bool VideoCaptureManager::GetDeviceFormatsInUse(
miu 2017/03/16 00:01:36 Not related to this CL, but this method signature
chfremer 2017/03/16 17:39:39 Agreed. Also it seems that the behavior of the imp
904 MediaStreamType stream_type, 631 MediaStreamType stream_type,
905 const std::string& device_id, 632 const std::string& device_id,
906 media::VideoCaptureFormats* formats_in_use) { 633 media::VideoCaptureFormats* formats_in_use) {
907 DCHECK_CURRENTLY_ON(BrowserThread::IO); 634 DCHECK_CURRENTLY_ON(BrowserThread::IO);
908 DCHECK(formats_in_use->empty()); 635 DCHECK(formats_in_use->empty());
909 // Return the currently in-use format(s) of the device, if it's started. 636 // Return the currently in-use format(s) of the device, if it's started.
910 DeviceEntry* device_in_use = 637 VideoCaptureController* device_in_use =
911 GetDeviceEntryByTypeAndId(stream_type, device_id); 638 LookupControllerByTypeAndId(stream_type, device_id);
912 if (device_in_use) { 639 if (device_in_use) {
913 // Currently only one format-in-use is supported at the VCC level. 640 // Currently only one format-in-use is supported at the VCC level.
914 formats_in_use->push_back( 641 formats_in_use->push_back(device_in_use->GetVideoCaptureFormat());
915 device_in_use->video_capture_controller.GetVideoCaptureFormat());
916 } 642 }
917 return true; 643 return true;
918 } 644 }
919 645
920 void VideoCaptureManager::SetDesktopCaptureWindowId( 646 void VideoCaptureManager::SetDesktopCaptureWindowId(
921 media::VideoCaptureSessionId session_id, 647 media::VideoCaptureSessionId session_id,
922 gfx::NativeViewId window_id) { 648 gfx::NativeViewId window_id) {
923 DCHECK_CURRENTLY_ON(BrowserThread::IO); 649 DCHECK_CURRENTLY_ON(BrowserThread::IO);
924 VLOG(2) << "SetDesktopCaptureWindowId called for session " << session_id; 650 VLOG(2) << "SetDesktopCaptureWindowId called for session " << session_id;
925 651
926 notification_window_ids_[session_id] = window_id; 652 notification_window_ids_[session_id] = window_id;
927 MaybePostDesktopCaptureWindowId(session_id); 653 MaybePostDesktopCaptureWindowId(session_id);
928 } 654 }
929 655
930 void VideoCaptureManager::MaybePostDesktopCaptureWindowId( 656 void VideoCaptureManager::MaybePostDesktopCaptureWindowId(
931 media::VideoCaptureSessionId session_id) { 657 media::VideoCaptureSessionId session_id) {
932 SessionMap::iterator session_it = sessions_.find(session_id); 658 SessionMap::iterator session_it = sessions_.find(session_id);
933 if (session_it == sessions_.end()) 659 if (session_it == sessions_.end())
934 return; 660 return;
935 661
936 DeviceEntry* const existing_device = 662 VideoCaptureController* const existing_device = LookupControllerByTypeAndId(
937 GetDeviceEntryByTypeAndId(session_it->second.type, session_it->second.id); 663 session_it->second.type, session_it->second.id);
938 if (!existing_device) { 664 if (!existing_device) {
939 DVLOG(2) << "Failed to find an existing screen capture device."; 665 DVLOG(2) << "Failed to find an existing screen capture device.";
940 return; 666 return;
941 } 667 }
942 668
943 if (!existing_device->video_capture_device) { 669 if (!existing_device->IsDeviceAlive()) {
944 DVLOG(2) << "Screen capture device not yet started."; 670 DVLOG(2) << "Screen capture device not yet started.";
945 return; 671 return;
946 } 672 }
947 673
948 DCHECK_EQ(MEDIA_DESKTOP_VIDEO_CAPTURE, existing_device->stream_type); 674 DCHECK_EQ(MEDIA_DESKTOP_VIDEO_CAPTURE, existing_device->stream_type());
949 DesktopMediaID id = DesktopMediaID::Parse(existing_device->id); 675 DesktopMediaID id = DesktopMediaID::Parse(existing_device->device_id());
950 if (id.is_null()) 676 if (id.is_null())
951 return; 677 return;
952 678
953 auto window_id_it = notification_window_ids_.find(session_id); 679 auto window_id_it = notification_window_ids_.find(session_id);
954 if (window_id_it == notification_window_ids_.end()) { 680 if (window_id_it == notification_window_ids_.end()) {
955 DVLOG(2) << "Notification window id not set for screen capture."; 681 DVLOG(2) << "Notification window id not set for screen capture.";
956 return; 682 return;
957 } 683 }
958 684
959 // Post |existing_device->video_capture_device| to the VideoCaptureDevice to 685 existing_device->SetDesktopCaptureWindowIdAsync(
960 // the device_task_runner_. This is safe since the device is destroyed on the 686 window_id_it->second,
961 // device_task_runner_. 687 MakeScopedRefptrOwnership(scoped_refptr<VideoCaptureManager>(this)));
962 device_task_runner_->PostTask(
963 FROM_HERE,
964 base::Bind(&VideoCaptureManager::SetDesktopCaptureWindowIdOnDeviceThread,
965 this, existing_device->video_capture_device.get(),
966 window_id_it->second));
967
968 notification_window_ids_.erase(window_id_it); 688 notification_window_ids_.erase(window_id_it);
969 } 689 }
970 690
971 void VideoCaptureManager::GetPhotoCapabilities( 691 void VideoCaptureManager::GetPhotoCapabilities(
972 int session_id, 692 int session_id,
973 VideoCaptureDevice::GetPhotoCapabilitiesCallback callback) { 693 media::VideoCaptureDevice::GetPhotoCapabilitiesCallback callback) {
974 DCHECK_CURRENTLY_ON(BrowserThread::IO); 694 DCHECK_CURRENTLY_ON(BrowserThread::IO);
975 695
976 const DeviceEntry* entry = GetDeviceEntryBySessionId(session_id); 696 const VideoCaptureController* controller =
977 if (!entry) 697 LookupControllerBySessionId(session_id);
698 if (!controller)
978 return; 699 return;
979 VideoCaptureDevice* device = entry->video_capture_device.get(); 700 if (controller->IsDeviceAlive()) {
980 if (device) { 701 controller->GetPhotoCapabilities(std::move(callback));
981 VideoCaptureManager::DoGetPhotoCapabilities(std::move(callback), device);
982 return; 702 return;
983 } 703 }
984 // |entry| is known but |device| is nullptr, queue up a request for later. 704 // Queue up a request for later.
985 photo_request_queue_.emplace_back( 705 photo_request_queue_.emplace_back(
986 session_id, base::Bind(&VideoCaptureManager::DoGetPhotoCapabilities, this, 706 session_id,
987 base::Passed(&callback))); 707 base::Bind(&VideoCaptureController::GetPhotoCapabilities,
708 base::Unretained(controller), base::Passed(&callback)));
988 } 709 }
989 710
990 void VideoCaptureManager::SetPhotoOptions( 711 void VideoCaptureManager::SetPhotoOptions(
991 int session_id, 712 int session_id,
992 media::mojom::PhotoSettingsPtr settings, 713 media::mojom::PhotoSettingsPtr settings,
993 VideoCaptureDevice::SetPhotoOptionsCallback callback) { 714 media::VideoCaptureDevice::SetPhotoOptionsCallback callback) {
994 DCHECK_CURRENTLY_ON(BrowserThread::IO); 715 DCHECK_CURRENTLY_ON(BrowserThread::IO);
995 716
996 const DeviceEntry* entry = GetDeviceEntryBySessionId(session_id); 717 VideoCaptureController* controller = LookupControllerBySessionId(session_id);
997 if (!entry) 718 if (!controller)
998 return; 719 return;
999 VideoCaptureDevice* device = entry->video_capture_device.get(); 720 if (controller->IsDeviceAlive()) {
1000 if (device) { 721 controller->SetPhotoOptions(std::move(settings), std::move(callback));
1001 VideoCaptureManager::DoSetPhotoOptions(std::move(callback),
1002 std::move(settings), device);
1003 return; 722 return;
1004 } 723 }
1005 // |entry| is known but |device| is nullptr, queue up a request for later. 724 // Queue up a request for later.
1006 photo_request_queue_.emplace_back( 725 photo_request_queue_.emplace_back(
1007 session_id, base::Bind(&VideoCaptureManager::DoSetPhotoOptions, this, 726 session_id, base::Bind(&VideoCaptureController::SetPhotoOptions,
1008 base::Passed(&callback), base::Passed(&settings))); 727 base::Unretained(controller),
728 base::Passed(&settings), base::Passed(&callback)));
1009 } 729 }
1010 730
1011 void VideoCaptureManager::TakePhoto( 731 void VideoCaptureManager::TakePhoto(
1012 int session_id, 732 int session_id,
1013 VideoCaptureDevice::TakePhotoCallback callback) { 733 media::VideoCaptureDevice::TakePhotoCallback callback) {
1014 DCHECK_CURRENTLY_ON(BrowserThread::IO); 734 DCHECK_CURRENTLY_ON(BrowserThread::IO);
1015 735
1016 const DeviceEntry* entry = GetDeviceEntryBySessionId(session_id); 736 VideoCaptureController* controller = LookupControllerBySessionId(session_id);
1017 if (!entry) 737 if (!controller)
1018 return; 738 return;
1019 VideoCaptureDevice* device = entry->video_capture_device.get(); 739 if (controller->IsDeviceAlive()) {
1020 if (device) { 740 controller->TakePhoto(std::move(callback));
1021 VideoCaptureManager::DoTakePhoto(std::move(callback), device);
1022 return; 741 return;
1023 } 742 }
1024 // |entry| is known but |device| is nullptr, queue up a request for later. 743 // Queue up a request for later.
1025 photo_request_queue_.emplace_back( 744 photo_request_queue_.emplace_back(
1026 session_id, base::Bind(&VideoCaptureManager::DoTakePhoto, this, 745 session_id,
1027 base::Passed(&callback))); 746 base::Bind(&VideoCaptureController::TakePhoto,
1028 } 747 base::Unretained(controller), base::Passed(&callback)));
1029
1030 void VideoCaptureManager::DoStopDeviceOnDeviceThread(
1031 std::unique_ptr<VideoCaptureDevice> device) {
1032 SCOPED_UMA_HISTOGRAM_TIMER("Media.VideoCaptureManager.StopDeviceTime");
1033 DCHECK(IsOnDeviceThread());
1034 device->StopAndDeAllocate();
1035 DVLOG(3) << "DoStopDeviceOnDeviceThread";
1036 } 748 }
1037 749
1038 void VideoCaptureManager::OnOpened( 750 void VideoCaptureManager::OnOpened(
1039 MediaStreamType stream_type, 751 MediaStreamType stream_type,
1040 media::VideoCaptureSessionId capture_session_id) { 752 media::VideoCaptureSessionId capture_session_id) {
1041 DCHECK_CURRENTLY_ON(BrowserThread::IO); 753 DCHECK_CURRENTLY_ON(BrowserThread::IO);
1042 for (auto& listener : listeners_) 754 for (auto& listener : listeners_)
1043 listener.Opened(stream_type, capture_session_id); 755 listener.Opened(stream_type, capture_session_id);
1044 } 756 }
1045 757
(...skipping 17 matching lines...) Expand all
1063 775
1064 // Walk the |devices_info_cache_| and produce a 776 // Walk the |devices_info_cache_| and produce a
1065 // media::VideoCaptureDeviceDescriptors for return purposes. 777 // media::VideoCaptureDeviceDescriptors for return purposes.
1066 media::VideoCaptureDeviceDescriptors devices; 778 media::VideoCaptureDeviceDescriptors devices;
1067 std::vector<std::tuple<media::VideoCaptureDeviceDescriptor, 779 std::vector<std::tuple<media::VideoCaptureDeviceDescriptor,
1068 media::VideoCaptureFormats>> 780 media::VideoCaptureFormats>>
1069 descriptors_and_formats; 781 descriptors_and_formats;
1070 for (const auto& it : devices_info_cache_) { 782 for (const auto& it : devices_info_cache_) {
1071 devices.emplace_back(it.descriptor); 783 devices.emplace_back(it.descriptor);
1072 descriptors_and_formats.emplace_back(it.descriptor, it.supported_formats); 784 descriptors_and_formats.emplace_back(it.descriptor, it.supported_formats);
1073 }
1074
1075 if (!descriptors_and_formats.empty()) {
1076 MediaInternals::GetInstance()->UpdateVideoCaptureDeviceCapabilities( 785 MediaInternals::GetInstance()->UpdateVideoCaptureDeviceCapabilities(
1077 descriptors_and_formats); 786 descriptors_and_formats);
1078 } 787 }
1079 788
1080 client_callback.Run(devices); 789 client_callback.Run(devices);
1081 } 790 }
1082 791
1083 bool VideoCaptureManager::IsOnDeviceThread() const {
1084 return device_task_runner_->BelongsToCurrentThread();
1085 }
1086
1087 void VideoCaptureManager::ConsolidateDevicesInfoOnDeviceThread( 792 void VideoCaptureManager::ConsolidateDevicesInfoOnDeviceThread(
1088 base::Callback<void(const VideoCaptureManager::DeviceInfos&)> 793 base::Callback<void(const VideoCaptureManager::DeviceInfos&)>
1089 on_devices_enumerated_callback, 794 on_devices_enumerated_callback,
1090 const VideoCaptureManager::DeviceInfos& old_device_info_cache, 795 const VideoCaptureManager::DeviceInfos& old_device_info_cache,
1091 std::unique_ptr<VideoCaptureDeviceDescriptors> descriptors_snapshot) { 796 std::unique_ptr<VideoCaptureDeviceDescriptors> descriptors_snapshot) {
1092 DCHECK(IsOnDeviceThread()); 797 DCHECK(device_task_runner_->BelongsToCurrentThread());
1093 // Construct |new_devices_info_cache| with the cached devices that are still 798 // Construct |new_devices_info_cache| with the cached devices that are still
1094 // present in the system, and remove their names from |names_snapshot|, so we 799 // present in the system, and remove their names from |names_snapshot|, so we
1095 // keep there the truly new devices. 800 // keep there the truly new devices.
1096 VideoCaptureManager::DeviceInfos new_devices_info_cache; 801 VideoCaptureManager::DeviceInfos new_devices_info_cache;
1097 for (const auto& device_info : old_device_info_cache) { 802 for (const auto& device_info : old_device_info_cache) {
1098 for (VideoCaptureDeviceDescriptors::iterator it = 803 for (VideoCaptureDeviceDescriptors::iterator it =
1099 descriptors_snapshot->begin(); 804 descriptors_snapshot->begin();
1100 it != descriptors_snapshot->end(); ++it) { 805 it != descriptors_snapshot->end(); ++it) {
1101 if (device_info.descriptor.device_id == it->device_id) { 806 if (device_info.descriptor.device_id == it->device_id) {
1102 new_devices_info_cache.push_back(device_info); 807 new_devices_info_cache.push_back(device_info);
1103 descriptors_snapshot->erase(it); 808 descriptors_snapshot->erase(it);
1104 break; 809 break;
1105 } 810 }
1106 } 811 }
1107 } 812 }
1108 813
1109 // Get the device info for the new devices in |names_snapshot|. 814 // Get the device info for the new devices in |names_snapshot|.
1110 for (const auto& it : *descriptors_snapshot) { 815 for (const auto& it : *descriptors_snapshot) {
1111 DeviceInfo device_info(it); 816 DeviceInfo device_info(it);
1112 video_capture_device_factory_->GetSupportedFormats( 817 video_capture_device_factory_->GetSupportedFormats(
1113 it, &device_info.supported_formats); 818 it, &device_info.supported_formats);
1114 ConsolidateCaptureFormats(&device_info.supported_formats); 819 ConsolidateCaptureFormats(&device_info.supported_formats);
1115 new_devices_info_cache.push_back(device_info); 820 new_devices_info_cache.push_back(device_info);
1116 } 821 }
1117 822
1118 on_devices_enumerated_callback.Run(new_devices_info_cache); 823 on_devices_enumerated_callback.Run(new_devices_info_cache);
1119 } 824 }
1120 825
1121 void VideoCaptureManager::DestroyDeviceEntryIfNoClients(DeviceEntry* entry) { 826 void VideoCaptureManager::DestroyDeviceEntryIfNoClients(
827 VideoCaptureController* controller) {
1122 DCHECK_CURRENTLY_ON(BrowserThread::IO); 828 DCHECK_CURRENTLY_ON(BrowserThread::IO);
1123 // Removal of the last client stops the device. 829 // Removal of the last client stops the device.
1124 if (!entry->video_capture_controller.HasActiveClient() && 830 if (!controller->HasActiveClient() && !controller->HasPausedClient()) {
1125 !entry->video_capture_controller.HasPausedClient()) {
1126 DVLOG(1) << "VideoCaptureManager stopping device (type = " 831 DVLOG(1) << "VideoCaptureManager stopping device (type = "
1127 << entry->stream_type << ", id = " << entry->id << ")"; 832 << controller->stream_type()
833 << ", id = " << controller->device_id() << ")";
1128 834
1129 // The DeviceEntry is removed from |devices_| immediately. The controller is 835 // The VideoCaptureController is removed from |controllers_| immediately.
1130 // deleted immediately, and the device is freed asynchronously. After this 836 // The controller is deleted immediately, and the device is freed
1131 // point, subsequent requests to open this same device ID will create a new 837 // asynchronously. After this point, subsequent requests to open this same
1132 // DeviceEntry, VideoCaptureController, and VideoCaptureDevice. 838 // device ID will create a new VideoCaptureController,
1133 DoStopDevice(entry); 839 // VideoCaptureController, and VideoCaptureDevice.
840 DoStopDevice(controller);
1134 // TODO(mcasas): use a helper function https://crbug.com/624854. 841 // TODO(mcasas): use a helper function https://crbug.com/624854.
1135 DeviceEntries::iterator device_it = 842 auto controller_iter = std::find_if(
1136 std::find_if(devices_.begin(), devices_.end(), 843 controllers_.begin(), controllers_.end(),
1137 [entry](const std::unique_ptr<DeviceEntry>& device_entry) { 844 [controller](
1138 return device_entry.get() == entry; 845 const scoped_refptr<VideoCaptureController>& device_entry) {
1139 }); 846 return device_entry.get() == controller;
1140 devices_.erase(device_it); 847 });
848 controllers_.erase(controller_iter);
1141 } 849 }
1142 } 850 }
1143 851
1144 VideoCaptureManager::DeviceEntry* 852 VideoCaptureController* VideoCaptureManager::LookupControllerBySessionId(
1145 VideoCaptureManager::GetDeviceEntryBySessionId(int session_id) { 853 int session_id) {
1146 DCHECK_CURRENTLY_ON(BrowserThread::IO); 854 DCHECK_CURRENTLY_ON(BrowserThread::IO);
1147 SessionMap::const_iterator session_it = sessions_.find(session_id); 855 SessionMap::const_iterator session_it = sessions_.find(session_id);
1148 if (session_it == sessions_.end()) 856 if (session_it == sessions_.end())
1149 return nullptr; 857 return nullptr;
1150 858
1151 return GetDeviceEntryByTypeAndId(session_it->second.type, 859 return LookupControllerByTypeAndId(session_it->second.type,
1152 session_it->second.id); 860 session_it->second.id);
1153 } 861 }
1154 862
1155 VideoCaptureManager::DeviceEntry* 863 VideoCaptureController* VideoCaptureManager::LookupControllerByTypeAndId(
1156 VideoCaptureManager::GetDeviceEntryByTypeAndId(
1157 MediaStreamType type, 864 MediaStreamType type,
1158 const std::string& device_id) const { 865 const std::string& device_id) const {
1159 DCHECK_CURRENTLY_ON(BrowserThread::IO); 866 DCHECK_CURRENTLY_ON(BrowserThread::IO);
1160 867
1161 for (const std::unique_ptr<DeviceEntry>& device : devices_) { 868 for (const auto& entry : controllers_) {
1162 if (type == device->stream_type && device_id == device->id) 869 if (type == entry->stream_type() && device_id == entry->device_id())
1163 return device.get(); 870 return entry.get();
1164 } 871 }
1165 return nullptr; 872 return nullptr;
1166 } 873 }
1167 874
1168 VideoCaptureManager::DeviceEntry* 875 bool VideoCaptureManager::IsControllerPointerValid(
1169 VideoCaptureManager::GetDeviceEntryByController(
1170 const VideoCaptureController* controller) const { 876 const VideoCaptureController* controller) const {
1171 DCHECK_CURRENTLY_ON(BrowserThread::IO); 877 DCHECK_CURRENTLY_ON(BrowserThread::IO);
878 return base::ContainsValue(controllers_, controller);
879 }
1172 880
1173 // Look up |controller| in |devices_|. 881 VideoCaptureController* VideoCaptureManager::LookupControllerBySerialId(
1174 for (const std::unique_ptr<DeviceEntry>& device : devices_) { 882 int serial_id) const {
1175 if (&device->video_capture_controller == controller) 883 DCHECK_CURRENTLY_ON(BrowserThread::IO);
1176 return device.get(); 884
885 for (const auto& entry : controllers_) {
886 if (entry->serial_id() == serial_id)
887 return entry.get();
1177 } 888 }
1178 return nullptr; 889 return nullptr;
1179 } 890 }
1180 891
1181 VideoCaptureManager::DeviceEntry* VideoCaptureManager::GetDeviceEntryBySerialId( 892 scoped_refptr<VideoCaptureController>
1182 int serial_id) const { 893 VideoCaptureManager::GetControllerSharedRefFromSerialId(int serial_id) const {
1183 DCHECK_CURRENTLY_ON(BrowserThread::IO); 894 DCHECK_CURRENTLY_ON(BrowserThread::IO);
1184 895
1185 for (const std::unique_ptr<DeviceEntry>& device : devices_) { 896 for (const auto& entry : controllers_) {
1186 if (device->serial_id == serial_id) 897 if (entry->serial_id() == serial_id)
1187 return device.get(); 898 return entry;
1188 } 899 }
1189 return nullptr; 900 return nullptr;
1190 } 901 }
1191 902
1192 VideoCaptureManager::DeviceInfo* VideoCaptureManager::GetDeviceInfoById( 903 VideoCaptureManager::DeviceInfo* VideoCaptureManager::GetDeviceInfoById(
1193 const std::string& id) { 904 const std::string& id) {
1194 for (auto& it : devices_info_cache_) { 905 for (auto& it : devices_info_cache_) {
1195 if (it.descriptor.device_id == id) 906 if (it.descriptor.device_id == id)
1196 return &it; 907 return &it;
1197 } 908 }
1198 return nullptr; 909 return nullptr;
1199 } 910 }
1200 911
1201 VideoCaptureManager::DeviceEntry* VideoCaptureManager::GetOrCreateDeviceEntry( 912 VideoCaptureController* VideoCaptureManager::GetOrCreateController(
1202 media::VideoCaptureSessionId capture_session_id, 913 media::VideoCaptureSessionId capture_session_id,
1203 const media::VideoCaptureParams& params) { 914 const media::VideoCaptureParams& params) {
1204 DCHECK_CURRENTLY_ON(BrowserThread::IO); 915 DCHECK_CURRENTLY_ON(BrowserThread::IO);
1205 916
1206 SessionMap::iterator session_it = sessions_.find(capture_session_id); 917 SessionMap::iterator session_it = sessions_.find(capture_session_id);
1207 if (session_it == sessions_.end()) 918 if (session_it == sessions_.end())
1208 return nullptr; 919 return nullptr;
1209 const MediaStreamDevice& device_info = session_it->second; 920 const MediaStreamDevice& device_info = session_it->second;
1210 921
1211 // Check if another session has already opened this device. If so, just 922 // Check if another session has already opened this device. If so, just
1212 // use that opened device. 923 // use that opened device.
1213 DeviceEntry* const existing_device = 924 VideoCaptureController* const existing_device =
1214 GetDeviceEntryByTypeAndId(device_info.type, device_info.id); 925 LookupControllerByTypeAndId(device_info.type, device_info.id);
1215 if (existing_device) { 926 if (existing_device) {
1216 DCHECK_EQ(device_info.type, existing_device->stream_type); 927 DCHECK_EQ(device_info.type, existing_device->stream_type());
1217 return existing_device; 928 return existing_device;
1218 } 929 }
1219 930
1220 devices_.emplace_back( 931 VideoCaptureController* new_device_entry = new VideoCaptureController(
1221 new DeviceEntry(device_info.type, device_info.id, params)); 932 device_info.id, device_info.type, params,
1222 return devices_.back().get(); 933 base::MakeUnique<InProcessBuildableVideoCaptureDevice>(
1223 } 934 device_task_runner_, video_capture_device_factory_.get()));
1224 935 controllers_.emplace_back(new_device_entry);
1225 void VideoCaptureManager::SetDesktopCaptureWindowIdOnDeviceThread( 936 return new_device_entry;
1226 media::VideoCaptureDevice* device,
1227 gfx::NativeViewId window_id) {
1228 DCHECK(IsOnDeviceThread());
1229 #if defined(ENABLE_SCREEN_CAPTURE) && BUILDFLAG(ENABLE_WEBRTC) && !defined(OS_AN DROID)
1230 DesktopCaptureDevice* desktop_device =
1231 static_cast<DesktopCaptureDevice*>(device);
1232 desktop_device->SetNotificationWindowId(window_id);
1233 VLOG(2) << "Screen capture notification window passed on device thread.";
1234 #endif
1235 }
1236
1237 void VideoCaptureManager::DoGetPhotoCapabilities(
1238 VideoCaptureDevice::GetPhotoCapabilitiesCallback callback,
1239 VideoCaptureDevice* device) {
1240 // Unretained() is safe to use here because |device| would be null if it
1241 // was scheduled for shutdown and destruction, and because this task is
1242 // guaranteed to run before the task that destroys the |device|.
1243 device_task_runner_->PostTask(
1244 FROM_HERE, base::Bind(&VideoCaptureDevice::GetPhotoCapabilities,
1245 base::Unretained(device), base::Passed(&callback)));
1246 }
1247
1248 void VideoCaptureManager::DoSetPhotoOptions(
1249 VideoCaptureDevice::SetPhotoOptionsCallback callback,
1250 media::mojom::PhotoSettingsPtr settings,
1251 VideoCaptureDevice* device) {
1252 // Unretained() is safe to use here because |device| would be null if it
1253 // was scheduled for shutdown and destruction, and because this task is
1254 // guaranteed to run before the task that destroys the |device|.
1255 device_task_runner_->PostTask(
1256 FROM_HERE,
1257 base::Bind(&VideoCaptureDevice::SetPhotoOptions, base::Unretained(device),
1258 base::Passed(&settings), base::Passed(&callback)));
1259 }
1260
1261 void VideoCaptureManager::DoTakePhoto(
1262 VideoCaptureDevice::TakePhotoCallback callback,
1263 VideoCaptureDevice* device) {
1264 // Unretained() is safe to use here because |device| would be null if it
1265 // was scheduled for shutdown and destruction, and because this task is
1266 // guaranteed to run before the task that destroys the |device|.
1267 device_task_runner_->PostTask(
1268 FROM_HERE, base::Bind(&VideoCaptureDevice::TakePhoto,
1269 base::Unretained(device), base::Passed(&callback)));
1270 } 937 }
1271 938
1272 base::Optional<CameraCalibration> VideoCaptureManager::GetCameraCalibration( 939 base::Optional<CameraCalibration> VideoCaptureManager::GetCameraCalibration(
1273 const std::string& device_id) { 940 const std::string& device_id) {
1274 VideoCaptureManager::DeviceInfo* info = GetDeviceInfoById(device_id); 941 VideoCaptureManager::DeviceInfo* info = GetDeviceInfoById(device_id);
1275 if (!info) 942 if (!info)
1276 return base::Optional<CameraCalibration>(); 943 return base::Optional<CameraCalibration>();
1277 return info->descriptor.camera_calibration; 944 return info->descriptor.camera_calibration;
1278 } 945 }
1279 946
(...skipping 10 matching lines...) Expand all
1290 application_state_has_running_activities_ = true; 957 application_state_has_running_activities_ = true;
1291 } else if (state == base::android::APPLICATION_STATE_HAS_STOPPED_ACTIVITIES) { 958 } else if (state == base::android::APPLICATION_STATE_HAS_STOPPED_ACTIVITIES) {
1292 ReleaseDevices(); 959 ReleaseDevices();
1293 application_state_has_running_activities_ = false; 960 application_state_has_running_activities_ = false;
1294 } 961 }
1295 } 962 }
1296 963
1297 void VideoCaptureManager::ReleaseDevices() { 964 void VideoCaptureManager::ReleaseDevices() {
1298 DCHECK_CURRENTLY_ON(BrowserThread::IO); 965 DCHECK_CURRENTLY_ON(BrowserThread::IO);
1299 966
1300 for (auto& entry : devices_) { 967 for (auto& controller : controllers_) {
1301 // Do not stop Content Video Capture devices, e.g. Tab or Screen capture. 968 // Do not stop Content Video Capture devices, e.g. Tab or Screen capture.
1302 if (entry->stream_type != MEDIA_DEVICE_VIDEO_CAPTURE) 969 if (controller->stream_type() != MEDIA_DEVICE_VIDEO_CAPTURE)
1303 continue; 970 continue;
1304 971
1305 DoStopDevice(entry.get()); 972 DoStopDevice(controller.get());
1306 } 973 }
1307 } 974 }
1308 975
1309 void VideoCaptureManager::ResumeDevices() { 976 void VideoCaptureManager::ResumeDevices() {
1310 DCHECK_CURRENTLY_ON(BrowserThread::IO); 977 DCHECK_CURRENTLY_ON(BrowserThread::IO);
1311 978
1312 for (auto& entry : devices_) { 979 for (auto& controller : controllers_) {
1313 // Do not resume Content Video Capture devices, e.g. Tab or Screen capture. 980 // Do not resume Content Video Capture devices, e.g. Tab or Screen capture.
1314 // Do not try to restart already running devices. 981 // Do not try to restart already running devices.
1315 if (entry->stream_type != MEDIA_DEVICE_VIDEO_CAPTURE || 982 if (controller->stream_type() != MEDIA_DEVICE_VIDEO_CAPTURE ||
1316 entry->video_capture_device) 983 controller->IsDeviceAlive())
1317 continue; 984 continue;
1318 985
1319 // Check if the device is already in the start queue. 986 // Check if the device is already in the start queue.
1320 bool device_in_queue = false; 987 bool device_in_queue = false;
1321 for (auto& request : device_start_queue_) { 988 for (auto& request : device_start_queue_) {
1322 if (request.serial_id() == entry->serial_id) { 989 if (request.serial_id() == controller->serial_id()) {
1323 device_in_queue = true; 990 device_in_queue = true;
1324 break; 991 break;
1325 } 992 }
1326 } 993 }
1327 994
1328 if (!device_in_queue) { 995 if (!device_in_queue) {
1329 // Session ID is only valid for Screen capture. So we can fake it to 996 // Session ID is only valid for Screen capture. So we can fake it to
1330 // resume video capture devices here. 997 // resume video capture devices here.
1331 QueueStartDevice(kFakeSessionId, entry.get(), entry->parameters); 998 QueueStartDevice(kFakeSessionId, controller.get(),
999 controller->parameters());
1332 } 1000 }
1333 } 1001 }
1334 } 1002 }
1335 #endif // defined(OS_ANDROID) 1003 #endif // defined(OS_ANDROID)
1336 1004
1337 } // namespace content 1005 } // namespace content
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698