summaryrefslogtreecommitdiffstats
path: root/media
diff options
context:
space:
mode:
authorhenrika@chromium.org <henrika@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2013-06-20 22:41:31 +0000
committerhenrika@chromium.org <henrika@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2013-06-20 22:41:31 +0000
commit1a5f6eacc2e704970d566b236c196645eab7d2aa (patch)
treed64368b52ef3e49b75e34b00ef4aad54f3f99e5a /media
parent0bf6ad7c727a13039c2e26fb7773868f37d55fad (diff)
downloadchromium_src-1a5f6eacc2e704970d566b236c196645eab7d2aa.zip
chromium_src-1a5f6eacc2e704970d566b236c196645eab7d2aa.tar.gz
chromium_src-1a5f6eacc2e704970d566b236c196645eab7d2aa.tar.bz2
Finalizes support of device selection for live-audio on Windows.
BUG=147327 TEST=media_unittests.exe --gtest_filter=WASAPIUni* gtest_also_run_disabled_tests where I've also hard coded uniqe device IDs for non-default capture devices. Also tested misc. live-audio clients where a non-default mic was selected under content/settings Review URL: https://chromiumcodereview.appspot.com/17410006 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@207615 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'media')
-rw-r--r--media/audio/win/audio_unified_win.cc25
-rw-r--r--media/audio/win/audio_unified_win_unittest.cc68
-rw-r--r--media/audio/win/core_audio_util_win.cc21
-rw-r--r--media/audio/win/core_audio_util_win.h7
4 files changed, 100 insertions, 21 deletions
diff --git a/media/audio/win/audio_unified_win.cc b/media/audio/win/audio_unified_win.cc
index a2f2c36..baf025a9 100644
--- a/media/audio/win/audio_unified_win.cc
+++ b/media/audio/win/audio_unified_win.cc
@@ -221,8 +221,16 @@ bool WASAPIUnifiedStream::Open() {
}
AudioParameters hw_input_params;
- hr = CoreAudioUtil::GetPreferredAudioParameters(
- eCapture, eConsole, &hw_input_params);
+ if (input_device_id_ == AudioManagerBase::kDefaultDeviceId) {
+ // Query native parameters for the default capture device.
+ hr = CoreAudioUtil::GetPreferredAudioParameters(
+ eCapture, eConsole, &hw_input_params);
+ } else {
+ // Query native parameters for the capture device given by
+ // |input_device_id_|.
+ hr = CoreAudioUtil::GetPreferredAudioParameters(
+ input_device_id_, &hw_input_params);
+ }
if (FAILED(hr)) {
LOG(ERROR) << "Failed to get preferred input audio parameters.";
return false;
@@ -333,10 +341,15 @@ bool WASAPIUnifiedStream::Open() {
return false;
// Capture side (always event driven but format depends on varispeed or not):
- // TODO(henrika): Open the correct input device with |input_device_id_|,
- // http://crbug.com/147327.
- ScopedComPtr<IAudioClient> audio_input_client =
- CoreAudioUtil::CreateDefaultClient(eCapture, eConsole);
+
+ ScopedComPtr<IAudioClient> audio_input_client;
+ if (input_device_id_ == AudioManagerBase::kDefaultDeviceId) {
+ audio_input_client = CoreAudioUtil::CreateDefaultClient(eCapture, eConsole);
+ } else {
+ ScopedComPtr<IMMDevice> audio_input_device(
+ CoreAudioUtil::CreateDevice(input_device_id_));
+ audio_input_client = CoreAudioUtil::CreateClient(audio_input_device);
+ }
if (!audio_input_client)
return false;
diff --git a/media/audio/win/audio_unified_win_unittest.cc b/media/audio/win/audio_unified_win_unittest.cc
index 807ca7f..772fd50 100644
--- a/media/audio/win/audio_unified_win_unittest.cc
+++ b/media/audio/win/audio_unified_win_unittest.cc
@@ -108,9 +108,9 @@ class UnifiedSourceCallback : public AudioOutputStream::AudioSourceCallback {
// Play out the recorded audio samples in loop back. Perform channel mixing
// if required using a channel mixer which is created only if needed.
- if (source->channels() == dest->channels())
+ if (source->channels() == dest->channels()) {
source->CopyTo(dest);
- else {
+ } else {
// A channel mixer is required for converting audio between two different
// channel layouts.
if (!channel_mixer_) {
@@ -145,7 +145,7 @@ class UnifiedSourceCallback : public AudioOutputStream::AudioSourceCallback {
// Convenience method which ensures that we fulfill all required conditions
// to run unified audio tests on Windows.
static bool CanRunUnifiedAudioTests(AudioManager* audio_man) {
- if (!CoreAudioUtil::IsSupported()) {
+ if (!CoreAudioUtil::IsSupported()) {
LOG(WARNING) << "This tests requires Windows Vista or higher.";
return false;
}
@@ -178,13 +178,6 @@ class AudioUnifiedStreamWrapper {
EXPECT_TRUE(SUCCEEDED(CoreAudioUtil::GetPreferredAudioParameters(
eRender, eConsole, &out_params)));
- // We use the number of channels for the input side to signal that
- // unified audio is requested. The audio manager will create a unified
- // audio backend only if in_params.channels() is larger than zero.M
- AudioParameters in_params;
- EXPECT_TRUE(SUCCEEDED(CoreAudioUtil::GetPreferredAudioParameters(
- eCapture, eConsole, &in_params)));
-
// WebAudio is the only real user of unified audio and it always asks
// for stereo.
// TODO(henrika): extend support to other input channel layouts as well.
@@ -201,11 +194,17 @@ class AudioUnifiedStreamWrapper {
~AudioUnifiedStreamWrapper() {}
- // Creates AudioOutputStream object using default parameters.
+ // Creates an AudioOutputStream object using default parameters.
WASAPIUnifiedStream* Create() {
return static_cast<WASAPIUnifiedStream*> (CreateOutputStream());
}
+ // Creates an AudioOutputStream object using default parameters but a
+ // specified input device.
+ WASAPIUnifiedStream* Create(const std::string device_id) {
+ return static_cast<WASAPIUnifiedStream*> (CreateOutputStream(device_id));
+ }
+
AudioParameters::Format format() const { return params_.format(); }
int channels() const { return params_.channels(); }
int bits_per_sample() const { return params_.bits_per_sample(); }
@@ -216,8 +215,28 @@ class AudioUnifiedStreamWrapper {
private:
AudioOutputStream* CreateOutputStream() {
+ // Get the unique device ID of the default capture device instead of using
+ // AudioManagerBase::kDefaultDeviceId since it provides slightly better
+ // test coverage and will utilize the same code path as if a non default
+ // input device was used.
+ ScopedComPtr<IMMDevice> audio_device =
+ CoreAudioUtil::CreateDefaultDevice(eCapture, eConsole);
+ AudioDeviceName name;
+ EXPECT_TRUE(SUCCEEDED(CoreAudioUtil::GetDeviceName(audio_device, &name)));
+ const std::string& device_id = name.unique_id;
+ EXPECT_TRUE(CoreAudioUtil::DeviceIsDefault(eCapture, eConsole, device_id));
+
+ // Create the unified audio I/O stream using the default input device.
+ AudioOutputStream* aos = audio_man_->MakeAudioOutputStream(params_,
+ device_id);
+ EXPECT_TRUE(aos);
+ return aos;
+ }
+
+ AudioOutputStream* CreateOutputStream(const std::string& device_id) {
+ // Create the unified audio I/O stream using the specified input device.
AudioOutputStream* aos = audio_man_->MakeAudioOutputStream(params_,
- std::string());
+ device_id);
EXPECT_TRUE(aos);
return aos;
}
@@ -234,6 +253,14 @@ static WASAPIUnifiedStream* CreateDefaultUnifiedStream(
return aosw.Create();
}
+// Convenience method which creates a default WASAPIUnifiedStream object but
+// with a specified audio input device.
+static WASAPIUnifiedStream* CreateDefaultUnifiedStream(
+ AudioManager* audio_manager, const std::string& device_id) {
+ AudioUnifiedStreamWrapper aosw(audio_manager);
+ return aosw.Create(device_id);
+}
+
// Test Open(), Close() calling sequence.
TEST(WASAPIUnifiedStreamTest, OpenAndClose) {
scoped_ptr<AudioManager> audio_manager(AudioManager::Create());
@@ -245,6 +272,23 @@ TEST(WASAPIUnifiedStreamTest, OpenAndClose) {
wus->Close();
}
+// Test Open(), Close() calling sequence for all available capture devices.
+TEST(WASAPIUnifiedStreamTest, OpenAndCloseForAllInputDevices) {
+ scoped_ptr<AudioManager> audio_manager(AudioManager::Create());
+ if (!CanRunUnifiedAudioTests(audio_manager.get()))
+ return;
+
+ AudioDeviceNames device_names;
+ audio_manager->GetAudioInputDeviceNames(&device_names);
+ for (AudioDeviceNames::iterator i = device_names.begin();
+ i != device_names.end(); ++i) {
+ WASAPIUnifiedStream* wus = CreateDefaultUnifiedStream(
+ audio_manager.get(), i->unique_id);
+ EXPECT_TRUE(wus->Open());
+ wus->Close();
+ }
+}
+
// Test Open(), Start(), Close() calling sequence.
TEST(WASAPIUnifiedStreamTest, OpenStartAndClose) {
scoped_ptr<AudioManager> audio_manager(AudioManager::Create());
diff --git a/media/audio/win/core_audio_util_win.cc b/media/audio/win/core_audio_util_win.cc
index 38a3d2e..392184b 100644
--- a/media/audio/win/core_audio_util_win.cc
+++ b/media/audio/win/core_audio_util_win.cc
@@ -333,7 +333,7 @@ std::string CoreAudioUtil::GetFriendlyName(const std::string& device_id) {
bool CoreAudioUtil::DeviceIsDefault(EDataFlow flow,
ERole role,
- std::string device_id) {
+ const std::string& device_id) {
DCHECK(IsSupported());
ScopedComPtr<IMMDevice> device = CreateDefaultDevice(flow, role);
if (!device)
@@ -579,6 +579,25 @@ HRESULT CoreAudioUtil::GetPreferredAudioParameters(
return GetPreferredAudioParameters(client, params);
}
+HRESULT CoreAudioUtil::GetPreferredAudioParameters(
+ const std::string& device_id, AudioParameters* params) {
+ DCHECK(IsSupported());
+ ScopedComPtr<IMMDevice> device(CreateDevice(device_id));
+ if (!device) {
+ // Map NULL-pointer to new error code which can be different from the
+ // actual error code. The exact value is not important here.
+ return AUDCLNT_E_DEVICE_INVALIDATED;
+ }
+
+ ScopedComPtr<IAudioClient> client(CreateClient(device));
+ if (!client) {
+ // Map NULL-pointer to new error code which can be different from the
+ // actual error code. The exact value is not important here.
+ return AUDCLNT_E_ENDPOINT_CREATE_FAILED;
+ }
+ return GetPreferredAudioParameters(client, params);
+}
+
HRESULT CoreAudioUtil::SharedModeInitialize(IAudioClient* client,
const WAVEFORMATPCMEX* format,
HANDLE event_handle,
diff --git a/media/audio/win/core_audio_util_win.h b/media/audio/win/core_audio_util_win.h
index 2dac60a..5e2e99f 100644
--- a/media/audio/win/core_audio_util_win.h
+++ b/media/audio/win/core_audio_util_win.h
@@ -75,7 +75,7 @@ class MEDIA_EXPORT CoreAudioUtil {
// Returns true if the provided unique |device_id| corresponds to the current
// default device for the specified by a data-flow direction and role.
static bool DeviceIsDefault(
- EDataFlow flow, ERole role, std::string device_id);
+ EDataFlow flow, ERole role, const std::string& device_id);
// Query if the audio device is a rendering device or a capture device.
static EDataFlow GetDataFlow(IMMDevice* device);
@@ -137,13 +137,16 @@ class MEDIA_EXPORT CoreAudioUtil {
REFERENCE_TIME* device_period);
// Get the preferred audio parameters for the specified |client| or the
- // given direction and role is define by |data_flow| and |role|.
+ // given direction and role is define by |data_flow| and |role|, or the
+ // unique device id given by |device_id|.
// The acquired values should only be utilized for shared mode streamed since
// there are no preferred settings for an exclusive mode stream.
static HRESULT GetPreferredAudioParameters(IAudioClient* client,
AudioParameters* params);
static HRESULT GetPreferredAudioParameters(EDataFlow data_flow, ERole role,
AudioParameters* params);
+ static HRESULT GetPreferredAudioParameters(const std::string& device_id,
+ AudioParameters* params);
// After activating an IAudioClient interface on an audio endpoint device,
// the client must initialize it once, and only once, to initialize the audio