summaryrefslogtreecommitdiffstats
path: root/media/audio/audio_output_controller.cc
diff options
context:
space:
mode:
authortommi@chromium.org <tommi@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2011-12-12 21:50:00 +0000
committertommi@chromium.org <tommi@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2011-12-12 21:50:00 +0000
commit2e77cb39b4b2760c6aa15fb194355cc429f9cb8a (patch)
tree5e90a41a0c15409cee0fca52719187b2025a6dc9 /media/audio/audio_output_controller.cc
parent25db386820026afcaf815b8e9290817146be111e (diff)
downloadchromium_src-2e77cb39b4b2760c6aa15fb194355cc429f9cb8a.zip
chromium_src-2e77cb39b4b2760c6aa15fb194355cc429f9cb8a.tar.gz
chromium_src-2e77cb39b4b2760c6aa15fb194355cc429f9cb8a.tar.bz2
Remove the AudioManager singleton.
Unit tests now instantiate their own AudioManager and can choose to use the default one or provide their own mock implementation without having to worry about conflicting with the singleton. The teardown sequence of the AudioManager and its thread has been cleaned up significantly and I don't think it has been completely tested before as the audio thread was terminated before all objects that belonged to the thread had a chance to do cleanup. The AudioManager unit tests do not use the actual audio thread, so this part seems to have been left out. In Chrome, the AudioManager instance is now owned by BrowserProcessImpl and always constructed on the UI thread. This instance is then shared in the same way that several other 'manager' type objects are shared to 'content' code, via content::ResourceContext. Audio specific classes do though receive a direct pointer to the AudioManager and are required to do proper reference counting if they need to hold onto the instance. I chose to use the ResourceContext rather than direct use of g_browser_process to avoid requiring another singleton when writing relatively simple tests that touch the AudioManager. I added a couple of safeguards to guard against future regressions: - Not more than one instance of the AudioManager should be created. - The AudioManager should not be addrefed by its own thread. This can basically become a circular reference and prevent deterministic shutdown. Reviewers: Of course you're free to review everything, but here's the breakdown in terms of the bare minimum from the standpoint of "Owners approval". I'm asking Henrik to be the main reviewer of the entire patch (sorry!). Henrik: Everything minus the below, but it would be great if you could take a look at the whole thing, specifically media/audio. Pawel: I'd like you to take a generic look at this approach. The key areas as far as the singleton itself goes are in media/audio/audio_manager[_base].* and chrome/browser/browser_process*.* Satish: content/browser/speech/* media/audio/audio_manager_base.* (new reference counting code) Andrew: content/browser/renderer_host/media/* content/renderer/media/webrtc_audio_device_unittest.cc (Owner) Avi: content/browser/renderer_host/render_process_host_impl.cc content/browser/resource_context.* William: chrome/browser/profiles/profile_io_data.cc chrome/browser/browser_process*.* Robert: This is basically a heads up. I hope that I didn't break the OpenBSD implementation, but unfortunately I have no way of knowing for sure. Shijing: Please take a look at AudioManagerLinux. I replaced the set of active streams with a simple counter. BUG=105249 TEST=content_unittests, media_unittests, browser_tests. Review URL: http://codereview.chromium.org/8818012 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@114084 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'media/audio/audio_output_controller.cc')
-rw-r--r--media/audio/audio_output_controller.cc67
1 files changed, 33 insertions, 34 deletions
diff --git a/media/audio/audio_output_controller.cc b/media/audio/audio_output_controller.cc
index b83aa61..d3cca44 100644
--- a/media/audio/audio_output_controller.cc
+++ b/media/audio/audio_output_controller.cc
@@ -21,10 +21,12 @@ const int AudioOutputController::kPauseMark = -1;
const int AudioOutputController::kPollNumAttempts = 3;
const int AudioOutputController::kPollPauseInMilliseconds = 3;
-AudioOutputController::AudioOutputController(EventHandler* handler,
+AudioOutputController::AudioOutputController(AudioManager* audio_manager,
+ EventHandler* handler,
uint32 capacity,
SyncReader* sync_reader)
- : handler_(handler),
+ : audio_manager_(audio_manager),
+ handler_(handler),
stream_(NULL),
volume_(1.0),
state_(kEmpty),
@@ -32,7 +34,8 @@ AudioOutputController::AudioOutputController(EventHandler* handler,
pending_request_(false),
sync_reader_(sync_reader),
message_loop_(NULL),
- number_polling_attempts_left_(0) {
+ number_polling_attempts_left_(0),
+ ALLOW_THIS_IN_INITIALIZER_LIST(weak_this_(this)) {
}
AudioOutputController::~AudioOutputController() {
@@ -42,81 +45,77 @@ AudioOutputController::~AudioOutputController() {
// static
scoped_refptr<AudioOutputController> AudioOutputController::Create(
+ AudioManager* audio_manager,
EventHandler* event_handler,
const AudioParameters& params,
uint32 buffer_capacity) {
-
- if (!params.IsValid())
- return NULL;
-
- if (!AudioManager::GetAudioManager())
+ DCHECK(audio_manager);
+ if (!params.IsValid() || !audio_manager)
return NULL;
// Starts the audio controller thread.
scoped_refptr<AudioOutputController> controller(new AudioOutputController(
- event_handler, buffer_capacity, NULL));
+ audio_manager, event_handler, buffer_capacity, NULL));
- controller->message_loop_ =
- AudioManager::GetAudioManager()->GetMessageLoop();
+ controller->message_loop_ = audio_manager->GetMessageLoop();
controller->message_loop_->PostTask(FROM_HERE, base::Bind(
- &AudioOutputController::DoCreate, controller.get(), params));
+ &AudioOutputController::DoCreate, base::Unretained(controller.get()),
+ params));
return controller;
}
// static
scoped_refptr<AudioOutputController> AudioOutputController::CreateLowLatency(
+ AudioManager* audio_manager,
EventHandler* event_handler,
const AudioParameters& params,
SyncReader* sync_reader) {
-
+ DCHECK(audio_manager);
DCHECK(sync_reader);
- if (!params.IsValid())
- return NULL;
-
- if (!AudioManager::GetAudioManager())
+ if (!params.IsValid() || !audio_manager)
return NULL;
// Starts the audio controller thread.
scoped_refptr<AudioOutputController> controller(new AudioOutputController(
- event_handler, 0, sync_reader));
+ audio_manager, event_handler, 0, sync_reader));
- controller->message_loop_ =
- AudioManager::GetAudioManager()->GetMessageLoop();
+ controller->message_loop_ = audio_manager->GetMessageLoop();
controller->message_loop_->PostTask(FROM_HERE, base::Bind(
- &AudioOutputController::DoCreate, controller.get(), params));
+ &AudioOutputController::DoCreate, base::Unretained(controller.get()),
+ params));
return controller;
}
void AudioOutputController::Play() {
DCHECK(message_loop_);
message_loop_->PostTask(FROM_HERE, base::Bind(
- &AudioOutputController::DoPlay, this));
+ &AudioOutputController::DoPlay, base::Unretained(this)));
}
void AudioOutputController::Pause() {
DCHECK(message_loop_);
message_loop_->PostTask(FROM_HERE, base::Bind(
- &AudioOutputController::DoPause, this));
+ &AudioOutputController::DoPause, base::Unretained(this)));
}
void AudioOutputController::Flush() {
DCHECK(message_loop_);
message_loop_->PostTask(FROM_HERE, base::Bind(
- &AudioOutputController::DoFlush, this));
+ &AudioOutputController::DoFlush, base::Unretained(this)));
}
void AudioOutputController::Close(const base::Closure& closed_task) {
DCHECK(!closed_task.is_null());
DCHECK(message_loop_);
message_loop_->PostTask(FROM_HERE, base::Bind(
- &AudioOutputController::DoClose, this, closed_task));
+ &AudioOutputController::DoClose, base::Unretained(this), closed_task));
}
void AudioOutputController::SetVolume(double volume) {
DCHECK(message_loop_);
message_loop_->PostTask(FROM_HERE, base::Bind(
- &AudioOutputController::DoSetVolume, this, volume));
+ &AudioOutputController::DoSetVolume, base::Unretained(this), volume));
}
void AudioOutputController::EnqueueData(const uint8* data, uint32 size) {
@@ -140,11 +139,8 @@ void AudioOutputController::DoCreate(const AudioParameters& params) {
return;
DCHECK_EQ(kEmpty, state_);
- if (!AudioManager::GetAudioManager())
- return;
-
StopCloseAndClearStream();
- stream_ = AudioManager::GetAudioManager()->MakeAudioOutputStreamProxy(params);
+ stream_ = audio_manager_->MakeAudioOutputStreamProxy(params);
if (!stream_) {
// TODO(hclam): Define error types.
handler_->OnError(this, 0);
@@ -193,7 +189,8 @@ void AudioOutputController::DoPlay() {
number_polling_attempts_left_ = kPollNumAttempts;
message_loop_->PostDelayedTask(
FROM_HERE,
- base::Bind(&AudioOutputController::PollAndStartIfDataReady, this),
+ base::Bind(&AudioOutputController::PollAndStartIfDataReady,
+ weak_this_.GetWeakPtr()),
kPollPauseInMilliseconds);
} else {
StartStream();
@@ -203,7 +200,7 @@ void AudioOutputController::DoPlay() {
void AudioOutputController::PollAndStartIfDataReady() {
DCHECK_EQ(message_loop_, MessageLoop::current());
- // Being paranoic: do nothing if state unexpectedly changed.
+ // Being paranoid: do nothing if state unexpectedly changed.
if ((state_ != kStarting) && (state_ != kPausedWhenStarting))
return;
@@ -220,7 +217,8 @@ void AudioOutputController::PollAndStartIfDataReady() {
} else {
message_loop_->PostDelayedTask(
FROM_HERE,
- base::Bind(&AudioOutputController::PollAndStartIfDataReady, this),
+ base::Bind(&AudioOutputController::PollAndStartIfDataReady,
+ weak_this_.GetWeakPtr()),
kPollPauseInMilliseconds);
}
}
@@ -379,7 +377,7 @@ void AudioOutputController::WaitTillDataReady() {
void AudioOutputController::OnError(AudioOutputStream* stream, int code) {
// Handle error on the audio controller thread.
message_loop_->PostTask(FROM_HERE, base::Bind(
- &AudioOutputController::DoReportError, this, code));
+ &AudioOutputController::DoReportError, base::Unretained(this), code));
}
void AudioOutputController::SubmitOnMoreData_Locked() {
@@ -409,6 +407,7 @@ void AudioOutputController::StopCloseAndClearStream() {
stream_->Stop();
stream_->Close();
stream_ = NULL;
+ weak_this_.InvalidateWeakPtrs();
}
} // namespace media