| 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 |