audio_renderer_mixer_unittest.cc revision 46d4c2bc3267f3f028f39e7e311b0f89aba2e4fd
15821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Copyright (c) 2012 The Chromium Authors. All rights reserved.
25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be
35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// found in the LICENSE file.
45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
55821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// MSVC++ requires this to be set before any other includes to get M_PI.
65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#define _USE_MATH_DEFINES
75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <cmath>
85821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
95821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/bind.h"
105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/bind_helpers.h"
115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/memory/scoped_ptr.h"
125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/memory/scoped_vector.h"
132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "base/synchronization/waitable_event.h"
142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "base/threading/platform_thread.h"
155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "media/base/audio_renderer_mixer.h"
165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "media/base/audio_renderer_mixer_input.h"
175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "media/base/fake_audio_render_callback.h"
185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "media/base/mock_audio_renderer_sink.h"
195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "testing/gmock/include/gmock/gmock.h"
205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "testing/gtest/include/gtest/gtest.h"
215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace media {
235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Parameters which control the many input case tests.
2568043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)const int kMixerInputs = 8;
2668043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)const int kMixerCycles = 3;
275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Parameters used for testing.
2968043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)const int kBitsPerChannel = 32;
3068043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)const ChannelLayout kChannelLayout = CHANNEL_LAYOUT_STEREO;
3168043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)const int kHighLatencyBufferSize = 8192;
3268043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)const int kLowLatencyBufferSize = 256;
335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Number of full sine wave cycles for each Render() call.
3568043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)const int kSineCycles = 4;
365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Tuple of <input sampling rate, output sampling rate, epsilon>.
385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)typedef std::tr1::tuple<int, int, double> AudioRendererMixerTestData;
395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class AudioRendererMixerTest
405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    : public testing::TestWithParam<AudioRendererMixerTestData> {
415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public:
425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  AudioRendererMixerTest()
435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      : epsilon_(std::tr1::get<2>(GetParam())),
445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        half_fill_(false) {
455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Create input and output parameters based on test parameters.
465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    input_parameters_ = AudioParameters(
475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        AudioParameters::AUDIO_PCM_LINEAR, kChannelLayout,
485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        std::tr1::get<0>(GetParam()), kBitsPerChannel, kHighLatencyBufferSize);
495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    output_parameters_ = AudioParameters(
505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        AudioParameters::AUDIO_PCM_LOW_LATENCY, kChannelLayout,
515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        std::tr1::get<1>(GetParam()), 16, kLowLatencyBufferSize);
525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    sink_ = new MockAudioRendererSink();
5446d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)    EXPECT_CALL(*sink_, Start());
5546d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)    EXPECT_CALL(*sink_, Stop());
565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    mixer_.reset(new AudioRendererMixer(
585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        input_parameters_, output_parameters_, sink_));
595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    mixer_callback_ = sink_->callback();
605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    audio_bus_ = AudioBus::Create(output_parameters_);
625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    expected_audio_bus_ = AudioBus::Create(output_parameters_);
635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Allocate one callback for generating expected results.
655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    double step = kSineCycles / static_cast<double>(
665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        output_parameters_.frames_per_buffer());
675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    expected_callback_.reset(new FakeAudioRenderCallback(step));
685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  AudioRendererMixer* GetMixer(const AudioParameters& params) {
715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return mixer_.get();
725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  MOCK_METHOD1(RemoveMixer, void(const AudioParameters&));
755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void InitializeInputs(int count) {
775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    mixer_inputs_.reserve(count);
785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    fake_callbacks_.reserve(count);
795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Setup FakeAudioRenderCallback step to compensate for resampling.
812a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    double scale_factor = input_parameters_.sample_rate() /
822a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        static_cast<double>(output_parameters_.sample_rate());
835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    double step = kSineCycles / (scale_factor *
845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        static_cast<double>(output_parameters_.frames_per_buffer()));
855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    for (int i = 0; i < count; ++i) {
875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      fake_callbacks_.push_back(new FakeAudioRenderCallback(step));
885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      mixer_inputs_.push_back(new AudioRendererMixerInput(
895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          base::Bind(&AudioRendererMixerTest::GetMixer,
905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                     base::Unretained(this)),
915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          base::Bind(&AudioRendererMixerTest::RemoveMixer,
925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                     base::Unretained(this))));
935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      mixer_inputs_[i]->Initialize(input_parameters_, fake_callbacks_[i]);
945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      mixer_inputs_[i]->SetVolume(1.0f);
955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    EXPECT_CALL(*this, RemoveMixer(testing::_)).Times(count);
975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
992a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  bool ValidateAudioData(int index, int frames, float scale, double epsilon) {
1005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    for (int i = 0; i < audio_bus_->channels(); ++i) {
1015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      for (int j = index; j < frames; j++) {
1025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        double error = fabs(audio_bus_->channel(i)[j] -
1035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            expected_audio_bus_->channel(i)[j] * scale);
1042a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        if (error > epsilon) {
1055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          EXPECT_NEAR(expected_audio_bus_->channel(i)[j] * scale,
1062a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                      audio_bus_->channel(i)[j], epsilon)
1075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)              << " i=" << i << ", j=" << j;
1085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          return false;
1095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        }
1105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
1115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
1125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return true;
1135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  bool ValidateAudioData(int index, int frames, float scale) {
1162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return ValidateAudioData(index, frames, scale, epsilon_);
1172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
1185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  bool RenderAndValidateAudioData(float scale) {
1205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (half_fill_) {
1215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      for (size_t i = 0; i < fake_callbacks_.size(); ++i)
1225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        fake_callbacks_[i]->set_half_fill(true);
1235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      expected_callback_->set_half_fill(true);
1242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      // Initialize the AudioBus completely or we'll run into Valgrind problems
1252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      // during the verification step below.
1265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      expected_audio_bus_->Zero();
1275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
1285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Render actual audio data.
1305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    int frames = mixer_callback_->Render(audio_bus_.get(), 0);
1315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (frames != audio_bus_->frames())
1325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return false;
1335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Render expected audio data (without scaling).
1355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    expected_callback_->Render(expected_audio_bus_.get(), 0);
1365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (half_fill_) {
1382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      // In this case, just verify that every frame was initialized, this will
1392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      // only fail under tooling such as valgrind.
1402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      return ValidateAudioData(
1412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)          0, frames, 0, std::numeric_limits<double>::max());
1425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    } else {
1435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return ValidateAudioData(0, frames, scale);
1445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
1455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Fill |audio_bus_| fully with |value|.
1485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void FillAudioData(float value) {
1495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    for (int i = 0; i < audio_bus_->channels(); ++i) {
1505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      std::fill(audio_bus_->channel(i),
1515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                audio_bus_->channel(i) + audio_bus_->frames(), value);
1525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
1535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Verify silence when mixer inputs are in pre-Start() and post-Start().
1565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void StartTest(int inputs) {
1575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    InitializeInputs(inputs);
1585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Verify silence before any inputs have been started.  Fill the buffer
1605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // before hand with non-zero data to ensure we get zeros back.
1615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    FillAudioData(1.0f);
1625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    EXPECT_TRUE(RenderAndValidateAudioData(0.0f));
1635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Start() all even numbered mixer inputs and ensure we still get silence.
1655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    for (size_t i = 0; i < mixer_inputs_.size(); i += 2)
1665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      mixer_inputs_[i]->Start();
1675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    FillAudioData(1.0f);
1685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    EXPECT_TRUE(RenderAndValidateAudioData(0.0f));
1695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Start() all mixer inputs and ensure we still get silence.
1715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    for (size_t i = 1; i < mixer_inputs_.size(); i += 2)
1725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      mixer_inputs_[i]->Start();
1735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    FillAudioData(1.0f);
1745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    EXPECT_TRUE(RenderAndValidateAudioData(0.0f));
1755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    for (size_t i = 0; i < mixer_inputs_.size(); ++i)
1775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      mixer_inputs_[i]->Stop();
1785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Verify output when mixer inputs are in post-Play() state.
1815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void PlayTest(int inputs) {
1825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    InitializeInputs(inputs);
1835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Play() all mixer inputs and ensure we get the right values.
1855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    for (size_t i = 0; i < mixer_inputs_.size(); ++i) {
1865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      mixer_inputs_[i]->Start();
1875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      mixer_inputs_[i]->Play();
1885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
1895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    for (int i = 0; i < kMixerCycles; ++i)
1915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      ASSERT_TRUE(RenderAndValidateAudioData(mixer_inputs_.size()));
1925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    for (size_t i = 0; i < mixer_inputs_.size(); ++i)
1945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      mixer_inputs_[i]->Stop();
1955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Verify volume adjusted output when mixer inputs are in post-Play() state.
1985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void PlayVolumeAdjustedTest(int inputs) {
1995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    InitializeInputs(inputs);
2005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    for (size_t i = 0; i < mixer_inputs_.size(); ++i) {
2025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      mixer_inputs_[i]->Start();
2035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      mixer_inputs_[i]->Play();
2045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
2055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Set a different volume for each mixer input and verify the results.
2075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    float total_scale = 0;
2085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    for (size_t i = 0; i < mixer_inputs_.size(); ++i) {
2095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      float volume = static_cast<float>(i) / mixer_inputs_.size();
2105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      total_scale += volume;
2115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      EXPECT_TRUE(mixer_inputs_[i]->SetVolume(volume));
2125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
2135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    for (int i = 0; i < kMixerCycles; ++i)
2145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      ASSERT_TRUE(RenderAndValidateAudioData(total_scale));
2155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    for (size_t i = 0; i < mixer_inputs_.size(); ++i)
2175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      mixer_inputs_[i]->Stop();
2185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Verify output when mixer inputs can only partially fulfill a Render().
2215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void PlayPartialRenderTest(int inputs) {
2225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    InitializeInputs(inputs);
2235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    for (size_t i = 0; i < mixer_inputs_.size(); ++i) {
2255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      mixer_inputs_[i]->Start();
2265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      mixer_inputs_[i]->Play();
2275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
2285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Verify a properly filled buffer when half filled (remainder zeroed).
2305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    half_fill_ = true;
2315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ASSERT_TRUE(RenderAndValidateAudioData(mixer_inputs_.size()));
2325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    for (size_t i = 0; i < mixer_inputs_.size(); ++i)
2345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      mixer_inputs_[i]->Stop();
2355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Verify output when mixer inputs are in Pause() state.
2385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void PauseTest(int inputs) {
2395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    InitializeInputs(inputs);
2405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    for (size_t i = 0; i < mixer_inputs_.size(); ++i) {
2425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      mixer_inputs_[i]->Start();
2435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      mixer_inputs_[i]->Play();
2445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
2455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Pause() all even numbered mixer inputs and ensure we get the right value.
2475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    for (size_t i = 0; i < mixer_inputs_.size(); i += 2)
248c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      mixer_inputs_[i]->Pause();
2495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    for (int i = 0; i < kMixerCycles; ++i)
2505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      ASSERT_TRUE(RenderAndValidateAudioData(mixer_inputs_.size() / 2));
2515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    for (size_t i = 0; i < mixer_inputs_.size(); ++i)
2535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      mixer_inputs_[i]->Stop();
2545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Verify output when mixer inputs are in post-Stop() state.
2575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void StopTest(int inputs) {
2585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    InitializeInputs(inputs);
2595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Start() and Stop() all inputs.
2615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    for (size_t i = 0; i < mixer_inputs_.size(); ++i) {
2625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      mixer_inputs_[i]->Start();
2635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      mixer_inputs_[i]->Stop();
2645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
2655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Verify we get silence back; fill |audio_bus_| before hand to be sure.
2675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    FillAudioData(1.0f);
2685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    EXPECT_TRUE(RenderAndValidateAudioData(0.0f));
2695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) protected:
2725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual ~AudioRendererMixerTest() {}
2735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  scoped_refptr<MockAudioRendererSink> sink_;
2755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  scoped_ptr<AudioRendererMixer> mixer_;
2765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  AudioRendererSink::RenderCallback* mixer_callback_;
2775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  AudioParameters input_parameters_;
2785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  AudioParameters output_parameters_;
2795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  scoped_ptr<AudioBus> audio_bus_;
2805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  scoped_ptr<AudioBus> expected_audio_bus_;
2815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::vector< scoped_refptr<AudioRendererMixerInput> > mixer_inputs_;
2825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ScopedVector<FakeAudioRenderCallback> fake_callbacks_;
2835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  scoped_ptr<FakeAudioRenderCallback> expected_callback_;
2845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  double epsilon_;
2855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bool half_fill_;
2865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DISALLOW_COPY_AND_ASSIGN(AudioRendererMixerTest);
2885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
2895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2902a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)class AudioRendererMixerBehavioralTest : public AudioRendererMixerTest {};
2912a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2922a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)ACTION_P(SignalEvent, event) {
2932a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  event->Signal();
2942a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
2952a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Verify a mixer with no inputs returns silence for all requested frames.
2975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TEST_P(AudioRendererMixerTest, NoInputs) {
2985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  FillAudioData(1.0f);
2995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_TRUE(RenderAndValidateAudioData(0.0f));
3005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Test mixer output with one input in the pre-Start() and post-Start() state.
3035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TEST_P(AudioRendererMixerTest, OneInputStart) {
3045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  StartTest(1);
3055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Test mixer output with many inputs in the pre-Start() and post-Start() state.
3085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TEST_P(AudioRendererMixerTest, ManyInputStart) {
3095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  StartTest(kMixerInputs);
3105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Test mixer output with one input in the post-Play() state.
3135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TEST_P(AudioRendererMixerTest, OneInputPlay) {
3145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  PlayTest(1);
3155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Test mixer output with many inputs in the post-Play() state.
3185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TEST_P(AudioRendererMixerTest, ManyInputPlay) {
3195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  PlayTest(kMixerInputs);
3205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Test volume adjusted mixer output with one input in the post-Play() state.
3235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TEST_P(AudioRendererMixerTest, OneInputPlayVolumeAdjusted) {
3245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  PlayVolumeAdjustedTest(1);
3255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Test volume adjusted mixer output with many inputs in the post-Play() state.
3285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TEST_P(AudioRendererMixerTest, ManyInputPlayVolumeAdjusted) {
3295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  PlayVolumeAdjustedTest(kMixerInputs);
3305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Test mixer output with one input and partial Render() in post-Play() state.
3335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TEST_P(AudioRendererMixerTest, OneInputPlayPartialRender) {
3345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  PlayPartialRenderTest(1);
3355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Test mixer output with many inputs and partial Render() in post-Play() state.
3385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TEST_P(AudioRendererMixerTest, ManyInputPlayPartialRender) {
3395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  PlayPartialRenderTest(kMixerInputs);
3405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Test mixer output with one input in the post-Pause() state.
3435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TEST_P(AudioRendererMixerTest, OneInputPause) {
3445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  PauseTest(1);
3455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Test mixer output with many inputs in the post-Pause() state.
3485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TEST_P(AudioRendererMixerTest, ManyInputPause) {
3495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  PauseTest(kMixerInputs);
3505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Test mixer output with one input in the post-Stop() state.
3535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TEST_P(AudioRendererMixerTest, OneInputStop) {
3545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  StopTest(1);
3555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Test mixer output with many inputs in the post-Stop() state.
3585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TEST_P(AudioRendererMixerTest, ManyInputStop) {
3595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  StopTest(kMixerInputs);
3605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Test mixer with many inputs in mixed post-Stop() and post-Play() states.
3635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TEST_P(AudioRendererMixerTest, ManyInputMixedStopPlay) {
3645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  InitializeInputs(kMixerInputs);
3655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Start() all inputs.
3675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (size_t i = 0; i < mixer_inputs_.size(); ++i)
3685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    mixer_inputs_[i]->Start();
3695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Stop() all even numbered mixer inputs and Play() all odd numbered inputs
3715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // and ensure we get the right value.
3725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (size_t i = 1; i < mixer_inputs_.size(); i += 2) {
3735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    mixer_inputs_[i - 1]->Stop();
3745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    mixer_inputs_[i]->Play();
3755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
3765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ASSERT_TRUE(RenderAndValidateAudioData(std::max(
3775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      mixer_inputs_.size() / 2, static_cast<size_t>(1))));
3785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (size_t i = 1; i < mixer_inputs_.size(); i += 2)
3805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    mixer_inputs_[i]->Stop();
3815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3832a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)TEST_P(AudioRendererMixerBehavioralTest, OnRenderError) {
3845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  InitializeInputs(kMixerInputs);
3855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (size_t i = 0; i < mixer_inputs_.size(); ++i) {
3865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    mixer_inputs_[i]->Start();
3872a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    mixer_inputs_[i]->Play();
3885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    EXPECT_CALL(*fake_callbacks_[i], OnRenderError()).Times(1);
3895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
3905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  mixer_callback_->OnRenderError();
3925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (size_t i = 0; i < mixer_inputs_.size(); ++i)
3935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    mixer_inputs_[i]->Stop();
3945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
39646d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)TEST_P(AudioRendererMixerBehavioralTest, OnRenderErrorPausedInput) {
39746d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  InitializeInputs(kMixerInputs);
39846d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)
39946d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  for (size_t i = 0; i < mixer_inputs_.size(); ++i)
40046d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)    EXPECT_CALL(*fake_callbacks_[i], OnRenderError()).Times(1);
40146d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)
40246d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  // Fire the error before attaching any inputs.  Ensure an error is recieved
40346d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  // even if the input is not connected.
40446d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  mixer_callback_->OnRenderError();
40546d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)
40646d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  for (size_t i = 0; i < mixer_inputs_.size(); ++i)
40746d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)    mixer_inputs_[i]->Stop();
40846d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)}
40946d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)
4105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Ensure constructing an AudioRendererMixerInput, but not initializing it does
4115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// not call RemoveMixer().
4122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)TEST_P(AudioRendererMixerBehavioralTest, NoInitialize) {
4135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_CALL(*this, RemoveMixer(testing::_)).Times(0);
4145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  scoped_refptr<AudioRendererMixerInput> audio_renderer_mixer =
4155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      new AudioRendererMixerInput(
4165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          base::Bind(&AudioRendererMixerTest::GetMixer,
4175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                     base::Unretained(this)),
4185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          base::Bind(&AudioRendererMixerTest::RemoveMixer,
4195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                     base::Unretained(this)));
4205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
4215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// Ensure the physical stream is paused after a certain amount of time with no
4232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// inputs playing.  The test will hang if the behavior is incorrect.
4242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)TEST_P(AudioRendererMixerBehavioralTest, MixerPausesStream) {
4252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  const base::TimeDelta kPauseTime = base::TimeDelta::FromMilliseconds(500);
4262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // This value can't be too low or valgrind, tsan will timeout on the bots.
4272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  const base::TimeDelta kTestTimeout = 10 * kPauseTime;
4282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  mixer_->set_pause_delay_for_testing(kPauseTime);
4292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
4302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  base::WaitableEvent pause_event(true, false);
431868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  EXPECT_CALL(*sink_.get(), Pause()).Times(2)
432868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      .WillRepeatedly(SignalEvent(&pause_event));
4332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  InitializeInputs(1);
4342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
4352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Ensure never playing the input results in a sink pause.
4362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  const base::TimeDelta kSleepTime = base::TimeDelta::FromMilliseconds(100);
4377d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  base::TimeTicks start_time = base::TimeTicks::Now();
4382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  while (!pause_event.IsSignaled()) {
4392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    mixer_callback_->Render(audio_bus_.get(), 0);
4402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    base::PlatformThread::Sleep(kSleepTime);
4417d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)    ASSERT_TRUE(base::TimeTicks::Now() - start_time < kTestTimeout);
4422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
4432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  pause_event.Reset();
4442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
4452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Playing the input for the first time should cause a sink play.
4462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  mixer_inputs_[0]->Start();
447868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  EXPECT_CALL(*sink_.get(), Play());
4482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  mixer_inputs_[0]->Play();
449c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  mixer_inputs_[0]->Pause();
4502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
4512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Ensure once the input is paused the sink eventually pauses.
4527d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  start_time = base::TimeTicks::Now();
4532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  while (!pause_event.IsSignaled()) {
4542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    mixer_callback_->Render(audio_bus_.get(), 0);
4552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    base::PlatformThread::Sleep(kSleepTime);
4567d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)    ASSERT_TRUE(base::TimeTicks::Now() - start_time < kTestTimeout);
4572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
4582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
4592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  mixer_inputs_[0]->Stop();
4602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
4612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
4625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)INSTANTIATE_TEST_CASE_P(
4635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    AudioRendererMixerTest, AudioRendererMixerTest, testing::Values(
4645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        // No resampling.
4655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        std::tr1::make_tuple(44100, 44100, 0.00000048),
4665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        // Upsampling.
4685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        std::tr1::make_tuple(44100, 48000, 0.033),
4695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        // Downsampling.
4715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        std::tr1::make_tuple(48000, 41000, 0.042)));
4725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// Test cases for behavior which is independent of parameters.  Values() doesn't
4742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// support single item lists and we don't want these test cases to run for every
4752a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// parameter set.
4762a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)INSTANTIATE_TEST_CASE_P(
4772a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    AudioRendererMixerBehavioralTest, AudioRendererMixerBehavioralTest,
4782a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    testing::ValuesIn(std::vector<AudioRendererMixerTestData>(
4792a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        1, std::tr1::make_tuple(44100, 44100, 0))));
4802a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
4815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}  // namespace media
482