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

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

Issue 24133002: Make VideoCaptureController single-threaded and not ref counted. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: git pull Created 7 years, 3 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 | Annotate | Revision Log
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 <set> 7 #include <set>
8 8
9 #include "base/bind.h" 9 #include "base/bind.h"
10 #include "base/command_line.h" 10 #include "base/command_line.h"
(...skipping 19 matching lines...) Expand all
30 namespace content { 30 namespace content {
31 31
32 // Starting id for the first capture session. 32 // Starting id for the first capture session.
33 // VideoCaptureManager::kStartOpenSessionId is used as default id without 33 // VideoCaptureManager::kStartOpenSessionId is used as default id without
34 // explicitly calling open device. 34 // explicitly calling open device.
35 enum { kFirstSessionId = VideoCaptureManager::kStartOpenSessionId + 1 }; 35 enum { kFirstSessionId = VideoCaptureManager::kStartOpenSessionId + 1 };
36 36
37 VideoCaptureManager::DeviceEntry::DeviceEntry( 37 VideoCaptureManager::DeviceEntry::DeviceEntry(
38 MediaStreamType stream_type, 38 MediaStreamType stream_type,
39 const std::string& id, 39 const std::string& id,
40 scoped_refptr<VideoCaptureController> controller) 40 scoped_ptr<VideoCaptureController> controller)
41 : stream_type(stream_type), 41 : stream_type(stream_type),
42 id(id), 42 id(id),
43 video_capture_controller(controller) {} 43 video_capture_controller(controller.Pass()) {}
44 44
45 VideoCaptureManager::DeviceEntry::~DeviceEntry() {} 45 VideoCaptureManager::DeviceEntry::~DeviceEntry() {}
46 46
47 VideoCaptureManager::VideoCaptureManager() 47 VideoCaptureManager::VideoCaptureManager()
48 : listener_(NULL), 48 : listener_(NULL),
49 new_capture_session_id_(kFirstSessionId), 49 new_capture_session_id_(kFirstSessionId),
50 use_fake_device_(false) { 50 use_fake_device_(false) {
51 } 51 }
52 52
53 VideoCaptureManager::~VideoCaptureManager() { 53 VideoCaptureManager::~VideoCaptureManager() {
(...skipping 78 matching lines...) Expand 10 before | Expand all | Expand 10 after
132 sessions_.erase(session_it); 132 sessions_.erase(session_it);
133 } 133 }
134 134
135 void VideoCaptureManager::UseFakeDevice() { 135 void VideoCaptureManager::UseFakeDevice() {
136 use_fake_device_ = true; 136 use_fake_device_ = true;
137 } 137 }
138 138
139 void VideoCaptureManager::DoStartDeviceOnDeviceThread( 139 void VideoCaptureManager::DoStartDeviceOnDeviceThread(
140 DeviceEntry* entry, 140 DeviceEntry* entry,
141 const media::VideoCaptureCapability& capture_params, 141 const media::VideoCaptureCapability& capture_params,
142 media::VideoCaptureDevice::EventHandler* controller_as_handler) { 142 scoped_ptr<media::VideoCaptureDevice::EventHandler> device_client) {
143 SCOPED_UMA_HISTOGRAM_TIMER("Media.VideoCaptureManager.StartDeviceTime"); 143 SCOPED_UMA_HISTOGRAM_TIMER("Media.VideoCaptureManager.StartDeviceTime");
144 DCHECK(IsOnDeviceThread()); 144 DCHECK(IsOnDeviceThread());
145 145
146 scoped_ptr<media::VideoCaptureDevice> video_capture_device; 146 scoped_ptr<media::VideoCaptureDevice> video_capture_device;
147 switch (entry->stream_type) { 147 switch (entry->stream_type) {
148 case MEDIA_DEVICE_VIDEO_CAPTURE: { 148 case MEDIA_DEVICE_VIDEO_CAPTURE: {
149 // We look up the device id from the renderer in our local enumeration 149 // We look up the device id from the renderer in our local enumeration
150 // since the renderer does not have all the information that might be 150 // since the renderer does not have all the information that might be
151 // held in the browser-side VideoCaptureDevice::Name structure. 151 // held in the browser-side VideoCaptureDevice::Name structure.
152 media::VideoCaptureDevice::Name* found = 152 media::VideoCaptureDevice::Name* found =
(...skipping 19 matching lines...) Expand all
172 #endif // defined(ENABLE_SCREEN_CAPTURE) 172 #endif // defined(ENABLE_SCREEN_CAPTURE)
173 break; 173 break;
174 } 174 }
175 default: { 175 default: {
176 NOTIMPLEMENTED(); 176 NOTIMPLEMENTED();
177 break; 177 break;
178 } 178 }
179 } 179 }
180 180
181 if (!video_capture_device) { 181 if (!video_capture_device) {
182 controller_as_handler->OnError(); 182 device_client->OnError();
183 return; 183 return;
184 } 184 }
185 185
186 // TODO(nick): Merge Allocate() and Start(). http://crbug.com/285562 186 video_capture_device->AllocateAndStart(capture_params, device_client.Pass());
187 video_capture_device->Allocate(capture_params, controller_as_handler);
188 video_capture_device->Start();
189 entry->video_capture_device = video_capture_device.Pass(); 187 entry->video_capture_device = video_capture_device.Pass();
190 } 188 }
191 189
192 void VideoCaptureManager::StartCaptureForClient( 190 void VideoCaptureManager::StartCaptureForClient(
193 const media::VideoCaptureParams& capture_params, 191 const media::VideoCaptureParams& capture_params,
194 base::ProcessHandle client_render_process, 192 base::ProcessHandle client_render_process,
195 VideoCaptureControllerID client_id, 193 VideoCaptureControllerID client_id,
196 VideoCaptureControllerEventHandler* client_handler, 194 VideoCaptureControllerEventHandler* client_handler,
197 base::Callback<void(VideoCaptureController*)> done_cb) { 195 const DoneCB& done_cb) {
198 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); 196 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
199 DVLOG(1) << "VideoCaptureManager::StartCaptureForClient, (" 197 DVLOG(1) << "VideoCaptureManager::StartCaptureForClient, ("
200 << capture_params.width 198 << capture_params.width
201 << ", " << capture_params.height 199 << ", " << capture_params.height
202 << ", " << capture_params.frame_rate 200 << ", " << capture_params.frame_rate
203 << ", #" << capture_params.session_id 201 << ", #" << capture_params.session_id
204 << ")"; 202 << ")";
205 203
206 if (capture_params.session_id == kStartOpenSessionId) { 204 if (capture_params.session_id == kStartOpenSessionId) {
207 // Solution for not using MediaStreamManager. Enumerate the devices and 205 // Solution for not using MediaStreamManager. Enumerate the devices and
208 // open the first one, and then start it. 206 // open the first one, and then start it.
209 base::PostTaskAndReplyWithResult(device_loop_, FROM_HERE, 207 base::PostTaskAndReplyWithResult(device_loop_, FROM_HERE,
210 base::Bind(&VideoCaptureManager::GetAvailableDevicesOnDeviceThread, 208 base::Bind(&VideoCaptureManager::GetAvailableDevicesOnDeviceThread,
211 this, MEDIA_DEVICE_VIDEO_CAPTURE), 209 this, MEDIA_DEVICE_VIDEO_CAPTURE),
212 base::Bind(&VideoCaptureManager::OpenAndStartDefaultSession, this, 210 base::Bind(&VideoCaptureManager::OpenAndStartDefaultSession, this,
213 capture_params, client_render_process, client_id, 211 capture_params, client_render_process, client_id,
214 client_handler, done_cb)); 212 client_handler, done_cb));
215 return; 213 return;
216 } else { 214 } else {
217 DoStartCaptureForClient(capture_params, client_render_process, client_id, 215 DoStartCaptureForClient(capture_params, client_render_process, client_id,
218 client_handler, done_cb); 216 client_handler, done_cb);
219 } 217 }
220 } 218 }
221 219
222 void VideoCaptureManager::DoStartCaptureForClient( 220 void VideoCaptureManager::DoStartCaptureForClient(
223 const media::VideoCaptureParams& capture_params, 221 const media::VideoCaptureParams& capture_params,
224 base::ProcessHandle client_render_process, 222 base::ProcessHandle client_render_process,
225 VideoCaptureControllerID client_id, 223 VideoCaptureControllerID client_id,
226 VideoCaptureControllerEventHandler* client_handler, 224 VideoCaptureControllerEventHandler* client_handler,
227 base::Callback<void(VideoCaptureController*)> done_cb) { 225 const DoneCB& done_cb) {
228 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); 226 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
229 227
230 DeviceEntry* entry = GetOrCreateDeviceEntry(capture_params.session_id); 228 DeviceEntry* entry = GetOrCreateDeviceEntry(capture_params.session_id);
231 if (!entry) { 229 if (!entry) {
232 done_cb.Run(NULL); 230 done_cb.Run(base::WeakPtr<VideoCaptureController>());
233 return; 231 return;
234 } 232 }
235 233
236 DCHECK(entry->video_capture_controller); 234 DCHECK(entry->video_capture_controller);
237 235
238 // First client starts the device. 236 // First client starts the device.
239 if (entry->video_capture_controller->GetClientCount() == 0) { 237 if (entry->video_capture_controller->GetClientCount() == 0) {
240 DVLOG(1) << "VideoCaptureManager starting device (type = " 238 DVLOG(1) << "VideoCaptureManager starting device (type = "
241 << entry->stream_type << ", id = " << entry->id << ")"; 239 << entry->stream_type << ", id = " << entry->id << ")";
242 240
243 media::VideoCaptureCapability params_as_capability; 241 media::VideoCaptureCapability params_as_capability;
244 params_as_capability.width = capture_params.width; 242 params_as_capability.width = capture_params.width;
245 params_as_capability.height = capture_params.height; 243 params_as_capability.height = capture_params.height;
246 params_as_capability.frame_rate = capture_params.frame_rate; 244 params_as_capability.frame_rate = capture_params.frame_rate;
247 params_as_capability.session_id = capture_params.session_id; 245 params_as_capability.session_id = capture_params.session_id;
248 params_as_capability.frame_size_type = capture_params.frame_size_type; 246 params_as_capability.frame_size_type = capture_params.frame_size_type;
249 247
250 device_loop_->PostTask(FROM_HERE, base::Bind( 248 device_loop_->PostTask(FROM_HERE, base::Bind(
251 &VideoCaptureManager::DoStartDeviceOnDeviceThread, this, 249 &VideoCaptureManager::DoStartDeviceOnDeviceThread, this,
252 entry, params_as_capability, entry->video_capture_controller)); 250 entry, params_as_capability,
251 base::Passed(entry->video_capture_controller->NewDeviceClient())));
253 } 252 }
254 // Run the callback first, as AddClient() may trigger OnFrameInfo(). 253 // Run the callback first, as AddClient() may trigger OnFrameInfo().
255 done_cb.Run(entry->video_capture_controller); 254 done_cb.Run(entry->video_capture_controller->GetWeakPtr());
256 entry->video_capture_controller->AddClient(client_id, 255 entry->video_capture_controller->AddClient(client_id,
257 client_handler, 256 client_handler,
258 client_render_process, 257 client_render_process,
259 capture_params); 258 capture_params);
260 } 259 }
261 260
262 void VideoCaptureManager::StopCaptureForClient( 261 void VideoCaptureManager::StopCaptureForClient(
263 VideoCaptureController* controller, 262 VideoCaptureController* controller,
264 VideoCaptureControllerID client_id, 263 VideoCaptureControllerID client_id,
265 VideoCaptureControllerEventHandler* client_handler) { 264 VideoCaptureControllerEventHandler* client_handler) {
(...skipping 21 matching lines...) Expand all
287 base::MessageLoop::current()->PostTask(FROM_HERE, 286 base::MessageLoop::current()->PostTask(FROM_HERE,
288 base::Bind(&VideoCaptureManager::OnClosed, this, 287 base::Bind(&VideoCaptureManager::OnClosed, this,
289 MEDIA_DEVICE_VIDEO_CAPTURE, kStartOpenSessionId)); 288 MEDIA_DEVICE_VIDEO_CAPTURE, kStartOpenSessionId));
290 } 289 }
291 } 290 }
292 291
293 void VideoCaptureManager::DoStopDeviceOnDeviceThread(DeviceEntry* entry) { 292 void VideoCaptureManager::DoStopDeviceOnDeviceThread(DeviceEntry* entry) {
294 SCOPED_UMA_HISTOGRAM_TIMER("Media.VideoCaptureManager.StopDeviceTime"); 293 SCOPED_UMA_HISTOGRAM_TIMER("Media.VideoCaptureManager.StopDeviceTime");
295 DCHECK(IsOnDeviceThread()); 294 DCHECK(IsOnDeviceThread());
296 if (entry->video_capture_device) { 295 if (entry->video_capture_device) {
297 // TODO(nick): Merge Stop() and DeAllocate(). http://crbug.com/285562 296 entry->video_capture_device->StopAndDeAllocate();
298 entry->video_capture_device->Stop();
299 entry->video_capture_device->DeAllocate();
300 entry->video_capture_device.reset();
301 } 297 }
302 } 298 entry->video_capture_device.reset();
303
304 void VideoCaptureManager::FreeDeviceEntryOnIOThread(
305 scoped_ptr<DeviceEntry> entry) {
306 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
307 entry->video_capture_controller = NULL;
308 entry.reset();
309 } 299 }
310 300
311 void VideoCaptureManager::OnOpened(MediaStreamType stream_type, 301 void VideoCaptureManager::OnOpened(MediaStreamType stream_type,
312 int capture_session_id) { 302 int capture_session_id) {
313 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); 303 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
314 if (!listener_) { 304 if (!listener_) {
315 // Listener has been removed. 305 // Listener has been removed.
316 return; 306 return;
317 } 307 }
318 listener_->Opened(stream_type, capture_session_id); 308 listener_->Opened(stream_type, capture_session_id);
(...skipping 97 matching lines...) Expand 10 before | Expand all | Expand 10 after
416 } 406 }
417 } 407 }
418 return NULL; 408 return NULL;
419 } 409 }
420 410
421 void VideoCaptureManager::OpenAndStartDefaultSession( 411 void VideoCaptureManager::OpenAndStartDefaultSession(
422 const media::VideoCaptureParams& capture_params, 412 const media::VideoCaptureParams& capture_params,
423 base::ProcessHandle client_render_process, 413 base::ProcessHandle client_render_process,
424 VideoCaptureControllerID client_id, 414 VideoCaptureControllerID client_id,
425 VideoCaptureControllerEventHandler* client_handler, 415 VideoCaptureControllerEventHandler* client_handler,
426 base::Callback<void(VideoCaptureController*)> done_cb, 416 const DoneCB& done_cb,
427 const media::VideoCaptureDevice::Names& device_names) { 417 const media::VideoCaptureDevice::Names& device_names) {
428 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); 418 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
429 419
430 // |device_names| is a value returned by GetAvailableDevicesOnDeviceThread(). 420 // |device_names| is a value returned by GetAvailableDevicesOnDeviceThread().
431 // We'll mimic an Open() operation on the first element in that list. 421 // We'll mimic an Open() operation on the first element in that list.
432 DCHECK(capture_params.session_id == kStartOpenSessionId); 422 DCHECK(capture_params.session_id == kStartOpenSessionId);
433 if (device_names.empty() || 423 if (device_names.empty() ||
434 sessions_.count(capture_params.session_id) != 0) { 424 sessions_.count(capture_params.session_id) != 0) {
435 done_cb.Run(NULL); 425 done_cb.Run(base::WeakPtr<VideoCaptureController>());
436 return; 426 return;
437 } 427 }
438 428
439 // Open the device by creating a |sessions_| entry. 429 // Open the device by creating a |sessions_| entry.
440 sessions_[capture_params.session_id] = 430 sessions_[capture_params.session_id] =
441 MediaStreamDevice(MEDIA_DEVICE_VIDEO_CAPTURE, 431 MediaStreamDevice(MEDIA_DEVICE_VIDEO_CAPTURE,
442 device_names.front().id(), 432 device_names.front().id(),
443 device_names.front().GetNameAndModel()); 433 device_names.front().GetNameAndModel());
444 434
445 BrowserThread::PostTask(BrowserThread::IO, FROM_HERE, 435 BrowserThread::PostTask(BrowserThread::IO, FROM_HERE,
446 base::Bind(&VideoCaptureManager::OnOpened, this, 436 base::Bind(&VideoCaptureManager::OnOpened, this,
447 MEDIA_DEVICE_VIDEO_CAPTURE, kStartOpenSessionId)); 437 MEDIA_DEVICE_VIDEO_CAPTURE, kStartOpenSessionId));
448 438
449 DoStartCaptureForClient(capture_params, client_render_process, client_id, 439 DoStartCaptureForClient(capture_params, client_render_process, client_id,
450 client_handler, done_cb); 440 client_handler, done_cb);
451 } 441 }
452 442
453 void VideoCaptureManager::DestroyDeviceEntryIfNoClients(DeviceEntry* entry) { 443 void VideoCaptureManager::DestroyDeviceEntryIfNoClients(DeviceEntry* entry) {
454 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); 444 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
455 // Removal of the last client stops the device. 445 // Removal of the last client stops the device.
456 if (entry->video_capture_controller->GetClientCount() == 0) { 446 if (entry->video_capture_controller->GetClientCount() == 0) {
457 DVLOG(1) << "VideoCaptureManager stopping device (type = " 447 DVLOG(1) << "VideoCaptureManager stopping device (type = "
458 << entry->stream_type << ", id = " << entry->id << ")"; 448 << entry->stream_type << ", id = " << entry->id << ")";
459 449
460 // The DeviceEntry is removed from |devices_| immediately, but will be torn 450 // The DeviceEntry is removed from |devices_| immediately. The controller is
461 // down asynchronously. After this point, subsequent request to open this 451 // deleted immediately, and the device is freed asynchronously. After this
462 // same device ID will create a new DeviceEntry, VideoCaptureController, 452 // point, subsequent requests to open this same device ID will create a new
463 // and VideoCaptureDevice. 453 // DeviceEntry, VideoCaptureController, and VideoCaptureDevice.
464 devices_.erase(entry); 454 devices_.erase(entry);
465 device_loop_->PostTaskAndReply( 455 entry->video_capture_controller.reset();
456 device_loop_->PostTask(
466 FROM_HERE, 457 FROM_HERE,
467 base::Bind(&VideoCaptureManager::DoStopDeviceOnDeviceThread, this, 458 base::Bind(&VideoCaptureManager::DoStopDeviceOnDeviceThread, this,
468 base::Unretained(entry)), 459 base::Owned(entry)));
469 base::Bind(&VideoCaptureManager::FreeDeviceEntryOnIOThread, this,
470 base::Passed(make_scoped_ptr(entry).Pass())));
471 } 460 }
472 } 461 }
473 462
474 VideoCaptureManager::DeviceEntry* VideoCaptureManager::GetOrCreateDeviceEntry( 463 VideoCaptureManager::DeviceEntry* VideoCaptureManager::GetOrCreateDeviceEntry(
475 int capture_session_id) { 464 int capture_session_id) {
476 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); 465 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
477 466
478 std::map<int, MediaStreamDevice>::iterator session_it = 467 std::map<int, MediaStreamDevice>::iterator session_it =
479 sessions_.find(capture_session_id); 468 sessions_.find(capture_session_id);
480 if (session_it == sessions_.end()) { 469 if (session_it == sessions_.end()) {
481 return NULL; 470 return NULL;
482 } 471 }
483 const MediaStreamDevice& device_info = session_it->second; 472 const MediaStreamDevice& device_info = session_it->second;
484 473
485 // Check if another session has already opened this device. If so, just 474 // Check if another session has already opened this device. If so, just
486 // use that opened device. 475 // use that opened device.
487 DeviceEntry* const existing_device = 476 DeviceEntry* const existing_device =
488 GetDeviceEntryForMediaStreamDevice(device_info); 477 GetDeviceEntryForMediaStreamDevice(device_info);
489 if (existing_device) { 478 if (existing_device) {
490 DCHECK_EQ(device_info.type, existing_device->stream_type); 479 DCHECK_EQ(device_info.type, existing_device->stream_type);
491 return existing_device; 480 return existing_device;
492 } 481 }
493 482
494 scoped_refptr<VideoCaptureController> video_capture_controller = 483 scoped_ptr<VideoCaptureController> video_capture_controller(
495 new VideoCaptureController(); 484 new VideoCaptureController());
496 DeviceEntry* new_device = new DeviceEntry(device_info.type, 485 DeviceEntry* new_device = new DeviceEntry(device_info.type,
497 device_info.id, 486 device_info.id,
498 video_capture_controller); 487 video_capture_controller.Pass());
499 devices_.insert(new_device); 488 devices_.insert(new_device);
500 return new_device; 489 return new_device;
501 } 490 }
502 491
503 } // namespace content 492 } // namespace content
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698