diff options
author | henrika@chromium.org <henrika@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2012-02-03 15:02:12 +0000 |
---|---|---|
committer | henrika@chromium.org <henrika@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2012-02-03 15:02:12 +0000 |
commit | 8bc74b44f18a1aad65c56d827b5f8f14c7e123b2 (patch) | |
tree | a681d9990b7cad9885af2f53c607aef045940101 /media/audio/audio_input_controller.cc | |
parent | f0f67736354e2e0162811a2308d7f2853ec81eb9 (diff) | |
download | chromium_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.cc | 129 |
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 |