summaryrefslogtreecommitdiffstats
path: root/chromium/media/audio/win/audio_unified_win_unittest.cc
diff options
context:
space:
mode:
Diffstat (limited to 'chromium/media/audio/win/audio_unified_win_unittest.cc')
-rw-r--r--chromium/media/audio/win/audio_unified_win_unittest.cc366
1 files changed, 0 insertions, 366 deletions
diff --git a/chromium/media/audio/win/audio_unified_win_unittest.cc b/chromium/media/audio/win/audio_unified_win_unittest.cc
deleted file mode 100644
index 15573aec76a..00000000000
--- a/chromium/media/audio/win/audio_unified_win_unittest.cc
+++ /dev/null
@@ -1,366 +0,0 @@
-// Copyright (c) 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 "base/command_line.h"
-#include "base/file_util.h"
-#include "base/message_loop/message_loop.h"
-#include "base/path_service.h"
-#include "base/test/test_timeouts.h"
-#include "base/time/time.h"
-#include "base/win/scoped_com_initializer.h"
-#include "media/audio/audio_io.h"
-#include "media/audio/audio_manager.h"
-#include "media/audio/win/audio_unified_win.h"
-#include "media/audio/win/core_audio_util_win.h"
-#include "media/base/channel_mixer.h"
-#include "media/base/media_switches.h"
-#include "testing/gmock/include/gmock/gmock.h"
-#include "testing/gtest/include/gtest/gtest.h"
-
-using ::testing::_;
-using ::testing::AtLeast;
-using ::testing::Between;
-using ::testing::DoAll;
-using ::testing::NotNull;
-using ::testing::Return;
-using base::win::ScopedCOMInitializer;
-
-namespace media {
-
-static const size_t kMaxDeltaSamples = 1000;
-static const char kDeltaTimeMsFileName[] = "unified_delta_times_ms.txt";
-
-// Verify that the delay estimate in the OnMoreIOData() callback is larger
-// than an expected minumum value.
-MATCHER_P(DelayGreaterThan, value, "") {
- return (arg.hardware_delay_bytes > value.hardware_delay_bytes);
-}
-
-// Used to terminate a loop from a different thread than the loop belongs to.
-// |loop| should be a MessageLoopProxy.
-ACTION_P(QuitLoop, loop) {
- loop->PostTask(FROM_HERE, base::MessageLoop::QuitClosure());
-}
-
-class MockUnifiedSourceCallback
- : public AudioOutputStream::AudioSourceCallback {
- public:
- MOCK_METHOD2(OnMoreData, int(AudioBus* audio_bus,
- AudioBuffersState buffers_state));
- MOCK_METHOD3(OnMoreIOData, int(AudioBus* source,
- AudioBus* dest,
- AudioBuffersState buffers_state));
- MOCK_METHOD1(OnError, void(AudioOutputStream* stream));
-};
-
-// AudioOutputStream::AudioSourceCallback implementation which enables audio
-// play-through. It also creates a text file that contains times between two
-// successive callbacks. Units are in milliseconds. This file can be used for
-// off-line analysis of the callback sequence.
-class UnifiedSourceCallback : public AudioOutputStream::AudioSourceCallback {
- public:
- explicit UnifiedSourceCallback()
- : previous_call_time_(base::TimeTicks::Now()),
- text_file_(NULL),
- elements_to_write_(0) {
- delta_times_.reset(new int[kMaxDeltaSamples]);
- }
-
- virtual ~UnifiedSourceCallback() {
- base::FilePath file_name;
- EXPECT_TRUE(PathService::Get(base::DIR_EXE, &file_name));
- file_name = file_name.AppendASCII(kDeltaTimeMsFileName);
-
- EXPECT_TRUE(!text_file_);
- text_file_ = base::OpenFile(file_name, "wt");
- DLOG_IF(ERROR, !text_file_) << "Failed to open log file.";
- VLOG(0) << ">> Output file " << file_name.value() << " has been created.";
-
- // Write the array which contains delta times to a text file.
- size_t elements_written = 0;
- while (elements_written < elements_to_write_) {
- fprintf(text_file_, "%d\n", delta_times_[elements_written]);
- ++elements_written;
- }
- base::CloseFile(text_file_);
- }
-
- virtual int OnMoreData(AudioBus* dest,
- AudioBuffersState buffers_state) {
- NOTREACHED();
- return 0;
- };
-
- virtual int OnMoreIOData(AudioBus* source,
- AudioBus* dest,
- AudioBuffersState buffers_state) {
- // Store time between this callback and the previous callback.
- const base::TimeTicks now_time = base::TimeTicks::Now();
- const int diff = (now_time - previous_call_time_).InMilliseconds();
- previous_call_time_ = now_time;
- if (elements_to_write_ < kMaxDeltaSamples) {
- delta_times_[elements_to_write_] = diff;
- ++elements_to_write_;
- }
-
- // 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()) {
- source->CopyTo(dest);
- } else {
- // A channel mixer is required for converting audio between two different
- // channel layouts.
- if (!channel_mixer_) {
- // Guessing the channel layout will work OK for this unit test.
- // Main thing is that the number of channels is correct.
- ChannelLayout input_layout = GuessChannelLayout(source->channels());
- ChannelLayout output_layout = GuessChannelLayout(dest->channels());
- channel_mixer_.reset(new ChannelMixer(input_layout, output_layout));
- DVLOG(1) << "Remixing channel layout from " << input_layout
- << " to " << output_layout << "; from "
- << source->channels() << " channels to "
- << dest->channels() << " channels.";
- }
- if (channel_mixer_)
- channel_mixer_->Transform(source, dest);
- }
- return source->frames();
- };
-
- virtual void OnError(AudioOutputStream* stream) {
- NOTREACHED();
- }
-
- private:
- base::TimeTicks previous_call_time_;
- scoped_ptr<int[]> delta_times_;
- FILE* text_file_;
- size_t elements_to_write_;
- scoped_ptr<ChannelMixer> channel_mixer_;
-};
-
-// 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()) {
- LOG(WARNING) << "This tests requires Windows Vista or higher.";
- return false;
- }
-
- if (!audio_man->HasAudioOutputDevices()) {
- LOG(WARNING) << "No output devices detected.";
- return false;
- }
-
- if (!audio_man->HasAudioInputDevices()) {
- LOG(WARNING) << "No input devices detected.";
- return false;
- }
-
- return true;
-}
-
-// Convenience class which simplifies creation of a unified AudioOutputStream
-// object.
-class AudioUnifiedStreamWrapper {
- public:
- explicit AudioUnifiedStreamWrapper(AudioManager* audio_manager)
- : com_init_(ScopedCOMInitializer::kMTA),
- audio_man_(audio_manager) {
- // We open up both both sides (input and output) using the preferred
- // set of audio parameters. These parameters corresponds to the mix format
- // that the audio engine uses internally for processing of shared-mode
- // output streams.
- AudioParameters out_params;
- EXPECT_TRUE(SUCCEEDED(CoreAudioUtil::GetPreferredAudioParameters(
- eRender, eConsole, &out_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.
- const int kInputChannels = 2;
-
- params_.Reset(out_params.format(),
- out_params.channel_layout(),
- out_params.channels(),
- kInputChannels,
- out_params.sample_rate(),
- out_params.bits_per_sample(),
- out_params.frames_per_buffer());
- }
-
- ~AudioUnifiedStreamWrapper() {}
-
- // 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(); }
- int sample_rate() const { return params_.sample_rate(); }
- int frames_per_buffer() const { return params_.frames_per_buffer(); }
- int bytes_per_buffer() const { return params_.GetBytesPerBuffer(); }
- int input_channels() const { return params_.input_channels(); }
-
- 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& input_device_id = name.unique_id;
- EXPECT_TRUE(CoreAudioUtil::DeviceIsDefault(eCapture, eConsole,
- input_device_id));
-
- // Create the unified audio I/O stream using the default input device.
- AudioOutputStream* aos = audio_man_->MakeAudioOutputStream(params_,
- "", input_device_id);
- EXPECT_TRUE(aos);
- return aos;
- }
-
- AudioOutputStream* CreateOutputStream(const std::string& input_device_id) {
- // Create the unified audio I/O stream using the specified input device.
- AudioOutputStream* aos = audio_man_->MakeAudioOutputStream(params_,
- "", input_device_id);
- EXPECT_TRUE(aos);
- return aos;
- }
-
- ScopedCOMInitializer com_init_;
- AudioManager* audio_man_;
- AudioParameters params_;
-};
-
-// Convenience method which creates a default WASAPIUnifiedStream object.
-static WASAPIUnifiedStream* CreateDefaultUnifiedStream(
- AudioManager* audio_manager) {
- AudioUnifiedStreamWrapper aosw(audio_manager);
- 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::CreateForTesting());
- if (!CanRunUnifiedAudioTests(audio_manager.get()))
- return;
-
- WASAPIUnifiedStream* wus = CreateDefaultUnifiedStream(audio_manager.get());
- EXPECT_TRUE(wus->Open());
- wus->Close();
-}
-
-// Test Open(), Close() calling sequence for all available capture devices.
-TEST(WASAPIUnifiedStreamTest, OpenAndCloseForAllInputDevices) {
- scoped_ptr<AudioManager> audio_manager(AudioManager::CreateForTesting());
- 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::CreateForTesting());
- if (!CanRunUnifiedAudioTests(audio_manager.get()))
- return;
-
- MockUnifiedSourceCallback source;
- AudioUnifiedStreamWrapper ausw(audio_manager.get());
- WASAPIUnifiedStream* wus = ausw.Create();
-
- EXPECT_TRUE(wus->Open());
- EXPECT_CALL(source, OnError(wus))
- .Times(0);
- EXPECT_CALL(source, OnMoreIOData(NotNull(), NotNull(), _))
- .Times(Between(0, 1))
- .WillOnce(Return(ausw.frames_per_buffer()));
- wus->Start(&source);
- wus->Close();
-}
-
-// Verify that IO callbacks starts as they should.
-TEST(WASAPIUnifiedStreamTest, StartLoopbackAudio) {
- scoped_ptr<AudioManager> audio_manager(AudioManager::CreateForTesting());
- if (!CanRunUnifiedAudioTests(audio_manager.get()))
- return;
-
- base::MessageLoopForUI loop;
- MockUnifiedSourceCallback source;
- AudioUnifiedStreamWrapper ausw(audio_manager.get());
- WASAPIUnifiedStream* wus = ausw.Create();
-
- // Set up expected minimum delay estimation where we use a minium delay
- // which is equal to the sum of render and capture sizes. We can never
- // reach a delay lower than this value.
- AudioBuffersState min_total_audio_delay(0, 2 * ausw.bytes_per_buffer());
-
- EXPECT_TRUE(wus->Open());
- EXPECT_CALL(source, OnError(wus))
- .Times(0);
- EXPECT_CALL(source, OnMoreIOData(
- NotNull(), NotNull(), DelayGreaterThan(min_total_audio_delay)))
- .Times(AtLeast(2))
- .WillOnce(Return(ausw.frames_per_buffer()))
- .WillOnce(DoAll(
- QuitLoop(loop.message_loop_proxy()),
- Return(ausw.frames_per_buffer())));
- wus->Start(&source);
- loop.PostDelayedTask(FROM_HERE, base::MessageLoop::QuitClosure(),
- TestTimeouts::action_timeout());
- loop.Run();
- wus->Stop();
- wus->Close();
-}
-
-// Perform a real-time test in loopback where the recorded audio is echoed
-// back to the speaker. This test allows the user to verify that the audio
-// sounds OK. A text file with name |kDeltaTimeMsFileName| is also generated.
-TEST(WASAPIUnifiedStreamTest, DISABLED_RealTimePlayThrough) {
- scoped_ptr<AudioManager> audio_manager(AudioManager::CreateForTesting());
- if (!CanRunUnifiedAudioTests(audio_manager.get()))
- return;
-
- base::MessageLoopForUI loop;
- UnifiedSourceCallback source;
- WASAPIUnifiedStream* wus = CreateDefaultUnifiedStream(audio_manager.get());
-
- EXPECT_TRUE(wus->Open());
- wus->Start(&source);
- loop.PostDelayedTask(FROM_HERE, base::MessageLoop::QuitClosure(),
- base::TimeDelta::FromMilliseconds(10000));
- loop.Run();
- wus->Close();
-}
-
-} // namespace media