Home | History | Annotate | Download | only in ios
      1 /*
      2  *  Copyright (c) 2015 The WebRTC project authors. All Rights Reserved.
      3  *
      4  *  Use of this source code is governed by a BSD-style license
      5  *  that can be found in the LICENSE file in the root of the source
      6  *  tree. An additional intellectual property rights grant can be found
      7  *  in the file PATENTS.  All contributing project authors may
      8  *  be found in the AUTHORS file in the root of the source tree.
      9  */
     10 
     11 #include <algorithm>
     12 #include <limits>
     13 #include <list>
     14 #include <numeric>
     15 #include <string>
     16 #include <vector>
     17 
     18 #include "testing/gmock/include/gmock/gmock.h"
     19 #include "testing/gtest/include/gtest/gtest.h"
     20 #include "webrtc/base/arraysize.h"
     21 #include "webrtc/base/criticalsection.h"
     22 #include "webrtc/base/format_macros.h"
     23 #include "webrtc/base/logging.h"
     24 #include "webrtc/base/scoped_ptr.h"
     25 #include "webrtc/base/scoped_ref_ptr.h"
     26 #include "webrtc/modules/audio_device/audio_device_impl.h"
     27 #include "webrtc/modules/audio_device/include/audio_device.h"
     28 #include "webrtc/modules/audio_device/ios/audio_device_ios.h"
     29 #include "webrtc/system_wrappers/include/clock.h"
     30 #include "webrtc/system_wrappers/include/event_wrapper.h"
     31 #include "webrtc/system_wrappers/include/sleep.h"
     32 #include "webrtc/test/testsupport/fileutils.h"
     33 
     34 using std::cout;
     35 using std::endl;
     36 using ::testing::_;
     37 using ::testing::AtLeast;
     38 using ::testing::Gt;
     39 using ::testing::Invoke;
     40 using ::testing::NiceMock;
     41 using ::testing::NotNull;
     42 using ::testing::Return;
     43 
     44 // #define ENABLE_DEBUG_PRINTF
     45 #ifdef ENABLE_DEBUG_PRINTF
     46 #define PRINTD(...) fprintf(stderr, __VA_ARGS__);
     47 #else
     48 #define PRINTD(...) ((void)0)
     49 #endif
     50 #define PRINT(...) fprintf(stderr, __VA_ARGS__);
     51 
     52 namespace webrtc {
     53 
     54 // Number of callbacks (input or output) the tests waits for before we set
     55 // an event indicating that the test was OK.
     56 static const size_t kNumCallbacks = 10;
     57 // Max amount of time we wait for an event to be set while counting callbacks.
     58 static const int kTestTimeOutInMilliseconds = 10 * 1000;
     59 // Number of bits per PCM audio sample.
     60 static const size_t kBitsPerSample = 16;
     61 // Number of bytes per PCM audio sample.
     62 static const size_t kBytesPerSample = kBitsPerSample / 8;
     63 // Average number of audio callbacks per second assuming 10ms packet size.
     64 static const size_t kNumCallbacksPerSecond = 100;
     65 // Play out a test file during this time (unit is in seconds).
     66 static const int kFilePlayTimeInSec = 15;
     67 // Run the full-duplex test during this time (unit is in seconds).
     68 // Note that first |kNumIgnoreFirstCallbacks| are ignored.
     69 static const int kFullDuplexTimeInSec = 10;
     70 // Wait for the callback sequence to stabilize by ignoring this amount of the
     71 // initial callbacks (avoids initial FIFO access).
     72 // Only used in the RunPlayoutAndRecordingInFullDuplex test.
     73 static const size_t kNumIgnoreFirstCallbacks = 50;
     74 // Sets the number of impulses per second in the latency test.
     75 // TODO(henrika): fine tune this setting for iOS.
     76 static const int kImpulseFrequencyInHz = 1;
     77 // Length of round-trip latency measurements. Number of transmitted impulses
     78 // is kImpulseFrequencyInHz * kMeasureLatencyTimeInSec - 1.
     79 // TODO(henrika): fine tune this setting for iOS.
     80 static const int kMeasureLatencyTimeInSec = 5;
     81 // Utilized in round-trip latency measurements to avoid capturing noise samples.
     82 // TODO(henrika): fine tune this setting for iOS.
     83 static const int kImpulseThreshold = 50;
     84 static const char kTag[] = "[..........] ";
     85 
     86 enum TransportType {
     87   kPlayout = 0x1,
     88   kRecording = 0x2,
     89 };
     90 
     91 // Interface for processing the audio stream. Real implementations can e.g.
     92 // run audio in loopback, read audio from a file or perform latency
     93 // measurements.
     94 class AudioStreamInterface {
     95  public:
     96   virtual void Write(const void* source, size_t num_frames) = 0;
     97   virtual void Read(void* destination, size_t num_frames) = 0;
     98 
     99  protected:
    100   virtual ~AudioStreamInterface() {}
    101 };
    102 
    103 // Reads audio samples from a PCM file where the file is stored in memory at
    104 // construction.
    105 class FileAudioStream : public AudioStreamInterface {
    106  public:
    107   FileAudioStream(size_t num_callbacks,
    108                   const std::string& file_name,
    109                   int sample_rate)
    110       : file_size_in_bytes_(0), sample_rate_(sample_rate), file_pos_(0) {
    111     file_size_in_bytes_ = test::GetFileSize(file_name);
    112     sample_rate_ = sample_rate;
    113     EXPECT_GE(file_size_in_callbacks(), num_callbacks)
    114         << "Size of test file is not large enough to last during the test.";
    115     const size_t num_16bit_samples =
    116         test::GetFileSize(file_name) / kBytesPerSample;
    117     file_.reset(new int16_t[num_16bit_samples]);
    118     FILE* audio_file = fopen(file_name.c_str(), "rb");
    119     EXPECT_NE(audio_file, nullptr);
    120     size_t num_samples_read =
    121         fread(file_.get(), sizeof(int16_t), num_16bit_samples, audio_file);
    122     EXPECT_EQ(num_samples_read, num_16bit_samples);
    123     fclose(audio_file);
    124   }
    125 
    126   // AudioStreamInterface::Write() is not implemented.
    127   void Write(const void* source, size_t num_frames) override {}
    128 
    129   // Read samples from file stored in memory (at construction) and copy
    130   // |num_frames| (<=> 10ms) to the |destination| byte buffer.
    131   void Read(void* destination, size_t num_frames) override {
    132     memcpy(destination, static_cast<int16_t*>(&file_[file_pos_]),
    133            num_frames * sizeof(int16_t));
    134     file_pos_ += num_frames;
    135   }
    136 
    137   int file_size_in_seconds() const {
    138     return static_cast<int>(
    139         file_size_in_bytes_ / (kBytesPerSample * sample_rate_));
    140   }
    141   size_t file_size_in_callbacks() const {
    142     return file_size_in_seconds() * kNumCallbacksPerSecond;
    143   }
    144 
    145  private:
    146   size_t file_size_in_bytes_;
    147   int sample_rate_;
    148   rtc::scoped_ptr<int16_t[]> file_;
    149   size_t file_pos_;
    150 };
    151 
    152 // Simple first in first out (FIFO) class that wraps a list of 16-bit audio
    153 // buffers of fixed size and allows Write and Read operations. The idea is to
    154 // store recorded audio buffers (using Write) and then read (using Read) these
    155 // stored buffers with as short delay as possible when the audio layer needs
    156 // data to play out. The number of buffers in the FIFO will stabilize under
    157 // normal conditions since there will be a balance between Write and Read calls.
    158 // The container is a std::list container and access is protected with a lock
    159 // since both sides (playout and recording) are driven by its own thread.
    160 class FifoAudioStream : public AudioStreamInterface {
    161  public:
    162   explicit FifoAudioStream(size_t frames_per_buffer)
    163       : frames_per_buffer_(frames_per_buffer),
    164         bytes_per_buffer_(frames_per_buffer_ * sizeof(int16_t)),
    165         fifo_(new AudioBufferList),
    166         largest_size_(0),
    167         total_written_elements_(0),
    168         write_count_(0) {
    169     EXPECT_NE(fifo_.get(), nullptr);
    170   }
    171 
    172   ~FifoAudioStream() { Flush(); }
    173 
    174   // Allocate new memory, copy |num_frames| samples from |source| into memory
    175   // and add pointer to the memory location to end of the list.
    176   // Increases the size of the FIFO by one element.
    177   void Write(const void* source, size_t num_frames) override {
    178     ASSERT_EQ(num_frames, frames_per_buffer_);
    179     PRINTD("+");
    180     if (write_count_++ < kNumIgnoreFirstCallbacks) {
    181       return;
    182     }
    183     int16_t* memory = new int16_t[frames_per_buffer_];
    184     memcpy(static_cast<int16_t*>(&memory[0]), source, bytes_per_buffer_);
    185     rtc::CritScope lock(&lock_);
    186     fifo_->push_back(memory);
    187     const size_t size = fifo_->size();
    188     if (size > largest_size_) {
    189       largest_size_ = size;
    190       PRINTD("(%" PRIuS ")", largest_size_);
    191     }
    192     total_written_elements_ += size;
    193   }
    194 
    195   // Read pointer to data buffer from front of list, copy |num_frames| of stored
    196   // data into |destination| and delete the utilized memory allocation.
    197   // Decreases the size of the FIFO by one element.
    198   void Read(void* destination, size_t num_frames) override {
    199     ASSERT_EQ(num_frames, frames_per_buffer_);
    200     PRINTD("-");
    201     rtc::CritScope lock(&lock_);
    202     if (fifo_->empty()) {
    203       memset(destination, 0, bytes_per_buffer_);
    204     } else {
    205       int16_t* memory = fifo_->front();
    206       fifo_->pop_front();
    207       memcpy(destination, static_cast<int16_t*>(&memory[0]), bytes_per_buffer_);
    208       delete memory;
    209     }
    210   }
    211 
    212   size_t size() const { return fifo_->size(); }
    213 
    214   size_t largest_size() const { return largest_size_; }
    215 
    216   size_t average_size() const {
    217     return (total_written_elements_ == 0)
    218                ? 0.0
    219                : 0.5 +
    220                      static_cast<float>(total_written_elements_) /
    221                          (write_count_ - kNumIgnoreFirstCallbacks);
    222   }
    223 
    224  private:
    225   void Flush() {
    226     for (auto it = fifo_->begin(); it != fifo_->end(); ++it) {
    227       delete *it;
    228     }
    229     fifo_->clear();
    230   }
    231 
    232   using AudioBufferList = std::list<int16_t*>;
    233   rtc::CriticalSection lock_;
    234   const size_t frames_per_buffer_;
    235   const size_t bytes_per_buffer_;
    236   rtc::scoped_ptr<AudioBufferList> fifo_;
    237   size_t largest_size_;
    238   size_t total_written_elements_;
    239   size_t write_count_;
    240 };
    241 
    242 // Inserts periodic impulses and measures the latency between the time of
    243 // transmission and time of receiving the same impulse.
    244 // Usage requires a special hardware called Audio Loopback Dongle.
    245 // See http://source.android.com/devices/audio/loopback.html for details.
    246 class LatencyMeasuringAudioStream : public AudioStreamInterface {
    247  public:
    248   explicit LatencyMeasuringAudioStream(size_t frames_per_buffer)
    249       : clock_(Clock::GetRealTimeClock()),
    250         frames_per_buffer_(frames_per_buffer),
    251         bytes_per_buffer_(frames_per_buffer_ * sizeof(int16_t)),
    252         play_count_(0),
    253         rec_count_(0),
    254         pulse_time_(0) {}
    255 
    256   // Insert periodic impulses in first two samples of |destination|.
    257   void Read(void* destination, size_t num_frames) override {
    258     ASSERT_EQ(num_frames, frames_per_buffer_);
    259     if (play_count_ == 0) {
    260       PRINT("[");
    261     }
    262     play_count_++;
    263     memset(destination, 0, bytes_per_buffer_);
    264     if (play_count_ % (kNumCallbacksPerSecond / kImpulseFrequencyInHz) == 0) {
    265       if (pulse_time_ == 0) {
    266         pulse_time_ = clock_->TimeInMilliseconds();
    267       }
    268       PRINT(".");
    269       const int16_t impulse = std::numeric_limits<int16_t>::max();
    270       int16_t* ptr16 = static_cast<int16_t*>(destination);
    271       for (size_t i = 0; i < 2; ++i) {
    272         ptr16[i] = impulse;
    273       }
    274     }
    275   }
    276 
    277   // Detect received impulses in |source|, derive time between transmission and
    278   // detection and add the calculated delay to list of latencies.
    279   void Write(const void* source, size_t num_frames) override {
    280     ASSERT_EQ(num_frames, frames_per_buffer_);
    281     rec_count_++;
    282     if (pulse_time_ == 0) {
    283       // Avoid detection of new impulse response until a new impulse has
    284       // been transmitted (sets |pulse_time_| to value larger than zero).
    285       return;
    286     }
    287     const int16_t* ptr16 = static_cast<const int16_t*>(source);
    288     std::vector<int16_t> vec(ptr16, ptr16 + num_frames);
    289     // Find max value in the audio buffer.
    290     int max = *std::max_element(vec.begin(), vec.end());
    291     // Find index (element position in vector) of the max element.
    292     int index_of_max =
    293         std::distance(vec.begin(), std::find(vec.begin(), vec.end(), max));
    294     if (max > kImpulseThreshold) {
    295       PRINTD("(%d,%d)", max, index_of_max);
    296       int64_t now_time = clock_->TimeInMilliseconds();
    297       int extra_delay = IndexToMilliseconds(static_cast<double>(index_of_max));
    298       PRINTD("[%d]", static_cast<int>(now_time - pulse_time_));
    299       PRINTD("[%d]", extra_delay);
    300       // Total latency is the difference between transmit time and detection
    301       // tome plus the extra delay within the buffer in which we detected the
    302       // received impulse. It is transmitted at sample 0 but can be received
    303       // at sample N where N > 0. The term |extra_delay| accounts for N and it
    304       // is a value between 0 and 10ms.
    305       latencies_.push_back(now_time - pulse_time_ + extra_delay);
    306       pulse_time_ = 0;
    307     } else {
    308       PRINTD("-");
    309     }
    310   }
    311 
    312   size_t num_latency_values() const { return latencies_.size(); }
    313 
    314   int min_latency() const {
    315     if (latencies_.empty())
    316       return 0;
    317     return *std::min_element(latencies_.begin(), latencies_.end());
    318   }
    319 
    320   int max_latency() const {
    321     if (latencies_.empty())
    322       return 0;
    323     return *std::max_element(latencies_.begin(), latencies_.end());
    324   }
    325 
    326   int average_latency() const {
    327     if (latencies_.empty())
    328       return 0;
    329     return 0.5 +
    330            static_cast<double>(
    331                std::accumulate(latencies_.begin(), latencies_.end(), 0)) /
    332                latencies_.size();
    333   }
    334 
    335   void PrintResults() const {
    336     PRINT("] ");
    337     for (auto it = latencies_.begin(); it != latencies_.end(); ++it) {
    338       PRINT("%d ", *it);
    339     }
    340     PRINT("\n");
    341     PRINT("%s[min, max, avg]=[%d, %d, %d] ms\n", kTag, min_latency(),
    342           max_latency(), average_latency());
    343   }
    344 
    345   int IndexToMilliseconds(double index) const {
    346     return 10.0 * (index / frames_per_buffer_) + 0.5;
    347   }
    348 
    349  private:
    350   Clock* clock_;
    351   const size_t frames_per_buffer_;
    352   const size_t bytes_per_buffer_;
    353   size_t play_count_;
    354   size_t rec_count_;
    355   int64_t pulse_time_;
    356   std::vector<int> latencies_;
    357 };
    358 // Mocks the AudioTransport object and proxies actions for the two callbacks
    359 // (RecordedDataIsAvailable and NeedMorePlayData) to different implementations
    360 // of AudioStreamInterface.
    361 class MockAudioTransport : public AudioTransport {
    362  public:
    363   explicit MockAudioTransport(int type)
    364       : num_callbacks_(0),
    365         type_(type),
    366         play_count_(0),
    367         rec_count_(0),
    368         audio_stream_(nullptr) {}
    369 
    370   virtual ~MockAudioTransport() {}
    371 
    372   MOCK_METHOD10(RecordedDataIsAvailable,
    373                 int32_t(const void* audioSamples,
    374                         const size_t nSamples,
    375                         const size_t nBytesPerSample,
    376                         const size_t nChannels,
    377                         const uint32_t samplesPerSec,
    378                         const uint32_t totalDelayMS,
    379                         const int32_t clockDrift,
    380                         const uint32_t currentMicLevel,
    381                         const bool keyPressed,
    382                         uint32_t& newMicLevel));
    383   MOCK_METHOD8(NeedMorePlayData,
    384                int32_t(const size_t nSamples,
    385                        const size_t nBytesPerSample,
    386                        const size_t nChannels,
    387                        const uint32_t samplesPerSec,
    388                        void* audioSamples,
    389                        size_t& nSamplesOut,
    390                        int64_t* elapsed_time_ms,
    391                        int64_t* ntp_time_ms));
    392 
    393   // Set default actions of the mock object. We are delegating to fake
    394   // implementations (of AudioStreamInterface) here.
    395   void HandleCallbacks(EventWrapper* test_is_done,
    396                        AudioStreamInterface* audio_stream,
    397                        size_t num_callbacks) {
    398     test_is_done_ = test_is_done;
    399     audio_stream_ = audio_stream;
    400     num_callbacks_ = num_callbacks;
    401     if (play_mode()) {
    402       ON_CALL(*this, NeedMorePlayData(_, _, _, _, _, _, _, _))
    403           .WillByDefault(
    404               Invoke(this, &MockAudioTransport::RealNeedMorePlayData));
    405     }
    406     if (rec_mode()) {
    407       ON_CALL(*this, RecordedDataIsAvailable(_, _, _, _, _, _, _, _, _, _))
    408           .WillByDefault(
    409               Invoke(this, &MockAudioTransport::RealRecordedDataIsAvailable));
    410     }
    411   }
    412 
    413   int32_t RealRecordedDataIsAvailable(const void* audioSamples,
    414                                       const size_t nSamples,
    415                                       const size_t nBytesPerSample,
    416                                       const size_t nChannels,
    417                                       const uint32_t samplesPerSec,
    418                                       const uint32_t totalDelayMS,
    419                                       const int32_t clockDrift,
    420                                       const uint32_t currentMicLevel,
    421                                       const bool keyPressed,
    422                                       uint32_t& newMicLevel) {
    423     EXPECT_TRUE(rec_mode()) << "No test is expecting these callbacks.";
    424     rec_count_++;
    425     // Process the recorded audio stream if an AudioStreamInterface
    426     // implementation exists.
    427     if (audio_stream_) {
    428       audio_stream_->Write(audioSamples, nSamples);
    429     }
    430     if (ReceivedEnoughCallbacks()) {
    431       if (test_is_done_) {
    432         test_is_done_->Set();
    433       }
    434     }
    435     return 0;
    436   }
    437 
    438   int32_t RealNeedMorePlayData(const size_t nSamples,
    439                                const size_t nBytesPerSample,
    440                                const size_t nChannels,
    441                                const uint32_t samplesPerSec,
    442                                void* audioSamples,
    443                                size_t& nSamplesOut,
    444                                int64_t* elapsed_time_ms,
    445                                int64_t* ntp_time_ms) {
    446     EXPECT_TRUE(play_mode()) << "No test is expecting these callbacks.";
    447     play_count_++;
    448     nSamplesOut = nSamples;
    449     // Read (possibly processed) audio stream samples to be played out if an
    450     // AudioStreamInterface implementation exists.
    451     if (audio_stream_) {
    452       audio_stream_->Read(audioSamples, nSamples);
    453     }
    454     if (ReceivedEnoughCallbacks()) {
    455       if (test_is_done_) {
    456         test_is_done_->Set();
    457       }
    458     }
    459     return 0;
    460   }
    461 
    462   bool ReceivedEnoughCallbacks() {
    463     bool recording_done = false;
    464     if (rec_mode())
    465       recording_done = rec_count_ >= num_callbacks_;
    466     else
    467       recording_done = true;
    468 
    469     bool playout_done = false;
    470     if (play_mode())
    471       playout_done = play_count_ >= num_callbacks_;
    472     else
    473       playout_done = true;
    474 
    475     return recording_done && playout_done;
    476   }
    477 
    478   bool play_mode() const { return type_ & kPlayout; }
    479   bool rec_mode() const { return type_ & kRecording; }
    480 
    481  private:
    482   EventWrapper* test_is_done_;
    483   size_t num_callbacks_;
    484   int type_;
    485   size_t play_count_;
    486   size_t rec_count_;
    487   AudioStreamInterface* audio_stream_;
    488 };
    489 
    490 // AudioDeviceTest test fixture.
    491 class AudioDeviceTest : public ::testing::Test {
    492  protected:
    493   AudioDeviceTest() : test_is_done_(EventWrapper::Create()) {
    494     old_sev_ = rtc::LogMessage::GetLogToDebug();
    495     // Set suitable logging level here. Change to rtc::LS_INFO for more verbose
    496     // output. See webrtc/base/logging.h for complete list of options.
    497     rtc::LogMessage::LogToDebug(rtc::LS_INFO);
    498     // Add extra logging fields here (timestamps and thread id).
    499     // rtc::LogMessage::LogTimestamps();
    500     rtc::LogMessage::LogThreads();
    501     // Creates an audio device using a default audio layer.
    502     audio_device_ = CreateAudioDevice(AudioDeviceModule::kPlatformDefaultAudio);
    503     EXPECT_NE(audio_device_.get(), nullptr);
    504     EXPECT_EQ(0, audio_device_->Init());
    505     EXPECT_EQ(0,
    506               audio_device()->GetPlayoutAudioParameters(&playout_parameters_));
    507     EXPECT_EQ(0, audio_device()->GetRecordAudioParameters(&record_parameters_));
    508   }
    509   virtual ~AudioDeviceTest() {
    510     EXPECT_EQ(0, audio_device_->Terminate());
    511     rtc::LogMessage::LogToDebug(old_sev_);
    512   }
    513 
    514   int playout_sample_rate() const { return playout_parameters_.sample_rate(); }
    515   int record_sample_rate() const { return record_parameters_.sample_rate(); }
    516   int playout_channels() const { return playout_parameters_.channels(); }
    517   int record_channels() const { return record_parameters_.channels(); }
    518   size_t playout_frames_per_10ms_buffer() const {
    519     return playout_parameters_.frames_per_10ms_buffer();
    520   }
    521   size_t record_frames_per_10ms_buffer() const {
    522     return record_parameters_.frames_per_10ms_buffer();
    523   }
    524 
    525   rtc::scoped_refptr<AudioDeviceModule> audio_device() const {
    526     return audio_device_;
    527   }
    528 
    529   AudioDeviceModuleImpl* audio_device_impl() const {
    530     return static_cast<AudioDeviceModuleImpl*>(audio_device_.get());
    531   }
    532 
    533   AudioDeviceBuffer* audio_device_buffer() const {
    534     return audio_device_impl()->GetAudioDeviceBuffer();
    535   }
    536 
    537   rtc::scoped_refptr<AudioDeviceModule> CreateAudioDevice(
    538       AudioDeviceModule::AudioLayer audio_layer) {
    539     rtc::scoped_refptr<AudioDeviceModule> module(
    540         AudioDeviceModuleImpl::Create(0, audio_layer));
    541     return module;
    542   }
    543 
    544   // Returns file name relative to the resource root given a sample rate.
    545   std::string GetFileName(int sample_rate) {
    546     EXPECT_TRUE(sample_rate == 48000 || sample_rate == 44100 ||
    547                 sample_rate == 16000);
    548     char fname[64];
    549     snprintf(fname, sizeof(fname), "audio_device/audio_short%d",
    550              sample_rate / 1000);
    551     std::string file_name(webrtc::test::ResourcePath(fname, "pcm"));
    552     EXPECT_TRUE(test::FileExists(file_name));
    553 #ifdef ENABLE_DEBUG_PRINTF
    554     PRINTD("file name: %s\n", file_name.c_str());
    555     const size_t bytes = test::GetFileSize(file_name);
    556     PRINTD("file size: %" PRIuS " [bytes]\n", bytes);
    557     PRINTD("file size: %" PRIuS " [samples]\n", bytes / kBytesPerSample);
    558     const int seconds =
    559         static_cast<int>(bytes / (sample_rate * kBytesPerSample));
    560     PRINTD("file size: %d [secs]\n", seconds);
    561     PRINTD("file size: %" PRIuS " [callbacks]\n",
    562            seconds * kNumCallbacksPerSecond);
    563 #endif
    564     return file_name;
    565   }
    566 
    567   void StartPlayout() {
    568     EXPECT_FALSE(audio_device()->PlayoutIsInitialized());
    569     EXPECT_FALSE(audio_device()->Playing());
    570     EXPECT_EQ(0, audio_device()->InitPlayout());
    571     EXPECT_TRUE(audio_device()->PlayoutIsInitialized());
    572     EXPECT_EQ(0, audio_device()->StartPlayout());
    573     EXPECT_TRUE(audio_device()->Playing());
    574   }
    575 
    576   void StopPlayout() {
    577     EXPECT_EQ(0, audio_device()->StopPlayout());
    578     EXPECT_FALSE(audio_device()->Playing());
    579     EXPECT_FALSE(audio_device()->PlayoutIsInitialized());
    580   }
    581 
    582   void StartRecording() {
    583     EXPECT_FALSE(audio_device()->RecordingIsInitialized());
    584     EXPECT_FALSE(audio_device()->Recording());
    585     EXPECT_EQ(0, audio_device()->InitRecording());
    586     EXPECT_TRUE(audio_device()->RecordingIsInitialized());
    587     EXPECT_EQ(0, audio_device()->StartRecording());
    588     EXPECT_TRUE(audio_device()->Recording());
    589   }
    590 
    591   void StopRecording() {
    592     EXPECT_EQ(0, audio_device()->StopRecording());
    593     EXPECT_FALSE(audio_device()->Recording());
    594   }
    595 
    596   rtc::scoped_ptr<EventWrapper> test_is_done_;
    597   rtc::scoped_refptr<AudioDeviceModule> audio_device_;
    598   AudioParameters playout_parameters_;
    599   AudioParameters record_parameters_;
    600   rtc::LoggingSeverity old_sev_;
    601 };
    602 
    603 TEST_F(AudioDeviceTest, ConstructDestruct) {
    604   // Using the test fixture to create and destruct the audio device module.
    605 }
    606 
    607 TEST_F(AudioDeviceTest, InitTerminate) {
    608   // Initialization is part of the test fixture.
    609   EXPECT_TRUE(audio_device()->Initialized());
    610   EXPECT_EQ(0, audio_device()->Terminate());
    611   EXPECT_FALSE(audio_device()->Initialized());
    612 }
    613 
    614 // Tests that playout can be initiated, started and stopped. No audio callback
    615 // is registered in this test.
    616 TEST_F(AudioDeviceTest, StartStopPlayout) {
    617   StartPlayout();
    618   StopPlayout();
    619   StartPlayout();
    620   StopPlayout();
    621 }
    622 
    623 // Tests that recording can be initiated, started and stopped. No audio callback
    624 // is registered in this test.
    625 TEST_F(AudioDeviceTest, StartStopRecording) {
    626   StartRecording();
    627   StopRecording();
    628   StartRecording();
    629   StopRecording();
    630 }
    631 
    632 // Verify that calling StopPlayout() will leave us in an uninitialized state
    633 // which will require a new call to InitPlayout(). This test does not call
    634 // StartPlayout() while being uninitialized since doing so will hit a
    635 // RTC_DCHECK.
    636 TEST_F(AudioDeviceTest, StopPlayoutRequiresInitToRestart) {
    637   EXPECT_EQ(0, audio_device()->InitPlayout());
    638   EXPECT_EQ(0, audio_device()->StartPlayout());
    639   EXPECT_EQ(0, audio_device()->StopPlayout());
    640   EXPECT_FALSE(audio_device()->PlayoutIsInitialized());
    641 }
    642 
    643 // Verify that we can create two ADMs and start playing on the second ADM.
    644 // Only the first active instance shall activate an audio session and the
    645 // last active instance shall deactivate the audio session. The test does not
    646 // explicitly verify correct audio session calls but instead focuses on
    647 // ensuring that audio starts for both ADMs.
    648 TEST_F(AudioDeviceTest, StartPlayoutOnTwoInstances) {
    649   // Create and initialize a second/extra ADM instance. The default ADM is
    650   // created by the test harness.
    651   rtc::scoped_refptr<AudioDeviceModule> second_audio_device =
    652       CreateAudioDevice(AudioDeviceModule::kPlatformDefaultAudio);
    653   EXPECT_NE(second_audio_device.get(), nullptr);
    654   EXPECT_EQ(0, second_audio_device->Init());
    655 
    656   // Start playout for the default ADM but don't wait here. Instead use the
    657   // upcoming second stream for that. We set the same expectation on number
    658   // of callbacks as for the second stream.
    659   NiceMock<MockAudioTransport> mock(kPlayout);
    660   mock.HandleCallbacks(nullptr, nullptr, 0);
    661   EXPECT_CALL(
    662       mock, NeedMorePlayData(playout_frames_per_10ms_buffer(), kBytesPerSample,
    663                              playout_channels(), playout_sample_rate(),
    664                              NotNull(), _, _, _))
    665       .Times(AtLeast(kNumCallbacks));
    666   EXPECT_EQ(0, audio_device()->RegisterAudioCallback(&mock));
    667   StartPlayout();
    668 
    669   // Initialize playout for the second ADM. If all is OK, the second ADM shall
    670   // reuse the audio session activated when the first ADM started playing.
    671   // This call will also ensure that we avoid a problem related to initializing
    672   // two different audio unit instances back to back (see webrtc:5166 for
    673   // details).
    674   EXPECT_EQ(0, second_audio_device->InitPlayout());
    675   EXPECT_TRUE(second_audio_device->PlayoutIsInitialized());
    676 
    677   // Start playout for the second ADM and verify that it starts as intended.
    678   // Passing this test ensures that initialization of the second audio unit
    679   // has been done successfully and that there is no conflict with the already
    680   // playing first ADM.
    681   MockAudioTransport mock2(kPlayout);
    682   mock2.HandleCallbacks(test_is_done_.get(), nullptr, kNumCallbacks);
    683   EXPECT_CALL(
    684       mock2, NeedMorePlayData(playout_frames_per_10ms_buffer(), kBytesPerSample,
    685                               playout_channels(), playout_sample_rate(),
    686                               NotNull(), _, _, _))
    687       .Times(AtLeast(kNumCallbacks));
    688   EXPECT_EQ(0, second_audio_device->RegisterAudioCallback(&mock2));
    689   EXPECT_EQ(0, second_audio_device->StartPlayout());
    690   EXPECT_TRUE(second_audio_device->Playing());
    691   test_is_done_->Wait(kTestTimeOutInMilliseconds);
    692   EXPECT_EQ(0, second_audio_device->StopPlayout());
    693   EXPECT_FALSE(second_audio_device->Playing());
    694   EXPECT_FALSE(second_audio_device->PlayoutIsInitialized());
    695 
    696   EXPECT_EQ(0, second_audio_device->Terminate());
    697 }
    698 
    699 // Start playout and verify that the native audio layer starts asking for real
    700 // audio samples to play out using the NeedMorePlayData callback.
    701 TEST_F(AudioDeviceTest, StartPlayoutVerifyCallbacks) {
    702   MockAudioTransport mock(kPlayout);
    703   mock.HandleCallbacks(test_is_done_.get(), nullptr, kNumCallbacks);
    704   EXPECT_CALL(mock, NeedMorePlayData(playout_frames_per_10ms_buffer(),
    705                                      kBytesPerSample, playout_channels(),
    706                                      playout_sample_rate(), NotNull(), _, _, _))
    707       .Times(AtLeast(kNumCallbacks));
    708   EXPECT_EQ(0, audio_device()->RegisterAudioCallback(&mock));
    709   StartPlayout();
    710   test_is_done_->Wait(kTestTimeOutInMilliseconds);
    711   StopPlayout();
    712 }
    713 
    714 // Start recording and verify that the native audio layer starts feeding real
    715 // audio samples via the RecordedDataIsAvailable callback.
    716 TEST_F(AudioDeviceTest, StartRecordingVerifyCallbacks) {
    717   MockAudioTransport mock(kRecording);
    718   mock.HandleCallbacks(test_is_done_.get(), nullptr, kNumCallbacks);
    719   EXPECT_CALL(mock,
    720               RecordedDataIsAvailable(
    721                   NotNull(), record_frames_per_10ms_buffer(), kBytesPerSample,
    722                   record_channels(), record_sample_rate(),
    723                   _,  // TODO(henrika): fix delay
    724                   0, 0, false, _)).Times(AtLeast(kNumCallbacks));
    725 
    726   EXPECT_EQ(0, audio_device()->RegisterAudioCallback(&mock));
    727   StartRecording();
    728   test_is_done_->Wait(kTestTimeOutInMilliseconds);
    729   StopRecording();
    730 }
    731 
    732 // Start playout and recording (full-duplex audio) and verify that audio is
    733 // active in both directions.
    734 TEST_F(AudioDeviceTest, StartPlayoutAndRecordingVerifyCallbacks) {
    735   MockAudioTransport mock(kPlayout | kRecording);
    736   mock.HandleCallbacks(test_is_done_.get(), nullptr, kNumCallbacks);
    737   EXPECT_CALL(mock, NeedMorePlayData(playout_frames_per_10ms_buffer(),
    738                                      kBytesPerSample, playout_channels(),
    739                                      playout_sample_rate(), NotNull(), _, _, _))
    740       .Times(AtLeast(kNumCallbacks));
    741   EXPECT_CALL(mock,
    742               RecordedDataIsAvailable(
    743                   NotNull(), record_frames_per_10ms_buffer(), kBytesPerSample,
    744                   record_channels(), record_sample_rate(),
    745                   _,  // TODO(henrika): fix delay
    746                   0, 0, false, _)).Times(AtLeast(kNumCallbacks));
    747   EXPECT_EQ(0, audio_device()->RegisterAudioCallback(&mock));
    748   StartPlayout();
    749   StartRecording();
    750   test_is_done_->Wait(kTestTimeOutInMilliseconds);
    751   StopRecording();
    752   StopPlayout();
    753 }
    754 
    755 // Start playout and read audio from an external PCM file when the audio layer
    756 // asks for data to play out. Real audio is played out in this test but it does
    757 // not contain any explicit verification that the audio quality is perfect.
    758 TEST_F(AudioDeviceTest, RunPlayoutWithFileAsSource) {
    759   // TODO(henrika): extend test when mono output is supported.
    760   EXPECT_EQ(1, playout_channels());
    761   NiceMock<MockAudioTransport> mock(kPlayout);
    762   const int num_callbacks = kFilePlayTimeInSec * kNumCallbacksPerSecond;
    763   std::string file_name = GetFileName(playout_sample_rate());
    764   rtc::scoped_ptr<FileAudioStream> file_audio_stream(
    765       new FileAudioStream(num_callbacks, file_name, playout_sample_rate()));
    766   mock.HandleCallbacks(test_is_done_.get(), file_audio_stream.get(),
    767                        num_callbacks);
    768   // SetMaxPlayoutVolume();
    769   EXPECT_EQ(0, audio_device()->RegisterAudioCallback(&mock));
    770   StartPlayout();
    771   test_is_done_->Wait(kTestTimeOutInMilliseconds);
    772   StopPlayout();
    773 }
    774 
    775 TEST_F(AudioDeviceTest, Devices) {
    776   // Device enumeration is not supported. Verify fixed values only.
    777   EXPECT_EQ(1, audio_device()->PlayoutDevices());
    778   EXPECT_EQ(1, audio_device()->RecordingDevices());
    779 }
    780 
    781 // Start playout and recording and store recorded data in an intermediate FIFO
    782 // buffer from which the playout side then reads its samples in the same order
    783 // as they were stored. Under ideal circumstances, a callback sequence would
    784 // look like: ...+-+-+-+-+-+-+-..., where '+' means 'packet recorded' and '-'
    785 // means 'packet played'. Under such conditions, the FIFO would only contain
    786 // one packet on average. However, under more realistic conditions, the size
    787 // of the FIFO will vary more due to an unbalance between the two sides.
    788 // This test tries to verify that the device maintains a balanced callback-
    789 // sequence by running in loopback for ten seconds while measuring the size
    790 // (max and average) of the FIFO. The size of the FIFO is increased by the
    791 // recording side and decreased by the playout side.
    792 // TODO(henrika): tune the final test parameters after running tests on several
    793 // different devices.
    794 TEST_F(AudioDeviceTest, RunPlayoutAndRecordingInFullDuplex) {
    795   EXPECT_EQ(record_channels(), playout_channels());
    796   EXPECT_EQ(record_sample_rate(), playout_sample_rate());
    797   NiceMock<MockAudioTransport> mock(kPlayout | kRecording);
    798   rtc::scoped_ptr<FifoAudioStream> fifo_audio_stream(
    799       new FifoAudioStream(playout_frames_per_10ms_buffer()));
    800   mock.HandleCallbacks(test_is_done_.get(), fifo_audio_stream.get(),
    801                        kFullDuplexTimeInSec * kNumCallbacksPerSecond);
    802   // SetMaxPlayoutVolume();
    803   EXPECT_EQ(0, audio_device()->RegisterAudioCallback(&mock));
    804   StartRecording();
    805   StartPlayout();
    806   test_is_done_->Wait(
    807       std::max(kTestTimeOutInMilliseconds, 1000 * kFullDuplexTimeInSec));
    808   StopPlayout();
    809   StopRecording();
    810   EXPECT_LE(fifo_audio_stream->average_size(), 10u);
    811   EXPECT_LE(fifo_audio_stream->largest_size(), 20u);
    812 }
    813 
    814 // Measures loopback latency and reports the min, max and average values for
    815 // a full duplex audio session.
    816 // The latency is measured like so:
    817 // - Insert impulses periodically on the output side.
    818 // - Detect the impulses on the input side.
    819 // - Measure the time difference between the transmit time and receive time.
    820 // - Store time differences in a vector and calculate min, max and average.
    821 // This test requires a special hardware called Audio Loopback Dongle.
    822 // See http://source.android.com/devices/audio/loopback.html for details.
    823 TEST_F(AudioDeviceTest, DISABLED_MeasureLoopbackLatency) {
    824   EXPECT_EQ(record_channels(), playout_channels());
    825   EXPECT_EQ(record_sample_rate(), playout_sample_rate());
    826   NiceMock<MockAudioTransport> mock(kPlayout | kRecording);
    827   rtc::scoped_ptr<LatencyMeasuringAudioStream> latency_audio_stream(
    828       new LatencyMeasuringAudioStream(playout_frames_per_10ms_buffer()));
    829   mock.HandleCallbacks(test_is_done_.get(), latency_audio_stream.get(),
    830                        kMeasureLatencyTimeInSec * kNumCallbacksPerSecond);
    831   EXPECT_EQ(0, audio_device()->RegisterAudioCallback(&mock));
    832   // SetMaxPlayoutVolume();
    833   // DisableBuiltInAECIfAvailable();
    834   StartRecording();
    835   StartPlayout();
    836   test_is_done_->Wait(
    837       std::max(kTestTimeOutInMilliseconds, 1000 * kMeasureLatencyTimeInSec));
    838   StopPlayout();
    839   StopRecording();
    840   // Verify that the correct number of transmitted impulses are detected.
    841   EXPECT_EQ(latency_audio_stream->num_latency_values(),
    842             static_cast<size_t>(
    843                 kImpulseFrequencyInHz * kMeasureLatencyTimeInSec - 1));
    844   latency_audio_stream->PrintResults();
    845 }
    846 
    847 }  // namespace webrtc
    848