diff options
author | satish@chromium.org <satish@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2010-07-16 05:58:04 +0000 |
---|---|---|
committer | satish@chromium.org <satish@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2010-07-16 05:58:04 +0000 |
commit | 41bdde54e45a13ff9c9f34b34f8e4f0395e9183b (patch) | |
tree | 5da8b35681a91144827aa8cd38f93814b6c9e8c2 /media/audio/audio_input_controller.cc | |
parent | c60d64ec89c1a8eb5279c38c101ec710c8d931f9 (diff) | |
download | chromium_src-41bdde54e45a13ff9c9f34b34f8e4f0395e9183b.zip chromium_src-41bdde54e45a13ff9c9f34b34f8e4f0395e9183b.tar.gz chromium_src-41bdde54e45a13ff9c9f34b34f8e4f0395e9183b.tar.bz2 |
Add an AudioInputController to help with audio recording.
This is similar to the existing AudioOutputController class used for playback.
Also adds a unit test which uses the new fake audio input stream, so this patch is dependant on http://codereview.chromium.org/2909015
TEST=no new user visible change to test, just some backend recording additions which are unused at the moment.
BUG=none
Review URL: http://codereview.chromium.org/2905010
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@52617 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'media/audio/audio_input_controller.cc')
-rw-r--r-- | media/audio/audio_input_controller.cc | 157 |
1 files changed, 157 insertions, 0 deletions
diff --git a/media/audio/audio_input_controller.cc b/media/audio/audio_input_controller.cc new file mode 100644 index 0000000..666d490 --- /dev/null +++ b/media/audio/audio_input_controller.cc @@ -0,0 +1,157 @@ +// Copyright (c) 2010 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "media/audio/audio_input_controller.h" + +namespace { + +const int kMaxSampleRate = 192000; +const int kMaxBitsPerSample = 64; +const int kMaxInputChannels = 2; +const int kMaxSamplesPerPacket = kMaxSampleRate; + +} // namespace + +namespace media { + +AudioInputController::AudioInputController(EventHandler* handler) + : handler_(handler), + state_(kEmpty), + thread_("AudioInputControllerThread") { +} + +AudioInputController::~AudioInputController() { + DCHECK(kClosed == state_ || kCreated == state_ || kEmpty == state_); +} + +// static +scoped_refptr<AudioInputController> AudioInputController::Create( + EventHandler* event_handler, + AudioManager::Format format, + int channels, + int sample_rate, + int bits_per_sample, + int samples_per_packet) { + if ((channels > kMaxInputChannels) || (channels <= 0) || + (sample_rate > kMaxSampleRate) || (sample_rate <= 0) || + (bits_per_sample > kMaxBitsPerSample) || (bits_per_sample <= 0) || + (samples_per_packet > kMaxSamplesPerPacket) || (samples_per_packet < 0)) + return NULL; + + scoped_refptr<AudioInputController> controller = new AudioInputController( + event_handler); + + // Start the thread and post a task to create the audio input stream. + controller->thread_.Start(); + controller->thread_.message_loop()->PostTask( + FROM_HERE, + NewRunnableMethod(controller.get(), &AudioInputController::DoCreate, + format, channels, sample_rate, bits_per_sample, + samples_per_packet)); + return controller; +} + +void AudioInputController::Record() { + DCHECK(thread_.IsRunning()); + thread_.message_loop()->PostTask( + FROM_HERE, + NewRunnableMethod(this, &AudioInputController::DoRecord)); +} + +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, + NewRunnableMethod(this, &AudioInputController::DoClose)); + thread_.Stop(); +} + +void AudioInputController::DoCreate(AudioManager::Format format, int channels, + int sample_rate, int bits_per_sample, + uint32 samples_per_packet) { + stream_ = AudioManager::GetAudioManager()->MakeAudioInputStream( + format, channels, sample_rate, bits_per_sample, samples_per_packet); + + if (!stream_) { + // TODO(satish): Define error types. + handler_->OnError(this, 0); + return; + } + + if (stream_ && !stream_->Open()) { + stream_->Close(); + stream_ = NULL; + // TODO(satish): Define error types. + handler_->OnError(this, 0); + return; + } + + state_ = kCreated; + handler_->OnCreated(this); +} + +void AudioInputController::DoRecord() { + DCHECK_EQ(thread_.message_loop(), MessageLoop::current()); + + if (state_ != kCreated) + return; + + { + AutoLock auto_lock(lock_); + state_ = kRecording; + } + + stream_->Start(this); + handler_->OnRecording(this); +} + +void AudioInputController::DoClose() { + DCHECK_EQ(thread_.message_loop(), MessageLoop::current()); + DCHECK_NE(kClosed, state_); + + // |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; + } + + // Since the stream is closed at this point there's no other threads reading + // |state_| so we don't need to lock. + state_ = kClosed; +} + +void AudioInputController::DoReportError(int code) { + DCHECK_EQ(thread_.message_loop(), MessageLoop::current()); + handler_->OnError(this, code); +} + +void AudioInputController::OnData(AudioInputStream* stream, const uint8* data, + uint32 size) { + { + AutoLock auto_lock(lock_); + if (state_ != kRecording) + return; + } + handler_->OnData(this, data, size); +} + +void AudioInputController::OnClose(AudioInputStream* stream) { +} + +void AudioInputController::OnError(AudioInputStream* stream, int code) { + // Handle error on the audio controller thread. + thread_.message_loop()->PostTask( + FROM_HERE, + NewRunnableMethod(this, &AudioInputController::DoReportError, code)); +} + +} // namespace media |