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 total_rendering_delay_error_us_ / sample_count_; |
| 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 total_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 total_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 total_rendering_delay_error_us_ += std::abs(error); |
| 261 if (error >= 0) { |
| 262 max_positive_rendering_delay_error_us_ = |
| 263 std::max(max_positive_rendering_delay_error_us_, error); |
| 264 } else { |
| 265 max_negative_rendering_delay_error_us_ = |
| 266 std::min(max_negative_rendering_delay_error_us_, error); |
| 267 } |
| 268 sample_count_++; |
233 } | 269 } |
234 } | 270 } |
235 pushed_us_ += last_push_length_us_; | 271 pushed_us_ += last_push_length_us_; |
236 | 272 |
237 if (feeding_completed_) | 273 if (feeding_completed_) |
238 return; | 274 return; |
239 | 275 |
240 base::ThreadTaskRunnerHandle::Get()->PostTask( | 276 base::ThreadTaskRunnerHandle::Get()->PostTask( |
241 FROM_HERE, base::Bind(&BufferFeeder::FeedBuffer, base::Unretained(this))); | 277 FROM_HERE, base::Bind(&BufferFeeder::FeedBuffer, base::Unretained(this))); |
242 } | 278 } |
243 | 279 |
244 } // namespace | 280 } // namespace |
245 | 281 |
246 MultizoneBackendTest::MultizoneBackendTest() {} | 282 MultizoneBackendTest::MultizoneBackendTest() {} |
247 | 283 |
248 MultizoneBackendTest::~MultizoneBackendTest() {} | 284 MultizoneBackendTest::~MultizoneBackendTest() {} |
249 | 285 |
250 void MultizoneBackendTest::Initialize(int sample_rate) { | 286 void MultizoneBackendTest::Initialize(int sample_rate) { |
251 AudioConfig config; | 287 AudioConfig config; |
252 config.codec = kCodecPCM; | 288 config.codec = kCodecPCM; |
253 config.sample_format = kSampleFormatPlanarF32; | 289 config.sample_format = kSampleFormatS32; |
254 config.channel_number = 2; | 290 config.channel_number = 2; |
255 config.bytes_per_channel = 4; | 291 config.bytes_per_channel = 4; |
256 config.samples_per_second = sample_rate; | 292 config.samples_per_second = sample_rate; |
257 | 293 |
258 audio_feeder_.reset( | 294 audio_feeder_.reset( |
259 new BufferFeeder(config, false /* effects_only */, | 295 new BufferFeeder(config, false /* effects_only */, |
260 base::Bind(&MultizoneBackendTest::OnEndOfStream, | 296 base::Bind(&MultizoneBackendTest::OnEndOfStream, |
261 base::Unretained(this)))); | 297 base::Unretained(this)))); |
262 audio_feeder_->Initialize(); | 298 audio_feeder_->Initialize(); |
263 } | 299 } |
(...skipping 20 matching lines...) Expand all Loading... |
284 CHECK(audio_feeder_); | 320 CHECK(audio_feeder_); |
285 audio_feeder_->Start(); | 321 audio_feeder_->Start(); |
286 } | 322 } |
287 | 323 |
288 void MultizoneBackendTest::OnEndOfStream() { | 324 void MultizoneBackendTest::OnEndOfStream() { |
289 audio_feeder_->Stop(); | 325 audio_feeder_->Stop(); |
290 for (auto& feeder : effects_feeders_) | 326 for (auto& feeder : effects_feeders_) |
291 feeder->Stop(); | 327 feeder->Stop(); |
292 | 328 |
293 base::MessageLoop::current()->QuitWhenIdle(); | 329 base::MessageLoop::current()->QuitWhenIdle(); |
| 330 |
| 331 EXPECT_LT(audio_feeder_->max_rendering_delay_error_us(), |
| 332 kMaxRenderingDelayErrorUs) |
| 333 << "Max positive rendering delay error: " |
| 334 << audio_feeder_->max_positive_rendering_delay_error_us() |
| 335 << "\nMax negative rendering delay error: " |
| 336 << audio_feeder_->max_negative_rendering_delay_error_us() |
| 337 << "\nAverage rendering delay error: " |
| 338 << audio_feeder_->average_rendering_delay_error_us(); |
294 } | 339 } |
295 | 340 |
296 TEST_P(MultizoneBackendTest, RenderingDelay) { | 341 TEST_P(MultizoneBackendTest, RenderingDelay) { |
297 std::unique_ptr<base::MessageLoop> message_loop(new base::MessageLoop()); | 342 std::unique_ptr<base::MessageLoop> message_loop(new base::MessageLoop()); |
298 | 343 |
299 Initialize(GetParam()); | 344 Initialize(GetParam()); |
300 AddEffectsStreams(); | 345 AddEffectsStreams(); |
301 Start(); | 346 Start(); |
302 message_loop->Run(); | 347 message_loop->Run(); |
303 } | 348 } |
304 | 349 |
305 INSTANTIATE_TEST_CASE_P(Required, | 350 INSTANTIATE_TEST_CASE_P(Required, |
306 MultizoneBackendTest, | 351 MultizoneBackendTest, |
307 ::testing::Values(8000, | 352 ::testing::Values(8000, |
308 11025, | 353 11025, |
309 12000, | 354 12000, |
310 16000, | 355 16000, |
311 22050, | 356 22050, |
312 24000, | 357 24000, |
313 32000, | 358 32000, |
314 44100, | 359 44100, |
315 48000)); | 360 48000)); |
316 | 361 |
317 INSTANTIATE_TEST_CASE_P(Optional, | 362 INSTANTIATE_TEST_CASE_P(Optional, |
318 MultizoneBackendTest, | 363 MultizoneBackendTest, |
319 ::testing::Values(64000, 88200, 96000)); | 364 ::testing::Values(64000, 88200, 96000)); |
320 | 365 |
321 } // namespace media | 366 } // namespace media |
322 } // namespace chromecast | 367 } // namespace chromecast |
OLD | NEW |