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
34using std::cout;
35using std::endl;
36using ::testing::_;
37using ::testing::AtLeast;
38using ::testing::Gt;
39using ::testing::Invoke;
40using ::testing::NiceMock;
41using ::testing::NotNull;
42using ::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
52namespace 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.
56static const size_t kNumCallbacks = 10;
57// Max amount of time we wait for an event to be set while counting callbacks.
58static const int kTestTimeOutInMilliseconds = 10 * 1000;
59// Number of bits per PCM audio sample.
60static const size_t kBitsPerSample = 16;
61// Number of bytes per PCM audio sample.
62static const size_t kBytesPerSample = kBitsPerSample / 8;
63// Average number of audio callbacks per second assuming 10ms packet size.
64static const size_t kNumCallbacksPerSecond = 100;
65// Play out a test file during this time (unit is in seconds).
66static const int kFilePlayTimeInSec = 15;
67// Run the full-duplex test during this time (unit is in seconds).
68// Note that first |kNumIgnoreFirstCallbacks| are ignored.
69static 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.
73static 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.
76static 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.
80static 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.
83static const int kImpulseThreshold = 50;
84static const char kTag[] = "[..........] ";
85
86enum 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.
94class 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.
105class 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.
160class 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.
246class 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.
361class 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.
491class 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
603TEST_F(AudioDeviceTest, ConstructDestruct) {
604  // Using the test fixture to create and destruct the audio device module.
605}
606
607TEST_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.
616TEST_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.
625TEST_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.
636TEST_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.
648TEST_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.
701TEST_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.
716TEST_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.
734TEST_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.
758TEST_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
775TEST_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.
794TEST_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.
823TEST_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