OLD | NEW |
---|---|
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 <limits> | 9 #include <limits> |
9 #include <memory> | 10 #include <memory> |
10 #include <vector> | 11 #include <vector> |
11 | 12 |
12 #include "base/bind.h" | 13 #include "base/bind.h" |
13 #include "base/command_line.h" | 14 #include "base/command_line.h" |
14 #include "base/logging.h" | 15 #include "base/logging.h" |
15 #include "base/memory/ref_counted.h" | 16 #include "base/memory/ref_counted.h" |
16 #include "base/message_loop/message_loop.h" | 17 #include "base/message_loop/message_loop.h" |
17 #include "base/threading/thread_checker.h" | 18 #include "base/threading/thread_checker.h" |
(...skipping 17 matching lines...) Expand all Loading... | |
35 class MultizoneBackendTest; | 36 class MultizoneBackendTest; |
36 | 37 |
37 namespace { | 38 namespace { |
38 | 39 |
39 const int64_t kMicrosecondsPerSecond = 1000 * 1000; | 40 const int64_t kMicrosecondsPerSecond = 1000 * 1000; |
40 // Total length of test, in microseconds. | 41 // Total length of test, in microseconds. |
41 const int64_t kPushTimeUs = 2 * kMicrosecondsPerSecond; | 42 const int64_t kPushTimeUs = 2 * kMicrosecondsPerSecond; |
42 const int64_t kStartPts = 0; | 43 const int64_t kStartPts = 0; |
43 const int64_t kRenderingDelayGracePeriodUs = 250 * 1000; | 44 const int64_t kRenderingDelayGracePeriodUs = 250 * 1000; |
44 const int64_t kMaxRenderingDelayErrorUs = 200; | 45 const int64_t kMaxRenderingDelayErrorUs = 200; |
45 const int kNumEffectsStreams = 3; | 46 const int kNumEffectsStreams = 1; |
46 | 47 |
47 void IgnoreEos() {} | 48 void IgnoreEos() {} |
48 | 49 |
49 class BufferFeeder : public MediaPipelineBackend::Decoder::Delegate { | 50 class BufferFeeder : public MediaPipelineBackend::Decoder::Delegate { |
50 public: | 51 public: |
51 BufferFeeder(const AudioConfig& config, | 52 BufferFeeder(const AudioConfig& config, |
52 bool effects_only, | 53 bool effects_only, |
53 const base::Closure& eos_cb); | 54 const base::Closure& eos_cb); |
54 ~BufferFeeder() override {} | 55 ~BufferFeeder() override {} |
55 | 56 |
56 void Initialize(); | 57 void Initialize(); |
57 void Start(); | 58 void Start(); |
58 void Stop(); | 59 void Stop(); |
59 | 60 |
61 int64_t max_rendering_delay_error_us() { | |
62 return max_rendering_delay_error_us_; | |
63 } | |
64 | |
65 int64_t max_positive_rendering_delay_error_us() { | |
66 return max_positive_rendering_delay_error_us_; | |
67 } | |
68 | |
69 int64_t max_negative_rendering_delay_error_us() { | |
70 return max_negative_rendering_delay_error_us_; | |
71 } | |
72 | |
73 int64_t average_rendering_delay_error_us() { | |
74 return average_rendering_delay_error_us_; | |
75 } | |
76 | |
60 private: | 77 private: |
61 void FeedBuffer(); | 78 void FeedBuffer(); |
62 | 79 |
63 // MediaPipelineBackend::Decoder::Delegate implementation: | 80 // MediaPipelineBackend::Decoder::Delegate implementation: |
64 void OnPushBufferComplete(MediaPipelineBackend::BufferStatus status) override; | 81 void OnPushBufferComplete(MediaPipelineBackend::BufferStatus status) override; |
65 void OnEndOfStream() override; | 82 void OnEndOfStream() override; |
66 void OnDecoderError() override { | 83 void OnDecoderError() override { |
67 DCHECK(thread_checker_.CalledOnValidThread()); | 84 DCHECK(thread_checker_.CalledOnValidThread()); |
68 if (effects_only_) { | 85 if (effects_only_) { |
69 feeding_completed_ = true; | 86 feeding_completed_ = true; |
70 } else { | 87 } else { |
71 ASSERT_TRUE(false); | 88 ASSERT_TRUE(false); |
72 } | 89 } |
73 } | 90 } |
74 void OnKeyStatusChanged(const std::string& key_id, | 91 void OnKeyStatusChanged(const std::string& key_id, |
75 CastKeyStatus key_status, | 92 CastKeyStatus key_status, |
76 uint32_t system_code) override { | 93 uint32_t system_code) override { |
77 DCHECK(thread_checker_.CalledOnValidThread()); | 94 DCHECK(thread_checker_.CalledOnValidThread()); |
78 ASSERT_TRUE(false); | 95 ASSERT_TRUE(false); |
79 } | 96 } |
80 void OnVideoResolutionChanged(const Size& size) override { | 97 void OnVideoResolutionChanged(const Size& size) override { |
81 DCHECK(thread_checker_.CalledOnValidThread()); | 98 DCHECK(thread_checker_.CalledOnValidThread()); |
82 } | 99 } |
83 | 100 |
84 const AudioConfig config_; | 101 const AudioConfig config_; |
85 const bool effects_only_; | 102 const bool effects_only_; |
86 const base::Closure eos_cb_; | 103 const base::Closure eos_cb_; |
104 int64_t max_rendering_delay_error_us_; | |
105 int64_t max_positive_rendering_delay_error_us_; | |
106 int64_t max_negative_rendering_delay_error_us_; | |
107 int64_t average_rendering_delay_error_us_; | |
108 size_t sample_count_; | |
87 bool feeding_completed_; | 109 bool feeding_completed_; |
88 std::unique_ptr<TaskRunnerImpl> task_runner_; | 110 std::unique_ptr<TaskRunnerImpl> task_runner_; |
89 std::unique_ptr<MediaPipelineBackend> backend_; | 111 std::unique_ptr<MediaPipelineBackend> backend_; |
90 MediaPipelineBackend::AudioDecoder* decoder_; | 112 MediaPipelineBackend::AudioDecoder* decoder_; |
91 int64_t push_limit_us_; | 113 int64_t push_limit_us_; |
92 int64_t last_push_length_us_; | 114 int64_t last_push_length_us_; |
93 int64_t pushed_us_; | 115 int64_t pushed_us_; |
94 int64_t next_push_playback_timestamp_; | 116 int64_t next_push_playback_timestamp_; |
95 scoped_refptr<DecoderBufferBase> pending_buffer_; | 117 scoped_refptr<DecoderBufferBase> pending_buffer_; |
96 base::ThreadChecker thread_checker_; | 118 base::ThreadChecker thread_checker_; |
(...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
131 }; | 153 }; |
132 | 154 |
133 namespace { | 155 namespace { |
134 | 156 |
135 BufferFeeder::BufferFeeder(const AudioConfig& config, | 157 BufferFeeder::BufferFeeder(const AudioConfig& config, |
136 bool effects_only, | 158 bool effects_only, |
137 const base::Closure& eos_cb) | 159 const base::Closure& eos_cb) |
138 : config_(config), | 160 : config_(config), |
139 effects_only_(effects_only), | 161 effects_only_(effects_only), |
140 eos_cb_(eos_cb), | 162 eos_cb_(eos_cb), |
163 max_rendering_delay_error_us_(0), | |
164 max_positive_rendering_delay_error_us_(0), | |
165 max_negative_rendering_delay_error_us_(0), | |
166 average_rendering_delay_error_us_(0), | |
167 sample_count_(0), | |
141 feeding_completed_(false), | 168 feeding_completed_(false), |
142 task_runner_(new TaskRunnerImpl()), | 169 task_runner_(new TaskRunnerImpl()), |
143 decoder_(nullptr), | 170 decoder_(nullptr), |
144 push_limit_us_(effects_only_ ? 0 : kPushTimeUs), | 171 push_limit_us_(effects_only_ ? 0 : kPushTimeUs), |
145 last_push_length_us_(0), | 172 last_push_length_us_(0), |
146 pushed_us_(0), | 173 pushed_us_(0), |
147 next_push_playback_timestamp_(0) { | 174 next_push_playback_timestamp_(0) { |
148 CHECK(!eos_cb_.is_null()); | 175 CHECK(!eos_cb_.is_null()); |
149 } | 176 } |
150 | 177 |
(...skipping 70 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
221 decoder_->GetRenderingDelay(); | 248 decoder_->GetRenderingDelay(); |
222 int64_t expected_next_push_playback_timestamp = | 249 int64_t expected_next_push_playback_timestamp = |
223 next_push_playback_timestamp_ + last_push_length_us_; | 250 next_push_playback_timestamp_ + last_push_length_us_; |
224 next_push_playback_timestamp_ = | 251 next_push_playback_timestamp_ = |
225 delay.timestamp_microseconds + delay.delay_microseconds; | 252 delay.timestamp_microseconds + delay.delay_microseconds; |
226 // Check rendering delay accuracy only if we have pushed more than | 253 // Check rendering delay accuracy only if we have pushed more than |
227 // kRenderingDelayGracePeriodUs of data. | 254 // kRenderingDelayGracePeriodUs of data. |
228 if (pushed_us_ > kRenderingDelayGracePeriodUs) { | 255 if (pushed_us_ > kRenderingDelayGracePeriodUs) { |
229 int64_t error = | 256 int64_t error = |
230 next_push_playback_timestamp_ - expected_next_push_playback_timestamp; | 257 next_push_playback_timestamp_ - expected_next_push_playback_timestamp; |
231 EXPECT_LT(std::abs(error), kMaxRenderingDelayErrorUs) | 258 max_rendering_delay_error_us_ = |
232 << "Bad rendering delay after " << pushed_us_ << " us"; | 259 std::max(max_rendering_delay_error_us_, std::abs(error)); |
260 average_rendering_delay_error_us_ = | |
kmackay
2016/06/15 20:26:48
Seems like it would be more accurate to maintain t
jameswest
2016/06/15 21:41:00
Done.
| |
261 (average_rendering_delay_error_us_ * sample_count_ + | |
262 std::abs(error)) / | |
263 (sample_count_ + 1); | |
264 if (error >= 0) { | |
265 max_positive_rendering_delay_error_us_ = | |
266 std::max(max_positive_rendering_delay_error_us_, error); | |
267 } else { | |
268 max_negative_rendering_delay_error_us_ = | |
269 std::min(max_negative_rendering_delay_error_us_, error); | |
270 } | |
271 sample_count_++; | |
233 } | 272 } |
234 } | 273 } |
235 pushed_us_ += last_push_length_us_; | 274 pushed_us_ += last_push_length_us_; |
236 | 275 |
237 if (feeding_completed_) | 276 if (feeding_completed_) |
238 return; | 277 return; |
239 | 278 |
240 base::ThreadTaskRunnerHandle::Get()->PostTask( | 279 base::ThreadTaskRunnerHandle::Get()->PostTask( |
241 FROM_HERE, base::Bind(&BufferFeeder::FeedBuffer, base::Unretained(this))); | 280 FROM_HERE, base::Bind(&BufferFeeder::FeedBuffer, base::Unretained(this))); |
242 } | 281 } |
243 | 282 |
244 } // namespace | 283 } // namespace |
245 | 284 |
246 MultizoneBackendTest::MultizoneBackendTest() {} | 285 MultizoneBackendTest::MultizoneBackendTest() {} |
247 | 286 |
248 MultizoneBackendTest::~MultizoneBackendTest() {} | 287 MultizoneBackendTest::~MultizoneBackendTest() {} |
249 | 288 |
250 void MultizoneBackendTest::Initialize(int sample_rate) { | 289 void MultizoneBackendTest::Initialize(int sample_rate) { |
251 AudioConfig config; | 290 AudioConfig config; |
252 config.codec = kCodecPCM; | 291 config.codec = kCodecPCM; |
253 config.sample_format = kSampleFormatPlanarF32; | 292 config.sample_format = kSampleFormatS32; |
254 config.channel_number = 2; | 293 config.channel_number = 2; |
255 config.bytes_per_channel = 4; | 294 config.bytes_per_channel = 4; |
256 config.samples_per_second = sample_rate; | 295 config.samples_per_second = sample_rate; |
257 | 296 |
258 audio_feeder_.reset( | 297 audio_feeder_.reset( |
259 new BufferFeeder(config, false /* effects_only */, | 298 new BufferFeeder(config, false /* effects_only */, |
260 base::Bind(&MultizoneBackendTest::OnEndOfStream, | 299 base::Bind(&MultizoneBackendTest::OnEndOfStream, |
261 base::Unretained(this)))); | 300 base::Unretained(this)))); |
262 audio_feeder_->Initialize(); | 301 audio_feeder_->Initialize(); |
263 } | 302 } |
(...skipping 20 matching lines...) Expand all Loading... | |
284 CHECK(audio_feeder_); | 323 CHECK(audio_feeder_); |
285 audio_feeder_->Start(); | 324 audio_feeder_->Start(); |
286 } | 325 } |
287 | 326 |
288 void MultizoneBackendTest::OnEndOfStream() { | 327 void MultizoneBackendTest::OnEndOfStream() { |
289 audio_feeder_->Stop(); | 328 audio_feeder_->Stop(); |
290 for (auto& feeder : effects_feeders_) | 329 for (auto& feeder : effects_feeders_) |
291 feeder->Stop(); | 330 feeder->Stop(); |
292 | 331 |
293 base::MessageLoop::current()->QuitWhenIdle(); | 332 base::MessageLoop::current()->QuitWhenIdle(); |
333 | |
334 EXPECT_LT(audio_feeder_->max_rendering_delay_error_us(), | |
335 kMaxRenderingDelayErrorUs) | |
336 << "Max positive rendering delay error: " | |
337 << audio_feeder_->max_positive_rendering_delay_error_us() | |
338 << "\nMax negative rendering delay error: " | |
339 << audio_feeder_->max_negative_rendering_delay_error_us() | |
340 << "\nAverage rendering delay error: " | |
341 << audio_feeder_->average_rendering_delay_error_us(); | |
294 } | 342 } |
295 | 343 |
296 TEST_P(MultizoneBackendTest, RenderingDelay) { | 344 TEST_P(MultizoneBackendTest, RenderingDelay) { |
297 std::unique_ptr<base::MessageLoop> message_loop(new base::MessageLoop()); | 345 std::unique_ptr<base::MessageLoop> message_loop(new base::MessageLoop()); |
298 | 346 |
299 Initialize(GetParam()); | 347 Initialize(GetParam()); |
300 AddEffectsStreams(); | 348 AddEffectsStreams(); |
301 Start(); | 349 Start(); |
302 message_loop->Run(); | 350 message_loop->Run(); |
303 } | 351 } |
304 | 352 |
305 INSTANTIATE_TEST_CASE_P(Required, | 353 INSTANTIATE_TEST_CASE_P(Required, |
306 MultizoneBackendTest, | 354 MultizoneBackendTest, |
307 ::testing::Values(8000, | 355 ::testing::Values(8000, |
308 11025, | 356 11025, |
309 12000, | 357 12000, |
310 16000, | 358 16000, |
311 22050, | 359 22050, |
312 24000, | 360 24000, |
313 32000, | 361 32000, |
314 44100, | 362 44100, |
315 48000)); | 363 48000)); |
316 | 364 |
317 INSTANTIATE_TEST_CASE_P(Optional, | 365 INSTANTIATE_TEST_CASE_P(Optional, |
318 MultizoneBackendTest, | 366 MultizoneBackendTest, |
319 ::testing::Values(64000, 88200, 96000)); | 367 ::testing::Values(64000, 88200, 96000)); |
320 | 368 |
321 } // namespace media | 369 } // namespace media |
322 } // namespace chromecast | 370 } // namespace chromecast |
OLD | NEW |