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

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

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