Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(264)

Unified Diff: webrtc/modules/audio_device/ios/audio_device_unittest_ios.cc

Issue 2872953002: iOS audio session isInterrupted flag does not get reset correctly: (Closed)
Patch Set: Errant dot Created 3 years, 7 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
Index: webrtc/modules/audio_device/ios/audio_device_unittest_ios.cc
diff --git a/webrtc/modules/audio_device/ios/audio_device_unittest_ios.cc b/webrtc/modules/audio_device/ios/audio_device_unittest_ios.cc
deleted file mode 100644
index 1b7ff5780f9177be6132f184b0b6e4713e904d24..0000000000000000000000000000000000000000
--- a/webrtc/modules/audio_device/ios/audio_device_unittest_ios.cc
+++ /dev/null
@@ -1,825 +0,0 @@
-/*
- * Copyright (c) 2015 The WebRTC project authors. All Rights Reserved.
- *
- * Use of this source code is governed by a BSD-style license
- * that can be found in the LICENSE file in the root of the source
- * tree. An additional intellectual property rights grant can be found
- * in the file PATENTS. All contributing project authors may
- * be found in the AUTHORS file in the root of the source tree.
- */
-
-#include <algorithm>
-#include <limits>
-#include <list>
-#include <memory>
-#include <numeric>
-#include <string>
-#include <vector>
-
-#include "webrtc/base/arraysize.h"
-#include "webrtc/base/criticalsection.h"
-#include "webrtc/base/format_macros.h"
-#include "webrtc/base/logging.h"
-#include "webrtc/base/scoped_ref_ptr.h"
-#include "webrtc/base/timeutils.h"
-#include "webrtc/modules/audio_device/audio_device_impl.h"
-#include "webrtc/modules/audio_device/include/audio_device.h"
-#include "webrtc/modules/audio_device/include/mock_audio_transport.h"
-#include "webrtc/modules/audio_device/ios/audio_device_ios.h"
-#include "webrtc/system_wrappers/include/event_wrapper.h"
-#include "webrtc/system_wrappers/include/sleep.h"
-#include "webrtc/test/gmock.h"
-#include "webrtc/test/gtest.h"
-#include "webrtc/test/testsupport/fileutils.h"
-
-using std::cout;
-using std::endl;
-using ::testing::_;
-using ::testing::AtLeast;
-using ::testing::Gt;
-using ::testing::Invoke;
-using ::testing::NiceMock;
-using ::testing::NotNull;
-using ::testing::Return;
-
-// #define ENABLE_DEBUG_PRINTF
-#ifdef ENABLE_DEBUG_PRINTF
-#define PRINTD(...) fprintf(stderr, __VA_ARGS__);
-#else
-#define PRINTD(...) ((void)0)
-#endif
-#define PRINT(...) fprintf(stderr, __VA_ARGS__);
-
-namespace webrtc {
-
-// Number of callbacks (input or output) the tests waits for before we set
-// an event indicating that the test was OK.
-static const size_t kNumCallbacks = 10;
-// Max amount of time we wait for an event to be set while counting callbacks.
-static const int kTestTimeOutInMilliseconds = 10 * 1000;
-// Number of bits per PCM audio sample.
-static const size_t kBitsPerSample = 16;
-// Number of bytes per PCM audio sample.
-static const size_t kBytesPerSample = kBitsPerSample / 8;
-// Average number of audio callbacks per second assuming 10ms packet size.
-static const size_t kNumCallbacksPerSecond = 100;
-// Play out a test file during this time (unit is in seconds).
-static const int kFilePlayTimeInSec = 15;
-// Run the full-duplex test during this time (unit is in seconds).
-// Note that first |kNumIgnoreFirstCallbacks| are ignored.
-static const int kFullDuplexTimeInSec = 10;
-// Wait for the callback sequence to stabilize by ignoring this amount of the
-// initial callbacks (avoids initial FIFO access).
-// Only used in the RunPlayoutAndRecordingInFullDuplex test.
-static const size_t kNumIgnoreFirstCallbacks = 50;
-// Sets the number of impulses per second in the latency test.
-// TODO(henrika): fine tune this setting for iOS.
-static const int kImpulseFrequencyInHz = 1;
-// Length of round-trip latency measurements. Number of transmitted impulses
-// is kImpulseFrequencyInHz * kMeasureLatencyTimeInSec - 1.
-// TODO(henrika): fine tune this setting for iOS.
-static const int kMeasureLatencyTimeInSec = 5;
-// Utilized in round-trip latency measurements to avoid capturing noise samples.
-// TODO(henrika): fine tune this setting for iOS.
-static const int kImpulseThreshold = 50;
-static const char kTag[] = "[..........] ";
-
-enum TransportType {
- kPlayout = 0x1,
- kRecording = 0x2,
-};
-
-// Interface for processing the audio stream. Real implementations can e.g.
-// run audio in loopback, read audio from a file or perform latency
-// measurements.
-class AudioStreamInterface {
- public:
- virtual void Write(const void* source, size_t num_frames) = 0;
- virtual void Read(void* destination, size_t num_frames) = 0;
-
- protected:
- virtual ~AudioStreamInterface() {}
-};
-
-// Reads audio samples from a PCM file where the file is stored in memory at
-// construction.
-class FileAudioStream : public AudioStreamInterface {
- public:
- FileAudioStream(size_t num_callbacks,
- const std::string& file_name,
- int sample_rate)
- : file_size_in_bytes_(0), sample_rate_(sample_rate), file_pos_(0) {
- file_size_in_bytes_ = test::GetFileSize(file_name);
- sample_rate_ = sample_rate;
- EXPECT_GE(file_size_in_callbacks(), num_callbacks)
- << "Size of test file is not large enough to last during the test.";
- const size_t num_16bit_samples =
- test::GetFileSize(file_name) / kBytesPerSample;
- file_.reset(new int16_t[num_16bit_samples]);
- FILE* audio_file = fopen(file_name.c_str(), "rb");
- EXPECT_NE(audio_file, nullptr);
- size_t num_samples_read =
- fread(file_.get(), sizeof(int16_t), num_16bit_samples, audio_file);
- EXPECT_EQ(num_samples_read, num_16bit_samples);
- fclose(audio_file);
- }
-
- // AudioStreamInterface::Write() is not implemented.
- void Write(const void* source, size_t num_frames) override {}
-
- // Read samples from file stored in memory (at construction) and copy
- // |num_frames| (<=> 10ms) to the |destination| byte buffer.
- void Read(void* destination, size_t num_frames) override {
- memcpy(destination, static_cast<int16_t*>(&file_[file_pos_]),
- num_frames * sizeof(int16_t));
- file_pos_ += num_frames;
- }
-
- int file_size_in_seconds() const {
- return static_cast<int>(
- file_size_in_bytes_ / (kBytesPerSample * sample_rate_));
- }
- size_t file_size_in_callbacks() const {
- return file_size_in_seconds() * kNumCallbacksPerSecond;
- }
-
- private:
- size_t file_size_in_bytes_;
- int sample_rate_;
- std::unique_ptr<int16_t[]> file_;
- size_t file_pos_;
-};
-
-// Simple first in first out (FIFO) class that wraps a list of 16-bit audio
-// buffers of fixed size and allows Write and Read operations. The idea is to
-// store recorded audio buffers (using Write) and then read (using Read) these
-// stored buffers with as short delay as possible when the audio layer needs
-// data to play out. The number of buffers in the FIFO will stabilize under
-// normal conditions since there will be a balance between Write and Read calls.
-// The container is a std::list container and access is protected with a lock
-// since both sides (playout and recording) are driven by its own thread.
-class FifoAudioStream : public AudioStreamInterface {
- public:
- explicit FifoAudioStream(size_t frames_per_buffer)
- : frames_per_buffer_(frames_per_buffer),
- bytes_per_buffer_(frames_per_buffer_ * sizeof(int16_t)),
- fifo_(new AudioBufferList),
- largest_size_(0),
- total_written_elements_(0),
- write_count_(0) {
- EXPECT_NE(fifo_.get(), nullptr);
- }
-
- ~FifoAudioStream() { Flush(); }
-
- // Allocate new memory, copy |num_frames| samples from |source| into memory
- // and add pointer to the memory location to end of the list.
- // Increases the size of the FIFO by one element.
- void Write(const void* source, size_t num_frames) override {
- ASSERT_EQ(num_frames, frames_per_buffer_);
- PRINTD("+");
- if (write_count_++ < kNumIgnoreFirstCallbacks) {
- return;
- }
- int16_t* memory = new int16_t[frames_per_buffer_];
- memcpy(static_cast<int16_t*>(&memory[0]), source, bytes_per_buffer_);
- rtc::CritScope lock(&lock_);
- fifo_->push_back(memory);
- const size_t size = fifo_->size();
- if (size > largest_size_) {
- largest_size_ = size;
- PRINTD("(%" PRIuS ")", largest_size_);
- }
- total_written_elements_ += size;
- }
-
- // Read pointer to data buffer from front of list, copy |num_frames| of stored
- // data into |destination| and delete the utilized memory allocation.
- // Decreases the size of the FIFO by one element.
- void Read(void* destination, size_t num_frames) override {
- ASSERT_EQ(num_frames, frames_per_buffer_);
- PRINTD("-");
- rtc::CritScope lock(&lock_);
- if (fifo_->empty()) {
- memset(destination, 0, bytes_per_buffer_);
- } else {
- int16_t* memory = fifo_->front();
- fifo_->pop_front();
- memcpy(destination, static_cast<int16_t*>(&memory[0]), bytes_per_buffer_);
- delete memory;
- }
- }
-
- size_t size() const { return fifo_->size(); }
-
- size_t largest_size() const { return largest_size_; }
-
- size_t average_size() const {
- return (total_written_elements_ == 0)
- ? 0.0
- : 0.5 +
- static_cast<float>(total_written_elements_) /
- (write_count_ - kNumIgnoreFirstCallbacks);
- }
-
- private:
- void Flush() {
- for (auto it = fifo_->begin(); it != fifo_->end(); ++it) {
- delete *it;
- }
- fifo_->clear();
- }
-
- using AudioBufferList = std::list<int16_t*>;
- rtc::CriticalSection lock_;
- const size_t frames_per_buffer_;
- const size_t bytes_per_buffer_;
- std::unique_ptr<AudioBufferList> fifo_;
- size_t largest_size_;
- size_t total_written_elements_;
- size_t write_count_;
-};
-
-// Inserts periodic impulses and measures the latency between the time of
-// transmission and time of receiving the same impulse.
-// Usage requires a special hardware called Audio Loopback Dongle.
-// See http://source.android.com/devices/audio/loopback.html for details.
-class LatencyMeasuringAudioStream : public AudioStreamInterface {
- public:
- explicit LatencyMeasuringAudioStream(size_t frames_per_buffer)
- : frames_per_buffer_(frames_per_buffer),
- bytes_per_buffer_(frames_per_buffer_ * sizeof(int16_t)),
- play_count_(0),
- rec_count_(0),
- pulse_time_(0) {}
-
- // Insert periodic impulses in first two samples of |destination|.
- void Read(void* destination, size_t num_frames) override {
- ASSERT_EQ(num_frames, frames_per_buffer_);
- if (play_count_ == 0) {
- PRINT("[");
- }
- play_count_++;
- memset(destination, 0, bytes_per_buffer_);
- if (play_count_ % (kNumCallbacksPerSecond / kImpulseFrequencyInHz) == 0) {
- if (pulse_time_ == 0) {
- pulse_time_ = rtc::TimeMillis();
- }
- PRINT(".");
- const int16_t impulse = std::numeric_limits<int16_t>::max();
- int16_t* ptr16 = static_cast<int16_t*>(destination);
- for (size_t i = 0; i < 2; ++i) {
- ptr16[i] = impulse;
- }
- }
- }
-
- // Detect received impulses in |source|, derive time between transmission and
- // detection and add the calculated delay to list of latencies.
- void Write(const void* source, size_t num_frames) override {
- ASSERT_EQ(num_frames, frames_per_buffer_);
- rec_count_++;
- if (pulse_time_ == 0) {
- // Avoid detection of new impulse response until a new impulse has
- // been transmitted (sets |pulse_time_| to value larger than zero).
- return;
- }
- const int16_t* ptr16 = static_cast<const int16_t*>(source);
- std::vector<int16_t> vec(ptr16, ptr16 + num_frames);
- // Find max value in the audio buffer.
- int max = *std::max_element(vec.begin(), vec.end());
- // Find index (element position in vector) of the max element.
- int index_of_max =
- std::distance(vec.begin(), std::find(vec.begin(), vec.end(), max));
- if (max > kImpulseThreshold) {
- PRINTD("(%d,%d)", max, index_of_max);
- int64_t now_time = rtc::TimeMillis();
- int extra_delay = IndexToMilliseconds(static_cast<double>(index_of_max));
- PRINTD("[%d]", static_cast<int>(now_time - pulse_time_));
- PRINTD("[%d]", extra_delay);
- // Total latency is the difference between transmit time and detection
- // tome plus the extra delay within the buffer in which we detected the
- // received impulse. It is transmitted at sample 0 but can be received
- // at sample N where N > 0. The term |extra_delay| accounts for N and it
- // is a value between 0 and 10ms.
- latencies_.push_back(now_time - pulse_time_ + extra_delay);
- pulse_time_ = 0;
- } else {
- PRINTD("-");
- }
- }
-
- size_t num_latency_values() const { return latencies_.size(); }
-
- int min_latency() const {
- if (latencies_.empty())
- return 0;
- return *std::min_element(latencies_.begin(), latencies_.end());
- }
-
- int max_latency() const {
- if (latencies_.empty())
- return 0;
- return *std::max_element(latencies_.begin(), latencies_.end());
- }
-
- int average_latency() const {
- if (latencies_.empty())
- return 0;
- return 0.5 +
- static_cast<double>(
- std::accumulate(latencies_.begin(), latencies_.end(), 0)) /
- latencies_.size();
- }
-
- void PrintResults() const {
- PRINT("] ");
- for (auto it = latencies_.begin(); it != latencies_.end(); ++it) {
- PRINT("%d ", *it);
- }
- PRINT("\n");
- PRINT("%s[min, max, avg]=[%d, %d, %d] ms\n", kTag, min_latency(),
- max_latency(), average_latency());
- }
-
- int IndexToMilliseconds(double index) const {
- return 10.0 * (index / frames_per_buffer_) + 0.5;
- }
-
- private:
- const size_t frames_per_buffer_;
- const size_t bytes_per_buffer_;
- size_t play_count_;
- size_t rec_count_;
- int64_t pulse_time_;
- std::vector<int> latencies_;
-};
-// Mocks the AudioTransport object and proxies actions for the two callbacks
-// (RecordedDataIsAvailable and NeedMorePlayData) to different implementations
-// of AudioStreamInterface.
-class MockAudioTransportIOS : public test::MockAudioTransport {
- public:
- explicit MockAudioTransportIOS(int type)
- : num_callbacks_(0),
- type_(type),
- play_count_(0),
- rec_count_(0),
- audio_stream_(nullptr) {}
-
- virtual ~MockAudioTransportIOS() {}
-
- // Set default actions of the mock object. We are delegating to fake
- // implementations (of AudioStreamInterface) here.
- void HandleCallbacks(EventWrapper* test_is_done,
- AudioStreamInterface* audio_stream,
- size_t num_callbacks) {
- test_is_done_ = test_is_done;
- audio_stream_ = audio_stream;
- num_callbacks_ = num_callbacks;
- if (play_mode()) {
- ON_CALL(*this, NeedMorePlayData(_, _, _, _, _, _, _, _))
- .WillByDefault(
- Invoke(this, &MockAudioTransportIOS::RealNeedMorePlayData));
- }
- if (rec_mode()) {
- ON_CALL(*this, RecordedDataIsAvailable(_, _, _, _, _, _, _, _, _, _))
- .WillByDefault(Invoke(
- this, &MockAudioTransportIOS::RealRecordedDataIsAvailable));
- }
- }
-
- int32_t RealRecordedDataIsAvailable(const void* audioSamples,
- const size_t nSamples,
- const size_t nBytesPerSample,
- const size_t nChannels,
- const uint32_t samplesPerSec,
- const uint32_t totalDelayMS,
- const int32_t clockDrift,
- const uint32_t currentMicLevel,
- const bool keyPressed,
- uint32_t& newMicLevel) {
- EXPECT_TRUE(rec_mode()) << "No test is expecting these callbacks.";
- rec_count_++;
- // Process the recorded audio stream if an AudioStreamInterface
- // implementation exists.
- if (audio_stream_) {
- audio_stream_->Write(audioSamples, nSamples);
- }
- if (ReceivedEnoughCallbacks()) {
- if (test_is_done_) {
- test_is_done_->Set();
- }
- }
- return 0;
- }
-
- int32_t RealNeedMorePlayData(const size_t nSamples,
- const size_t nBytesPerSample,
- const size_t nChannels,
- const uint32_t samplesPerSec,
- void* audioSamples,
- size_t& nSamplesOut,
- int64_t* elapsed_time_ms,
- int64_t* ntp_time_ms) {
- EXPECT_TRUE(play_mode()) << "No test is expecting these callbacks.";
- play_count_++;
- nSamplesOut = nSamples;
- // Read (possibly processed) audio stream samples to be played out if an
- // AudioStreamInterface implementation exists.
- if (audio_stream_) {
- audio_stream_->Read(audioSamples, nSamples);
- }
- if (ReceivedEnoughCallbacks()) {
- if (test_is_done_) {
- test_is_done_->Set();
- }
- }
- return 0;
- }
-
- bool ReceivedEnoughCallbacks() {
- bool recording_done = false;
- if (rec_mode())
- recording_done = rec_count_ >= num_callbacks_;
- else
- recording_done = true;
-
- bool playout_done = false;
- if (play_mode())
- playout_done = play_count_ >= num_callbacks_;
- else
- playout_done = true;
-
- return recording_done && playout_done;
- }
-
- bool play_mode() const { return type_ & kPlayout; }
- bool rec_mode() const { return type_ & kRecording; }
-
- private:
- EventWrapper* test_is_done_;
- size_t num_callbacks_;
- int type_;
- size_t play_count_;
- size_t rec_count_;
- AudioStreamInterface* audio_stream_;
-};
-
-// AudioDeviceTest test fixture.
-class AudioDeviceTest : public ::testing::Test {
- protected:
- AudioDeviceTest() : test_is_done_(EventWrapper::Create()) {
- old_sev_ = rtc::LogMessage::GetLogToDebug();
- // Set suitable logging level here. Change to rtc::LS_INFO for more verbose
- // output. See webrtc/base/logging.h for complete list of options.
- rtc::LogMessage::LogToDebug(rtc::LS_INFO);
- // Add extra logging fields here (timestamps and thread id).
- // rtc::LogMessage::LogTimestamps();
- rtc::LogMessage::LogThreads();
- // Creates an audio device using a default audio layer.
- audio_device_ = CreateAudioDevice(AudioDeviceModule::kPlatformDefaultAudio);
- EXPECT_NE(audio_device_.get(), nullptr);
- EXPECT_EQ(0, audio_device_->Init());
- EXPECT_EQ(0,
- audio_device()->GetPlayoutAudioParameters(&playout_parameters_));
- EXPECT_EQ(0, audio_device()->GetRecordAudioParameters(&record_parameters_));
- }
- virtual ~AudioDeviceTest() {
- EXPECT_EQ(0, audio_device_->Terminate());
- rtc::LogMessage::LogToDebug(old_sev_);
- }
-
- int playout_sample_rate() const { return playout_parameters_.sample_rate(); }
- int record_sample_rate() const { return record_parameters_.sample_rate(); }
- int playout_channels() const { return playout_parameters_.channels(); }
- int record_channels() const { return record_parameters_.channels(); }
- size_t playout_frames_per_10ms_buffer() const {
- return playout_parameters_.frames_per_10ms_buffer();
- }
- size_t record_frames_per_10ms_buffer() const {
- return record_parameters_.frames_per_10ms_buffer();
- }
-
- rtc::scoped_refptr<AudioDeviceModule> audio_device() const {
- return audio_device_;
- }
-
- AudioDeviceModuleImpl* audio_device_impl() const {
- return static_cast<AudioDeviceModuleImpl*>(audio_device_.get());
- }
-
- AudioDeviceBuffer* audio_device_buffer() const {
- return audio_device_impl()->GetAudioDeviceBuffer();
- }
-
- rtc::scoped_refptr<AudioDeviceModule> CreateAudioDevice(
- AudioDeviceModule::AudioLayer audio_layer) {
- rtc::scoped_refptr<AudioDeviceModule> module(
- AudioDeviceModule::Create(0, audio_layer));
- return module;
- }
-
- // Returns file name relative to the resource root given a sample rate.
- std::string GetFileName(int sample_rate) {
- EXPECT_TRUE(sample_rate == 48000 || sample_rate == 44100 ||
- sample_rate == 16000);
- char fname[64];
- snprintf(fname, sizeof(fname), "audio_device/audio_short%d",
- sample_rate / 1000);
- std::string file_name(webrtc::test::ResourcePath(fname, "pcm"));
- EXPECT_TRUE(test::FileExists(file_name));
-#ifdef ENABLE_DEBUG_PRINTF
- PRINTD("file name: %s\n", file_name.c_str());
- const size_t bytes = test::GetFileSize(file_name);
- PRINTD("file size: %" PRIuS " [bytes]\n", bytes);
- PRINTD("file size: %" PRIuS " [samples]\n", bytes / kBytesPerSample);
- const int seconds =
- static_cast<int>(bytes / (sample_rate * kBytesPerSample));
- PRINTD("file size: %d [secs]\n", seconds);
- PRINTD("file size: %" PRIuS " [callbacks]\n",
- seconds * kNumCallbacksPerSecond);
-#endif
- return file_name;
- }
-
- void StartPlayout() {
- EXPECT_FALSE(audio_device()->Playing());
- EXPECT_EQ(0, audio_device()->InitPlayout());
- EXPECT_TRUE(audio_device()->PlayoutIsInitialized());
- EXPECT_EQ(0, audio_device()->StartPlayout());
- EXPECT_TRUE(audio_device()->Playing());
- }
-
- void StopPlayout() {
- EXPECT_EQ(0, audio_device()->StopPlayout());
- EXPECT_FALSE(audio_device()->Playing());
- }
-
- void StartRecording() {
- EXPECT_FALSE(audio_device()->Recording());
- EXPECT_EQ(0, audio_device()->InitRecording());
- EXPECT_TRUE(audio_device()->RecordingIsInitialized());
- EXPECT_EQ(0, audio_device()->StartRecording());
- EXPECT_TRUE(audio_device()->Recording());
- }
-
- void StopRecording() {
- EXPECT_EQ(0, audio_device()->StopRecording());
- EXPECT_FALSE(audio_device()->Recording());
- }
-
- std::unique_ptr<EventWrapper> test_is_done_;
- rtc::scoped_refptr<AudioDeviceModule> audio_device_;
- AudioParameters playout_parameters_;
- AudioParameters record_parameters_;
- rtc::LoggingSeverity old_sev_;
-};
-
-TEST_F(AudioDeviceTest, ConstructDestruct) {
- // Using the test fixture to create and destruct the audio device module.
-}
-
-TEST_F(AudioDeviceTest, InitTerminate) {
- // Initialization is part of the test fixture.
- EXPECT_TRUE(audio_device()->Initialized());
- EXPECT_EQ(0, audio_device()->Terminate());
- EXPECT_FALSE(audio_device()->Initialized());
-}
-
-// Tests that playout can be initiated, started and stopped. No audio callback
-// is registered in this test.
-// Failing when running on real iOS devices: bugs.webrtc.org/6889.
-TEST_F(AudioDeviceTest, DISABLED_StartStopPlayout) {
- StartPlayout();
- StopPlayout();
- StartPlayout();
- StopPlayout();
-}
-
-// Tests that recording can be initiated, started and stopped. No audio callback
-// is registered in this test.
-TEST_F(AudioDeviceTest, StartStopRecording) {
- StartRecording();
- StopRecording();
- StartRecording();
- StopRecording();
-}
-
-// Verify that calling StopPlayout() will leave us in an uninitialized state
-// which will require a new call to InitPlayout(). This test does not call
-// StartPlayout() while being uninitialized since doing so will hit a
-// RTC_DCHECK.
-TEST_F(AudioDeviceTest, StopPlayoutRequiresInitToRestart) {
- EXPECT_EQ(0, audio_device()->InitPlayout());
- EXPECT_EQ(0, audio_device()->StartPlayout());
- EXPECT_EQ(0, audio_device()->StopPlayout());
- EXPECT_FALSE(audio_device()->PlayoutIsInitialized());
-}
-
-// Verify that we can create two ADMs and start playing on the second ADM.
-// Only the first active instance shall activate an audio session and the
-// last active instance shall deactivate the audio session. The test does not
-// explicitly verify correct audio session calls but instead focuses on
-// ensuring that audio starts for both ADMs.
-
-// Failing when running on real iOS devices: bugs.webrtc.org/6889.
-TEST_F(AudioDeviceTest, DISABLED_StartPlayoutOnTwoInstances) {
- // Create and initialize a second/extra ADM instance. The default ADM is
- // created by the test harness.
- rtc::scoped_refptr<AudioDeviceModule> second_audio_device =
- CreateAudioDevice(AudioDeviceModule::kPlatformDefaultAudio);
- EXPECT_NE(second_audio_device.get(), nullptr);
- EXPECT_EQ(0, second_audio_device->Init());
-
- // Start playout for the default ADM but don't wait here. Instead use the
- // upcoming second stream for that. We set the same expectation on number
- // of callbacks as for the second stream.
- NiceMock<MockAudioTransportIOS> mock(kPlayout);
- mock.HandleCallbacks(nullptr, nullptr, 0);
- EXPECT_CALL(
- mock, NeedMorePlayData(playout_frames_per_10ms_buffer(), kBytesPerSample,
- playout_channels(), playout_sample_rate(),
- NotNull(), _, _, _))
- .Times(AtLeast(kNumCallbacks));
- EXPECT_EQ(0, audio_device()->RegisterAudioCallback(&mock));
- StartPlayout();
-
- // Initialize playout for the second ADM. If all is OK, the second ADM shall
- // reuse the audio session activated when the first ADM started playing.
- // This call will also ensure that we avoid a problem related to initializing
- // two different audio unit instances back to back (see webrtc:5166 for
- // details).
- EXPECT_EQ(0, second_audio_device->InitPlayout());
- EXPECT_TRUE(second_audio_device->PlayoutIsInitialized());
-
- // Start playout for the second ADM and verify that it starts as intended.
- // Passing this test ensures that initialization of the second audio unit
- // has been done successfully and that there is no conflict with the already
- // playing first ADM.
- MockAudioTransportIOS mock2(kPlayout);
- mock2.HandleCallbacks(test_is_done_.get(), nullptr, kNumCallbacks);
- EXPECT_CALL(
- mock2, NeedMorePlayData(playout_frames_per_10ms_buffer(), kBytesPerSample,
- playout_channels(), playout_sample_rate(),
- NotNull(), _, _, _))
- .Times(AtLeast(kNumCallbacks));
- EXPECT_EQ(0, second_audio_device->RegisterAudioCallback(&mock2));
- EXPECT_EQ(0, second_audio_device->StartPlayout());
- EXPECT_TRUE(second_audio_device->Playing());
- test_is_done_->Wait(kTestTimeOutInMilliseconds);
- EXPECT_EQ(0, second_audio_device->StopPlayout());
- EXPECT_FALSE(second_audio_device->Playing());
- EXPECT_FALSE(second_audio_device->PlayoutIsInitialized());
-
- EXPECT_EQ(0, second_audio_device->Terminate());
-}
-
-// Start playout and verify that the native audio layer starts asking for real
-// audio samples to play out using the NeedMorePlayData callback.
-TEST_F(AudioDeviceTest, StartPlayoutVerifyCallbacks) {
- MockAudioTransportIOS mock(kPlayout);
- mock.HandleCallbacks(test_is_done_.get(), nullptr, kNumCallbacks);
- EXPECT_CALL(mock, NeedMorePlayData(playout_frames_per_10ms_buffer(),
- kBytesPerSample, playout_channels(),
- playout_sample_rate(), NotNull(), _, _, _))
- .Times(AtLeast(kNumCallbacks));
- EXPECT_EQ(0, audio_device()->RegisterAudioCallback(&mock));
- StartPlayout();
- test_is_done_->Wait(kTestTimeOutInMilliseconds);
- StopPlayout();
-}
-
-// Start recording and verify that the native audio layer starts feeding real
-// audio samples via the RecordedDataIsAvailable callback.
-TEST_F(AudioDeviceTest, StartRecordingVerifyCallbacks) {
- MockAudioTransportIOS mock(kRecording);
- mock.HandleCallbacks(test_is_done_.get(), nullptr, kNumCallbacks);
- EXPECT_CALL(mock,
- RecordedDataIsAvailable(
- NotNull(), record_frames_per_10ms_buffer(), kBytesPerSample,
- record_channels(), record_sample_rate(),
- _, // TODO(henrika): fix delay
- 0, 0, false, _)).Times(AtLeast(kNumCallbacks));
-
- EXPECT_EQ(0, audio_device()->RegisterAudioCallback(&mock));
- StartRecording();
- test_is_done_->Wait(kTestTimeOutInMilliseconds);
- StopRecording();
-}
-
-// Start playout and recording (full-duplex audio) and verify that audio is
-// active in both directions.
-TEST_F(AudioDeviceTest, StartPlayoutAndRecordingVerifyCallbacks) {
- MockAudioTransportIOS mock(kPlayout | kRecording);
- mock.HandleCallbacks(test_is_done_.get(), nullptr, kNumCallbacks);
- EXPECT_CALL(mock, NeedMorePlayData(playout_frames_per_10ms_buffer(),
- kBytesPerSample, playout_channels(),
- playout_sample_rate(), NotNull(), _, _, _))
- .Times(AtLeast(kNumCallbacks));
- EXPECT_CALL(mock,
- RecordedDataIsAvailable(
- NotNull(), record_frames_per_10ms_buffer(), kBytesPerSample,
- record_channels(), record_sample_rate(),
- _, // TODO(henrika): fix delay
- 0, 0, false, _)).Times(AtLeast(kNumCallbacks));
- EXPECT_EQ(0, audio_device()->RegisterAudioCallback(&mock));
- StartPlayout();
- StartRecording();
- test_is_done_->Wait(kTestTimeOutInMilliseconds);
- StopRecording();
- StopPlayout();
-}
-
-// Start playout and read audio from an external PCM file when the audio layer
-// asks for data to play out. Real audio is played out in this test but it does
-// not contain any explicit verification that the audio quality is perfect.
-TEST_F(AudioDeviceTest, RunPlayoutWithFileAsSource) {
- // TODO(henrika): extend test when mono output is supported.
- EXPECT_EQ(1, playout_channels());
- NiceMock<MockAudioTransportIOS> mock(kPlayout);
- const int num_callbacks = kFilePlayTimeInSec * kNumCallbacksPerSecond;
- std::string file_name = GetFileName(playout_sample_rate());
- std::unique_ptr<FileAudioStream> file_audio_stream(
- new FileAudioStream(num_callbacks, file_name, playout_sample_rate()));
- mock.HandleCallbacks(test_is_done_.get(), file_audio_stream.get(),
- num_callbacks);
- // SetMaxPlayoutVolume();
- EXPECT_EQ(0, audio_device()->RegisterAudioCallback(&mock));
- StartPlayout();
- test_is_done_->Wait(kTestTimeOutInMilliseconds);
- StopPlayout();
-}
-
-TEST_F(AudioDeviceTest, Devices) {
- // Device enumeration is not supported. Verify fixed values only.
- EXPECT_EQ(1, audio_device()->PlayoutDevices());
- EXPECT_EQ(1, audio_device()->RecordingDevices());
-}
-
-// Start playout and recording and store recorded data in an intermediate FIFO
-// buffer from which the playout side then reads its samples in the same order
-// as they were stored. Under ideal circumstances, a callback sequence would
-// look like: ...+-+-+-+-+-+-+-..., where '+' means 'packet recorded' and '-'
-// means 'packet played'. Under such conditions, the FIFO would only contain
-// one packet on average. However, under more realistic conditions, the size
-// of the FIFO will vary more due to an unbalance between the two sides.
-// This test tries to verify that the device maintains a balanced callback-
-// sequence by running in loopback for ten seconds while measuring the size
-// (max and average) of the FIFO. The size of the FIFO is increased by the
-// recording side and decreased by the playout side.
-// TODO(henrika): tune the final test parameters after running tests on several
-// different devices.
-TEST_F(AudioDeviceTest, RunPlayoutAndRecordingInFullDuplex) {
- EXPECT_EQ(record_channels(), playout_channels());
- EXPECT_EQ(record_sample_rate(), playout_sample_rate());
- NiceMock<MockAudioTransportIOS> mock(kPlayout | kRecording);
- std::unique_ptr<FifoAudioStream> fifo_audio_stream(
- new FifoAudioStream(playout_frames_per_10ms_buffer()));
- mock.HandleCallbacks(test_is_done_.get(), fifo_audio_stream.get(),
- kFullDuplexTimeInSec * kNumCallbacksPerSecond);
- // SetMaxPlayoutVolume();
- EXPECT_EQ(0, audio_device()->RegisterAudioCallback(&mock));
- StartRecording();
- StartPlayout();
- test_is_done_->Wait(
- std::max(kTestTimeOutInMilliseconds, 1000 * kFullDuplexTimeInSec));
- StopPlayout();
- StopRecording();
- EXPECT_LE(fifo_audio_stream->average_size(), 10u);
- EXPECT_LE(fifo_audio_stream->largest_size(), 20u);
-}
-
-// Measures loopback latency and reports the min, max and average values for
-// a full duplex audio session.
-// The latency is measured like so:
-// - Insert impulses periodically on the output side.
-// - Detect the impulses on the input side.
-// - Measure the time difference between the transmit time and receive time.
-// - Store time differences in a vector and calculate min, max and average.
-// This test requires a special hardware called Audio Loopback Dongle.
-// See http://source.android.com/devices/audio/loopback.html for details.
-TEST_F(AudioDeviceTest, DISABLED_MeasureLoopbackLatency) {
- EXPECT_EQ(record_channels(), playout_channels());
- EXPECT_EQ(record_sample_rate(), playout_sample_rate());
- NiceMock<MockAudioTransportIOS> mock(kPlayout | kRecording);
- std::unique_ptr<LatencyMeasuringAudioStream> latency_audio_stream(
- new LatencyMeasuringAudioStream(playout_frames_per_10ms_buffer()));
- mock.HandleCallbacks(test_is_done_.get(), latency_audio_stream.get(),
- kMeasureLatencyTimeInSec * kNumCallbacksPerSecond);
- EXPECT_EQ(0, audio_device()->RegisterAudioCallback(&mock));
- // SetMaxPlayoutVolume();
- // DisableBuiltInAECIfAvailable();
- StartRecording();
- StartPlayout();
- test_is_done_->Wait(
- std::max(kTestTimeOutInMilliseconds, 1000 * kMeasureLatencyTimeInSec));
- StopPlayout();
- StopRecording();
- // Verify that the correct number of transmitted impulses are detected.
- EXPECT_EQ(latency_audio_stream->num_latency_values(),
- static_cast<size_t>(
- kImpulseFrequencyInHz * kMeasureLatencyTimeInSec - 1));
- latency_audio_stream->PrintResults();
-}
-
-} // namespace webrtc

Powered by Google App Engine
This is Rietveld 408576698