audio_renderer_mixer_unittest.cc revision c2e0dbddbe15c98d52c4786dac06cb8952a8ae6d
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.
255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static const int kMixerInputs = 8;
265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static const int kMixerCycles = 3;
275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Parameters used for testing.
295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static const int kBitsPerChannel = 32;
305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static const ChannelLayout kChannelLayout = CHANNEL_LAYOUT_STEREO;
315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static const int kHighLatencyBufferSize = 8192;
325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static const int kLowLatencyBufferSize = 256;
335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static const int kSampleRate = 48000;
345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Number of full sine wave cycles for each Render() call.
365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static const int kSineCycles = 4;
375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Tuple of <input sampling rate, output sampling rate, epsilon>.
395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)typedef std::tr1::tuple<int, int, double> AudioRendererMixerTestData;
405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class AudioRendererMixerTest
415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    : public testing::TestWithParam<AudioRendererMixerTestData> {
425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public:
435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  AudioRendererMixerTest()
445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      : epsilon_(std::tr1::get<2>(GetParam())),
455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        half_fill_(false) {
465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Create input and output parameters based on test parameters.
475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    input_parameters_ = AudioParameters(
485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        AudioParameters::AUDIO_PCM_LINEAR, kChannelLayout,
495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        std::tr1::get<0>(GetParam()), kBitsPerChannel, kHighLatencyBufferSize);
505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    output_parameters_ = AudioParameters(
515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        AudioParameters::AUDIO_PCM_LOW_LATENCY, kChannelLayout,
525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        std::tr1::get<1>(GetParam()), 16, kLowLatencyBufferSize);
535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    sink_ = new MockAudioRendererSink();
555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    EXPECT_CALL(*sink_, Start());
565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    EXPECT_CALL(*sink_, Stop());
575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    mixer_.reset(new AudioRendererMixer(
595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        input_parameters_, output_parameters_, sink_));
605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    mixer_callback_ = sink_->callback();
615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    audio_bus_ = AudioBus::Create(output_parameters_);
635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    expected_audio_bus_ = AudioBus::Create(output_parameters_);
645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Allocate one callback for generating expected results.
665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    double step = kSineCycles / static_cast<double>(
675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        output_parameters_.frames_per_buffer());
685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    expected_callback_.reset(new FakeAudioRenderCallback(step));
695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  AudioRendererMixer* GetMixer(const AudioParameters& params) {
725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return mixer_.get();
735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  MOCK_METHOD1(RemoveMixer, void(const AudioParameters&));
765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void InitializeInputs(int count) {
785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    mixer_inputs_.reserve(count);
795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    fake_callbacks_.reserve(count);
805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Setup FakeAudioRenderCallback step to compensate for resampling.
822a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    double scale_factor = input_parameters_.sample_rate() /
832a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        static_cast<double>(output_parameters_.sample_rate());
845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    double step = kSineCycles / (scale_factor *
855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        static_cast<double>(output_parameters_.frames_per_buffer()));
865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    for (int i = 0; i < count; ++i) {
885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      fake_callbacks_.push_back(new FakeAudioRenderCallback(step));
895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      mixer_inputs_.push_back(new AudioRendererMixerInput(
905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          base::Bind(&AudioRendererMixerTest::GetMixer,
915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                     base::Unretained(this)),
925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          base::Bind(&AudioRendererMixerTest::RemoveMixer,
935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                     base::Unretained(this))));
945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      mixer_inputs_[i]->Initialize(input_parameters_, fake_callbacks_[i]);
955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      mixer_inputs_[i]->SetVolume(1.0f);
965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    EXPECT_CALL(*this, RemoveMixer(testing::_)).Times(count);
985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1002a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  bool ValidateAudioData(int index, int frames, float scale, double epsilon) {
1015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    for (int i = 0; i < audio_bus_->channels(); ++i) {
1025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      for (int j = index; j < frames; j++) {
1035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        double error = fabs(audio_bus_->channel(i)[j] -
1045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            expected_audio_bus_->channel(i)[j] * scale);
1052a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        if (error > epsilon) {
1065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          EXPECT_NEAR(expected_audio_bus_->channel(i)[j] * scale,
1072a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                      audio_bus_->channel(i)[j], epsilon)
1085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)              << " i=" << i << ", j=" << j;
1095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          return false;
1105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        }
1115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
1125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
1135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return true;
1145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  bool ValidateAudioData(int index, int frames, float scale) {
1172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return ValidateAudioData(index, frames, scale, epsilon_);
1182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
1195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  bool RenderAndValidateAudioData(float scale) {
1215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (half_fill_) {
1225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      for (size_t i = 0; i < fake_callbacks_.size(); ++i)
1235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        fake_callbacks_[i]->set_half_fill(true);
1245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      expected_callback_->set_half_fill(true);
1252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      // Initialize the AudioBus completely or we'll run into Valgrind problems
1262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      // during the verification step below.
1275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      expected_audio_bus_->Zero();
1285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
1295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Render actual audio data.
1315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    int frames = mixer_callback_->Render(audio_bus_.get(), 0);
1325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (frames != audio_bus_->frames())
1335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return false;
1345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Render expected audio data (without scaling).
1365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    expected_callback_->Render(expected_audio_bus_.get(), 0);
1375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (half_fill_) {
1392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      // In this case, just verify that every frame was initialized, this will
1402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      // only fail under tooling such as valgrind.
1412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      return ValidateAudioData(
1422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)          0, frames, 0, std::numeric_limits<double>::max());
1435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    } else {
1445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return ValidateAudioData(0, frames, scale);
1455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
1465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Fill |audio_bus_| fully with |value|.
1495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void FillAudioData(float value) {
1505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    for (int i = 0; i < audio_bus_->channels(); ++i) {
1515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      std::fill(audio_bus_->channel(i),
1525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                audio_bus_->channel(i) + audio_bus_->frames(), value);
1535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
1545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Verify silence when mixer inputs are in pre-Start() and post-Start().
1575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void StartTest(int inputs) {
1585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    InitializeInputs(inputs);
1595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Verify silence before any inputs have been started.  Fill the buffer
1615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // before hand with non-zero data to ensure we get zeros back.
1625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    FillAudioData(1.0f);
1635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    EXPECT_TRUE(RenderAndValidateAudioData(0.0f));
1645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Start() all even numbered mixer inputs and ensure we still get silence.
1665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    for (size_t i = 0; i < mixer_inputs_.size(); i += 2)
1675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      mixer_inputs_[i]->Start();
1685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    FillAudioData(1.0f);
1695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    EXPECT_TRUE(RenderAndValidateAudioData(0.0f));
1705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Start() all mixer inputs and ensure we still get silence.
1725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    for (size_t i = 1; i < mixer_inputs_.size(); i += 2)
1735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      mixer_inputs_[i]->Start();
1745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    FillAudioData(1.0f);
1755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    EXPECT_TRUE(RenderAndValidateAudioData(0.0f));
1765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    for (size_t i = 0; i < mixer_inputs_.size(); ++i)
1785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      mixer_inputs_[i]->Stop();
1795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Verify output when mixer inputs are in post-Play() state.
1825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void PlayTest(int inputs) {
1835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    InitializeInputs(inputs);
1845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Play() all mixer inputs and ensure we get the right values.
1865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    for (size_t i = 0; i < mixer_inputs_.size(); ++i) {
1875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      mixer_inputs_[i]->Start();
1885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      mixer_inputs_[i]->Play();
1895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
1905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    for (int i = 0; i < kMixerCycles; ++i)
1925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      ASSERT_TRUE(RenderAndValidateAudioData(mixer_inputs_.size()));
1935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    for (size_t i = 0; i < mixer_inputs_.size(); ++i)
1955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      mixer_inputs_[i]->Stop();
1965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Verify volume adjusted output when mixer inputs are in post-Play() state.
1995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void PlayVolumeAdjustedTest(int inputs) {
2005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    InitializeInputs(inputs);
2015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    for (size_t i = 0; i < mixer_inputs_.size(); ++i) {
2035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      mixer_inputs_[i]->Start();
2045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      mixer_inputs_[i]->Play();
2055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
2065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Set a different volume for each mixer input and verify the results.
2085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    float total_scale = 0;
2095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    for (size_t i = 0; i < mixer_inputs_.size(); ++i) {
2105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      float volume = static_cast<float>(i) / mixer_inputs_.size();
2115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      total_scale += volume;
2125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      EXPECT_TRUE(mixer_inputs_[i]->SetVolume(volume));
2135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
2145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    for (int i = 0; i < kMixerCycles; ++i)
2155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      ASSERT_TRUE(RenderAndValidateAudioData(total_scale));
2165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    for (size_t i = 0; i < mixer_inputs_.size(); ++i)
2185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      mixer_inputs_[i]->Stop();
2195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Verify output when mixer inputs can only partially fulfill a Render().
2225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void PlayPartialRenderTest(int inputs) {
2235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    InitializeInputs(inputs);
2245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    for (size_t i = 0; i < mixer_inputs_.size(); ++i) {
2265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      mixer_inputs_[i]->Start();
2275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      mixer_inputs_[i]->Play();
2285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
2295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Verify a properly filled buffer when half filled (remainder zeroed).
2315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    half_fill_ = true;
2325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ASSERT_TRUE(RenderAndValidateAudioData(mixer_inputs_.size()));
2335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    for (size_t i = 0; i < mixer_inputs_.size(); ++i)
2355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      mixer_inputs_[i]->Stop();
2365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Verify output when mixer inputs are in Pause() state.
2395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void PauseTest(int inputs) {
2405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    InitializeInputs(inputs);
2415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    for (size_t i = 0; i < mixer_inputs_.size(); ++i) {
2435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      mixer_inputs_[i]->Start();
2445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      mixer_inputs_[i]->Play();
2455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
2465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Pause() all even numbered mixer inputs and ensure we get the right value.
2485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    for (size_t i = 0; i < mixer_inputs_.size(); i += 2)
249c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      mixer_inputs_[i]->Pause();
2505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    for (int i = 0; i < kMixerCycles; ++i)
2515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      ASSERT_TRUE(RenderAndValidateAudioData(mixer_inputs_.size() / 2));
2525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    for (size_t i = 0; i < mixer_inputs_.size(); ++i)
2545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      mixer_inputs_[i]->Stop();
2555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Verify output when mixer inputs are in post-Stop() state.
2585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void StopTest(int inputs) {
2595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    InitializeInputs(inputs);
2605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Start() and Stop() all inputs.
2625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    for (size_t i = 0; i < mixer_inputs_.size(); ++i) {
2635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      mixer_inputs_[i]->Start();
2645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      mixer_inputs_[i]->Stop();
2655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
2665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Verify we get silence back; fill |audio_bus_| before hand to be sure.
2685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    FillAudioData(1.0f);
2695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    EXPECT_TRUE(RenderAndValidateAudioData(0.0f));
2705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) protected:
2735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual ~AudioRendererMixerTest() {}
2745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  scoped_refptr<MockAudioRendererSink> sink_;
2765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  scoped_ptr<AudioRendererMixer> mixer_;
2775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  AudioRendererSink::RenderCallback* mixer_callback_;
2785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  AudioParameters input_parameters_;
2795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  AudioParameters output_parameters_;
2805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  scoped_ptr<AudioBus> audio_bus_;
2815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  scoped_ptr<AudioBus> expected_audio_bus_;
2825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::vector< scoped_refptr<AudioRendererMixerInput> > mixer_inputs_;
2835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ScopedVector<FakeAudioRenderCallback> fake_callbacks_;
2845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  scoped_ptr<FakeAudioRenderCallback> expected_callback_;
2855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  double epsilon_;
2865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bool half_fill_;
2875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DISALLOW_COPY_AND_ASSIGN(AudioRendererMixerTest);
2895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
2905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2912a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)class AudioRendererMixerBehavioralTest : public AudioRendererMixerTest {};
2922a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2932a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)ACTION_P(SignalEvent, event) {
2942a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  event->Signal();
2952a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
2962a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Verify a mixer with no inputs returns silence for all requested frames.
2985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TEST_P(AudioRendererMixerTest, NoInputs) {
2995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  FillAudioData(1.0f);
3005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_TRUE(RenderAndValidateAudioData(0.0f));
3015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Test mixer output with one input in the pre-Start() and post-Start() state.
3045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TEST_P(AudioRendererMixerTest, OneInputStart) {
3055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  StartTest(1);
3065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Test mixer output with many inputs in the pre-Start() and post-Start() state.
3095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TEST_P(AudioRendererMixerTest, ManyInputStart) {
3105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  StartTest(kMixerInputs);
3115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Test mixer output with one input in the post-Play() state.
3145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TEST_P(AudioRendererMixerTest, OneInputPlay) {
3155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  PlayTest(1);
3165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Test mixer output with many inputs in the post-Play() state.
3195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TEST_P(AudioRendererMixerTest, ManyInputPlay) {
3205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  PlayTest(kMixerInputs);
3215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Test volume adjusted mixer output with one input in the post-Play() state.
3245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TEST_P(AudioRendererMixerTest, OneInputPlayVolumeAdjusted) {
3255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  PlayVolumeAdjustedTest(1);
3265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Test volume adjusted mixer output with many inputs in the post-Play() state.
3295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TEST_P(AudioRendererMixerTest, ManyInputPlayVolumeAdjusted) {
3305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  PlayVolumeAdjustedTest(kMixerInputs);
3315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Test mixer output with one input and partial Render() in post-Play() state.
3345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TEST_P(AudioRendererMixerTest, OneInputPlayPartialRender) {
3355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  PlayPartialRenderTest(1);
3365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Test mixer output with many inputs and partial Render() in post-Play() state.
3395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TEST_P(AudioRendererMixerTest, ManyInputPlayPartialRender) {
3405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  PlayPartialRenderTest(kMixerInputs);
3415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Test mixer output with one input in the post-Pause() state.
3445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TEST_P(AudioRendererMixerTest, OneInputPause) {
3455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  PauseTest(1);
3465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Test mixer output with many inputs in the post-Pause() state.
3495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TEST_P(AudioRendererMixerTest, ManyInputPause) {
3505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  PauseTest(kMixerInputs);
3515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Test mixer output with one input in the post-Stop() state.
3545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TEST_P(AudioRendererMixerTest, OneInputStop) {
3555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  StopTest(1);
3565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Test mixer output with many inputs in the post-Stop() state.
3595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TEST_P(AudioRendererMixerTest, ManyInputStop) {
3605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  StopTest(kMixerInputs);
3615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Test mixer with many inputs in mixed post-Stop() and post-Play() states.
3645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TEST_P(AudioRendererMixerTest, ManyInputMixedStopPlay) {
3655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  InitializeInputs(kMixerInputs);
3665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Start() all inputs.
3685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (size_t i = 0; i < mixer_inputs_.size(); ++i)
3695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    mixer_inputs_[i]->Start();
3705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Stop() all even numbered mixer inputs and Play() all odd numbered inputs
3725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // and ensure we get the right value.
3735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (size_t i = 1; i < mixer_inputs_.size(); i += 2) {
3745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    mixer_inputs_[i - 1]->Stop();
3755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    mixer_inputs_[i]->Play();
3765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
3775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ASSERT_TRUE(RenderAndValidateAudioData(std::max(
3785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      mixer_inputs_.size() / 2, static_cast<size_t>(1))));
3795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (size_t i = 1; i < mixer_inputs_.size(); i += 2)
3815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    mixer_inputs_[i]->Stop();
3825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3842a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)TEST_P(AudioRendererMixerBehavioralTest, OnRenderError) {
3855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  InitializeInputs(kMixerInputs);
3865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (size_t i = 0; i < mixer_inputs_.size(); ++i) {
3875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    mixer_inputs_[i]->Start();
3882a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    mixer_inputs_[i]->Play();
3895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    EXPECT_CALL(*fake_callbacks_[i], OnRenderError()).Times(1);
3905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
3915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  mixer_callback_->OnRenderError();
3935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (size_t i = 0; i < mixer_inputs_.size(); ++i)
3945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    mixer_inputs_[i]->Stop();
3955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Ensure constructing an AudioRendererMixerInput, but not initializing it does
3985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// not call RemoveMixer().
3992a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)TEST_P(AudioRendererMixerBehavioralTest, NoInitialize) {
4005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_CALL(*this, RemoveMixer(testing::_)).Times(0);
4015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  scoped_refptr<AudioRendererMixerInput> audio_renderer_mixer =
4025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      new AudioRendererMixerInput(
4035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          base::Bind(&AudioRendererMixerTest::GetMixer,
4045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                     base::Unretained(this)),
4055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          base::Bind(&AudioRendererMixerTest::RemoveMixer,
4065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                     base::Unretained(this)));
4075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
4085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4092a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// Ensure the physical stream is paused after a certain amount of time with no
4102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// inputs playing.  The test will hang if the behavior is incorrect.
4112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)TEST_P(AudioRendererMixerBehavioralTest, MixerPausesStream) {
4122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  const base::TimeDelta kPauseTime = base::TimeDelta::FromMilliseconds(500);
4132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // This value can't be too low or valgrind, tsan will timeout on the bots.
4142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  const base::TimeDelta kTestTimeout = 10 * kPauseTime;
4152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  mixer_->set_pause_delay_for_testing(kPauseTime);
4162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
4172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  base::WaitableEvent pause_event(true, false);
418c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  EXPECT_CALL(*sink_, Pause())
4192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      .Times(2).WillRepeatedly(SignalEvent(&pause_event));
4202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  InitializeInputs(1);
4212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
4222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Ensure never playing the input results in a sink pause.
4232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  const base::TimeDelta kSleepTime = base::TimeDelta::FromMilliseconds(100);
4242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  base::Time start_time = base::Time::Now();
4252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  while (!pause_event.IsSignaled()) {
4262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    mixer_callback_->Render(audio_bus_.get(), 0);
4272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    base::PlatformThread::Sleep(kSleepTime);
4282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    ASSERT_TRUE(base::Time::Now() - start_time < kTestTimeout);
4292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
4302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  pause_event.Reset();
4312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
4322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Playing the input for the first time should cause a sink play.
4332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  mixer_inputs_[0]->Start();
4342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_CALL(*sink_, Play());
4352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  mixer_inputs_[0]->Play();
436c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  mixer_inputs_[0]->Pause();
4372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
4382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Ensure once the input is paused the sink eventually pauses.
4392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  start_time = base::Time::Now();
4402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  while (!pause_event.IsSignaled()) {
4412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    mixer_callback_->Render(audio_bus_.get(), 0);
4422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    base::PlatformThread::Sleep(kSleepTime);
4432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    ASSERT_TRUE(base::Time::Now() - start_time < kTestTimeout);
4442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
4452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
4462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  mixer_inputs_[0]->Stop();
4472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
4482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
4495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)INSTANTIATE_TEST_CASE_P(
4505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    AudioRendererMixerTest, AudioRendererMixerTest, testing::Values(
4515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        // No resampling.
4525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        std::tr1::make_tuple(44100, 44100, 0.00000048),
4535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        // Upsampling.
4555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        std::tr1::make_tuple(44100, 48000, 0.033),
4565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        // Downsampling.
4585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        std::tr1::make_tuple(48000, 41000, 0.042)));
4595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// Test cases for behavior which is independent of parameters.  Values() doesn't
4612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// support single item lists and we don't want these test cases to run for every
4622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// parameter set.
4632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)INSTANTIATE_TEST_CASE_P(
4642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    AudioRendererMixerBehavioralTest, AudioRendererMixerBehavioralTest,
4652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    testing::ValuesIn(std::vector<AudioRendererMixerTestData>(
4662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        1, std::tr1::make_tuple(44100, 44100, 0))));
4672a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
4685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}  // namespace media
469