diff options
author | blundell@chromium.org <blundell@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2012-09-07 17:38:54 +0000 |
---|---|---|
committer | blundell@chromium.org <blundell@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2012-09-07 17:38:54 +0000 |
commit | f197e838dea659748724adaffda7a4c9db0c3bc6 (patch) | |
tree | a64f37745baecdd3d123bcef00b1eb355d68e69f /media | |
parent | 392738bbb1f7d1e25429fbf53e70054f71d9101a (diff) | |
download | chromium_src-f197e838dea659748724adaffda7a4c9db0c3bc6.zip chromium_src-f197e838dea659748724adaffda7a4c9db0c3bc6.tar.gz chromium_src-f197e838dea659748724adaffda7a4c9db0c3bc6.tar.bz2 |
Create iOS Audio Manager implementation.
The iOS audio manager supports audio input only (for voice search). This CL
also makes slight changes to audio_input_mac to make it usable on iOS.
BUG=None
Review URL: https://chromiumcodereview.appspot.com/10907110
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@155416 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'media')
-rw-r--r-- | media/audio/ios/audio_manager_ios.h | 55 | ||||
-rw-r--r-- | media/audio/ios/audio_manager_ios.mm | 119 | ||||
-rw-r--r-- | media/audio/ios/audio_manager_ios_unittest.cc | 33 | ||||
-rw-r--r-- | media/audio/mac/audio_input_mac.cc | 15 | ||||
-rw-r--r-- | media/audio/mac/audio_input_mac.h | 6 | ||||
-rw-r--r-- | media/media.gyp | 17 |
6 files changed, 236 insertions, 9 deletions
diff --git a/media/audio/ios/audio_manager_ios.h b/media/audio/ios/audio_manager_ios.h new file mode 100644 index 0000000..55cbe6e --- /dev/null +++ b/media/audio/ios/audio_manager_ios.h @@ -0,0 +1,55 @@ +// Copyright 2012 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. + +#ifndef MEDIA_AUDIO_IOS_AUDIO_MANAGER_IOS_H_ +#define MEDIA_AUDIO_IOS_AUDIO_MANAGER_IOS_H_ + +#include "base/basictypes.h" +#include "media/audio/audio_manager_base.h" + +namespace media { + +class PCMQueueInAudioInputStream; +class PCMQueueOutAudioOutputStream; + +// iOS implementation of the AudioManager singleton. Supports only audio input. +class MEDIA_EXPORT AudioManagerIOS : public AudioManagerBase { + public: + AudioManagerIOS(); + + // Implementation of AudioManager. + virtual bool HasAudioOutputDevices() OVERRIDE; + virtual bool HasAudioInputDevices() OVERRIDE; + virtual AudioOutputStream* MakeAudioOutputStream( + const AudioParameters& params) OVERRIDE; + virtual AudioInputStream* MakeAudioInputStream( + const AudioParameters& params, const std::string& device_id) OVERRIDE; + + // Implementation of AudioManagerBase. + virtual AudioOutputStream* MakeLinearOutputStream( + const AudioParameters& params) OVERRIDE; + virtual AudioOutputStream* MakeLowLatencyOutputStream( + const AudioParameters& params) OVERRIDE; + virtual AudioInputStream* MakeLinearInputStream( + const AudioParameters& params, const std::string& device_id) OVERRIDE; + virtual AudioInputStream* MakeLowLatencyInputStream( + const AudioParameters& params, const std::string& device_id) OVERRIDE; + virtual void ReleaseOutputStream(AudioOutputStream* stream) OVERRIDE; + virtual void ReleaseInputStream(AudioInputStream* stream) OVERRIDE; + + protected: + virtual ~AudioManagerIOS(); + + private: + // Initializes the audio session if necessary. Safe to call multiple times. + // Returns a bool indicating whether the audio session has been successfully + // initialized (either in the current call or in a previous call). + bool InitAudioSession(); + + DISALLOW_COPY_AND_ASSIGN(AudioManagerIOS); +}; + +} // namespace media + +#endif // MEDIA_AUDIO_IOS_AUDIO_MANAGER_IOS_H_ diff --git a/media/audio/ios/audio_manager_ios.mm b/media/audio/ios/audio_manager_ios.mm new file mode 100644 index 0000000..fe93aee --- /dev/null +++ b/media/audio/ios/audio_manager_ios.mm @@ -0,0 +1,119 @@ +// Copyright 2012 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/ios/audio_manager_ios.h" + +#import <AudioToolbox/AudioToolbox.h> + +#include "base/sys_info.h" +#include "media/audio/fake_audio_input_stream.h" +#include "media/audio/mac/audio_input_mac.h" +#include "media/base/limits.h" + +namespace media { + +enum { kMaxInputChannels = 2 }; + +// Initializes the audio session, returning a bool indicating whether +// initialization was successful. Should only be called once. +static bool InitAudioSessionInternal() { + OSStatus error = AudioSessionInitialize(NULL, NULL, NULL, NULL); + DCHECK(error != kAudioSessionAlreadyInitialized); + return error == kAudioSessionNoError; +} + +AudioManagerIOS::AudioManagerIOS() { +} + +AudioManagerIOS::~AudioManagerIOS() { + Shutdown(); +} + +bool AudioManagerIOS::HasAudioOutputDevices() { + return false; +} + +bool AudioManagerIOS::HasAudioInputDevices() { + if (!InitAudioSession()) + return false; + // Note that the |kAudioSessionProperty_AudioInputAvailable| property is a + // 32-bit integer, not a boolean. + UInt32 property_size; + OSStatus error = + AudioSessionGetPropertySize(kAudioSessionProperty_AudioInputAvailable, + &property_size); + if (error != kAudioSessionNoError) + return false; + UInt32 audio_input_is_available = false; + DCHECK(property_size == sizeof(audio_input_is_available)); + error = AudioSessionGetProperty(kAudioSessionProperty_AudioInputAvailable, + &property_size, + &audio_input_is_available); + return error == kAudioSessionNoError ? audio_input_is_available : false; +} + +AudioOutputStream* AudioManagerIOS::MakeAudioOutputStream( + const AudioParameters& params) { + NOTIMPLEMENTED(); // Only input is supported on iOS. + return NULL; +} + +AudioInputStream* AudioManagerIOS::MakeAudioInputStream( + const AudioParameters& params, const std::string& device_id) { + // Current line of iOS devices has only one audio input. + // Ignore the device_id (unittest uses a test value in it). + if (!params.IsValid() || (params.channels() > kMaxInputChannels)) + return NULL; + + if (params.format() == AudioParameters::AUDIO_MOCK) + return FakeAudioInputStream::MakeFakeStream(this, params); + else if (params.format() == AudioParameters::AUDIO_PCM_LINEAR) + return new PCMQueueInAudioInputStream(this, params); + return NULL; +} + +AudioOutputStream* AudioManagerIOS::MakeLinearOutputStream( + const AudioParameters& params) { + NOTIMPLEMENTED(); // Only input is supported on iOS. + return NULL; +} + +AudioOutputStream* AudioManagerIOS::MakeLowLatencyOutputStream( + const AudioParameters& params) { + NOTIMPLEMENTED(); // Only input is supported on iOS. + return NULL; +} + +AudioInputStream* AudioManagerIOS::MakeLinearInputStream( + const AudioParameters& params, const std::string& device_id) { + return MakeAudioInputStream(params, device_id); +} + +AudioInputStream* AudioManagerIOS::MakeLowLatencyInputStream( + const AudioParameters& params, const std::string& device_id) { + NOTIMPLEMENTED(); // Only linear audio input is supported on iOS. + return MakeAudioInputStream(params, device_id); +} + +// Called by the stream when it has been released by calling Close(). +void AudioManagerIOS::ReleaseOutputStream(AudioOutputStream* stream) { + NOTIMPLEMENTED(); // Only input is supported on iOS. +} + +// Called by the stream when it has been released by calling Close(). +void AudioManagerIOS::ReleaseInputStream(AudioInputStream* stream) { + delete stream; +} + +bool AudioManagerIOS::InitAudioSession() { + static const bool kSessionInitialized = InitAudioSessionInternal(); + return kSessionInitialized; +} + +// static +AudioManager* CreateAudioManager() { + return new AudioManagerIOS(); +} + +} // namespace media diff --git a/media/audio/ios/audio_manager_ios_unittest.cc b/media/audio/ios/audio_manager_ios_unittest.cc new file mode 100644 index 0000000..e8013cc --- /dev/null +++ b/media/audio/ios/audio_manager_ios_unittest.cc @@ -0,0 +1,33 @@ +// Copyright 2012 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 "base/basictypes.h" +#include "media/audio/audio_io.h" +#include "media/audio/audio_manager.h" +#include "testing/gtest/include/gtest/gtest.h" + +using namespace media; + +// Test that input is supported and output is not. +TEST(IOSAudioTest, AudioSupport) { + AudioManager* audio_manager = AudioManager::Create(); + ASSERT_TRUE(NULL != audio_manager); + ASSERT_FALSE(audio_manager->HasAudioOutputDevices()); + ASSERT_TRUE(audio_manager->HasAudioInputDevices()); +} + +// Test that input stream can be opened and closed. +TEST(IOSAudioTest, InputStreamOpenAndClose) { + AudioManager* audio_manager = AudioManager::Create(); + ASSERT_TRUE(NULL != audio_manager); + if (!audio_manager->HasAudioInputDevices()) + return; + AudioInputStream* ias = audio_manager->MakeAudioInputStream( + AudioParameters(AudioParameters::AUDIO_PCM_LINEAR, CHANNEL_LAYOUT_STEREO, + 8000, 16, 1024), + std::string("test_device")); + ASSERT_TRUE(NULL != ias); + EXPECT_TRUE(ias->Open()); + ias->Close(); +} diff --git a/media/audio/mac/audio_input_mac.cc b/media/audio/mac/audio_input_mac.cc index c70b80b..fd2d9be 100644 --- a/media/audio/mac/audio_input_mac.cc +++ b/media/audio/mac/audio_input_mac.cc @@ -4,17 +4,20 @@ #include "media/audio/mac/audio_input_mac.h" -#include <CoreServices/CoreServices.h> - #include "base/basictypes.h" #include "base/logging.h" +#include "base/mac/mac_logging.h" +#include "media/audio/audio_manager_base.h" #include "media/audio/audio_util.h" -#include "media/audio/mac/audio_manager_mac.h" + +#if !defined(OS_IOS) +#include <CoreServices/CoreServices.h> +#endif namespace media { PCMQueueInAudioInputStream::PCMQueueInAudioInputStream( - AudioManagerMac* manager, const AudioParameters& params) + AudioManagerBase* manager, const AudioParameters& params) : manager_(manager), callback_(NULL), audio_queue_(NULL), @@ -134,8 +137,8 @@ bool PCMQueueInAudioInputStream::GetAutomaticGainControl() { void PCMQueueInAudioInputStream::HandleError(OSStatus err) { if (callback_) callback_->OnError(this, static_cast<int>(err)); - NOTREACHED() << "error " << GetMacOSStatusErrorString(err) - << " (" << err << ")"; + // This point should never be reached. + OSSTATUS_DCHECK(0, err); } bool PCMQueueInAudioInputStream::SetupBuffers() { diff --git a/media/audio/mac/audio_input_mac.h b/media/audio/mac/audio_input_mac.h index d290bcb..5f52d53 100644 --- a/media/audio/mac/audio_input_mac.h +++ b/media/audio/mac/audio_input_mac.h @@ -14,14 +14,14 @@ namespace media { -class AudioManagerMac; +class AudioManagerBase; // Implementation of AudioInputStream for Mac OS X using the audio queue service // present in OS 10.5 and later. Design reflects PCMQueueOutAudioOutputStream. class PCMQueueInAudioInputStream : public AudioInputStream { public: // Parameters as per AudioManager::MakeAudioInputStream. - PCMQueueInAudioInputStream(AudioManagerMac* manager, + PCMQueueInAudioInputStream(AudioManagerBase* manager, const AudioParameters& params); virtual ~PCMQueueInAudioInputStream(); @@ -65,7 +65,7 @@ class PCMQueueInAudioInputStream : public AudioInputStream { static const int kNumberBuffers = 3; // Manager that owns this stream, used for closing down. - AudioManagerMac* manager_; + AudioManagerBase* manager_; // We use the callback mostly to periodically supply the recorded audio data. AudioInputCallback* callback_; // Structure that holds the stream format details such as bitrate. diff --git a/media/media.gyp b/media/media.gyp index c039481..3cfcc2e 100644 --- a/media/media.gyp +++ b/media/media.gyp @@ -89,6 +89,8 @@ 'audio/fake_audio_input_stream.h', 'audio/fake_audio_output_stream.cc', 'audio/fake_audio_output_stream.h', + 'audio/ios/audio_manager_ios.h', + 'audio/ios/audio_manager_ios.mm', 'audio/linux/alsa_input.cc', 'audio/linux/alsa_input.h', 'audio/linux/alsa_output.cc', @@ -379,6 +381,8 @@ ['include', '^audio/audio_parameters\\.'], ['include', '^audio/fake_audio_input_stream\\.'], ['include', '^audio/fake_audio_output_stream\\.'], + ['include', '^audio/ios/audio_manager_ios\\.'], + ['include', '^base/audio_bus\\.'], ['include', '^base/channel_layout\\.'], ['include', '^base/media\\.h$'], ['include', '^base/media_stub\\.cc$'], @@ -539,6 +543,15 @@ ], }], ], + 'target_conditions': [ + ['OS == "ios"', { + 'sources/': [ + # Pull in specific Mac files for iOS (which have been filtered out + # by file name rules). + ['include', '^audio/mac/audio_input_mac\\.'], + ], + }], + ], }, { 'target_name': 'media_unittests', @@ -566,6 +579,7 @@ 'audio/audio_parameters_unittest.cc', 'audio/audio_util_unittest.cc', 'audio/cross_process_notification_unittest.cc', + 'audio/ios/audio_manager_ios_unittest.cc', 'audio/linux/alsa_output_unittest.cc', 'audio/mac/audio_low_latency_input_mac_unittest.cc', 'audio/mac/audio_output_mac_unittest.cc', @@ -646,7 +660,10 @@ ['OS == "ios"', { 'sources/': [ ['exclude', '.*'], + ['include', '^audio/audio_input_controller_unittest\\.cc$'], + ['include', '^audio/audio_input_unittest\\.cc$'], ['include', '^audio/audio_parameters_unittest\\.cc$'], + ['include', '^audio/ios/audio_manager_ios_unittest\\.cc$'], ['include', '^base/mock_reader\\.h$'], ['include', '^base/run_all_unittests\\.cc$'], ], |