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

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

Issue 8304017: enable video capture to support sharing across multiple renderer processes (Closed) Base URL: svn://chrome-svn/chrome/trunk/src/
Patch Set: rebase Created 9 years, 1 month 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 | Annotate | Revision Log
OLDNEW
1 // Copyright (c) 2011 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2011 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 "base/bind.h" 7 #include "base/bind.h"
8 #include "base/memory/scoped_ptr.h" 8 #include "base/stl_util.h"
9 #include "content/browser/browser_thread.h" 9 #include "content/browser/browser_thread.h"
10 #include "content/browser/renderer_host/media/video_capture_controller.h"
11 #include "content/browser/renderer_host/media/video_capture_controller_event_han dler.h"
perkj_chrome 2011/10/28 08:37:19 can and should this be made 80 by breaking the lin
wjia(left Chromium) 2011/10/29 02:34:40 Header files should be always on one line. This li
10 #include "media/video/capture/fake_video_capture_device.h" 12 #include "media/video/capture/fake_video_capture_device.h"
11 #include "media/video/capture/video_capture_device.h" 13 #include "media/video/capture/video_capture_device.h"
12 14
13 namespace media_stream { 15 namespace media_stream {
14 16
15 // Starting id for the first capture session. 17 // Starting id for the first capture session.
16 // VideoCaptureManager::kStartOpenSessionId is used as default id without 18 // VideoCaptureManager::kStartOpenSessionId is used as default id without
17 // explicitly calling open device. 19 // explicitly calling open device.
18 enum { kFirstSessionId = VideoCaptureManager::kStartOpenSessionId + 1 }; 20 enum { kFirstSessionId = VideoCaptureManager::kStartOpenSessionId + 1 };
19 21
22 struct VideoCaptureManager::Controller {
23 Controller(
24 VideoCaptureController* vc_controller,
25 VideoCaptureControllerEventHandler* handler)
26 : controller(vc_controller),
27 ready_to_delete(false) {
28 handlers.push_front(handler);
29 }
30 ~Controller() {}
31
32 scoped_refptr<VideoCaptureController> controller;
33 bool ready_to_delete;
34 Handlers handlers;
35 };
36
20 VideoCaptureManager::VideoCaptureManager() 37 VideoCaptureManager::VideoCaptureManager()
21 : vc_device_thread_("VideoCaptureManagerThread"), 38 : vc_device_thread_("VideoCaptureManagerThread"),
22 listener_(NULL), 39 listener_(NULL),
23 new_capture_session_id_(kFirstSessionId), 40 new_capture_session_id_(kFirstSessionId),
24 use_fake_device_(false) { 41 use_fake_device_(false) {
25 vc_device_thread_.Start(); 42 vc_device_thread_.Start();
26 } 43 }
27 44
28 VideoCaptureManager::~VideoCaptureManager() { 45 VideoCaptureManager::~VideoCaptureManager() {
29 vc_device_thread_.Stop(); 46 vc_device_thread_.Stop();
30 // TODO(mflodman) Remove this temporary solution when shut-down issue is 47 // TODO(mflodman) Remove this temporary solution when shut-down issue is
31 // resolved, i.e. all code below this comment. 48 // resolved, i.e. all code below this comment.
32 // Temporary solution: close all open devices and delete them, after the 49 // Temporary solution: close all open devices and delete them, after the
33 // thread is stopped. 50 // thread is stopped.
34 DLOG_IF(ERROR, !devices_.empty()) << "VideoCaptureManager: Open devices!"; 51 DLOG_IF(ERROR, !devices_.empty()) << "VideoCaptureManager: Open devices!";
35 for (VideoCaptureDevices::iterator it = devices_.begin(); 52 for (VideoCaptureDevices::iterator it = devices_.begin();
36 it != devices_.end(); 53 it != devices_.end();
37 ++it) { 54 ++it) {
38 it->second->DeAllocate(); 55 it->second->DeAllocate();
39 delete it->second; 56 delete it->second;
40 } 57 }
58 STLDeleteValues(&controllers_);
41 } 59 }
42 60
43 void VideoCaptureManager::Register(MediaStreamProviderListener* listener) { 61 void VideoCaptureManager::Register(MediaStreamProviderListener* listener) {
44 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); 62 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
45 DCHECK(!listener_); 63 DCHECK(!listener_);
46 listener_ = listener; 64 listener_ = listener;
47 } 65 }
48 66
49 void VideoCaptureManager::Unregister() { 67 void VideoCaptureManager::Unregister() {
50 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); 68 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
(...skipping 135 matching lines...) Expand 10 before | Expand all | Expand 10 after
186 204
187 PostOnClosed(capture_session_id); 205 PostOnClosed(capture_session_id);
188 } 206 }
189 207
190 void VideoCaptureManager::OnStart( 208 void VideoCaptureManager::OnStart(
191 const media::VideoCaptureParams capture_params, 209 const media::VideoCaptureParams capture_params,
192 media::VideoCaptureDevice::EventHandler* video_capture_receiver) { 210 media::VideoCaptureDevice::EventHandler* video_capture_receiver) {
193 DCHECK(IsOnCaptureDeviceThread()); 211 DCHECK(IsOnCaptureDeviceThread());
194 DCHECK(video_capture_receiver != NULL); 212 DCHECK(video_capture_receiver != NULL);
195 213
196 // Solution for not using MediaStreamManager. 214 media::VideoCaptureDevice* video_capture_device =
197 // This session id won't be returned by Open(). 215 GetDeviceInternal(capture_params.session_id);
198 if (capture_params.session_id == kStartOpenSessionId) { 216 if (!video_capture_device) {
199 // Start() is called without using Open(), we need to open a device.
200 media::VideoCaptureDevice::Names device_names;
201 GetAvailableDevices(&device_names);
202 if (device_names.empty()) {
203 // No devices available.
204 video_capture_receiver->OnError();
205 return;
206 }
207 StreamDeviceInfo device(kVideoCapture,
208 device_names.front().device_name,
209 device_names.front().unique_id, false);
210
211 // Call OnOpen to open using the first device in the list.
212 OnOpen(capture_params.session_id, device);
213 }
214
215 VideoCaptureDevices::iterator it = devices_.find(capture_params.session_id);
216 if (it == devices_.end()) {
217 // Invalid session id. 217 // Invalid session id.
218 video_capture_receiver->OnError(); 218 video_capture_receiver->OnError();
219 return; 219 return;
220 } 220 }
221 media::VideoCaptureDevice* video_capture_device = it->second; 221 Controllers::iterator cit = controllers_.find(video_capture_device);
222 if (cit != controllers_.end()) {
223 cit->second->ready_to_delete = false;
224 }
222 225
223 // Possible errors are signaled to video_capture_receiver by 226 // Possible errors are signaled to video_capture_receiver by
224 // video_capture_device. video_capture_receiver to perform actions. 227 // video_capture_device. video_capture_receiver to perform actions.
225 video_capture_device->Allocate(capture_params.width, capture_params.height, 228 video_capture_device->Allocate(capture_params.width, capture_params.height,
226 capture_params.frame_per_second, 229 capture_params.frame_per_second,
227 video_capture_receiver); 230 video_capture_receiver);
228 video_capture_device->Start(); 231 video_capture_device->Start();
229 } 232 }
230 233
231 void VideoCaptureManager::OnStop( 234 void VideoCaptureManager::OnStop(
232 const media::VideoCaptureSessionId capture_session_id, 235 const media::VideoCaptureSessionId capture_session_id,
233 base::Closure stopped_cb) { 236 base::Closure stopped_cb) {
234 DCHECK(IsOnCaptureDeviceThread()); 237 DCHECK(IsOnCaptureDeviceThread());
235 238
236 VideoCaptureDevices::iterator it = devices_.find(capture_session_id); 239 VideoCaptureDevices::iterator it = devices_.find(capture_session_id);
237 if (it != devices_.end()) { 240 if (it != devices_.end()) {
238 media::VideoCaptureDevice* video_capture_device = it->second; 241 media::VideoCaptureDevice* video_capture_device = it->second;
239 // Possible errors are signaled to video_capture_receiver by 242 // Possible errors are signaled to video_capture_receiver by
240 // video_capture_device. video_capture_receiver to perform actions. 243 // video_capture_device. video_capture_receiver to perform actions.
241 video_capture_device->Stop(); 244 video_capture_device->Stop();
242 video_capture_device->DeAllocate(); 245 video_capture_device->DeAllocate();
246 Controllers::iterator cit = controllers_.find(video_capture_device);
247 if (cit != controllers_.end()) {
248 cit->second->ready_to_delete = true;
249 if (cit->second->handlers.size() == 0) {
250 delete cit->second;
251 controllers_.erase(cit);
252 }
253 }
243 } 254 }
244 255
245 if (!stopped_cb.is_null()) 256 if (!stopped_cb.is_null())
246 stopped_cb.Run(); 257 stopped_cb.Run();
perkj_chrome 2011/10/28 08:37:19 Do this on IO thread instead please.
247 258
248 if (capture_session_id == kStartOpenSessionId) { 259 if (capture_session_id == kStartOpenSessionId) {
249 // This device was opened from Start(), not Open(). Close it! 260 // This device was opened from Start(), not Open(). Close it!
250 OnClose(capture_session_id); 261 OnClose(capture_session_id);
251 } 262 }
252 } 263 }
253 264
254 void VideoCaptureManager::OnOpened(int capture_session_id) { 265 void VideoCaptureManager::OnOpened(int capture_session_id) {
255 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); 266 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
256 if (!listener_) { 267 if (!listener_) {
(...skipping 106 matching lines...) Expand 10 before | Expand all | Expand 10 after
363 for (VideoCaptureDevices::iterator it = devices_.begin(); 374 for (VideoCaptureDevices::iterator it = devices_.begin();
364 it != devices_.end(); 375 it != devices_.end();
365 it++) { 376 it++) {
366 if (device_info.device_id == it->second->device_name().unique_id) { 377 if (device_info.device_id == it->second->device_name().unique_id) {
367 return true; 378 return true;
368 } 379 }
369 } 380 }
370 return false; 381 return false;
371 } 382 }
372 383
384 void VideoCaptureManager::AddController(
385 const media::VideoCaptureParams& capture_params,
386 VideoCaptureControllerEventHandler* handler,
387 base::Callback<void(VideoCaptureController*)> added_cb) {
388 DCHECK(handler);
389 vc_device_thread_.message_loop()->PostTask(
390 FROM_HERE,
391 base::Bind(&VideoCaptureManager::DoAddControllerOnDeviceThread,
392 base::Unretained(this), capture_params, handler, added_cb));
393 }
394
395 void VideoCaptureManager::DoAddControllerOnDeviceThread(
396 const media::VideoCaptureParams capture_params,
397 VideoCaptureControllerEventHandler* handler,
398 base::Callback<void(VideoCaptureController*)> added_cb) {
399 DCHECK(IsOnCaptureDeviceThread());
400
401 media::VideoCaptureDevice* video_capture_device =
402 GetDeviceInternal(capture_params.session_id);
403 scoped_refptr<VideoCaptureController> ctrller = NULL;
404 if (video_capture_device) {
405 Controllers::iterator cit = controllers_.find(video_capture_device);
406 if (cit == controllers_.end()) {
407 ctrller = new VideoCaptureController(this);
408 controllers_[video_capture_device] = new Controller(ctrller, handler);
409 } else {
410 controllers_[video_capture_device]->handlers.push_front(handler);
411 ctrller = controllers_[video_capture_device]->controller;
412 }
413 }
414 added_cb.Run(ctrller);
perkj_chrome 2011/10/28 08:37:19 Do added_cb.Run(ctrller); on IO thread instead ple
415 }
416
417 void VideoCaptureManager::RemoveController(
418 VideoCaptureController* controller,
419 VideoCaptureControllerEventHandler* handler) {
420 DCHECK(handler);
421 vc_device_thread_.message_loop()->PostTask(
422 FROM_HERE,
423 base::Bind(&VideoCaptureManager::DoRemoveControllerOnDeviceThread,
424 base::Unretained(this),
425 make_scoped_refptr(controller),
426 handler));
427 }
428
429 void VideoCaptureManager::DoRemoveControllerOnDeviceThread(
430 VideoCaptureController* controller,
431 VideoCaptureControllerEventHandler* handler) {
432 DCHECK(IsOnCaptureDeviceThread());
433
434 for (Controllers::iterator cit = controllers_.begin();
435 cit != controllers_.end(); ++cit) {
436 if (controller == cit->second->controller) {
437 Handlers& handlers = cit->second->handlers;
438 for (Handlers::iterator hit = handlers.begin();
439 hit != handlers.end(); ++hit) {
440 if ((*hit) == handler) {
441 handlers.erase(hit);
442 break;
443 }
444 }
445 if (handlers.size() == 0 && cit->second->ready_to_delete) {
446 delete cit->second;
447 controllers_.erase(cit);
448 }
449 return;
450 }
451 }
452 }
453
454 media::VideoCaptureDevice* VideoCaptureManager::GetDeviceInternal(
455 int capture_session_id) {
456 DCHECK(IsOnCaptureDeviceThread());
457 VideoCaptureDevices::iterator dit = devices_.find(capture_session_id);
458 if (dit != devices_.end()) {
459 return dit->second;
460 }
461
462 // Solution for not using MediaStreamManager.
463 // This session id won't be returned by Open().
464 if (capture_session_id == kStartOpenSessionId) {
465 media::VideoCaptureDevice::Names device_names;
466 GetAvailableDevices(&device_names);
467 if (device_names.empty()) {
468 // No devices available.
469 return NULL;
470 }
471 StreamDeviceInfo device(kVideoCapture,
472 device_names.front().device_name,
473 device_names.front().unique_id, false);
474
475 // Call OnOpen to open using the first device in the list.
476 OnOpen(capture_session_id, device);
477
478 VideoCaptureDevices::iterator dit = devices_.find(capture_session_id);
479 if (dit != devices_.end()) {
480 return dit->second;
481 }
482 }
483 return NULL;
484 }
485
373 } // namespace media_stream 486 } // namespace media_stream
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698