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

Side by Side Diff: chromecast/media/cma/backend/multizone_backend_unittest.cc

Issue 2908893002: [Chromecast] Make MultizoneBackendTest work on AMP devices. (Closed)
Patch Set: Change number of seconds back to int. Created 3 years, 6 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « no previous file | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright 2016 The Chromium Authors. All rights reserved. 1 // Copyright 2016 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include <stdint.h> 5 #include <stdint.h>
6 #include <stdlib.h> 6 #include <stdlib.h>
7 7
8 #include <algorithm> 8 #include <algorithm>
9 #include <limits> 9 #include <limits>
10 #include <memory> 10 #include <memory>
11 #include <vector> 11 #include <vector>
12 12
13 #include "base/bind.h" 13 #include "base/bind.h"
14 #include "base/bind_helpers.h"
14 #include "base/command_line.h" 15 #include "base/command_line.h"
15 #include "base/logging.h" 16 #include "base/logging.h"
17 #include "base/memory/ptr_util.h"
16 #include "base/memory/ref_counted.h" 18 #include "base/memory/ref_counted.h"
17 #include "base/message_loop/message_loop.h" 19 #include "base/message_loop/message_loop.h"
18 #include "base/run_loop.h" 20 #include "base/run_loop.h"
19 #include "base/threading/thread_checker.h" 21 #include "base/threading/thread_checker.h"
20 #include "base/threading/thread_task_runner_handle.h" 22 #include "base/threading/thread_task_runner_handle.h"
21 #include "base/time/time.h" 23 #include "base/time/time.h"
22 #include "chromecast/base/task_runner_impl.h" 24 #include "chromecast/base/task_runner_impl.h"
23 #include "chromecast/media/cma/base/decoder_buffer_adapter.h" 25 #include "chromecast/media/cma/base/decoder_buffer_adapter.h"
24 #include "chromecast/media/cma/base/decoder_config_adapter.h" 26 #include "chromecast/media/cma/base/decoder_config_adapter.h"
25 #include "chromecast/public/cast_media_shlib.h" 27 #include "chromecast/public/cast_media_shlib.h"
26 #include "chromecast/public/media/cast_decoder_buffer.h" 28 #include "chromecast/public/media/cast_decoder_buffer.h"
27 #include "chromecast/public/media/decoder_config.h" 29 #include "chromecast/public/media/decoder_config.h"
28 #include "chromecast/public/media/media_pipeline_backend.h" 30 #include "chromecast/public/media/media_pipeline_backend.h"
29 #include "chromecast/public/media/media_pipeline_device_params.h" 31 #include "chromecast/public/media/media_pipeline_device_params.h"
30 #include "chromecast/public/volume_control.h" 32 #include "chromecast/public/volume_control.h"
31 #include "media/audio/audio_device_description.h" 33 #include "media/audio/audio_device_description.h"
32 #include "media/base/audio_decoder_config.h" 34 #include "media/base/audio_decoder_config.h"
33 #include "media/base/decoder_buffer.h" 35 #include "media/base/decoder_buffer.h"
34 #include "testing/gtest/include/gtest/gtest.h" 36 #include "testing/gtest/include/gtest/gtest.h"
35 37
36 namespace chromecast { 38 namespace chromecast {
37 namespace media { 39 namespace media {
38 40
39 class MultizoneBackendTest; 41 class MultizoneBackendTest;
40 42
41 namespace { 43 namespace {
42 44
43 const int64_t kMicrosecondsPerSecond = 1000 * 1000;
44 // Total length of test, in microseconds. 45 // Total length of test, in microseconds.
45 const int64_t kPushTimeUs = 2 * kMicrosecondsPerSecond; 46 const int64_t kPushTimeUs = 2 * base::Time::kMicrosecondsPerSecond;
46 const int64_t kStartPts = 0; 47 const int64_t kStartPts = 0;
47 const int64_t kMaxRenderingDelayErrorUs = 200; 48 const int64_t kMaxRenderingDelayErrorUs = 200;
48 const int kNumEffectsStreams = 1; 49 const int kNumEffectsStreams = 1;
49 const int64_t kNoTimestamp = std::numeric_limits<int64_t>::min(); 50 const int64_t kNoTimestamp = std::numeric_limits<int64_t>::min();
50 51
51 void IgnoreEos() {} 52 void IgnoreEos() {}
52 53
53 class BufferFeeder : public MediaPipelineBackend::Decoder::Delegate { 54 class BufferFeeder : public MediaPipelineBackend::Decoder::Delegate {
54 public: 55 public:
55 BufferFeeder(const AudioConfig& config, 56 BufferFeeder(const AudioConfig& config,
56 bool effects_only, 57 bool effects_only,
57 const base::Closure& eos_cb); 58 base::OnceClosure eos_cb,
59 int playback_rate_change_count);
58 ~BufferFeeder() override {} 60 ~BufferFeeder() override {}
59 61
60 void Initialize(float playback_rate); 62 void Initialize();
61 void Start(); 63 void Start(float playback_rate);
62 void Stop(); 64 void Stop();
63 65
64 int64_t max_rendering_delay_error_us() { 66 int64_t GetMaxRenderingDelayErrorUs() {
65 return max_rendering_delay_error_us_; 67 int64_t max = 0;
66 } 68 for (int64_t error : errors_) {
67 69 if (error == kNoTimestamp) {
68 int64_t max_positive_rendering_delay_error_us() { 70 continue;
69 return max_positive_rendering_delay_error_us_; 71 }
70 } 72 max = std::max(max, std::abs(error));
71 73 }
72 int64_t max_negative_rendering_delay_error_us() { 74 return max;
73 return max_negative_rendering_delay_error_us_;
74 }
75
76 int64_t average_rendering_delay_error_us() {
77 return total_rendering_delay_error_us_ / sample_count_;
78 } 75 }
79 76
80 private: 77 private:
81 void FeedBuffer(); 78 void FeedBuffer();
82 79
83 // MediaPipelineBackend::Decoder::Delegate implementation: 80 // MediaPipelineBackend::Decoder::Delegate implementation:
84 void OnPushBufferComplete(MediaPipelineBackend::BufferStatus status) override; 81 void OnPushBufferComplete(MediaPipelineBackend::BufferStatus status) override;
85 void OnEndOfStream() override; 82 void OnEndOfStream() override;
86 void OnDecoderError() override { 83 void OnDecoderError() override {
87 DCHECK(thread_checker_.CalledOnValidThread()); 84 DCHECK(thread_checker_.CalledOnValidThread());
88 if (effects_only_) { 85 if (effects_only_) {
89 feeding_completed_ = true; 86 feeding_completed_ = true;
90 } else { 87 } else {
91 ASSERT_TRUE(false); 88 ASSERT_TRUE(false);
92 } 89 }
93 } 90 }
94 void OnKeyStatusChanged(const std::string& key_id, 91 void OnKeyStatusChanged(const std::string& key_id,
95 CastKeyStatus key_status, 92 CastKeyStatus key_status,
96 uint32_t system_code) override { 93 uint32_t system_code) override {
97 DCHECK(thread_checker_.CalledOnValidThread()); 94 DCHECK(thread_checker_.CalledOnValidThread());
98 ASSERT_TRUE(false); 95 ASSERT_TRUE(false);
99 } 96 }
100 void OnVideoResolutionChanged(const Size& size) override { 97 void OnVideoResolutionChanged(const Size& size) override {
101 DCHECK(thread_checker_.CalledOnValidThread()); 98 DCHECK(thread_checker_.CalledOnValidThread());
102 } 99 }
103 100
104 const AudioConfig config_; 101 const AudioConfig config_;
105 const bool effects_only_; 102 const bool effects_only_;
106 const base::Closure eos_cb_; 103 base::OnceClosure eos_cb_;
107 double original_playback_rate_; 104 const int64_t push_limit_us_;
108 double playback_rate_; 105 const int64_t playback_rate_change_interval_us_;
109 int64_t max_rendering_delay_error_us_; 106 float original_playback_rate_;
110 int64_t max_positive_rendering_delay_error_us_; 107 float playback_rate_;
111 int64_t max_negative_rendering_delay_error_us_; 108 std::vector<int64_t> errors_;
112 int64_t total_rendering_delay_error_us_;
113 size_t sample_count_;
114 bool feeding_completed_; 109 bool feeding_completed_;
115 std::unique_ptr<TaskRunnerImpl> task_runner_; 110 TaskRunnerImpl task_runner_;
116 std::unique_ptr<MediaPipelineBackend> backend_; 111 std::unique_ptr<MediaPipelineBackend> backend_;
117 MediaPipelineBackend::AudioDecoder* decoder_; 112 MediaPipelineBackend::AudioDecoder* decoder_;
118 int64_t push_limit_us_;
119 int64_t last_push_length_us_; 113 int64_t last_push_length_us_;
120 int64_t pushed_us_; 114 int64_t pushed_us_;
115 int64_t pushed_us_when_rate_changed_;
121 int64_t next_push_playback_timestamp_; 116 int64_t next_push_playback_timestamp_;
122 scoped_refptr<DecoderBufferBase> pending_buffer_; 117 scoped_refptr<DecoderBufferBase> pending_buffer_;
123 base::ThreadChecker thread_checker_; 118 base::ThreadChecker thread_checker_;
124 119
125 DISALLOW_COPY_AND_ASSIGN(BufferFeeder); 120 DISALLOW_COPY_AND_ASSIGN(BufferFeeder);
126 }; 121 };
127 122
128 } // namespace 123 } // namespace
129 124
130 using TestParams = std::tr1::tuple<int, // sample rate 125 using TestParams =
131 float>; // playback rate 126 std::tr1::tuple<int /* sample rate */, float /* playback rate */>;
132 127
133 class MultizoneBackendTest : public testing::TestWithParam<TestParams> { 128 class MultizoneBackendTest : public testing::TestWithParam<TestParams> {
134 public: 129 public:
135 MultizoneBackendTest(); 130 MultizoneBackendTest();
136 ~MultizoneBackendTest() override; 131 ~MultizoneBackendTest() override;
137 132
138 void SetUp() override { 133 void SetUp() override {
139 srand(12345); 134 srand(12345);
140 CastMediaShlib::Initialize(base::CommandLine::ForCurrentProcess()->argv()); 135 CastMediaShlib::Initialize(base::CommandLine::ForCurrentProcess()->argv());
141 if (VolumeControl::Initialize) { 136 if (VolumeControl::Initialize) {
142 VolumeControl::Initialize(base::CommandLine::ForCurrentProcess()->argv()); 137 VolumeControl::Initialize(base::CommandLine::ForCurrentProcess()->argv());
143 } 138 }
144 } 139 }
145 140
146 void TearDown() override { 141 void TearDown() override {
147 // Pipeline must be destroyed before finalizing media shlib. 142 // Pipeline must be destroyed before finalizing media shlib.
148 audio_feeder_.reset(); 143 audio_feeder_.reset();
149 effects_feeders_.clear(); 144 effects_feeders_.clear();
150 if (VolumeControl::Finalize) { 145 if (VolumeControl::Finalize) {
151 VolumeControl::Finalize(); 146 VolumeControl::Finalize();
152 } 147 }
153 CastMediaShlib::Finalize(); 148 CastMediaShlib::Finalize();
154 } 149 }
155 150
156 void AddEffectsStreams(); 151 void AddEffectsStreams();
157 152
158 void Initialize(int sample_rate, float playback_rate); 153 void Initialize(int sample_rate, int playback_rate_change_count);
159 void Start(); 154 void Start(float playback_rate);
160 void OnEndOfStream(); 155 void OnEndOfStream();
161 156
162 private: 157 private:
158 base::MessageLoop message_loop_;
163 std::vector<std::unique_ptr<BufferFeeder>> effects_feeders_; 159 std::vector<std::unique_ptr<BufferFeeder>> effects_feeders_;
164 std::unique_ptr<BufferFeeder> audio_feeder_; 160 std::unique_ptr<BufferFeeder> audio_feeder_;
165 161
166 DISALLOW_COPY_AND_ASSIGN(MultizoneBackendTest); 162 DISALLOW_COPY_AND_ASSIGN(MultizoneBackendTest);
167 }; 163 };
168 164
169 namespace { 165 namespace {
170 166
171 BufferFeeder::BufferFeeder(const AudioConfig& config, 167 BufferFeeder::BufferFeeder(const AudioConfig& config,
172 bool effects_only, 168 bool effects_only,
173 const base::Closure& eos_cb) 169 base::OnceClosure eos_cb,
170 int playback_rate_change_count)
174 : config_(config), 171 : config_(config),
175 effects_only_(effects_only), 172 effects_only_(effects_only),
176 eos_cb_(eos_cb), 173 eos_cb_(std::move(eos_cb)),
177 original_playback_rate_(1.0), 174 push_limit_us_(effects_only_ ? 0 : kPushTimeUs),
178 playback_rate_(1.0), 175 playback_rate_change_interval_us_(push_limit_us_ /
179 max_rendering_delay_error_us_(0), 176 (playback_rate_change_count + 1)),
180 max_positive_rendering_delay_error_us_(0), 177 original_playback_rate_(1.0f),
181 max_negative_rendering_delay_error_us_(0), 178 playback_rate_(1.0f),
182 total_rendering_delay_error_us_(0),
183 sample_count_(0),
184 feeding_completed_(false), 179 feeding_completed_(false),
185 task_runner_(new TaskRunnerImpl()),
186 decoder_(nullptr), 180 decoder_(nullptr),
187 push_limit_us_(effects_only_ ? 0 : kPushTimeUs),
188 last_push_length_us_(0), 181 last_push_length_us_(0),
189 pushed_us_(0), 182 pushed_us_(0),
183 pushed_us_when_rate_changed_(0),
190 next_push_playback_timestamp_(kNoTimestamp) { 184 next_push_playback_timestamp_(kNoTimestamp) {
191 CHECK(!eos_cb_.is_null()); 185 CHECK(eos_cb_);
192 } 186 }
193 187
194 void BufferFeeder::Initialize(float playback_rate) { 188 void BufferFeeder::Initialize() {
195 original_playback_rate_ = playback_rate_ = playback_rate;
196 MediaPipelineDeviceParams params( 189 MediaPipelineDeviceParams params(
197 MediaPipelineDeviceParams::kModeIgnorePts, 190 MediaPipelineDeviceParams::kModeIgnorePts,
198 effects_only_ ? MediaPipelineDeviceParams::kAudioStreamSoundEffects 191 effects_only_ ? MediaPipelineDeviceParams::kAudioStreamSoundEffects
199 : MediaPipelineDeviceParams::kAudioStreamNormal, 192 : MediaPipelineDeviceParams::kAudioStreamNormal,
200 task_runner_.get(), AudioContentType::kMedia, 193 &task_runner_, AudioContentType::kMedia,
201 ::media::AudioDeviceDescription::kDefaultDeviceId); 194 ::media::AudioDeviceDescription::kDefaultDeviceId);
202 backend_.reset(CastMediaShlib::CreateMediaPipelineBackend(params)); 195 backend_.reset(CastMediaShlib::CreateMediaPipelineBackend(params));
203 CHECK(backend_); 196 CHECK(backend_);
204 197
205 decoder_ = backend_->CreateAudioDecoder(); 198 decoder_ = backend_->CreateAudioDecoder();
206 CHECK(decoder_); 199 CHECK(decoder_);
207 ASSERT_TRUE(decoder_->SetConfig(config_)); 200 ASSERT_TRUE(decoder_->SetConfig(config_));
208 decoder_->SetDelegate(this); 201 decoder_->SetDelegate(this);
209 202
210 ASSERT_TRUE(backend_->Initialize()); 203 ASSERT_TRUE(backend_->Initialize());
211 ASSERT_TRUE(backend_->SetPlaybackRate(playback_rate));
212 } 204 }
213 205
214 void BufferFeeder::Start() { 206 void BufferFeeder::Start(float playback_rate) {
207 // AMP devices only support playback rates between 0.5 and 2.0.
208 ASSERT_GE(playback_rate, 0.5f);
209 ASSERT_LE(playback_rate, 2.0f);
210 original_playback_rate_ = playback_rate_ = playback_rate;
215 ASSERT_TRUE(backend_->Start(kStartPts)); 211 ASSERT_TRUE(backend_->Start(kStartPts));
212 ASSERT_TRUE(backend_->SetPlaybackRate(playback_rate));
216 base::ThreadTaskRunnerHandle::Get()->PostTask( 213 base::ThreadTaskRunnerHandle::Get()->PostTask(
217 FROM_HERE, base::Bind(&BufferFeeder::FeedBuffer, base::Unretained(this))); 214 FROM_HERE,
215 base::BindOnce(&BufferFeeder::FeedBuffer, base::Unretained(this)));
218 } 216 }
219 217
220 void BufferFeeder::Stop() { 218 void BufferFeeder::Stop() {
221 feeding_completed_ = true; 219 feeding_completed_ = true;
222 backend_->Stop(); 220 backend_->Stop();
223 } 221 }
224 222
225 void BufferFeeder::FeedBuffer() { 223 void BufferFeeder::FeedBuffer() {
226 CHECK(decoder_); 224 CHECK(decoder_);
227 if (feeding_completed_) 225 if (feeding_completed_)
228 return; 226 return;
229 227
230 if (!effects_only_ && pushed_us_ >= push_limit_us_ / 2 && 228 if (!effects_only_ && pushed_us_ > pushed_us_when_rate_changed_ +
231 playback_rate_ == original_playback_rate_) { 229 playback_rate_change_interval_us_) {
232 if (original_playback_rate_ < 1.0) { 230 pushed_us_when_rate_changed_ = pushed_us_;
231 if (playback_rate_ != original_playback_rate_) {
232 playback_rate_ = original_playback_rate_;
233 } else if (original_playback_rate_ < 1.0) {
233 playback_rate_ = original_playback_rate_ * 2; 234 playback_rate_ = original_playback_rate_ * 2;
234 ASSERT_TRUE(backend_->SetPlaybackRate(playback_rate_));
235 } else { 235 } else {
236 playback_rate_ = original_playback_rate_ / 2; 236 playback_rate_ = original_playback_rate_ / 2;
237 ASSERT_TRUE(backend_->SetPlaybackRate(playback_rate_));
238 } 237 }
238 ASSERT_TRUE(backend_->SetPlaybackRate(playback_rate_));
239 // Changing the playback rate will change the rendering delay on devices
240 // where playback rate changes apply to audio that has already been pushed.
241 // Ignore the next rendering delay.
242 next_push_playback_timestamp_ = kNoTimestamp;
239 } 243 }
240 244
241 if (!effects_only_ && pushed_us_ >= push_limit_us_) { 245 if (!effects_only_ && pushed_us_ >= push_limit_us_) {
242 pending_buffer_ = new media::DecoderBufferAdapter( 246 pending_buffer_ = new media::DecoderBufferAdapter(
243 ::media::DecoderBuffer::CreateEOSBuffer()); 247 ::media::DecoderBuffer::CreateEOSBuffer());
244 feeding_completed_ = true; 248 feeding_completed_ = true;
245 last_push_length_us_ = 0; 249 last_push_length_us_ = 0;
246 } else { 250 } else {
247 int size_bytes = (rand() % 96 + 32) * 16; 251 int size_bytes = (rand() % 96 + 32) * 16;
248 int num_samples = 252 int num_samples =
249 size_bytes / (config_.bytes_per_channel * config_.channel_number); 253 size_bytes / (config_.bytes_per_channel * config_.channel_number);
250 last_push_length_us_ = num_samples * kMicrosecondsPerSecond / 254 last_push_length_us_ = num_samples * base::Time::kMicrosecondsPerSecond /
251 (config_.samples_per_second * playback_rate_); 255 (config_.samples_per_second * playback_rate_);
252 scoped_refptr<::media::DecoderBuffer> silence_buffer( 256 scoped_refptr<::media::DecoderBuffer> silence_buffer(
253 new ::media::DecoderBuffer(size_bytes)); 257 new ::media::DecoderBuffer(size_bytes));
254 memset(silence_buffer->writable_data(), 0, silence_buffer->data_size()); 258 memset(silence_buffer->writable_data(), 0, silence_buffer->data_size());
255 pending_buffer_ = new media::DecoderBufferAdapter(silence_buffer); 259 pending_buffer_ = new media::DecoderBufferAdapter(silence_buffer);
256 pending_buffer_->set_timestamp( 260 pending_buffer_->set_timestamp(
257 base::TimeDelta::FromMicroseconds(pushed_us_)); 261 base::TimeDelta::FromMicroseconds(pushed_us_));
258 } 262 }
259 BufferStatus status = decoder_->PushBuffer(pending_buffer_.get()); 263 BufferStatus status = decoder_->PushBuffer(pending_buffer_.get());
260 ASSERT_NE(status, MediaPipelineBackend::kBufferFailed); 264 ASSERT_NE(status, MediaPipelineBackend::kBufferFailed);
261 if (status == MediaPipelineBackend::kBufferPending) 265 if (status == MediaPipelineBackend::kBufferPending)
262 return; 266 return;
263 OnPushBufferComplete(MediaPipelineBackend::kBufferSuccess); 267 OnPushBufferComplete(MediaPipelineBackend::kBufferSuccess);
264 } 268 }
265 269
266 void BufferFeeder::OnEndOfStream() { 270 void BufferFeeder::OnEndOfStream() {
267 DCHECK(thread_checker_.CalledOnValidThread()); 271 DCHECK(thread_checker_.CalledOnValidThread());
268 eos_cb_.Run(); 272 std::move(eos_cb_).Run();
269 } 273 }
270 274
271 void BufferFeeder::OnPushBufferComplete(BufferStatus status) { 275 void BufferFeeder::OnPushBufferComplete(BufferStatus status) {
272 DCHECK(thread_checker_.CalledOnValidThread()); 276 DCHECK(thread_checker_.CalledOnValidThread());
273 pending_buffer_ = nullptr; 277 pending_buffer_ = nullptr;
274 278
275 if (!effects_only_) { 279 if (!effects_only_) {
276 ASSERT_NE(status, MediaPipelineBackend::kBufferFailed); 280 ASSERT_NE(status, MediaPipelineBackend::kBufferFailed);
277 MediaPipelineBackend::AudioDecoder::RenderingDelay delay = 281 MediaPipelineBackend::AudioDecoder::RenderingDelay delay =
278 decoder_->GetRenderingDelay(); 282 decoder_->GetRenderingDelay();
279 283
284 int64_t error = kNoTimestamp;
280 if (delay.timestamp_microseconds == kNoTimestamp) { 285 if (delay.timestamp_microseconds == kNoTimestamp) {
281 next_push_playback_timestamp_ = kNoTimestamp; 286 next_push_playback_timestamp_ = kNoTimestamp;
282 } else { 287 } else {
283 if (next_push_playback_timestamp_ == kNoTimestamp) { 288 if (next_push_playback_timestamp_ == kNoTimestamp) {
284 next_push_playback_timestamp_ = 289 next_push_playback_timestamp_ =
285 delay.timestamp_microseconds + delay.delay_microseconds; 290 delay.timestamp_microseconds + delay.delay_microseconds;
286 } else { 291 } else {
287 int64_t expected_next_push_playback_timestamp = 292 int64_t expected_next_push_playback_timestamp =
288 next_push_playback_timestamp_ + last_push_length_us_; 293 next_push_playback_timestamp_ + last_push_length_us_;
289 next_push_playback_timestamp_ = 294 next_push_playback_timestamp_ =
290 delay.timestamp_microseconds + delay.delay_microseconds; 295 delay.timestamp_microseconds + delay.delay_microseconds;
291 int64_t error = next_push_playback_timestamp_ - 296 error = next_push_playback_timestamp_ -
292 expected_next_push_playback_timestamp; 297 expected_next_push_playback_timestamp;
293
294 max_rendering_delay_error_us_ =
295 std::max(max_rendering_delay_error_us_, std::abs(error));
296 total_rendering_delay_error_us_ += std::abs(error);
297 if (error >= 0) {
298 max_positive_rendering_delay_error_us_ =
299 std::max(max_positive_rendering_delay_error_us_, error);
300 } else {
301 max_negative_rendering_delay_error_us_ =
302 std::min(max_negative_rendering_delay_error_us_, error);
303 }
304 sample_count_++;
305 } 298 }
306 } 299 }
300 errors_.push_back(error);
307 } 301 }
308 pushed_us_ += last_push_length_us_; 302 pushed_us_ += last_push_length_us_;
309 303
310 if (feeding_completed_) 304 if (feeding_completed_)
311 return; 305 return;
312 306
313 base::ThreadTaskRunnerHandle::Get()->PostTask( 307 base::ThreadTaskRunnerHandle::Get()->PostTask(
314 FROM_HERE, base::Bind(&BufferFeeder::FeedBuffer, base::Unretained(this))); 308 FROM_HERE,
309 base::BindOnce(&BufferFeeder::FeedBuffer, base::Unretained(this)));
315 } 310 }
316 311
317 } // namespace 312 } // namespace
318 313
319 MultizoneBackendTest::MultizoneBackendTest() {} 314 MultizoneBackendTest::MultizoneBackendTest() {}
320 315
321 MultizoneBackendTest::~MultizoneBackendTest() {} 316 MultizoneBackendTest::~MultizoneBackendTest() {}
322 317
323 void MultizoneBackendTest::Initialize(int sample_rate, float playback_rate) { 318 void MultizoneBackendTest::Initialize(int sample_rate,
319 int playback_rate_change_count) {
324 AudioConfig config; 320 AudioConfig config;
325 config.codec = kCodecPCM; 321 config.codec = kCodecPCM;
326 config.sample_format = kSampleFormatS32; 322 config.sample_format = kSampleFormatPlanarF32;
327 config.channel_number = 2; 323 config.channel_number = 2;
328 config.bytes_per_channel = 4; 324 config.bytes_per_channel = 4;
329 config.samples_per_second = sample_rate; 325 config.samples_per_second = sample_rate;
330 326
331 audio_feeder_.reset( 327 audio_feeder_ = base::MakeUnique<BufferFeeder>(
332 new BufferFeeder(config, false /* effects_only */, 328 config, false /* effects_only */,
333 base::Bind(&MultizoneBackendTest::OnEndOfStream, 329 base::BindOnce(&MultizoneBackendTest::OnEndOfStream,
334 base::Unretained(this)))); 330 base::Unretained(this)),
335 audio_feeder_->Initialize(playback_rate); 331 playback_rate_change_count);
332 audio_feeder_->Initialize();
336 } 333 }
337 334
338 void MultizoneBackendTest::AddEffectsStreams() { 335 void MultizoneBackendTest::AddEffectsStreams() {
339 AudioConfig effects_config; 336 AudioConfig effects_config;
340 effects_config.codec = kCodecPCM; 337 effects_config.codec = kCodecPCM;
341 effects_config.sample_format = kSampleFormatS16; 338 effects_config.sample_format = kSampleFormatS16;
342 effects_config.channel_number = 2; 339 effects_config.channel_number = 2;
343 effects_config.bytes_per_channel = 2; 340 effects_config.bytes_per_channel = 2;
344 effects_config.samples_per_second = 48000; 341 effects_config.samples_per_second = 48000;
345 342
346 for (int i = 0; i < kNumEffectsStreams; ++i) { 343 for (int i = 0; i < kNumEffectsStreams; ++i) {
347 std::unique_ptr<BufferFeeder> feeder(new BufferFeeder( 344 auto feeder = base::MakeUnique<BufferFeeder>(
348 effects_config, true /* effects_only */, base::Bind(&IgnoreEos))); 345 effects_config, true /* effects_only */, base::BindOnce(&IgnoreEos), 0);
349 feeder->Initialize(1.0f); 346 feeder->Initialize();
350 effects_feeders_.push_back(std::move(feeder)); 347 effects_feeders_.push_back(std::move(feeder));
351 } 348 }
352 } 349 }
353 350
354 void MultizoneBackendTest::Start() { 351 void MultizoneBackendTest::Start(float playback_rate) {
355 for (auto& feeder : effects_feeders_) 352 for (auto& feeder : effects_feeders_)
356 feeder->Start(); 353 feeder->Start(1.0f);
357 CHECK(audio_feeder_); 354 CHECK(audio_feeder_);
358 audio_feeder_->Start(); 355 audio_feeder_->Start(playback_rate);
356 base::RunLoop().Run();
359 } 357 }
360 358
361 void MultizoneBackendTest::OnEndOfStream() { 359 void MultizoneBackendTest::OnEndOfStream() {
362 audio_feeder_->Stop(); 360 audio_feeder_->Stop();
363 for (auto& feeder : effects_feeders_) 361 for (auto& feeder : effects_feeders_)
364 feeder->Stop(); 362 feeder->Stop();
365 363
366 base::MessageLoop::current()->QuitWhenIdle(); 364 base::MessageLoop::current()->QuitWhenIdle();
367 365
368 EXPECT_LT(audio_feeder_->max_rendering_delay_error_us(), 366 EXPECT_LT(audio_feeder_->GetMaxRenderingDelayErrorUs(),
369 kMaxRenderingDelayErrorUs) 367 kMaxRenderingDelayErrorUs);
370 << "Max positive rendering delay error: "
371 << audio_feeder_->max_positive_rendering_delay_error_us()
372 << "\nMax negative rendering delay error: "
373 << audio_feeder_->max_negative_rendering_delay_error_us()
374 << "\nAverage rendering delay error: "
375 << audio_feeder_->average_rendering_delay_error_us();
376 } 368 }
377 369
378 TEST_P(MultizoneBackendTest, RenderingDelay) { 370 TEST_P(MultizoneBackendTest, RenderingDelay) {
379 std::unique_ptr<base::MessageLoop> message_loop(new base::MessageLoop());
380 const TestParams& params = GetParam(); 371 const TestParams& params = GetParam();
381 int sample_rate = testing::get<0>(params); 372 int sample_rate = testing::get<0>(params);
382 float playback_rate = testing::get<1>(params); 373 float playback_rate = testing::get<1>(params);
383 374
384 Initialize(sample_rate, playback_rate); 375 Initialize(sample_rate, 1 /* playback_rate_change_count */);
385 AddEffectsStreams(); 376 AddEffectsStreams();
386 Start(); 377 Start(playback_rate);
387 base::RunLoop().Run(); 378 }
379
380 TEST_F(MultizoneBackendTest, RenderingDelayWithMultipleRateChanges) {
381 Initialize(48000 /* sample_rate */, 10 /* playback_rate_change_count */);
382 AddEffectsStreams();
383 Start(1.0f /* playback_rate */);
388 } 384 }
389 385
390 INSTANTIATE_TEST_CASE_P( 386 INSTANTIATE_TEST_CASE_P(
391 Required, 387 Required,
392 MultizoneBackendTest, 388 MultizoneBackendTest,
393 testing::Combine(::testing::Values(8000, 389 testing::Combine(::testing::Values(8000,
394 11025, 390 11025,
395 12000, 391 12000,
396 16000, 392 16000,
397 22050, 393 22050,
398 24000, 394 24000,
399 32000, 395 32000,
400 44100, 396 44100,
401 48000), 397 48000),
402 ::testing::Values(0.5f, 0.99f, 1.0f, 1.01f, 2.0f))); 398 ::testing::Values(0.5f, 0.99f, 1.0f, 1.01f, 2.0f)));
403 399
404 INSTANTIATE_TEST_CASE_P( 400 INSTANTIATE_TEST_CASE_P(
405 Optional, 401 Optional,
406 MultizoneBackendTest, 402 MultizoneBackendTest,
407 testing::Combine(::testing::Values(64000, 88200, 96000), 403 testing::Combine(::testing::Values(64000, 88200, 96000),
408 ::testing::Values(0.5f, 0.99f, 1.0f, 1.01f, 2.0f))); 404 ::testing::Values(0.5f, 0.99f, 1.0f, 1.01f, 2.0f)));
409 405
410 } // namespace media 406 } // namespace media
411 } // namespace chromecast 407 } // namespace chromecast
OLDNEW
« no previous file with comments | « no previous file | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698