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

Side by Side Diff: content/renderer/media/video_capture_impl_manager.cc

Issue 242013002: Refactor video capturing code in the render process (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: merged Created 6 years, 8 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 //
5 // Implementation notes about lifetime of VideoCaptureImpl.
6 //
7 // VideoCaptureImpl is an internal class visible only by this class.
8 // Since it is an IO thread object we manage the lifetime of it manually.
9 // It is first created on the render thread. We also post a task to
10 // access it on the IO thread. It is accessed with Unretained() because
11 // we delete it on the IO thread after all clients have stopped.
4 12
5 #include "content/renderer/media/video_capture_impl_manager.h" 13 #include "content/renderer/media/video_capture_impl_manager.h"
6 14
7 #include "base/bind.h" 15 #include "base/bind.h"
8 #include "base/bind_helpers.h" 16 #include "base/bind_helpers.h"
9 #include "content/public/renderer/render_thread.h" 17 #include "content/child/child_process.h"
10 #include "content/renderer/media/video_capture_impl.h" 18 #include "content/renderer/media/video_capture_impl.h"
11 #include "content/renderer/media/video_capture_message_filter.h" 19 #include "content/renderer/media/video_capture_message_filter.h"
12 #include "media/base/bind_to_current_loop.h" 20 #include "media/base/bind_to_current_loop.h"
13 21
14 namespace content { 22 namespace content {
15 23
16 VideoCaptureHandle::VideoCaptureHandle(
17 media::VideoCapture* impl, base::Closure destruction_cb)
18 : impl_(impl), destruction_cb_(destruction_cb) {
19 }
20
21 VideoCaptureHandle::~VideoCaptureHandle() {
22 destruction_cb_.Run();
23 }
24
25 void VideoCaptureHandle::StartCapture(
26 EventHandler* handler,
27 const media::VideoCaptureParams& params) {
28 impl_->StartCapture(handler, params);
29 }
30
31 void VideoCaptureHandle::StopCapture(EventHandler* handler) {
32 impl_->StopCapture(handler);
33 }
34
35 bool VideoCaptureHandle::CaptureStarted() {
36 return impl_->CaptureStarted();
37 }
38
39 int VideoCaptureHandle::CaptureFrameRate() {
40 return impl_->CaptureFrameRate();
41 }
42
43 void VideoCaptureHandle::GetDeviceSupportedFormats(
44 const DeviceFormatsCallback& callback) {
45 impl_->GetDeviceSupportedFormats(callback);
46 }
47
48 void VideoCaptureHandle::GetDeviceFormatsInUse(
49 const DeviceFormatsInUseCallback& callback) {
50 impl_->GetDeviceFormatsInUse(callback);
51 }
52
53 VideoCaptureImplManager::VideoCaptureImplManager() 24 VideoCaptureImplManager::VideoCaptureImplManager()
54 : filter_(new VideoCaptureMessageFilter()), 25 : next_client_id_(0),
26 filter_(new VideoCaptureMessageFilter()),
55 weak_factory_(this) { 27 weak_factory_(this) {
56 } 28 }
57 29
58 VideoCaptureImplManager::~VideoCaptureImplManager() { 30 VideoCaptureImplManager::~VideoCaptureImplManager() {
59 DCHECK(thread_checker_.CalledOnValidThread()); 31 DCHECK(thread_checker_.CalledOnValidThread());
32 if (devices_.empty())
33 return;
34 // Forcibly release all video capture resources.
35 for (VideoCaptureDeviceMap::iterator it = devices_.begin();
36 it != devices_.end(); ++it) {
37 VideoCaptureImpl* impl = it->second.second;
38 ChildProcess::current()->io_message_loop_proxy()->PostTask(
Ami GONE FROM CHROMIUM 2014/04/21 23:42:53 ChildProcess::current()->io_message_loop_proxy() i
Alpha Left Google 2014/04/23 18:48:33 MessageLoopProxy::current() is the IO message loop
39 FROM_HERE,
40 base::Bind(&VideoCaptureImpl::DeInit,
Ami GONE FROM CHROMIUM 2014/04/21 23:42:53 why not DeInit+delete directly in-line here?
Alpha Left Google 2014/04/23 18:48:33 VCI is an IO thread only object. It is accessed vi
41 base::Unretained(impl)));
Ami GONE FROM CHROMIUM 2014/04/21 23:42:53 any "Unretained" use should be covered by an expla
Alpha Left Google 2014/04/23 18:48:33 I documented it at the top of this file.
42 ChildProcess::current()->io_message_loop_proxy()->PostTask(
43 FROM_HERE,
44 base::Bind(&base::DeletePointer<VideoCaptureImpl>, impl));
45 }
46 devices_.clear();
60 } 47 }
61 48
62 scoped_ptr<VideoCaptureHandle> VideoCaptureImplManager::UseDevice( 49 base::Closure VideoCaptureImplManager::UseDevice(
63 media::VideoCaptureSessionId id) { 50 media::VideoCaptureSessionId id) {
64 DCHECK(thread_checker_.CalledOnValidThread()); 51 DCHECK(thread_checker_.CalledOnValidThread());
65 52
66 VideoCaptureImpl* video_capture_device = NULL; 53 VideoCaptureImpl* impl = NULL;
67 VideoCaptureDeviceMap::iterator it = devices_.find(id); 54 VideoCaptureDeviceMap::iterator it = devices_.find(id);
68 if (it == devices_.end()) { 55 if (it == devices_.end()) {
69 video_capture_device = CreateVideoCaptureImpl(id, filter_.get()); 56 impl = CreateVideoCaptureImpl(id, filter_.get());
70 devices_[id] = 57 devices_[id] = std::make_pair(1, impl);
71 std::make_pair(1, linked_ptr<VideoCaptureImpl>(video_capture_device)); 58 ChildProcess::current()->io_message_loop_proxy()->PostTask(
Ami GONE FROM CHROMIUM 2014/04/21 23:42:53 ditto why post instead of running in-line?
Alpha Left Google 2014/04/23 18:48:33 VCIM is render thread only. VideoCaptureImpl is IO
72 video_capture_device->Init(); 59 FROM_HERE,
60 base::Bind(&VideoCaptureImpl::Init,
61 base::Unretained(impl)));
Ami GONE FROM CHROMIUM 2014/04/21 23:42:53 ditto Unretained
Alpha Left Google 2014/04/23 18:48:33 Please see comments at the top of this file.
73 } else { 62 } else {
74 ++it->second.first; 63 ++it->second.first;
75 video_capture_device = it->second.second.get(); 64 impl = it->second.second;
Ami GONE FROM CHROMIUM 2014/04/21 23:42:53 unused?
Alpha Left Google 2014/04/23 18:48:33 Removed.
76 } 65 }
66 return base::Bind(&VideoCaptureImplManager::UnrefDevice, this, id);
67 }
77 68
78 // This callback ensures UnrefDevice() happens on the render thread. 69 base::Closure VideoCaptureImplManager::StartCapture(
79 return scoped_ptr<VideoCaptureHandle>( 70 media::VideoCaptureSessionId id,
80 new VideoCaptureHandle( 71 const media::VideoCaptureParams& params,
81 video_capture_device, 72 const VideoCaptureStateUpdateCB& state_update_cb,
82 media::BindToCurrentLoop( 73 const VideoCaptureDeliverFrameCB& deliver_frame_cb) {
83 base::Bind( 74 DCHECK(thread_checker_.CalledOnValidThread());
84 &VideoCaptureImplManager::UnrefDevice, 75 VideoCaptureDeviceMap::iterator it = devices_.find(id);
85 weak_factory_.GetWeakPtr(), 76 DCHECK(it != devices_.end());
86 id)))); 77 VideoCaptureImpl* impl = it->second.second;
78
79 // This ID is used to identify a client of VideoCaptureImpl.
80 const int client_id = ++next_client_id_;
81
82 ChildProcess::current()->io_message_loop_proxy()->PostTask(
Ami GONE FROM CHROMIUM 2014/04/21 23:42:53 not reviewing the rest of this file since I hope y
Alpha Left Google 2014/04/23 18:48:33 I have changed the access pattern. Instead of VCI
83 FROM_HERE,
84 base::Bind(&VideoCaptureImpl::StartCapture,
85 base::Unretained(impl),
86 client_id,
87 params,
88 state_update_cb,
89 deliver_frame_cb));
90 return base::Bind(&VideoCaptureImplManager::StopCapture, this,
91 client_id, id);
92 }
93
94 void VideoCaptureImplManager::GetDeviceSupportedFormats(
95 media::VideoCaptureSessionId id,
96 const VideoCaptureDeviceFormatsCB& callback) {
97 DCHECK(thread_checker_.CalledOnValidThread());
98 VideoCaptureDeviceMap::iterator it = devices_.find(id);
99 DCHECK(it != devices_.end());
100 VideoCaptureImpl* impl = it->second.second;
101 ChildProcess::current()->io_message_loop_proxy()->PostTask(
102 FROM_HERE,
103 base::Bind(&VideoCaptureImpl::GetDeviceSupportedFormats,
104 base::Unretained(impl), callback));
105 }
106
107 void VideoCaptureImplManager::GetDeviceFormatsInUse(
108 media::VideoCaptureSessionId id,
109 const VideoCaptureDeviceFormatsCB& callback) {
110 DCHECK(thread_checker_.CalledOnValidThread());
111 VideoCaptureDeviceMap::iterator it = devices_.find(id);
112 DCHECK(it != devices_.end());
113 VideoCaptureImpl* impl = it->second.second;
114 ChildProcess::current()->io_message_loop_proxy()->PostTask(
115 FROM_HERE,
116 base::Bind(&VideoCaptureImpl::GetDeviceFormatsInUse,
117 base::Unretained(impl), callback));
87 } 118 }
88 119
89 VideoCaptureImpl* VideoCaptureImplManager::CreateVideoCaptureImpl( 120 VideoCaptureImpl* VideoCaptureImplManager::CreateVideoCaptureImpl(
90 media::VideoCaptureSessionId id, 121 media::VideoCaptureSessionId id,
91 VideoCaptureMessageFilter* filter) const { 122 VideoCaptureMessageFilter* filter) const {
92 return new VideoCaptureImpl(id, filter); 123 return new VideoCaptureImpl(id, filter);
93 } 124 }
94 125
126 void VideoCaptureImplManager::StopCapture(
127 int client_id, media::VideoCaptureSessionId id) {
128 DCHECK(thread_checker_.CalledOnValidThread());
129 VideoCaptureDeviceMap::iterator it = devices_.find(id);
130 DCHECK(it != devices_.end());
131 VideoCaptureImpl* impl = it->second.second;
132 ChildProcess::current()->io_message_loop_proxy()->PostTask(
133 FROM_HERE,
134 base::Bind(&VideoCaptureImpl::StopCapture,
135 base::Unretained(impl), client_id));
136 }
137
95 void VideoCaptureImplManager::UnrefDevice( 138 void VideoCaptureImplManager::UnrefDevice(
96 media::VideoCaptureSessionId id) { 139 media::VideoCaptureSessionId id) {
97 DCHECK(thread_checker_.CalledOnValidThread()); 140 DCHECK(thread_checker_.CalledOnValidThread());
98 VideoCaptureDeviceMap::iterator it = devices_.find(id); 141 VideoCaptureDeviceMap::iterator it = devices_.find(id);
99 DCHECK(it != devices_.end()); 142 DCHECK(it != devices_.end());
143 VideoCaptureImpl* impl = it->second.second;
100 144
145 // Unref and destroy on the IO thread if there's no more client.
101 DCHECK(it->second.first); 146 DCHECK(it->second.first);
102 --it->second.first; 147 --it->second.first;
103 if (!it->second.first) { 148 if (!it->second.first) {
104 VideoCaptureImpl* impl = it->second.second.release();
105 devices_.erase(id); 149 devices_.erase(id);
106 impl->DeInit(base::Bind(&base::DeletePointer<VideoCaptureImpl>, impl)); 150 ChildProcess::current()->io_message_loop_proxy()->PostTask(
151 FROM_HERE,
152 base::Bind(&VideoCaptureImpl::DeInit,
153 base::Unretained(impl)));
154 ChildProcess::current()->io_message_loop_proxy()->PostTask(
155 FROM_HERE,
156 base::Bind(&base::DeletePointer<VideoCaptureImpl>, impl));
107 } 157 }
108 } 158 }
109 159
110 void VideoCaptureImplManager::SuspendDevices(bool suspend) { 160 void VideoCaptureImplManager::SuspendDevices(bool suspend) {
111 DCHECK(thread_checker_.CalledOnValidThread()); 161 DCHECK(thread_checker_.CalledOnValidThread());
112 for (VideoCaptureDeviceMap::iterator it = devices_.begin(); 162 for (VideoCaptureDeviceMap::iterator it = devices_.begin();
113 it != devices_.end(); ++it) 163 it != devices_.end(); ++it) {
114 it->second.second->SuspendCapture(suspend); 164 VideoCaptureImpl* impl = it->second.second;
165 ChildProcess::current()->io_message_loop_proxy()->PostTask(
166 FROM_HERE,
167 base::Bind(&VideoCaptureImpl::SuspendCapture,
168 base::Unretained(impl), suspend));
169 }
115 } 170 }
116 171
117 } // namespace content 172 } // namespace content
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698