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

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

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

Powered by Google App Engine
This is Rietveld 408576698