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

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

Issue 17334005: Re-land r207105 (Mac audio capture threading fix) with unit test memory leak issue resolved. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Using ref-counting (Patch Set 2 from Issue 17122006). Created 7 years, 6 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) 2013 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2013 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/web_contents_audio_input_stream.h" 5 #include "content/browser/renderer_host/media/web_contents_audio_input_stream.h"
6 6
7 #include <string> 7 #include <string>
8 8
9 #include "base/bind.h" 9 #include "base/bind.h"
10 #include "base/bind_helpers.h" 10 #include "base/bind_helpers.h"
11 #include "base/logging.h" 11 #include "base/logging.h"
12 #include "base/memory/scoped_ptr.h" 12 #include "base/memory/scoped_ptr.h"
13 #include "base/message_loop/message_loop_proxy.h" 13 #include "base/threading/thread_checker.h"
14 #include "content/browser/renderer_host/media/audio_mirroring_manager.h" 14 #include "content/browser/renderer_host/media/audio_mirroring_manager.h"
15 #include "content/browser/renderer_host/media/web_contents_capture_util.h" 15 #include "content/browser/renderer_host/media/web_contents_capture_util.h"
16 #include "content/browser/renderer_host/media/web_contents_tracker.h" 16 #include "content/browser/renderer_host/media/web_contents_tracker.h"
17 #include "content/public/browser/browser_thread.h" 17 #include "content/public/browser/browser_thread.h"
18 #include "media/audio/virtual_audio_input_stream.h" 18 #include "media/audio/virtual_audio_input_stream.h"
19 #include "media/audio/virtual_audio_output_stream.h" 19 #include "media/audio/virtual_audio_output_stream.h"
20 20
21 namespace content { 21 namespace content {
22 22
23 class WebContentsAudioInputStream::Impl 23 class WebContentsAudioInputStream::Impl
24 : public base::RefCountedThreadSafe<WebContentsAudioInputStream::Impl>, 24 : public base::RefCountedThreadSafe<WebContentsAudioInputStream::Impl>,
25 public AudioMirroringManager::MirroringDestination { 25 public AudioMirroringManager::MirroringDestination {
26 public: 26 public:
27 // Takes ownership of |mixer_stream|. The rest outlive this instance. 27 // Takes ownership of |mixer_stream|. The rest outlive this instance.
28 Impl(int render_process_id, int render_view_id, 28 Impl(int render_process_id, int render_view_id,
29 const scoped_refptr<base::MessageLoopProxy>& message_loop,
30 AudioMirroringManager* mirroring_manager, 29 AudioMirroringManager* mirroring_manager,
31 const scoped_refptr<WebContentsTracker>& tracker, 30 const scoped_refptr<WebContentsTracker>& tracker,
32 media::VirtualAudioInputStream* mixer_stream); 31 media::VirtualAudioInputStream* mixer_stream);
33 32
34 // Open underlying VirtualAudioInputStream and start tracker. 33 // Open underlying VirtualAudioInputStream and start tracker.
35 bool Open(); 34 bool Open();
36 35
37 // Start the underlying VirtualAudioInputStream and instruct 36 // Start the underlying VirtualAudioInputStream and instruct
38 // AudioMirroringManager to begin a mirroring session. 37 // AudioMirroringManager to begin a mirroring session.
39 void Start(AudioInputCallback* callback); 38 void Start(AudioInputCallback* callback);
(...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after
78 const media::AudioParameters& params) OVERRIDE; 77 const media::AudioParameters& params) OVERRIDE;
79 78
80 // Callback which is run when |stream| is closed. Deletes |stream|. 79 // Callback which is run when |stream| is closed. Deletes |stream|.
81 void ReleaseInput(media::VirtualAudioOutputStream* stream); 80 void ReleaseInput(media::VirtualAudioOutputStream* stream);
82 81
83 // Called by WebContentsTracker when the target of the audio mirroring has 82 // Called by WebContentsTracker when the target of the audio mirroring has
84 // changed. 83 // changed.
85 void OnTargetChanged(int render_process_id, int render_view_id); 84 void OnTargetChanged(int render_process_id, int render_view_id);
86 85
87 // Injected dependencies. 86 // Injected dependencies.
88 const scoped_refptr<base::MessageLoopProxy> message_loop_;
89 AudioMirroringManager* const mirroring_manager_; 87 AudioMirroringManager* const mirroring_manager_;
90 const scoped_refptr<WebContentsTracker> tracker_; 88 const scoped_refptr<WebContentsTracker> tracker_;
91 // The AudioInputStream implementation that handles the audio conversion and 89 // The AudioInputStream implementation that handles the audio conversion and
92 // mixing details. 90 // mixing details.
93 const scoped_ptr<media::VirtualAudioInputStream> mixer_stream_; 91 const scoped_ptr<media::VirtualAudioInputStream> mixer_stream_;
94 92
95 State state_; 93 State state_;
96 94
97 // Current audio mirroring target. 95 // Current audio mirroring target.
98 int target_render_process_id_; 96 int target_render_process_id_;
99 int target_render_view_id_; 97 int target_render_view_id_;
100 98
101 // Current callback used to consume the resulting mixed audio data. 99 // Current callback used to consume the resulting mixed audio data.
102 AudioInputCallback* callback_; 100 AudioInputCallback* callback_;
103 101
102 base::ThreadChecker thread_checker_;
103
104 DISALLOW_COPY_AND_ASSIGN(Impl); 104 DISALLOW_COPY_AND_ASSIGN(Impl);
105 }; 105 };
106 106
107 WebContentsAudioInputStream::Impl::Impl( 107 WebContentsAudioInputStream::Impl::Impl(
108 int render_process_id, int render_view_id, 108 int render_process_id, int render_view_id,
109 const scoped_refptr<base::MessageLoopProxy>& message_loop,
110 AudioMirroringManager* mirroring_manager, 109 AudioMirroringManager* mirroring_manager,
111 const scoped_refptr<WebContentsTracker>& tracker, 110 const scoped_refptr<WebContentsTracker>& tracker,
112 media::VirtualAudioInputStream* mixer_stream) 111 media::VirtualAudioInputStream* mixer_stream)
113 : message_loop_(message_loop), mirroring_manager_(mirroring_manager), 112 : mirroring_manager_(mirroring_manager),
114 tracker_(tracker), mixer_stream_(mixer_stream), state_(CONSTRUCTED), 113 tracker_(tracker), mixer_stream_(mixer_stream), state_(CONSTRUCTED),
115 target_render_process_id_(render_process_id), 114 target_render_process_id_(render_process_id),
116 target_render_view_id_(render_view_id), 115 target_render_view_id_(render_view_id),
117 callback_(NULL) { 116 callback_(NULL) {
118 DCHECK(message_loop_.get());
119 DCHECK(mirroring_manager_); 117 DCHECK(mirroring_manager_);
120 DCHECK(tracker_.get()); 118 DCHECK(tracker_.get());
121 DCHECK(mixer_stream_.get()); 119 DCHECK(mixer_stream_.get());
120
121 // WAIS::Impl can be constructed on any thread, but will DCHECK that all
122 // its methods from here on are called from the same thread.
123 thread_checker_.DetachFromThread();
122 } 124 }
123 125
124 WebContentsAudioInputStream::Impl::~Impl() { 126 WebContentsAudioInputStream::Impl::~Impl() {
125 DCHECK(state_ == CONSTRUCTED || state_ == CLOSED); 127 DCHECK(state_ == CONSTRUCTED || state_ == CLOSED);
126 } 128 }
127 129
128 bool WebContentsAudioInputStream::Impl::Open() { 130 bool WebContentsAudioInputStream::Impl::Open() {
129 DCHECK(message_loop_->BelongsToCurrentThread()); 131 DCHECK(thread_checker_.CalledOnValidThread());
130 132
131 DCHECK_EQ(CONSTRUCTED, state_) << "Illegal to Open more than once."; 133 DCHECK_EQ(CONSTRUCTED, state_) << "Illegal to Open more than once.";
132 134
133 if (!mixer_stream_->Open()) 135 if (!mixer_stream_->Open())
134 return false; 136 return false;
135 137
136 state_ = OPENED; 138 state_ = OPENED;
137 139
138 tracker_->Start( 140 tracker_->Start(
139 target_render_process_id_, target_render_view_id_, 141 target_render_process_id_, target_render_view_id_,
140 base::Bind(&Impl::OnTargetChanged, this)); 142 base::Bind(&Impl::OnTargetChanged, this));
141 143
142 return true; 144 return true;
143 } 145 }
144 146
145 void WebContentsAudioInputStream::Impl::Start(AudioInputCallback* callback) { 147 void WebContentsAudioInputStream::Impl::Start(AudioInputCallback* callback) {
146 DCHECK(message_loop_->BelongsToCurrentThread()); 148 DCHECK(thread_checker_.CalledOnValidThread());
147 DCHECK(callback); 149 DCHECK(callback);
148 150
149 if (state_ != OPENED) 151 if (state_ != OPENED)
150 return; 152 return;
151 153
152 callback_ = callback; 154 callback_ = callback;
153 if (IsTargetLost()) { 155 if (IsTargetLost()) {
154 ReportError(); 156 ReportError();
155 callback_ = NULL; 157 callback_ = NULL;
156 return; 158 return;
157 } 159 }
158 160
159 state_ = MIRRORING; 161 state_ = MIRRORING;
160 mixer_stream_->Start(callback); 162 mixer_stream_->Start(callback);
161 163
162 StartMirroring(); 164 StartMirroring();
163 } 165 }
164 166
165 void WebContentsAudioInputStream::Impl::Stop() { 167 void WebContentsAudioInputStream::Impl::Stop() {
166 DCHECK(message_loop_->BelongsToCurrentThread()); 168 DCHECK(thread_checker_.CalledOnValidThread());
167 169
168 if (state_ != MIRRORING) 170 if (state_ != MIRRORING)
169 return; 171 return;
170 172
171 state_ = OPENED; 173 state_ = OPENED;
172 174
173 mixer_stream_->Stop(); 175 mixer_stream_->Stop();
174 callback_ = NULL; 176 callback_ = NULL;
175 177
176 if (!IsTargetLost()) 178 if (!IsTargetLost())
177 StopMirroring(); 179 StopMirroring();
178 } 180 }
179 181
180 void WebContentsAudioInputStream::Impl::Close() { 182 void WebContentsAudioInputStream::Impl::Close() {
181 DCHECK(message_loop_->BelongsToCurrentThread()); 183 DCHECK(thread_checker_.CalledOnValidThread());
182 184
183 Stop(); 185 Stop();
184 186
185 if (state_ == OPENED) { 187 if (state_ == OPENED) {
186 state_ = CONSTRUCTED; 188 state_ = CONSTRUCTED;
187 tracker_->Stop(); 189 tracker_->Stop();
188 mixer_stream_->Close(); 190 mixer_stream_->Close();
189 } 191 }
190 192
191 DCHECK_EQ(CONSTRUCTED, state_); 193 DCHECK_EQ(CONSTRUCTED, state_);
192 state_ = CLOSED; 194 state_ = CLOSED;
193 } 195 }
194 196
195 bool WebContentsAudioInputStream::Impl::IsTargetLost() const { 197 bool WebContentsAudioInputStream::Impl::IsTargetLost() const {
196 DCHECK(message_loop_->BelongsToCurrentThread()); 198 DCHECK(thread_checker_.CalledOnValidThread());
197 199
198 return target_render_process_id_ <= 0 || target_render_view_id_ <= 0; 200 return target_render_process_id_ <= 0 || target_render_view_id_ <= 0;
199 } 201 }
200 202
201 void WebContentsAudioInputStream::Impl::ReportError() { 203 void WebContentsAudioInputStream::Impl::ReportError() {
202 DCHECK(message_loop_->BelongsToCurrentThread()); 204 DCHECK(thread_checker_.CalledOnValidThread());
203 205
204 // TODO(miu): Need clean-up of AudioInputCallback interface in a future 206 // TODO(miu): Need clean-up of AudioInputCallback interface in a future
205 // change, since its only implementation ignores the first argument entirely 207 // change, since its only implementation ignores the first argument entirely
206 callback_->OnError(NULL); 208 callback_->OnError(NULL);
207 } 209 }
208 210
209 void WebContentsAudioInputStream::Impl::StartMirroring() { 211 void WebContentsAudioInputStream::Impl::StartMirroring() {
210 DCHECK(message_loop_->BelongsToCurrentThread()); 212 DCHECK(thread_checker_.CalledOnValidThread());
211 213
212 BrowserThread::PostTask( 214 BrowserThread::PostTask(
213 BrowserThread::IO, 215 BrowserThread::IO,
214 FROM_HERE, 216 FROM_HERE,
215 base::Bind(&AudioMirroringManager::StartMirroring, 217 base::Bind(&AudioMirroringManager::StartMirroring,
216 base::Unretained(mirroring_manager_), 218 base::Unretained(mirroring_manager_),
217 target_render_process_id_, target_render_view_id_, 219 target_render_process_id_, target_render_view_id_,
218 make_scoped_refptr(this))); 220 make_scoped_refptr(this)));
219 } 221 }
220 222
221 void WebContentsAudioInputStream::Impl::StopMirroring() { 223 void WebContentsAudioInputStream::Impl::StopMirroring() {
222 DCHECK(message_loop_->BelongsToCurrentThread()); 224 DCHECK(thread_checker_.CalledOnValidThread());
223 225
224 BrowserThread::PostTask( 226 BrowserThread::PostTask(
225 BrowserThread::IO, 227 BrowserThread::IO,
226 FROM_HERE, 228 FROM_HERE,
227 base::Bind(&AudioMirroringManager::StopMirroring, 229 base::Bind(&AudioMirroringManager::StopMirroring,
228 base::Unretained(mirroring_manager_), 230 base::Unretained(mirroring_manager_),
229 target_render_process_id_, target_render_view_id_, 231 target_render_process_id_, target_render_view_id_,
230 make_scoped_refptr(this))); 232 make_scoped_refptr(this)));
231 } 233 }
232 234
233 media::AudioOutputStream* WebContentsAudioInputStream::Impl::AddInput( 235 media::AudioOutputStream* WebContentsAudioInputStream::Impl::AddInput(
234 const media::AudioParameters& params) { 236 const media::AudioParameters& params) {
235 // Note: The closure created here holds a reference to "this," which will 237 // Note: The closure created here holds a reference to "this," which will
236 // guarantee the VirtualAudioInputStream (mixer_stream_) outlives the 238 // guarantee the VirtualAudioInputStream (mixer_stream_) outlives the
237 // VirtualAudioOutputStream. 239 // VirtualAudioOutputStream.
238 return new media::VirtualAudioOutputStream( 240 return new media::VirtualAudioOutputStream(
239 params, 241 params,
240 message_loop_.get(),
241 mixer_stream_.get(), 242 mixer_stream_.get(),
242 base::Bind(&Impl::ReleaseInput, this)); 243 base::Bind(&Impl::ReleaseInput, this));
243 } 244 }
244 245
245 void WebContentsAudioInputStream::Impl::ReleaseInput( 246 void WebContentsAudioInputStream::Impl::ReleaseInput(
246 media::VirtualAudioOutputStream* stream) { 247 media::VirtualAudioOutputStream* stream) {
247 delete stream; 248 delete stream;
248 } 249 }
249 250
250 void WebContentsAudioInputStream::Impl::OnTargetChanged(int render_process_id, 251 void WebContentsAudioInputStream::Impl::OnTargetChanged(int render_process_id,
251 int render_view_id) { 252 int render_view_id) {
252 DCHECK(message_loop_->BelongsToCurrentThread()); 253 DCHECK(thread_checker_.CalledOnValidThread());
253 254
254 if (target_render_process_id_ == render_process_id && 255 if (target_render_process_id_ == render_process_id &&
255 target_render_view_id_ == render_view_id) { 256 target_render_view_id_ == render_view_id) {
256 return; 257 return;
257 } 258 }
258 259
259 DVLOG(1) << "Target RenderView has changed from " 260 DVLOG(1) << "Target RenderView has changed from "
260 << target_render_process_id_ << ':' << target_render_view_id_ 261 << target_render_process_id_ << ':' << target_render_view_id_
261 << " to " << render_process_id << ':' << render_view_id; 262 << " to " << render_process_id << ':' << render_view_id;
262 263
(...skipping 10 matching lines...) Expand all
273 } else { 274 } else {
274 StartMirroring(); 275 StartMirroring();
275 } 276 }
276 } 277 }
277 } 278 }
278 279
279 // static 280 // static
280 WebContentsAudioInputStream* WebContentsAudioInputStream::Create( 281 WebContentsAudioInputStream* WebContentsAudioInputStream::Create(
281 const std::string& device_id, 282 const std::string& device_id,
282 const media::AudioParameters& params, 283 const media::AudioParameters& params,
283 const scoped_refptr<base::MessageLoopProxy>& message_loop, 284 const scoped_refptr<base::MessageLoopProxy>& worker_loop,
284 AudioMirroringManager* audio_mirroring_manager) { 285 AudioMirroringManager* audio_mirroring_manager) {
285 int render_process_id; 286 int render_process_id;
286 int render_view_id; 287 int render_view_id;
287 if (!WebContentsCaptureUtil::ExtractTabCaptureTarget( 288 if (!WebContentsCaptureUtil::ExtractTabCaptureTarget(
288 device_id, &render_process_id, &render_view_id)) { 289 device_id, &render_process_id, &render_view_id)) {
289 return NULL; 290 return NULL;
290 } 291 }
291 292
292 return new WebContentsAudioInputStream( 293 return new WebContentsAudioInputStream(
293 render_process_id, render_view_id, message_loop, 294 render_process_id, render_view_id,
294 audio_mirroring_manager, 295 audio_mirroring_manager,
295 new WebContentsTracker(), 296 new WebContentsTracker(),
296 new media::VirtualAudioInputStream( 297 new media::VirtualAudioInputStream(
297 params, message_loop, 298 params, worker_loop,
298 media::VirtualAudioInputStream::AfterCloseCallback())); 299 media::VirtualAudioInputStream::AfterCloseCallback()));
299 } 300 }
300 301
301 WebContentsAudioInputStream::WebContentsAudioInputStream( 302 WebContentsAudioInputStream::WebContentsAudioInputStream(
302 int render_process_id, int render_view_id, 303 int render_process_id, int render_view_id,
303 const scoped_refptr<base::MessageLoopProxy>& message_loop,
304 AudioMirroringManager* mirroring_manager, 304 AudioMirroringManager* mirroring_manager,
305 const scoped_refptr<WebContentsTracker>& tracker, 305 const scoped_refptr<WebContentsTracker>& tracker,
306 media::VirtualAudioInputStream* mixer_stream) 306 media::VirtualAudioInputStream* mixer_stream)
307 : impl_(new Impl(render_process_id, render_view_id, message_loop, 307 : impl_(new Impl(render_process_id, render_view_id,
308 mirroring_manager, tracker, mixer_stream)) {} 308 mirroring_manager, tracker, mixer_stream)) {}
309 309
310 WebContentsAudioInputStream::~WebContentsAudioInputStream() {} 310 WebContentsAudioInputStream::~WebContentsAudioInputStream() {}
311 311
312 bool WebContentsAudioInputStream::Open() { 312 bool WebContentsAudioInputStream::Open() {
313 return impl_->Open(); 313 return impl_->Open();
314 } 314 }
315 315
316 void WebContentsAudioInputStream::Start(AudioInputCallback* callback) { 316 void WebContentsAudioInputStream::Start(AudioInputCallback* callback) {
317 impl_->Start(callback); 317 impl_->Start(callback);
(...skipping 22 matching lines...) Expand all
340 340
341 void WebContentsAudioInputStream::SetAutomaticGainControl(bool enabled) { 341 void WebContentsAudioInputStream::SetAutomaticGainControl(bool enabled) {
342 impl_->mixer_stream()->SetAutomaticGainControl(enabled); 342 impl_->mixer_stream()->SetAutomaticGainControl(enabled);
343 } 343 }
344 344
345 bool WebContentsAudioInputStream::GetAutomaticGainControl() { 345 bool WebContentsAudioInputStream::GetAutomaticGainControl() {
346 return impl_->mixer_stream()->GetAutomaticGainControl(); 346 return impl_->mixer_stream()->GetAutomaticGainControl();
347 } 347 }
348 348
349 } // namespace content 349 } // namespace content
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698