summaryrefslogtreecommitdiffstats
path: root/media/audio/audio_input_controller.cc
diff options
context:
space:
mode:
authorhenrika@chromium.org <henrika@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2012-02-03 15:02:12 +0000
committerhenrika@chromium.org <henrika@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2012-02-03 15:02:12 +0000
commit8bc74b44f18a1aad65c56d827b5f8f14c7e123b2 (patch)
treea681d9990b7cad9885af2f53c607aef045940101 /media/audio/audio_input_controller.cc
parentf0f67736354e2e0162811a2308d7f2853ec81eb9 (diff)
downloadchromium_src-8bc74b44f18a1aad65c56d827b5f8f14c7e123b2.zip
chromium_src-8bc74b44f18a1aad65c56d827b5f8f14c7e123b2.tar.gz
chromium_src-8bc74b44f18a1aad65c56d827b5f8f14c7e123b2.tar.bz2
Removes the AudioInputControllerThread from AudioInputController.
Now runs on the audio-manager thread instead. BUG=none TEST=media_unitest and content_unittests Review URL: https://chromiumcodereview.appspot.com/9307049 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@120330 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'media/audio/audio_input_controller.cc')
-rw-r--r--media/audio/audio_input_controller.cc129
1 files changed, 68 insertions, 61 deletions
diff --git a/media/audio/audio_input_controller.cc b/media/audio/audio_input_controller.cc
index 7bb1d26..824bb17 100644
--- a/media/audio/audio_input_controller.cc
+++ b/media/audio/audio_input_controller.cc
@@ -21,7 +21,9 @@ AudioInputController::Factory* AudioInputController::factory_ = NULL;
AudioInputController::AudioInputController(AudioManager* audio_manager,
EventHandler* handler,
SyncWriter* sync_writer)
- : audio_manager_(audio_manager),
+ : creator_loop_(base::MessageLoopProxy::current()),
+ audio_manager_(audio_manager),
+ message_loop_(audio_manager->GetMessageLoop()),
handler_(handler),
stream_(NULL),
ALLOW_THIS_IN_INITIALIZER_LIST(no_data_timer_(FROM_HERE,
@@ -29,9 +31,8 @@ AudioInputController::AudioInputController(AudioManager* audio_manager,
this,
&AudioInputController::DoReportNoDataError)),
state_(kEmpty),
- thread_("AudioInputControllerThread"),
sync_writer_(sync_writer) {
- DCHECK(audio_manager_); // Fail early.
+ DCHECK(creator_loop_);
}
AudioInputController::~AudioInputController() {
@@ -44,6 +45,7 @@ scoped_refptr<AudioInputController> AudioInputController::Create(
EventHandler* event_handler,
const AudioParameters& params) {
DCHECK(audio_manager);
+
if (!params.IsValid() || (params.channels > kMaxInputChannels))
return NULL;
@@ -54,13 +56,13 @@ scoped_refptr<AudioInputController> AudioInputController::Create(
scoped_refptr<AudioInputController> controller(new AudioInputController(
audio_manager, event_handler, NULL));
- // Start the thread and post a task to create the audio input stream.
- // Pass an empty string to indicate using default device.
+ // Create and open a new audio input stream from the existing
+ // audio-device thread. Use the default audio-input device.
std::string device_id = AudioManagerBase::kDefaultDeviceId;
- controller->thread_.Start();
- controller->thread_.message_loop()->PostTask(FROM_HERE, base::Bind(
- &AudioInputController::DoCreate, controller.get(),
+ controller->message_loop_->PostTask(FROM_HERE, base::Bind(
+ &AudioInputController::DoCreate, base::Unretained(controller.get()),
params, device_id));
+
return controller;
}
@@ -77,47 +79,35 @@ scoped_refptr<AudioInputController> AudioInputController::CreateLowLatency(
if (!params.IsValid() || (params.channels > kMaxInputChannels))
return NULL;
- // Starts the audio controller thread.
+ // Create the AudioInputController object and ensure that it runs on
+ // the audio-manager thread.
scoped_refptr<AudioInputController> controller(new AudioInputController(
audio_manager, event_handler, sync_writer));
- // Start the thread and post a task to create the audio input stream.
- controller->thread_.Start();
- controller->thread_.message_loop()->PostTask(FROM_HERE, base::Bind(
- &AudioInputController::DoCreate, controller.get(), params, device_id));
+ // Create and open a new audio input stream from the existing
+ // audio-device thread. Use the provided audio-input device.
+ controller->message_loop_->PostTask(FROM_HERE, base::Bind(
+ &AudioInputController::DoCreate, base::Unretained(controller.get()),
+ params, device_id));
+
return controller;
}
void AudioInputController::Record() {
- DCHECK(thread_.IsRunning());
- thread_.message_loop()->PostTask(FROM_HERE, base::Bind(
- &AudioInputController::DoRecord, this));
+ message_loop_->PostTask(FROM_HERE, base::Bind(
+ &AudioInputController::DoRecord, base::Unretained(this)));
}
-void AudioInputController::Close() {
- if (!thread_.IsRunning()) {
- // If the thread is not running make sure we are stopped.
- DCHECK_EQ(kClosed, state_);
- return;
- }
-
- // Wait for all tasks to complete on the audio thread.
- thread_.message_loop()->PostTask(FROM_HERE, base::Bind(
- &AudioInputController::DoClose, this));
-
- // A ScopedAllowIO object is required to join the thread when calling Stop.
- // This is because as joining threads may be a long operation it's now
- // not allowed in threads without IO access, which is the case of the IO
- // thread (it is missnamed) being used here. This object overrides
- // temporarily this restriction and should be used only in specific
- // infrequent cases where joining is guaranteed to be fast.
- // Bug: http://code.google.com/p/chromium/issues/detail?id=67806
- base::ThreadRestrictions::ScopedAllowIO allow_io_for_thread_join;
- thread_.Stop();
+void AudioInputController::Close(const base::Closure& closed_task) {
+ DCHECK(!closed_task.is_null());
+ message_loop_->PostTask(FROM_HERE, base::Bind(
+ &AudioInputController::DoClose, base::Unretained(this), closed_task));
}
void AudioInputController::DoCreate(const AudioParameters& params,
const std::string& device_id) {
+ DCHECK(message_loop_->BelongsToCurrentThread());
+
stream_ = audio_manager_->MakeAudioInputStream(params, device_id);
if (!stream_) {
@@ -134,14 +124,15 @@ void AudioInputController::DoCreate(const AudioParameters& params,
return;
}
- thread_.message_loop()->PostTask(FROM_HERE, base::Bind(
+ creator_loop_->PostTask(FROM_HERE, base::Bind(
&AudioInputController::DoResetNoDataTimer, this));
+
state_ = kCreated;
handler_->OnCreated(this);
}
void AudioInputController::DoRecord() {
- DCHECK_EQ(thread_.message_loop(), MessageLoop::current());
+ DCHECK(message_loop_->BelongsToCurrentThread());
if (state_ != kCreated)
return;
@@ -155,39 +146,38 @@ void AudioInputController::DoRecord() {
handler_->OnRecording(this);
}
-void AudioInputController::DoClose() {
- DCHECK_EQ(thread_.message_loop(), MessageLoop::current());
- DCHECK_NE(kClosed, state_);
+void AudioInputController::DoClose(const base::Closure& closed_task) {
+ DCHECK(message_loop_->BelongsToCurrentThread());
- // |stream_| can be null if creating the device failed in DoCreate().
- if (stream_) {
- stream_->Stop();
- stream_->Close();
- // After stream is closed it is destroyed, so don't keep a reference to it.
- stream_ = NULL;
- }
+ if (state_ != kClosed) {
+ DoStopCloseAndClearStream(NULL);
- if (LowLatencyMode()) {
- sync_writer_->Close();
+ if (LowLatencyMode()) {
+ sync_writer_->Close();
+ }
+
+ state_ = kClosed;
}
- // Since the stream is closed at this point there's no other threads reading
- // |state_| so we don't need to lock.
- state_ = kClosed;
+ closed_task.Run();
}
void AudioInputController::DoReportError(int code) {
- DCHECK_EQ(thread_.message_loop(), MessageLoop::current());
+ DCHECK(message_loop_->BelongsToCurrentThread());
handler_->OnError(this, code);
}
void AudioInputController::DoReportNoDataError() {
- DCHECK_EQ(thread_.message_loop(), MessageLoop::current());
- handler_->OnError(this, 0);
+ DCHECK(creator_loop_->BelongsToCurrentThread());
+
+ // Error notifications should be sent on the audio-manager thread.
+ int code = 0;
+ message_loop_->PostTask(FROM_HERE, base::Bind(
+ &AudioInputController::DoReportError, base::Unretained(this), code));
}
void AudioInputController::DoResetNoDataTimer() {
- DCHECK_EQ(thread_.message_loop(), MessageLoop::current());
+ DCHECK(creator_loop_->BelongsToCurrentThread());
no_data_timer_.Reset();
}
@@ -199,7 +189,7 @@ void AudioInputController::OnData(AudioInputStream* stream, const uint8* data,
return;
}
- thread_.message_loop()->PostTask(FROM_HERE, base::Bind(
+ creator_loop_->PostTask(FROM_HERE, base::Bind(
&AudioInputController::DoResetNoDataTimer, this));
// Use SyncSocket if we are in a low-latency mode.
@@ -213,15 +203,32 @@ void AudioInputController::OnData(AudioInputStream* stream, const uint8* data,
}
void AudioInputController::OnClose(AudioInputStream* stream) {
+ DVLOG(1) << "AudioInputController::OnClose()";
// TODO(satish): Sometimes the device driver closes the input stream without
// us asking for it (may be if the device was unplugged?). Check how to handle
// such cases here.
}
void AudioInputController::OnError(AudioInputStream* stream, int code) {
- // Handle error on the audio controller thread.
- thread_.message_loop()->PostTask(FROM_HERE, base::Bind(
- &AudioInputController::DoReportError, this, code));
+ // Handle error on the audio-manager thread.
+ message_loop_->PostTask(FROM_HERE, base::Bind(
+ &AudioInputController::DoReportError, base::Unretained(this), code));
+}
+
+void AudioInputController::DoStopCloseAndClearStream(
+ base::WaitableEvent *done) {
+ DCHECK(message_loop_->BelongsToCurrentThread());
+
+ // Allow calling unconditionally and bail if we don't have a stream to close.
+ if (stream_ != NULL) {
+ stream_->Stop();
+ stream_->Close();
+ stream_ = NULL;
+ }
+
+ // Should be last in the method, do not touch "this" from here on.
+ if (done != NULL)
+ done->Signal();
}
} // namespace media