summaryrefslogtreecommitdiffstats
path: root/media/audio/audio_input_controller.cc
diff options
context:
space:
mode:
authorsatish@chromium.org <satish@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2010-07-16 05:58:04 +0000
committersatish@chromium.org <satish@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2010-07-16 05:58:04 +0000
commit41bdde54e45a13ff9c9f34b34f8e4f0395e9183b (patch)
tree5da8b35681a91144827aa8cd38f93814b6c9e8c2 /media/audio/audio_input_controller.cc
parentc60d64ec89c1a8eb5279c38c101ec710c8d931f9 (diff)
downloadchromium_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.cc157
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