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

Side by Side Diff: media/audio/audio_manager_base.cc

Issue 66183002: Replace MessageLoopProxy with SingleThreadTaskRunner for the rest of media/. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: fix win and audio tests Created 6 years, 11 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
« no previous file with comments | « media/audio/audio_manager_base.h ('k') | media/audio/audio_output_controller.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
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 "media/audio/audio_manager_base.h" 5 #include "media/audio/audio_manager_base.h"
6 6
7 #include "base/bind.h" 7 #include "base/bind.h"
8 #include "base/bind_helpers.h" 8 #include "base/bind_helpers.h"
9 #include "base/command_line.h" 9 #include "base/command_line.h"
10 #include "base/message_loop/message_loop_proxy.h"
11 #include "base/strings/string_number_conversions.h" 10 #include "base/strings/string_number_conversions.h"
12 #include "build/build_config.h" 11 #include "build/build_config.h"
13 #include "media/audio/audio_output_dispatcher_impl.h" 12 #include "media/audio/audio_output_dispatcher_impl.h"
14 #include "media/audio/audio_output_proxy.h" 13 #include "media/audio/audio_output_proxy.h"
15 #include "media/audio/audio_output_resampler.h" 14 #include "media/audio/audio_output_resampler.h"
16 #include "media/audio/fake_audio_input_stream.h" 15 #include "media/audio/fake_audio_input_stream.h"
17 #include "media/audio/fake_audio_output_stream.h" 16 #include "media/audio/fake_audio_output_stream.h"
18 #include "media/base/media_switches.h" 17 #include "media/base/media_switches.h"
19 18
20 namespace media { 19 namespace media {
(...skipping 71 matching lines...) Expand 10 before | Expand all | Expand 10 after
92 audio_thread_.init_com_with_mta(true); 91 audio_thread_.init_com_with_mta(true);
93 #elif defined(OS_MACOSX) 92 #elif defined(OS_MACOSX)
94 // CoreAudio calls must occur on the main thread of the process, which in our 93 // CoreAudio calls must occur on the main thread of the process, which in our
95 // case is sadly the browser UI thread. Failure to execute calls on the right 94 // case is sadly the browser UI thread. Failure to execute calls on the right
96 // thread leads to crashes and odd behavior. See http://crbug.com/158170. 95 // thread leads to crashes and odd behavior. See http://crbug.com/158170.
97 // TODO(dalecurtis): We should require the message loop to be passed in. 96 // TODO(dalecurtis): We should require the message loop to be passed in.
98 const CommandLine* cmd_line = CommandLine::ForCurrentProcess(); 97 const CommandLine* cmd_line = CommandLine::ForCurrentProcess();
99 if (!cmd_line->HasSwitch(switches::kDisableMainThreadAudio) && 98 if (!cmd_line->HasSwitch(switches::kDisableMainThreadAudio) &&
100 base::MessageLoopProxy::current().get() && 99 base::MessageLoopProxy::current().get() &&
101 base::MessageLoop::current()->IsType(base::MessageLoop::TYPE_UI)) { 100 base::MessageLoop::current()->IsType(base::MessageLoop::TYPE_UI)) {
102 message_loop_ = base::MessageLoopProxy::current(); 101 task_runner_ = base::MessageLoopProxy::current();
103 return; 102 return;
104 } 103 }
105 #endif 104 #endif
106 105
107 CHECK(audio_thread_.Start()); 106 CHECK(audio_thread_.Start());
108 message_loop_ = audio_thread_.message_loop_proxy(); 107 task_runner_ = audio_thread_.message_loop_proxy();
109 } 108 }
110 109
111 AudioManagerBase::~AudioManagerBase() { 110 AudioManagerBase::~AudioManagerBase() {
112 // The platform specific AudioManager implementation must have already 111 // The platform specific AudioManager implementation must have already
113 // stopped the audio thread. Otherwise, we may destroy audio streams before 112 // stopped the audio thread. Otherwise, we may destroy audio streams before
114 // stopping the thread, resulting an unexpected behavior. 113 // stopping the thread, resulting an unexpected behavior.
115 // This way we make sure activities of the audio streams are all stopped 114 // This way we make sure activities of the audio streams are all stopped
116 // before we destroy them. 115 // before we destroy them.
117 CHECK(!audio_thread_.IsRunning()); 116 CHECK(!audio_thread_.IsRunning());
118 // All the output streams should have been deleted. 117 // All the output streams should have been deleted.
119 DCHECK_EQ(0, num_output_streams_); 118 DCHECK_EQ(0, num_output_streams_);
120 // All the input streams should have been deleted. 119 // All the input streams should have been deleted.
121 DCHECK_EQ(0, num_input_streams_); 120 DCHECK_EQ(0, num_input_streams_);
122 } 121 }
123 122
124 base::string16 AudioManagerBase::GetAudioInputDeviceModel() { 123 base::string16 AudioManagerBase::GetAudioInputDeviceModel() {
125 return base::string16(); 124 return base::string16();
126 } 125 }
127 126
128 scoped_refptr<base::MessageLoopProxy> AudioManagerBase::GetMessageLoop() { 127 scoped_refptr<base::SingleThreadTaskRunner> AudioManagerBase::GetTaskRunner() {
129 return message_loop_; 128 return task_runner_;
130 } 129 }
131 130
132 scoped_refptr<base::MessageLoopProxy> AudioManagerBase::GetWorkerLoop() { 131 scoped_refptr<base::SingleThreadTaskRunner>
132 AudioManagerBase::GetWorkerTaskRunner() {
133 // Lazily start the worker thread. 133 // Lazily start the worker thread.
134 if (!audio_thread_.IsRunning()) 134 if (!audio_thread_.IsRunning())
135 CHECK(audio_thread_.Start()); 135 CHECK(audio_thread_.Start());
136 136
137 return audio_thread_.message_loop_proxy(); 137 return audio_thread_.message_loop_proxy();
138 } 138 }
139 139
140 AudioOutputStream* AudioManagerBase::MakeAudioOutputStream( 140 AudioOutputStream* AudioManagerBase::MakeAudioOutputStream(
141 const AudioParameters& params, 141 const AudioParameters& params,
142 const std::string& device_id, 142 const std::string& device_id,
143 const std::string& input_device_id) { 143 const std::string& input_device_id) {
144 // TODO(miu): Fix ~50 call points across several unit test modules to call 144 // TODO(miu): Fix ~50 call points across several unit test modules to call
145 // this method on the audio thread, then uncomment the following: 145 // this method on the audio thread, then uncomment the following:
146 // DCHECK(message_loop_->BelongsToCurrentThread()); 146 // DCHECK(task_runner_->BelongsToCurrentThread());
147 147
148 if (!params.IsValid()) { 148 if (!params.IsValid()) {
149 DLOG(ERROR) << "Audio parameters are invalid"; 149 DLOG(ERROR) << "Audio parameters are invalid";
150 return NULL; 150 return NULL;
151 } 151 }
152 152
153 // Limit the number of audio streams opened. This is to prevent using 153 // Limit the number of audio streams opened. This is to prevent using
154 // excessive resources for a large number of audio streams. More 154 // excessive resources for a large number of audio streams. More
155 // importantly it prevents instability on certain systems. 155 // importantly it prevents instability on certain systems.
156 // See bug: http://crbug.com/30242. 156 // See bug: http://crbug.com/30242.
(...skipping 28 matching lines...) Expand all
185 } 185 }
186 186
187 return stream; 187 return stream;
188 } 188 }
189 189
190 AudioInputStream* AudioManagerBase::MakeAudioInputStream( 190 AudioInputStream* AudioManagerBase::MakeAudioInputStream(
191 const AudioParameters& params, 191 const AudioParameters& params,
192 const std::string& device_id) { 192 const std::string& device_id) {
193 // TODO(miu): Fix ~20 call points across several unit test modules to call 193 // TODO(miu): Fix ~20 call points across several unit test modules to call
194 // this method on the audio thread, then uncomment the following: 194 // this method on the audio thread, then uncomment the following:
195 // DCHECK(message_loop_->BelongsToCurrentThread()); 195 // DCHECK(task_runner_->BelongsToCurrentThread());
196 196
197 if (!params.IsValid() || (params.channels() > kMaxInputChannels) || 197 if (!params.IsValid() || (params.channels() > kMaxInputChannels) ||
198 device_id.empty()) { 198 device_id.empty()) {
199 DLOG(ERROR) << "Audio parameters are invalid for device " << device_id; 199 DLOG(ERROR) << "Audio parameters are invalid for device " << device_id;
200 return NULL; 200 return NULL;
201 } 201 }
202 202
203 if (num_input_streams_ >= max_num_input_streams_) { 203 if (num_input_streams_ >= max_num_input_streams_) {
204 DLOG(ERROR) << "Number of opened input audio streams " 204 DLOG(ERROR) << "Number of opened input audio streams "
205 << num_input_streams_ 205 << num_input_streams_
(...skipping 21 matching lines...) Expand all
227 ++num_input_streams_; 227 ++num_input_streams_;
228 } 228 }
229 229
230 return stream; 230 return stream;
231 } 231 }
232 232
233 AudioOutputStream* AudioManagerBase::MakeAudioOutputStreamProxy( 233 AudioOutputStream* AudioManagerBase::MakeAudioOutputStreamProxy(
234 const AudioParameters& params, 234 const AudioParameters& params,
235 const std::string& device_id, 235 const std::string& device_id,
236 const std::string& input_device_id) { 236 const std::string& input_device_id) {
237 DCHECK(message_loop_->BelongsToCurrentThread()); 237 DCHECK(task_runner_->BelongsToCurrentThread());
238 238
239 // If the caller supplied an empty device id to select the default device, 239 // If the caller supplied an empty device id to select the default device,
240 // we fetch the actual device id of the default device so that the lookup 240 // we fetch the actual device id of the default device so that the lookup
241 // will find the correct device regardless of whether it was opened as 241 // will find the correct device regardless of whether it was opened as
242 // "default" or via the specific id. 242 // "default" or via the specific id.
243 // NOTE: Implementations that don't yet support opening non-default output 243 // NOTE: Implementations that don't yet support opening non-default output
244 // devices may return an empty string from GetDefaultOutputDeviceID(). 244 // devices may return an empty string from GetDefaultOutputDeviceID().
245 std::string output_device_id = device_id.empty() ? 245 std::string output_device_id = device_id.empty() ?
246 GetDefaultOutputDeviceID() : device_id; 246 GetDefaultOutputDeviceID() : device_id;
247 247
(...skipping 77 matching lines...) Expand 10 before | Expand all | Expand 10 after
325 void AudioManagerBase::ReleaseInputStream(AudioInputStream* stream) { 325 void AudioManagerBase::ReleaseInputStream(AudioInputStream* stream) {
326 DCHECK(stream); 326 DCHECK(stream);
327 // TODO(xians) : Have a clearer destruction path for the AudioInputStream. 327 // TODO(xians) : Have a clearer destruction path for the AudioInputStream.
328 --num_input_streams_; 328 --num_input_streams_;
329 delete stream; 329 delete stream;
330 } 330 }
331 331
332 void AudioManagerBase::Shutdown() { 332 void AudioManagerBase::Shutdown() {
333 // Only true when we're sharing the UI message loop with the browser. The UI 333 // Only true when we're sharing the UI message loop with the browser. The UI
334 // loop is no longer running at this time and browser destruction is imminent. 334 // loop is no longer running at this time and browser destruction is imminent.
335 if (message_loop_->BelongsToCurrentThread()) { 335 if (task_runner_->BelongsToCurrentThread()) {
336 ShutdownOnAudioThread(); 336 ShutdownOnAudioThread();
337 } else { 337 } else {
338 message_loop_->PostTask(FROM_HERE, base::Bind( 338 task_runner_->PostTask(FROM_HERE, base::Bind(
339 &AudioManagerBase::ShutdownOnAudioThread, base::Unretained(this))); 339 &AudioManagerBase::ShutdownOnAudioThread, base::Unretained(this)));
340 } 340 }
341 341
342 // Stop() will wait for any posted messages to be processed first. 342 // Stop() will wait for any posted messages to be processed first.
343 audio_thread_.Stop(); 343 audio_thread_.Stop();
344 } 344 }
345 345
346 void AudioManagerBase::ShutdownOnAudioThread() { 346 void AudioManagerBase::ShutdownOnAudioThread() {
347 DCHECK(message_loop_->BelongsToCurrentThread()); 347 DCHECK(task_runner_->BelongsToCurrentThread());
348 348
349 AudioOutputDispatchers::iterator it = output_dispatchers_.begin(); 349 AudioOutputDispatchers::iterator it = output_dispatchers_.begin();
350 for (; it != output_dispatchers_.end(); ++it) { 350 for (; it != output_dispatchers_.end(); ++it) {
351 scoped_refptr<AudioOutputDispatcher>& dispatcher = (*it)->dispatcher; 351 scoped_refptr<AudioOutputDispatcher>& dispatcher = (*it)->dispatcher;
352 dispatcher->Shutdown(); 352 dispatcher->Shutdown();
353 353
354 // All AudioOutputProxies must have been freed before Shutdown is called. 354 // All AudioOutputProxies must have been freed before Shutdown is called.
355 // If they still exist, things will go bad. They have direct pointers to 355 // If they still exist, things will go bad. They have direct pointers to
356 // both physical audio stream objects that belong to the dispatcher as 356 // both physical audio stream objects that belong to the dispatcher as
357 // well as the message loop of the audio thread that will soon go away. 357 // well as the message loop of the audio thread that will soon go away.
358 // So, better crash now than later. 358 // So, better crash now than later.
359 DCHECK(dispatcher->HasOneRef()) << "AudioOutputProxies are still alive"; 359 DCHECK(dispatcher->HasOneRef()) << "AudioOutputProxies are still alive";
360 dispatcher = NULL; 360 dispatcher = NULL;
361 } 361 }
362 362
363 output_dispatchers_.clear(); 363 output_dispatchers_.clear();
364 } 364 }
365 365
366 void AudioManagerBase::AddOutputDeviceChangeListener( 366 void AudioManagerBase::AddOutputDeviceChangeListener(
367 AudioDeviceListener* listener) { 367 AudioDeviceListener* listener) {
368 DCHECK(message_loop_->BelongsToCurrentThread()); 368 DCHECK(task_runner_->BelongsToCurrentThread());
369 output_listeners_.AddObserver(listener); 369 output_listeners_.AddObserver(listener);
370 } 370 }
371 371
372 void AudioManagerBase::RemoveOutputDeviceChangeListener( 372 void AudioManagerBase::RemoveOutputDeviceChangeListener(
373 AudioDeviceListener* listener) { 373 AudioDeviceListener* listener) {
374 DCHECK(message_loop_->BelongsToCurrentThread()); 374 DCHECK(task_runner_->BelongsToCurrentThread());
375 output_listeners_.RemoveObserver(listener); 375 output_listeners_.RemoveObserver(listener);
376 } 376 }
377 377
378 void AudioManagerBase::NotifyAllOutputDeviceChangeListeners() { 378 void AudioManagerBase::NotifyAllOutputDeviceChangeListeners() {
379 DCHECK(message_loop_->BelongsToCurrentThread()); 379 DCHECK(task_runner_->BelongsToCurrentThread());
380 DVLOG(1) << "Firing OnDeviceChange() notifications."; 380 DVLOG(1) << "Firing OnDeviceChange() notifications.";
381 FOR_EACH_OBSERVER(AudioDeviceListener, output_listeners_, OnDeviceChange()); 381 FOR_EACH_OBSERVER(AudioDeviceListener, output_listeners_, OnDeviceChange());
382 } 382 }
383 383
384 AudioParameters AudioManagerBase::GetDefaultOutputStreamParameters() { 384 AudioParameters AudioManagerBase::GetDefaultOutputStreamParameters() {
385 return GetPreferredOutputStreamParameters(GetDefaultOutputDeviceID(), 385 return GetPreferredOutputStreamParameters(GetDefaultOutputDeviceID(),
386 AudioParameters()); 386 AudioParameters());
387 } 387 }
388 388
389 AudioParameters AudioManagerBase::GetOutputStreamParameters( 389 AudioParameters AudioManagerBase::GetOutputStreamParameters(
(...skipping 28 matching lines...) Expand all
418 418
419 return 0; 419 return 0;
420 } 420 }
421 421
422 scoped_ptr<AudioLog> AudioManagerBase::CreateAudioLog( 422 scoped_ptr<AudioLog> AudioManagerBase::CreateAudioLog(
423 AudioLogFactory::AudioComponent component) { 423 AudioLogFactory::AudioComponent component) {
424 return audio_log_factory_->CreateAudioLog(component); 424 return audio_log_factory_->CreateAudioLog(component);
425 } 425 }
426 426
427 void AudioManagerBase::FixWedgedAudio() { 427 void AudioManagerBase::FixWedgedAudio() {
428 DCHECK(message_loop_->BelongsToCurrentThread()); 428 DCHECK(task_runner_->BelongsToCurrentThread());
429 #if defined(OS_MACOSX) 429 #if defined(OS_MACOSX)
430 // Through trial and error, we've found that one way to restore audio after a 430 // Through trial and error, we've found that one way to restore audio after a
431 // hang is to close all outstanding audio streams. Once all streams have been 431 // hang is to close all outstanding audio streams. Once all streams have been
432 // closed, new streams appear to work correctly. 432 // closed, new streams appear to work correctly.
433 // 433 //
434 // In Chrome terms, this means we need to ask all AudioOutputDispatchers to 434 // In Chrome terms, this means we need to ask all AudioOutputDispatchers to
435 // close all Open()'d streams. Once all streams across all dispatchers have 435 // close all Open()'d streams. Once all streams across all dispatchers have
436 // been closed, we ask for all previously Start()'d streams to be recreated 436 // been closed, we ask for all previously Start()'d streams to be recreated
437 // using the same AudioSourceCallback they had before. 437 // using the same AudioSourceCallback they had before.
438 // 438 //
439 // Since this operation takes place on the audio thread we can be sure that no 439 // Since this operation takes place on the audio thread we can be sure that no
440 // other state-changing stream operations will take place while the fix is in 440 // other state-changing stream operations will take place while the fix is in
441 // progress. 441 // progress.
442 // 442 //
443 // See http://crbug.com/160920 for additional details. 443 // See http://crbug.com/160920 for additional details.
444 for (AudioOutputDispatchers::iterator it = output_dispatchers_.begin(); 444 for (AudioOutputDispatchers::iterator it = output_dispatchers_.begin();
445 it != output_dispatchers_.end(); ++it) { 445 it != output_dispatchers_.end(); ++it) {
446 (*it)->dispatcher->CloseStreamsForWedgeFix(); 446 (*it)->dispatcher->CloseStreamsForWedgeFix();
447 } 447 }
448 for (AudioOutputDispatchers::iterator it = output_dispatchers_.begin(); 448 for (AudioOutputDispatchers::iterator it = output_dispatchers_.begin();
449 it != output_dispatchers_.end(); ++it) { 449 it != output_dispatchers_.end(); ++it) {
450 (*it)->dispatcher->RestartStreamsForWedgeFix(); 450 (*it)->dispatcher->RestartStreamsForWedgeFix();
451 } 451 }
452 #endif 452 #endif
453 } 453 }
454 454
455 } // namespace media 455 } // namespace media
OLDNEW
« no previous file with comments | « media/audio/audio_manager_base.h ('k') | media/audio/audio_output_controller.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698