Partial revert of disabling low latency audio for remote desktop.
[chromium-blink-merge.git] / media / base / audio_shifter_unittest.cc
blobe47067e21c4fbd580d403e54b589c0c3612ff7f3
1 // Copyright (c) 2014 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 #include <cmath>
6 #include <vector>
8 #include "media/base/audio_bus.h"
9 #include "media/base/audio_shifter.h"
10 #include "testing/gtest/include/gtest/gtest.h"
12 namespace media {
14 const int kSampleRate = 48000;
15 const int kInputPacketSize = 48;
16 const int kOutputPacketSize = 24;
18 #if GTEST_HAS_COMBINE
20 class AudioShifterTest :
21 public ::testing::TestWithParam<::testing::tuple<int, int, int, bool> > {
22 public:
23 AudioShifterTest()
24 : shifter_(base::TimeDelta::FromMilliseconds(2000),
25 base::TimeDelta::FromMilliseconds(3),
26 base::TimeDelta::FromMilliseconds(100),
27 kSampleRate,
28 2),
29 end2end_latency_(base::TimeDelta::FromMilliseconds(30)),
30 playback_latency_(base::TimeDelta::FromMilliseconds(10)),
31 tag_input_(false),
32 expect_smooth_output_(true),
33 input_sample_n_(0),
34 output_sample_(0) {
37 void SetupInput(int size, base::TimeDelta rate) {
38 input_size_ = size;
39 input_rate_ = rate;
42 scoped_ptr<AudioBus> CreateTestInput() {
43 scoped_ptr<AudioBus> input(AudioBus::Create(2, input_size_));
44 for (size_t i = 0; i < input_size_; i++) {
45 input->channel(0)[i] = input->channel(1)[i] = input_sample_n_;
46 input_sample_n_++;
48 if (tag_input_) {
49 input->channel(0)[0] = 10000000.0;
50 tag_input_ = false;
51 expect_smooth_output_ = false;
53 return input.Pass();
56 void SetupOutput(int size, base::TimeDelta rate) {
57 test_output_ = AudioBus::Create(2, size);
58 output_rate_ = rate;
61 void SetUp() override {
62 SetupInput(
63 kInputPacketSize + ::testing::get<0>(GetParam()) - 1,
64 base::TimeDelta::FromMicroseconds(
65 1000 + ::testing::get<1>(GetParam()) * 5 - 5));
66 SetupOutput(
67 kOutputPacketSize,
68 base::TimeDelta::FromMicroseconds(
69 500 + ::testing::get<2>(GetParam()) * 3 - 3));
70 if (::testing::get<3>(GetParam())) {
71 end2end_latency_ = -end2end_latency_;
75 void Run(size_t loops) {
76 for (size_t i = 0; i < loops;) {
77 if (now_ >= time_to_push_) {
78 shifter_.Push(CreateTestInput(), now_ + end2end_latency_);
79 time_to_push_ += input_rate_;
80 i++;
82 if (now_ >= time_to_pull_) {
83 shifter_.Pull(test_output_.get(), now_ + playback_latency_);
84 bool silence = true;
85 for (size_t j = 0;
86 j < static_cast<size_t>(test_output_->frames());
87 j++) {
88 if (test_output_->channel(0)[j] != 0.0) {
89 silence = false;
90 if (test_output_->channel(0)[j] > 3000000.0) {
91 marker_outputs_.push_back(
92 now_ + playback_latency_ +
93 base::TimeDelta::FromSeconds(j) / kSampleRate);
94 } else {
95 // We don't expect smooth output once we insert a tag,
96 // or in the very beginning.
97 if (expect_smooth_output_ && output_sample_ > 500.0) {
98 EXPECT_GT(test_output_->channel(0)[j], output_sample_ - 3)
99 << "j = " << j;
100 if (test_output_->channel(0)[j] >
101 output_sample_ + kOutputPacketSize / 2) {
102 skip_outputs_.push_back(now_ + playback_latency_);
105 output_sample_ = test_output_->channel(0)[j];
109 if (silence) {
110 silent_outputs_.push_back(now_);
112 time_to_pull_ += output_rate_;
114 now_ += std::min(time_to_push_ - now_,
115 time_to_pull_ - now_);
119 void RunAndCheckSync(size_t loops) {
120 Run(100);
121 size_t expected_silent_outputs = silent_outputs_.size();
122 Run(loops);
123 tag_input_ = true;
124 CHECK(marker_outputs_.empty());
125 base::TimeTicks expected_mark_time = time_to_push_ + end2end_latency_;
126 Run(100);
127 if (end2end_latency_ > base::TimeDelta()) {
128 CHECK(!marker_outputs_.empty());
129 base::TimeDelta actual_offset = marker_outputs_[0] - expected_mark_time;
130 EXPECT_LT(actual_offset, base::TimeDelta::FromMicroseconds(100));
131 EXPECT_GT(actual_offset, base::TimeDelta::FromMicroseconds(-100));
132 } else {
133 EXPECT_GT(marker_outputs_.size(), 0UL);
135 EXPECT_EQ(expected_silent_outputs, silent_outputs_.size());
138 protected:
139 AudioShifter shifter_;
140 base::TimeDelta input_rate_;
141 base::TimeDelta output_rate_;
142 base::TimeDelta end2end_latency_;
143 base::TimeDelta playback_latency_;
144 base::TimeTicks time_to_push_;
145 base::TimeTicks time_to_pull_;
146 base::TimeTicks now_;
147 scoped_ptr<AudioBus> test_input_;
148 scoped_ptr<AudioBus> test_output_;
149 std::vector<base::TimeTicks> silent_outputs_;
150 std::vector<base::TimeTicks> skip_outputs_;
151 std::vector<base::TimeTicks> marker_outputs_;
152 size_t input_size_;
153 bool tag_input_;
154 bool expect_smooth_output_;
155 size_t input_sample_n_;
156 double output_sample_;
159 TEST_P(AudioShifterTest, TestSync) {
160 RunAndCheckSync(1000);
161 EXPECT_EQ(0UL, skip_outputs_.size());
164 TEST_P(AudioShifterTest, TestSyncWithPush) {
165 // Push some extra audio.
166 shifter_.Push(CreateTestInput().Pass(), now_ - base::TimeDelta(input_rate_));
167 RunAndCheckSync(1000);
168 EXPECT_LE(skip_outputs_.size(), 2UL);
171 TEST_P(AudioShifterTest, TestSyncWithPull) {
172 // Output should smooth out eventually, but that is not tested yet.
173 expect_smooth_output_ = false;
174 Run(100);
175 for (int i = 0; i < 100; i++) {
176 shifter_.Pull(test_output_.get(),
177 now_ + base::TimeDelta::FromMilliseconds(i));
179 RunAndCheckSync(1000);
180 EXPECT_LE(skip_outputs_.size(), 1UL);
183 TEST_P(AudioShifterTest, UnderOverFlow) {
184 expect_smooth_output_ = false;
185 SetupInput(
186 kInputPacketSize + ::testing::get<0>(GetParam()) * 10 - 10,
187 base::TimeDelta::FromMicroseconds(
188 1000 + ::testing::get<1>(GetParam()) * 100 - 100));
189 SetupOutput(
190 kOutputPacketSize,
191 base::TimeDelta::FromMicroseconds(
192 500 + ::testing::get<2>(GetParam()) * 50 - 50));
193 // Sane output is not expected, but let's make sure we don't crash.
194 Run(1000);
197 // Note: First argument is optional and intentionally left blank.
198 // (it's a prefix for the generated test cases)
199 INSTANTIATE_TEST_CASE_P(
201 AudioShifterTest,
202 ::testing::Combine(::testing::Range(0, 3),
203 ::testing::Range(0, 3),
204 ::testing::Range(0, 3),
205 ::testing::Bool()));
207 #endif
209 } // namespace media