1d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)// Copyright 2013 The Chromium Authors. All rights reserved. 2d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be 3d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)// found in the LICENSE file. 4d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) 55d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "base/android/build_info.h" 6d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)#include "base/basictypes.h" 71320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci#include "base/files/file_util.h" 8d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)#include "base/memory/scoped_ptr.h" 9d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)#include "base/message_loop/message_loop.h" 10d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)#include "base/path_service.h" 11a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)#include "base/run_loop.h" 12d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)#include "base/strings/stringprintf.h" 13d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)#include "base/synchronization/lock.h" 14d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)#include "base/synchronization/waitable_event.h" 15d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)#include "base/test/test_timeouts.h" 16d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)#include "base/time/time.h" 17d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)#include "build/build_config.h" 18d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)#include "media/audio/android/audio_manager_android.h" 19d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)#include "media/audio/audio_io.h" 20d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)#include "media/audio/audio_manager_base.h" 215d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "media/audio/mock_audio_source_callback.h" 22d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)#include "media/base/decoder_buffer.h" 23d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)#include "media/base/seekable_buffer.h" 24d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)#include "media/base/test_data_util.h" 25d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)#include "testing/gmock/include/gmock/gmock.h" 26d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)#include "testing/gtest/include/gtest/gtest.h" 27d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) 28d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)using ::testing::_; 29d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)using ::testing::AtLeast; 30d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)using ::testing::DoAll; 31d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)using ::testing::Invoke; 32d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)using ::testing::NotNull; 33d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)using ::testing::Return; 34d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) 35d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)namespace media { 36d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) 37d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)ACTION_P3(CheckCountAndPostQuitTask, count, limit, loop) { 38d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) if (++*count >= limit) { 39d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) loop->PostTask(FROM_HERE, base::MessageLoop::QuitClosure()); 40d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) } 41d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)} 42d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) 43d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)static const char kSpeechFile_16b_s_48k[] = "speech_16b_stereo_48kHz.raw"; 44d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)static const char kSpeechFile_16b_m_48k[] = "speech_16b_mono_48kHz.raw"; 45d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)static const char kSpeechFile_16b_s_44k[] = "speech_16b_stereo_44kHz.raw"; 46d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)static const char kSpeechFile_16b_m_44k[] = "speech_16b_mono_44kHz.raw"; 47d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) 48d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)static const float kCallbackTestTimeMs = 2000.0; 49d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)static const int kBitsPerSample = 16; 50d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)static const int kBytesPerSample = kBitsPerSample / 8; 51d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) 52d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)// Converts AudioParameters::Format enumerator to readable string. 53d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)static std::string FormatToString(AudioParameters::Format format) { 54d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) switch (format) { 55d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) case AudioParameters::AUDIO_PCM_LINEAR: 56d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) return std::string("AUDIO_PCM_LINEAR"); 57d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) case AudioParameters::AUDIO_PCM_LOW_LATENCY: 58d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) return std::string("AUDIO_PCM_LOW_LATENCY"); 59d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) case AudioParameters::AUDIO_FAKE: 60d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) return std::string("AUDIO_FAKE"); 61d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) case AudioParameters::AUDIO_LAST_FORMAT: 62d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) return std::string("AUDIO_LAST_FORMAT"); 63d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) default: 64d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) return std::string(); 65d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) } 66d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)} 67d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) 68d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)// Converts ChannelLayout enumerator to readable string. Does not include 69d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)// multi-channel cases since these layouts are not supported on Android. 70d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)static std::string LayoutToString(ChannelLayout channel_layout) { 71d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) switch (channel_layout) { 72d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) case CHANNEL_LAYOUT_NONE: 73d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) return std::string("CHANNEL_LAYOUT_NONE"); 74d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) case CHANNEL_LAYOUT_MONO: 75d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) return std::string("CHANNEL_LAYOUT_MONO"); 76d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) case CHANNEL_LAYOUT_STEREO: 77d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) return std::string("CHANNEL_LAYOUT_STEREO"); 78d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) case CHANNEL_LAYOUT_UNSUPPORTED: 79d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) default: 80d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) return std::string("CHANNEL_LAYOUT_UNSUPPORTED"); 81d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) } 82d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)} 83d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) 84d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)static double ExpectedTimeBetweenCallbacks(AudioParameters params) { 85d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) return (base::TimeDelta::FromMicroseconds( 86d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) params.frames_per_buffer() * base::Time::kMicrosecondsPerSecond / 87d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) static_cast<double>(params.sample_rate()))).InMillisecondsF(); 88d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)} 89d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) 905d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// Helper method which verifies that the device list starts with a valid 915d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// default device name followed by non-default device names. 925d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)static void CheckDeviceNames(const AudioDeviceNames& device_names) { 935d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) VLOG(2) << "Got " << device_names.size() << " audio devices."; 945d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if (device_names.empty()) { 955d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) // Log a warning so we can see the status on the build bots. No need to 965d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) // break the test though since this does successfully test the code and 975d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) // some failure cases. 985d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) LOG(WARNING) << "No input devices detected"; 995d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) return; 1005d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) } 1015d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 1025d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) AudioDeviceNames::const_iterator it = device_names.begin(); 1035d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 1045d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) // The first device in the list should always be the default device. 1055d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) EXPECT_EQ(std::string(AudioManagerBase::kDefaultDeviceName), 1065d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) it->device_name); 1075d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) EXPECT_EQ(std::string(AudioManagerBase::kDefaultDeviceId), it->unique_id); 1085d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) ++it; 1095d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 1105d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) // Other devices should have non-empty name and id and should not contain 1115d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) // default name or id. 1125d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) while (it != device_names.end()) { 1135d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) EXPECT_FALSE(it->device_name.empty()); 1145d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) EXPECT_FALSE(it->unique_id.empty()); 1155d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) VLOG(2) << "Device ID(" << it->unique_id 1165d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) << "), label: " << it->device_name; 1175d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) EXPECT_NE(std::string(AudioManagerBase::kDefaultDeviceName), 1185d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) it->device_name); 1195d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) EXPECT_NE(std::string(AudioManagerBase::kDefaultDeviceId), 1205d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) it->unique_id); 1215d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) ++it; 1225d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) } 1235d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)} 1245d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 1255d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// We clear the data bus to ensure that the test does not cause noise. 1265d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)static int RealOnMoreData(AudioBus* dest, AudioBuffersState buffers_state) { 1275d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) dest->Zero(); 1285d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) return dest->frames(); 1295d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)} 1305d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 131d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)std::ostream& operator<<(std::ostream& os, const AudioParameters& params) { 132d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) using namespace std; 133d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) os << endl << "format: " << FormatToString(params.format()) << endl 134d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) << "channel layout: " << LayoutToString(params.channel_layout()) << endl 135d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) << "sample rate: " << params.sample_rate() << endl 136d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) << "bits per sample: " << params.bits_per_sample() << endl 137d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) << "frames per buffer: " << params.frames_per_buffer() << endl 138d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) << "channels: " << params.channels() << endl 139d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) << "bytes per buffer: " << params.GetBytesPerBuffer() << endl 140d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) << "bytes per second: " << params.GetBytesPerSecond() << endl 141d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) << "bytes per frame: " << params.GetBytesPerFrame() << endl 1425d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) << "chunk size in ms: " << ExpectedTimeBetweenCallbacks(params) << endl 1435d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) << "echo_canceller: " 1445d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) << (params.effects() & AudioParameters::ECHO_CANCELLER); 145d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) return os; 146d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)} 147d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) 148d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)// Gmock implementation of AudioInputStream::AudioInputCallback. 149d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)class MockAudioInputCallback : public AudioInputStream::AudioInputCallback { 150d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) public: 1516d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles) MOCK_METHOD4(OnData, 152d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) void(AudioInputStream* stream, 1536d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles) const AudioBus* src, 154d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) uint32 hardware_delay_bytes, 155d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) double volume)); 156d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) MOCK_METHOD1(OnError, void(AudioInputStream* stream)); 157d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)}; 158d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) 159d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)// Implements AudioOutputStream::AudioSourceCallback and provides audio data 160d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)// by reading from a data file. 161d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)class FileAudioSource : public AudioOutputStream::AudioSourceCallback { 162d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) public: 163d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) explicit FileAudioSource(base::WaitableEvent* event, const std::string& name) 164d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) : event_(event), pos_(0) { 165d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) // Reads a test file from media/test/data directory and stores it in 166d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) // a DecoderBuffer. 167d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) file_ = ReadTestDataFile(name); 168d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) 169d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) // Log the name of the file which is used as input for this test. 170d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) base::FilePath file_path = GetTestDataFilePath(name); 171f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) VLOG(0) << "Reading from file: " << file_path.value().c_str(); 172d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) } 173d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) 174d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) virtual ~FileAudioSource() {} 175d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) 176d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) // AudioOutputStream::AudioSourceCallback implementation. 177d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) 178d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) // Use samples read from a data file and fill up the audio buffer 179d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) // provided to us in the callback. 180d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) virtual int OnMoreData(AudioBus* audio_bus, 181d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) AudioBuffersState buffers_state) OVERRIDE { 182d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) bool stop_playing = false; 183d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) int max_size = 184d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) audio_bus->frames() * audio_bus->channels() * kBytesPerSample; 185d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) 186d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) // Adjust data size and prepare for end signal if file has ended. 187d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) if (pos_ + max_size > file_size()) { 188d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) stop_playing = true; 189d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) max_size = file_size() - pos_; 190d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) } 191d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) 192d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) // File data is stored as interleaved 16-bit values. Copy data samples from 193d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) // the file and deinterleave to match the audio bus format. 194d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) // FromInterleaved() will zero out any unfilled frames when there is not 195d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) // sufficient data remaining in the file to fill up the complete frame. 196d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) int frames = max_size / (audio_bus->channels() * kBytesPerSample); 197d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) if (max_size) { 198d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) audio_bus->FromInterleaved(file_->data() + pos_, frames, kBytesPerSample); 199d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) pos_ += max_size; 200d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) } 201d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) 202d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) // Set event to ensure that the test can stop when the file has ended. 203d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) if (stop_playing) 204d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) event_->Signal(); 205d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) 206d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) return frames; 207d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) } 208d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) 209d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) virtual void OnError(AudioOutputStream* stream) OVERRIDE {} 210d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) 211d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) int file_size() { return file_->data_size(); } 212d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) 213d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) private: 214d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) base::WaitableEvent* event_; 215d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) int pos_; 216d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) scoped_refptr<DecoderBuffer> file_; 217d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) 218d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) DISALLOW_COPY_AND_ASSIGN(FileAudioSource); 219d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)}; 220d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) 221d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)// Implements AudioInputStream::AudioInputCallback and writes the recorded 222d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)// audio data to a local output file. Note that this implementation should 223d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)// only be used for manually invoked and evaluated tests, hence the created 224d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)// file will not be destroyed after the test is done since the intention is 225d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)// that it shall be available for off-line analysis. 226d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)class FileAudioSink : public AudioInputStream::AudioInputCallback { 227d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) public: 228d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) explicit FileAudioSink(base::WaitableEvent* event, 229d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) const AudioParameters& params, 230d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) const std::string& file_name) 231d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) : event_(event), params_(params) { 232d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) // Allocate space for ~10 seconds of data. 233d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) const int kMaxBufferSize = 10 * params.GetBytesPerSecond(); 234d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) buffer_.reset(new media::SeekableBuffer(0, kMaxBufferSize)); 235d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) 236d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) // Open up the binary file which will be written to in the destructor. 237d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) base::FilePath file_path; 238d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) EXPECT_TRUE(PathService::Get(base::DIR_SOURCE_ROOT, &file_path)); 239d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) file_path = file_path.AppendASCII(file_name.c_str()); 240a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) binary_file_ = base::OpenFile(file_path, "wb"); 241d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) DLOG_IF(ERROR, !binary_file_) << "Failed to open binary PCM data file."; 242f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) VLOG(0) << "Writing to file: " << file_path.value().c_str(); 243d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) } 244d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) 245d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) virtual ~FileAudioSink() { 246d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) int bytes_written = 0; 247d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) while (bytes_written < buffer_->forward_capacity()) { 248d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) const uint8* chunk; 249d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) int chunk_size; 250d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) 251d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) // Stop writing if no more data is available. 252d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) if (!buffer_->GetCurrentChunk(&chunk, &chunk_size)) 253d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) break; 254d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) 255d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) // Write recorded data chunk to the file and prepare for next chunk. 256d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) // TODO(henrika): use file_util:: instead. 257d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) fwrite(chunk, 1, chunk_size, binary_file_); 258d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) buffer_->Seek(chunk_size); 259d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) bytes_written += chunk_size; 260d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) } 261a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) base::CloseFile(binary_file_); 262d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) } 263d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) 264d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) // AudioInputStream::AudioInputCallback implementation. 265d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) virtual void OnData(AudioInputStream* stream, 2666d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles) const AudioBus* src, 267d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) uint32 hardware_delay_bytes, 268d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) double volume) OVERRIDE { 2696d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles) const int num_samples = src->frames() * src->channels(); 2706d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles) scoped_ptr<int16> interleaved(new int16[num_samples]); 2716d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles) const int bytes_per_sample = sizeof(*interleaved); 2726d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles) src->ToInterleaved(src->frames(), bytes_per_sample, interleaved.get()); 2736d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles) 274d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) // Store data data in a temporary buffer to avoid making blocking 275d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) // fwrite() calls in the audio callback. The complete buffer will be 276d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) // written to file in the destructor. 2776d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles) const int size = bytes_per_sample * num_samples; 2786d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles) if (!buffer_->Append((const uint8*)interleaved.get(), size)) 279d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) event_->Signal(); 280d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) } 281d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) 282d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) virtual void OnError(AudioInputStream* stream) OVERRIDE {} 283d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) 284d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) private: 285d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) base::WaitableEvent* event_; 286d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) AudioParameters params_; 287d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) scoped_ptr<media::SeekableBuffer> buffer_; 288d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) FILE* binary_file_; 289d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) 290d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) DISALLOW_COPY_AND_ASSIGN(FileAudioSink); 291d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)}; 292d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) 293d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)// Implements AudioInputCallback and AudioSourceCallback to support full 294d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)// duplex audio where captured samples are played out in loopback after 295d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)// reading from a temporary FIFO storage. 296d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)class FullDuplexAudioSinkSource 297d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) : public AudioInputStream::AudioInputCallback, 298d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) public AudioOutputStream::AudioSourceCallback { 299d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) public: 300d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) explicit FullDuplexAudioSinkSource(const AudioParameters& params) 301d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) : params_(params), 302d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) previous_time_(base::TimeTicks::Now()), 303d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) started_(false) { 304d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) // Start with a reasonably small FIFO size. It will be increased 305d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) // dynamically during the test if required. 306d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) fifo_.reset(new media::SeekableBuffer(0, 2 * params.GetBytesPerBuffer())); 307d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) buffer_.reset(new uint8[params_.GetBytesPerBuffer()]); 308d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) } 309d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) 310d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) virtual ~FullDuplexAudioSinkSource() {} 311d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) 312d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) // AudioInputStream::AudioInputCallback implementation 313d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) virtual void OnData(AudioInputStream* stream, 3146d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles) const AudioBus* src, 315d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) uint32 hardware_delay_bytes, 316d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) double volume) OVERRIDE { 317d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) const base::TimeTicks now_time = base::TimeTicks::Now(); 318d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) const int diff = (now_time - previous_time_).InMilliseconds(); 319d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) 3206d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles) EXPECT_EQ(params_.bits_per_sample(), 16); 3216d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles) const int num_samples = src->frames() * src->channels(); 3226d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles) scoped_ptr<int16> interleaved(new int16[num_samples]); 3236d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles) const int bytes_per_sample = sizeof(*interleaved); 3246d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles) src->ToInterleaved(src->frames(), bytes_per_sample, interleaved.get()); 3256d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles) const int size = bytes_per_sample * num_samples; 3266d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles) 327d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) base::AutoLock lock(lock_); 328d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) if (diff > 1000) { 329d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) started_ = true; 330d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) previous_time_ = now_time; 331d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) 332d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) // Log out the extra delay added by the FIFO. This is a best effort 333d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) // estimate. We might be +- 10ms off here. 334d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) int extra_fifo_delay = 335d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) static_cast<int>(BytesToMilliseconds(fifo_->forward_bytes() + size)); 336d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) DVLOG(1) << extra_fifo_delay; 337d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) } 338d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) 339d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) // We add an initial delay of ~1 second before loopback starts to ensure 340d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) // a stable callback sequence and to avoid initial bursts which might add 341d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) // to the extra FIFO delay. 342d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) if (!started_) 343d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) return; 344d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) 345d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) // Append new data to the FIFO and extend the size if the max capacity 346d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) // was exceeded. Flush the FIFO when extended just in case. 3476d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles) if (!fifo_->Append((const uint8*)interleaved.get(), size)) { 348d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) fifo_->set_forward_capacity(2 * fifo_->forward_capacity()); 349d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) fifo_->Clear(); 350d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) } 351d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) } 352d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) 353d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) virtual void OnError(AudioInputStream* stream) OVERRIDE {} 354d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) 355d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) // AudioOutputStream::AudioSourceCallback implementation 356d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) virtual int OnMoreData(AudioBus* dest, 357d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) AudioBuffersState buffers_state) OVERRIDE { 358d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) const int size_in_bytes = 359d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) (params_.bits_per_sample() / 8) * dest->frames() * dest->channels(); 360d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) EXPECT_EQ(size_in_bytes, params_.GetBytesPerBuffer()); 361d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) 362d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) base::AutoLock lock(lock_); 363d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) 364d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) // We add an initial delay of ~1 second before loopback starts to ensure 365d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) // a stable callback sequences and to avoid initial bursts which might add 366d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) // to the extra FIFO delay. 367d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) if (!started_) { 368d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) dest->Zero(); 369d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) return dest->frames(); 370d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) } 371d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) 372d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) // Fill up destination with zeros if the FIFO does not contain enough 373d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) // data to fulfill the request. 374d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) if (fifo_->forward_bytes() < size_in_bytes) { 375d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) dest->Zero(); 376d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) } else { 377d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) fifo_->Read(buffer_.get(), size_in_bytes); 378d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) dest->FromInterleaved( 379d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) buffer_.get(), dest->frames(), params_.bits_per_sample() / 8); 380d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) } 381d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) 382d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) return dest->frames(); 383d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) } 384d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) 385d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) virtual void OnError(AudioOutputStream* stream) OVERRIDE {} 386d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) 387d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) private: 388d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) // Converts from bytes to milliseconds given number of bytes and existing 389d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) // audio parameters. 390d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) double BytesToMilliseconds(int bytes) const { 391d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) const int frames = bytes / params_.GetBytesPerFrame(); 392d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) return (base::TimeDelta::FromMicroseconds( 393d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) frames * base::Time::kMicrosecondsPerSecond / 394d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) static_cast<double>(params_.sample_rate()))).InMillisecondsF(); 395d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) } 396d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) 397d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) AudioParameters params_; 398d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) base::TimeTicks previous_time_; 399d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) base::Lock lock_; 400d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) scoped_ptr<media::SeekableBuffer> fifo_; 401d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) scoped_ptr<uint8[]> buffer_; 402d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) bool started_; 403d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) 404d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) DISALLOW_COPY_AND_ASSIGN(FullDuplexAudioSinkSource); 405d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)}; 406d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) 4075d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// Test fixture class for tests which only exercise the output path. 4085d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)class AudioAndroidOutputTest : public testing::Test { 409d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) public: 410a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) AudioAndroidOutputTest() 411a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) : loop_(new base::MessageLoopForUI()), 412a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) audio_manager_(AudioManager::CreateForTesting()), 413a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) audio_output_stream_(NULL) { 414d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) } 415d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) 416a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) virtual ~AudioAndroidOutputTest() { 417a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) } 418d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) 419a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) protected: 420d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) AudioManager* audio_manager() { return audio_manager_.get(); } 421d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) base::MessageLoopForUI* loop() { return loop_.get(); } 422a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) const AudioParameters& audio_output_parameters() { 423a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) return audio_output_parameters_; 424a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) } 425a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) 426a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) // Synchronously runs the provided callback/closure on the audio thread. 427a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) void RunOnAudioThread(const base::Closure& closure) { 428a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) if (!audio_manager()->GetTaskRunner()->BelongsToCurrentThread()) { 429a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) base::WaitableEvent event(false, false); 430a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) audio_manager()->GetTaskRunner()->PostTask( 431a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) FROM_HERE, 432a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) base::Bind(&AudioAndroidOutputTest::RunOnAudioThreadImpl, 433a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) base::Unretained(this), 434a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) closure, 435a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) &event)); 436a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) event.Wait(); 437a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) } else { 438a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) closure.Run(); 439a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) } 440a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) } 441a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) 442a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) void RunOnAudioThreadImpl(const base::Closure& closure, 443a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) base::WaitableEvent* event) { 444a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) DCHECK(audio_manager()->GetTaskRunner()->BelongsToCurrentThread()); 445a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) closure.Run(); 446a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) event->Signal(); 447a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) } 448a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) 449a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) void GetDefaultOutputStreamParametersOnAudioThread() { 450a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) RunOnAudioThread( 451a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) base::Bind(&AudioAndroidOutputTest::GetDefaultOutputStreamParameters, 452a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) base::Unretained(this))); 453a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) } 454a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) 455a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) void MakeAudioOutputStreamOnAudioThread(const AudioParameters& params) { 456a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) RunOnAudioThread( 457a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) base::Bind(&AudioAndroidOutputTest::MakeOutputStream, 458a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) base::Unretained(this), 459a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) params)); 460a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) } 461d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) 462a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) void OpenAndCloseAudioOutputStreamOnAudioThread() { 463a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) RunOnAudioThread( 464a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) base::Bind(&AudioAndroidOutputTest::OpenAndClose, 465a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) base::Unretained(this))); 466a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) } 467a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) 468a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) void OpenAndStartAudioOutputStreamOnAudioThread( 469a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) AudioOutputStream::AudioSourceCallback* source) { 470a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) RunOnAudioThread( 471a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) base::Bind(&AudioAndroidOutputTest::OpenAndStart, 472a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) base::Unretained(this), 473a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) source)); 474a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) } 475a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) 476a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) void StopAndCloseAudioOutputStreamOnAudioThread() { 477a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) RunOnAudioThread( 478a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) base::Bind(&AudioAndroidOutputTest::StopAndClose, 479a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) base::Unretained(this))); 480d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) } 481d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) 482d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) double AverageTimeBetweenCallbacks(int num_callbacks) const { 483d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) return ((end_time_ - start_time_) / static_cast<double>(num_callbacks - 1)) 484d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) .InMillisecondsF(); 485d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) } 486d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) 4875d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) void StartOutputStreamCallbacks(const AudioParameters& params) { 488d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) double expected_time_between_callbacks_ms = 489d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) ExpectedTimeBetweenCallbacks(params); 490d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) const int num_callbacks = 491d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) (kCallbackTestTimeMs / expected_time_between_callbacks_ms); 492a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) MakeAudioOutputStreamOnAudioThread(params); 493d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) 494d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) int count = 0; 4955d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) MockAudioSourceCallback source; 496d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) 4975d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) EXPECT_CALL(source, OnMoreData(NotNull(), _)) 498d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) .Times(AtLeast(num_callbacks)) 499d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) .WillRepeatedly( 5005d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) DoAll(CheckCountAndPostQuitTask(&count, num_callbacks, loop()), 5015d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) Invoke(RealOnMoreData))); 502a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) EXPECT_CALL(source, OnError(audio_output_stream_)).Times(0); 503d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) 504a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) OpenAndStartAudioOutputStreamOnAudioThread(&source); 505a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) 506d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) start_time_ = base::TimeTicks::Now(); 507d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) loop()->Run(); 508d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) end_time_ = base::TimeTicks::Now(); 509a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) 510a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) StopAndCloseAudioOutputStreamOnAudioThread(); 511d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) 512d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) double average_time_between_callbacks_ms = 513d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) AverageTimeBetweenCallbacks(num_callbacks); 514f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) VLOG(0) << "expected time between callbacks: " 515f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) << expected_time_between_callbacks_ms << " ms"; 516f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) VLOG(0) << "average time between callbacks: " 517f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) << average_time_between_callbacks_ms << " ms"; 518d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) EXPECT_GE(average_time_between_callbacks_ms, 519d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) 0.70 * expected_time_between_callbacks_ms); 520d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) EXPECT_LE(average_time_between_callbacks_ms, 5216e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) 1.50 * expected_time_between_callbacks_ms); 522d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) } 523d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) 524a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) void GetDefaultOutputStreamParameters() { 525a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) DCHECK(audio_manager()->GetTaskRunner()->BelongsToCurrentThread()); 526a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) audio_output_parameters_ = 527a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) audio_manager()->GetDefaultOutputStreamParameters(); 528a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) EXPECT_TRUE(audio_output_parameters_.IsValid()); 529a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) } 530a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) 531a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) void MakeOutputStream(const AudioParameters& params) { 532a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) DCHECK(audio_manager()->GetTaskRunner()->BelongsToCurrentThread()); 533a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) audio_output_stream_ = audio_manager()->MakeAudioOutputStream( 534a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) params, std::string()); 535a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) EXPECT_TRUE(audio_output_stream_); 536a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) } 537a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) 538a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) void OpenAndClose() { 539a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) DCHECK(audio_manager()->GetTaskRunner()->BelongsToCurrentThread()); 540a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) EXPECT_TRUE(audio_output_stream_->Open()); 541a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) audio_output_stream_->Close(); 542a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) audio_output_stream_ = NULL; 543a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) } 544a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) 545a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) void OpenAndStart(AudioOutputStream::AudioSourceCallback* source) { 546a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) DCHECK(audio_manager()->GetTaskRunner()->BelongsToCurrentThread()); 547a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) EXPECT_TRUE(audio_output_stream_->Open()); 548a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) audio_output_stream_->Start(source); 549a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) } 550a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) 551a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) void StopAndClose() { 552a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) DCHECK(audio_manager()->GetTaskRunner()->BelongsToCurrentThread()); 553a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) audio_output_stream_->Stop(); 554a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) audio_output_stream_->Close(); 555a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) audio_output_stream_ = NULL; 556a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) } 557a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) 5585d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) scoped_ptr<base::MessageLoopForUI> loop_; 5595d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) scoped_ptr<AudioManager> audio_manager_; 560a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) AudioParameters audio_output_parameters_; 561a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) AudioOutputStream* audio_output_stream_; 5625d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) base::TimeTicks start_time_; 5635d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) base::TimeTicks end_time_; 5645d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 5655d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) private: 5665d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) DISALLOW_COPY_AND_ASSIGN(AudioAndroidOutputTest); 5675d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)}; 5685d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 5695d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// AudioRecordInputStream should only be created on Jelly Bean and higher. This 5705d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// ensures we only test against the AudioRecord path when that is satisfied. 5715d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)std::vector<bool> RunAudioRecordInputPathTests() { 5725d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) std::vector<bool> tests; 5735d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) tests.push_back(false); 5745d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if (base::android::BuildInfo::GetInstance()->sdk_int() >= 16) 5755d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) tests.push_back(true); 5765d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) return tests; 5775d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)} 5785d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 5795d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// Test fixture class for tests which exercise the input path, or both input and 5805d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// output paths. It is value-parameterized to test against both the Java 5815d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// AudioRecord (when true) and native OpenSLES (when false) input paths. 5825d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)class AudioAndroidInputTest : public AudioAndroidOutputTest, 5835d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) public testing::WithParamInterface<bool> { 5845d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) public: 585a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) AudioAndroidInputTest() : audio_input_stream_(NULL) {} 5865d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 5875d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) protected: 588a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) const AudioParameters& audio_input_parameters() { 589a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) return audio_input_parameters_; 590a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) } 591a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) 5925d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) AudioParameters GetInputStreamParameters() { 593a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) GetDefaultInputStreamParametersOnAudioThread(); 594a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) 5955d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) // Override the platform effects setting to use the AudioRecord or OpenSLES 5965d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) // path as requested. 5975d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) int effects = GetParam() ? AudioParameters::ECHO_CANCELLER : 5985d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) AudioParameters::NO_EFFECTS; 599a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) AudioParameters params(audio_input_parameters().format(), 600a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) audio_input_parameters().channel_layout(), 601a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) audio_input_parameters().sample_rate(), 602a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) audio_input_parameters().bits_per_sample(), 603a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) audio_input_parameters().frames_per_buffer(), 6045d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) effects); 6055d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) return params; 6065d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) } 6075d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 608a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) void GetDefaultInputStreamParametersOnAudioThread() { 609a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) RunOnAudioThread( 610a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) base::Bind(&AudioAndroidInputTest::GetDefaultInputStreamParameters, 611a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) base::Unretained(this))); 612a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) } 613a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) 614a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) void MakeAudioInputStreamOnAudioThread(const AudioParameters& params) { 615a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) RunOnAudioThread( 616a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) base::Bind(&AudioAndroidInputTest::MakeInputStream, 617a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) base::Unretained(this), 618a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) params)); 619a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) } 620a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) 621a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) void OpenAndCloseAudioInputStreamOnAudioThread() { 622a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) RunOnAudioThread( 623a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) base::Bind(&AudioAndroidInputTest::OpenAndClose, 624a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) base::Unretained(this))); 625a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) } 626a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) 627a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) void OpenAndStartAudioInputStreamOnAudioThread( 628a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) AudioInputStream::AudioInputCallback* sink) { 629a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) RunOnAudioThread( 630a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) base::Bind(&AudioAndroidInputTest::OpenAndStart, 631a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) base::Unretained(this), 632a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) sink)); 633a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) } 634a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) 635a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) void StopAndCloseAudioInputStreamOnAudioThread() { 636a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) RunOnAudioThread( 637a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) base::Bind(&AudioAndroidInputTest::StopAndClose, 638a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) base::Unretained(this))); 639a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) } 640a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) 6415d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) void StartInputStreamCallbacks(const AudioParameters& params) { 642d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) double expected_time_between_callbacks_ms = 643d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) ExpectedTimeBetweenCallbacks(params); 644d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) const int num_callbacks = 645d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) (kCallbackTestTimeMs / expected_time_between_callbacks_ms); 646a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) 647a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) MakeAudioInputStreamOnAudioThread(params); 648d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) 649d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) int count = 0; 6505d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) MockAudioInputCallback sink; 651d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) 6526d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles) EXPECT_CALL(sink, OnData(audio_input_stream_, NotNull(), _, _)) 653d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) .Times(AtLeast(num_callbacks)) 654d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) .WillRepeatedly( 6556d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles) CheckCountAndPostQuitTask(&count, num_callbacks, loop())); 656a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) EXPECT_CALL(sink, OnError(audio_input_stream_)).Times(0); 657a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) 658a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) OpenAndStartAudioInputStreamOnAudioThread(&sink); 659d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) 660d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) start_time_ = base::TimeTicks::Now(); 661d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) loop()->Run(); 662d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) end_time_ = base::TimeTicks::Now(); 663a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) 664a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) StopAndCloseAudioInputStreamOnAudioThread(); 665d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) 666d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) double average_time_between_callbacks_ms = 667d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) AverageTimeBetweenCallbacks(num_callbacks); 668f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) VLOG(0) << "expected time between callbacks: " 669f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) << expected_time_between_callbacks_ms << " ms"; 670f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) VLOG(0) << "average time between callbacks: " 671f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) << average_time_between_callbacks_ms << " ms"; 672d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) EXPECT_GE(average_time_between_callbacks_ms, 673d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) 0.70 * expected_time_between_callbacks_ms); 674d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) EXPECT_LE(average_time_between_callbacks_ms, 675d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) 1.30 * expected_time_between_callbacks_ms); 676d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) } 677d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) 678a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) void GetDefaultInputStreamParameters() { 679a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) DCHECK(audio_manager()->GetTaskRunner()->BelongsToCurrentThread()); 680a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) audio_input_parameters_ = audio_manager()->GetInputStreamParameters( 681a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) AudioManagerBase::kDefaultDeviceId); 682a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) } 683a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) 684a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) void MakeInputStream(const AudioParameters& params) { 685a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) DCHECK(audio_manager()->GetTaskRunner()->BelongsToCurrentThread()); 686a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) audio_input_stream_ = audio_manager()->MakeAudioInputStream( 687a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) params, AudioManagerBase::kDefaultDeviceId); 688a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) EXPECT_TRUE(audio_input_stream_); 689a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) } 690a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) 691a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) void OpenAndClose() { 692a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) DCHECK(audio_manager()->GetTaskRunner()->BelongsToCurrentThread()); 693a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) EXPECT_TRUE(audio_input_stream_->Open()); 694a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) audio_input_stream_->Close(); 695a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) audio_input_stream_ = NULL; 696a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) } 697a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) 698a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) void OpenAndStart(AudioInputStream::AudioInputCallback* sink) { 699a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) DCHECK(audio_manager()->GetTaskRunner()->BelongsToCurrentThread()); 700a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) EXPECT_TRUE(audio_input_stream_->Open()); 701a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) audio_input_stream_->Start(sink); 702a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) } 703a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) 704a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) void StopAndClose() { 705a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) DCHECK(audio_manager()->GetTaskRunner()->BelongsToCurrentThread()); 706a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) audio_input_stream_->Stop(); 707a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) audio_input_stream_->Close(); 708a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) audio_input_stream_ = NULL; 709a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) } 710a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) 711a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) AudioInputStream* audio_input_stream_; 712a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) AudioParameters audio_input_parameters_; 713d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) 7145d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) private: 7155d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) DISALLOW_COPY_AND_ASSIGN(AudioAndroidInputTest); 716d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)}; 717d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) 718d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)// Get the default audio input parameters and log the result. 7195d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)TEST_P(AudioAndroidInputTest, GetDefaultInputStreamParameters) { 7205d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) // We don't go through AudioAndroidInputTest::GetInputStreamParameters() here 7215d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) // so that we can log the real (non-overridden) values of the effects. 722a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) GetDefaultInputStreamParametersOnAudioThread(); 723a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) EXPECT_TRUE(audio_input_parameters().IsValid()); 724a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) VLOG(1) << audio_input_parameters(); 725d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)} 726d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) 727d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)// Get the default audio output parameters and log the result. 7285d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)TEST_F(AudioAndroidOutputTest, GetDefaultOutputStreamParameters) { 729a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) GetDefaultOutputStreamParametersOnAudioThread(); 730a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) VLOG(1) << audio_output_parameters(); 731d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)} 732d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) 7335d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// Verify input device enumeration. 7345d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)TEST_F(AudioAndroidInputTest, GetAudioInputDeviceNames) { 7355d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if (!audio_manager()->HasAudioInputDevices()) 7365d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) return; 7375d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) AudioDeviceNames devices; 738a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) RunOnAudioThread( 739a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) base::Bind(&AudioManager::GetAudioInputDeviceNames, 740a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) base::Unretained(audio_manager()), 741a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) &devices)); 7425d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) CheckDeviceNames(devices); 7435d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)} 7445d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 7455d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// Verify output device enumeration. 7465d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)TEST_F(AudioAndroidOutputTest, GetAudioOutputDeviceNames) { 7475d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if (!audio_manager()->HasAudioOutputDevices()) 7485d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) return; 7495d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) AudioDeviceNames devices; 750a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) RunOnAudioThread( 751a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) base::Bind(&AudioManager::GetAudioOutputDeviceNames, 752a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) base::Unretained(audio_manager()), 753a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) &devices)); 7545d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) CheckDeviceNames(devices); 7555d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)} 7565d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 757d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)// Ensure that a default input stream can be created and closed. 7585d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)TEST_P(AudioAndroidInputTest, CreateAndCloseInputStream) { 7595d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) AudioParameters params = GetInputStreamParameters(); 760a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) MakeAudioInputStreamOnAudioThread(params); 761a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) RunOnAudioThread( 762a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) base::Bind(&AudioInputStream::Close, 763a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) base::Unretained(audio_input_stream_))); 764d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)} 765d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) 766d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)// Ensure that a default output stream can be created and closed. 767d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)// TODO(henrika): should we also verify that this API changes the audio mode 768d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)// to communication mode, and calls RegisterHeadsetReceiver, the first time 769d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)// it is called? 7705d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)TEST_F(AudioAndroidOutputTest, CreateAndCloseOutputStream) { 771a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) GetDefaultOutputStreamParametersOnAudioThread(); 772a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) MakeAudioOutputStreamOnAudioThread(audio_output_parameters()); 773a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) RunOnAudioThread( 774a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) base::Bind(&AudioOutputStream::Close, 775a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) base::Unretained(audio_output_stream_))); 776d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)} 777d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) 778d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)// Ensure that a default input stream can be opened and closed. 7795d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)TEST_P(AudioAndroidInputTest, OpenAndCloseInputStream) { 7805d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) AudioParameters params = GetInputStreamParameters(); 781a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) MakeAudioInputStreamOnAudioThread(params); 782a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) OpenAndCloseAudioInputStreamOnAudioThread(); 783d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)} 784d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) 785d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)// Ensure that a default output stream can be opened and closed. 7865d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)TEST_F(AudioAndroidOutputTest, OpenAndCloseOutputStream) { 787a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) GetDefaultOutputStreamParametersOnAudioThread(); 788a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) MakeAudioOutputStreamOnAudioThread(audio_output_parameters()); 789a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) OpenAndCloseAudioOutputStreamOnAudioThread(); 790d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)} 791d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) 792d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)// Start input streaming using default input parameters and ensure that the 793d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)// callback sequence is sane. 7945d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)TEST_P(AudioAndroidInputTest, DISABLED_StartInputStreamCallbacks) { 795a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) AudioParameters native_params = GetInputStreamParameters(); 796a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) StartInputStreamCallbacks(native_params); 797d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)} 798d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) 799d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)// Start input streaming using non default input parameters and ensure that the 800d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)// callback sequence is sane. The only change we make in this test is to select 801d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)// a 10ms buffer size instead of the default size. 802a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)TEST_P(AudioAndroidInputTest, 803a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) DISABLED_StartInputStreamCallbacksNonDefaultParameters) { 8045d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) AudioParameters native_params = GetInputStreamParameters(); 805d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) AudioParameters params(native_params.format(), 806d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) native_params.channel_layout(), 807d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) native_params.sample_rate(), 808d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) native_params.bits_per_sample(), 8095d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) native_params.sample_rate() / 100, 8105d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) native_params.effects()); 811d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) StartInputStreamCallbacks(params); 812d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)} 813d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) 8141320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 8151320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci#if defined(__aarch64__) 8161320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci// Disable StartOutputStreamCallbacks and 8171320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci// StartOutputStreamCallbacksNonDefaultParameters on Arm64: crbug.com/418029 8181320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci#define MAYBE_StartOutputStreamCallbacks DISABLED_StartOutputStreamCallbacks 8191320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci#define MAYBE_StartOutputStreamCallbacksNonDefaultParameters \ 8201320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci DISABLED_StartOutputStreamCallbacksNonDefaultParameters 8211320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci#else 8221320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci#define MAYBE_StartOutputStreamCallbacks StartOutputStreamCallbacks 8231320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci#define MAYBE_StartOutputStreamCallbacksNonDefaultParameters \ 8241320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci StartOutputStreamCallbacksNonDefaultParameters 8251320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci#endif 8261320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 8271320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 828d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)// Start output streaming using default output parameters and ensure that the 829d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)// callback sequence is sane. 8301320f92c476a1ad9d19dba2a48c72b75566198e9Primiano TucciTEST_F(AudioAndroidOutputTest, MAYBE_StartOutputStreamCallbacks) { 831a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) GetDefaultOutputStreamParametersOnAudioThread(); 832a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) StartOutputStreamCallbacks(audio_output_parameters()); 833d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)} 834d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) 835d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)// Start output streaming using non default output parameters and ensure that 836d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)// the callback sequence is sane. The only change we make in this test is to 837d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)// select a 10ms buffer size instead of the default size and to open up the 838d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)// device in mono. 839d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)// TODO(henrika): possibly add support for more variations. 8401320f92c476a1ad9d19dba2a48c72b75566198e9Primiano TucciTEST_F(AudioAndroidOutputTest, 8411320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci MAYBE_StartOutputStreamCallbacksNonDefaultParameters) { 842a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) GetDefaultOutputStreamParametersOnAudioThread(); 843a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) AudioParameters params(audio_output_parameters().format(), 844d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) CHANNEL_LAYOUT_MONO, 845a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) audio_output_parameters().sample_rate(), 846a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) audio_output_parameters().bits_per_sample(), 847a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) audio_output_parameters().sample_rate() / 100); 848d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) StartOutputStreamCallbacks(params); 849d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)} 850d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) 851d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)// Play out a PCM file segment in real time and allow the user to verify that 852d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)// the rendered audio sounds OK. 853d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)// NOTE: this test requires user interaction and is not designed to run as an 854d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)// automatized test on bots. 8555d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)TEST_F(AudioAndroidOutputTest, DISABLED_RunOutputStreamWithFileAsSource) { 856a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) GetDefaultOutputStreamParametersOnAudioThread(); 857a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) VLOG(1) << audio_output_parameters(); 858a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) MakeAudioOutputStreamOnAudioThread(audio_output_parameters()); 859d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) 860d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) std::string file_name; 861a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) const AudioParameters params = audio_output_parameters(); 862d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) if (params.sample_rate() == 48000 && params.channels() == 2) { 863d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) file_name = kSpeechFile_16b_s_48k; 864d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) } else if (params.sample_rate() == 48000 && params.channels() == 1) { 865d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) file_name = kSpeechFile_16b_m_48k; 866d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) } else if (params.sample_rate() == 44100 && params.channels() == 2) { 867d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) file_name = kSpeechFile_16b_s_44k; 868d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) } else if (params.sample_rate() == 44100 && params.channels() == 1) { 869d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) file_name = kSpeechFile_16b_m_44k; 870d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) } else { 871d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) FAIL() << "This test supports 44.1kHz and 48kHz mono/stereo only."; 872d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) return; 873d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) } 874d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) 875d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) base::WaitableEvent event(false, false); 876d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) FileAudioSource source(&event, file_name); 877d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) 878a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) OpenAndStartAudioOutputStreamOnAudioThread(&source); 879f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) VLOG(0) << ">> Verify that the file is played out correctly..."; 880d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) EXPECT_TRUE(event.TimedWait(TestTimeouts::action_max_timeout())); 881a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) StopAndCloseAudioOutputStreamOnAudioThread(); 882d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)} 883d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) 884d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)// Start input streaming and run it for ten seconds while recording to a 885d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)// local audio file. 886d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)// NOTE: this test requires user interaction and is not designed to run as an 887d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)// automatized test on bots. 8885d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)TEST_P(AudioAndroidInputTest, DISABLED_RunSimplexInputStreamWithFileAsSink) { 8895d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) AudioParameters params = GetInputStreamParameters(); 890d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) VLOG(1) << params; 891a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) MakeAudioInputStreamOnAudioThread(params); 892d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) 893d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) std::string file_name = base::StringPrintf("out_simplex_%d_%d_%d.pcm", 894d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) params.sample_rate(), 895d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) params.frames_per_buffer(), 896d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) params.channels()); 897d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) 898d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) base::WaitableEvent event(false, false); 899d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) FileAudioSink sink(&event, params, file_name); 900d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) 901a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) OpenAndStartAudioInputStreamOnAudioThread(&sink); 902f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) VLOG(0) << ">> Speak into the microphone to record audio..."; 903d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) EXPECT_TRUE(event.TimedWait(TestTimeouts::action_max_timeout())); 904a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) StopAndCloseAudioInputStreamOnAudioThread(); 905d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)} 906d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) 907d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)// Same test as RunSimplexInputStreamWithFileAsSink but this time output 908d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)// streaming is active as well (reads zeros only). 909d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)// NOTE: this test requires user interaction and is not designed to run as an 910d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)// automatized test on bots. 9115d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)TEST_P(AudioAndroidInputTest, DISABLED_RunDuplexInputStreamWithFileAsSink) { 9125d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) AudioParameters in_params = GetInputStreamParameters(); 913a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) VLOG(1) << in_params; 914a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) MakeAudioInputStreamOnAudioThread(in_params); 915d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) 916a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) GetDefaultOutputStreamParametersOnAudioThread(); 917a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) VLOG(1) << audio_output_parameters(); 918a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) MakeAudioOutputStreamOnAudioThread(audio_output_parameters()); 919d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) 920d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) std::string file_name = base::StringPrintf("out_duplex_%d_%d_%d.pcm", 921d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) in_params.sample_rate(), 922d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) in_params.frames_per_buffer(), 923d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) in_params.channels()); 924d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) 925d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) base::WaitableEvent event(false, false); 926d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) FileAudioSink sink(&event, in_params, file_name); 9275d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) MockAudioSourceCallback source; 928d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) 9295d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) EXPECT_CALL(source, OnMoreData(NotNull(), _)) 9305d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) .WillRepeatedly(Invoke(RealOnMoreData)); 931a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) EXPECT_CALL(source, OnError(audio_output_stream_)).Times(0); 932d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) 933a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) OpenAndStartAudioInputStreamOnAudioThread(&sink); 934a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) OpenAndStartAudioOutputStreamOnAudioThread(&source); 935f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) VLOG(0) << ">> Speak into the microphone to record audio"; 936d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) EXPECT_TRUE(event.TimedWait(TestTimeouts::action_max_timeout())); 937a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) StopAndCloseAudioOutputStreamOnAudioThread(); 938a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) StopAndCloseAudioInputStreamOnAudioThread(); 939d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)} 940d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) 941d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)// Start audio in both directions while feeding captured data into a FIFO so 942d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)// it can be read directly (in loopback) by the render side. A small extra 943d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)// delay will be added by the FIFO and an estimate of this delay will be 944d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)// printed out during the test. 945d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)// NOTE: this test requires user interaction and is not designed to run as an 946d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)// automatized test on bots. 9475d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)TEST_P(AudioAndroidInputTest, 948d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) DISABLED_RunSymmetricInputAndOutputStreamsInFullDuplex) { 949d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) // Get native audio parameters for the input side. 9505d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) AudioParameters default_input_params = GetInputStreamParameters(); 951d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) 952d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) // Modify the parameters so that both input and output can use the same 953d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) // parameters by selecting 10ms as buffer size. This will also ensure that 954d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) // the output stream will be a mono stream since mono is default for input 955d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) // audio on Android. 956d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) AudioParameters io_params(default_input_params.format(), 957d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) default_input_params.channel_layout(), 9585d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) ChannelLayoutToChannelCount( 9595d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) default_input_params.channel_layout()), 960d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) default_input_params.sample_rate(), 961d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) default_input_params.bits_per_sample(), 9625d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) default_input_params.sample_rate() / 100, 9635d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) default_input_params.effects()); 964d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) VLOG(1) << io_params; 965d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) 966d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) // Create input and output streams using the common audio parameters. 967a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) MakeAudioInputStreamOnAudioThread(io_params); 968a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) MakeAudioOutputStreamOnAudioThread(io_params); 969d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) 970d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) FullDuplexAudioSinkSource full_duplex(io_params); 971d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) 972d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) // Start a full duplex audio session and print out estimates of the extra 973d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) // delay we should expect from the FIFO. If real-time delay measurements are 974d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) // performed, the result should be reduced by this extra delay since it is 975d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) // something that has been added by the test. 976a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) OpenAndStartAudioInputStreamOnAudioThread(&full_duplex); 977a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) OpenAndStartAudioOutputStreamOnAudioThread(&full_duplex); 978d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) VLOG(1) << "HINT: an estimate of the extra FIFO delay will be updated " 979d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) << "once per second during this test."; 980f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) VLOG(0) << ">> Speak into the mic and listen to the audio in loopback..."; 981d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) fflush(stdout); 982d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) base::PlatformThread::Sleep(base::TimeDelta::FromSeconds(20)); 983d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) printf("\n"); 984a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) StopAndCloseAudioOutputStreamOnAudioThread(); 985a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) StopAndCloseAudioInputStreamOnAudioThread(); 986d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)} 987d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) 9885d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)INSTANTIATE_TEST_CASE_P(AudioAndroidInputTest, AudioAndroidInputTest, 9895d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) testing::ValuesIn(RunAudioRecordInputPathTests())); 9905d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 991d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)} // namespace media 992