| OLD | NEW |
| 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2012 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 "media/renderers/audio_renderer_impl.h" | 5 #include "media/renderers/audio_renderer_impl.h" |
| 6 | 6 |
| 7 #include <memory> | 7 #include <memory> |
| 8 #include <utility> | 8 #include <utility> |
| 9 | 9 |
| 10 #include "base/bind.h" | 10 #include "base/bind.h" |
| (...skipping 65 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 76 sink_(new FakeAudioRendererSink(hardware_params_)), | 76 sink_(new FakeAudioRendererSink(hardware_params_)), |
| 77 tick_clock_(new base::SimpleTestTickClock()), | 77 tick_clock_(new base::SimpleTestTickClock()), |
| 78 demuxer_stream_(DemuxerStream::AUDIO), | 78 demuxer_stream_(DemuxerStream::AUDIO), |
| 79 decoder_(new MockAudioDecoder()), | 79 decoder_(new MockAudioDecoder()), |
| 80 ended_(false) { | 80 ended_(false) { |
| 81 AudioDecoderConfig audio_config(kCodec, kSampleFormat, kChannelLayout, | 81 AudioDecoderConfig audio_config(kCodec, kSampleFormat, kChannelLayout, |
| 82 kInputSamplesPerSecond, EmptyExtraData(), | 82 kInputSamplesPerSecond, EmptyExtraData(), |
| 83 Unencrypted()); | 83 Unencrypted()); |
| 84 demuxer_stream_.set_audio_decoder_config(audio_config); | 84 demuxer_stream_.set_audio_decoder_config(audio_config); |
| 85 | 85 |
| 86 // Used to save callbacks and run them at a later time. | 86 ConfigureDecoder(); |
| 87 EXPECT_CALL(*decoder_, Decode(_, _)) | 87 ConfigureDemuxerStream(true); |
| 88 .WillRepeatedly(Invoke(this, &AudioRendererImplTest::DecodeDecoder)); | |
| 89 EXPECT_CALL(*decoder_, Reset(_)) | |
| 90 .WillRepeatedly(Invoke(this, &AudioRendererImplTest::ResetDecoder)); | |
| 91 | 88 |
| 92 // Mock out demuxer reads. | |
| 93 EXPECT_CALL(demuxer_stream_, Read(_)).WillRepeatedly( | |
| 94 RunCallback<0>(DemuxerStream::kOk, | |
| 95 scoped_refptr<DecoderBuffer>(new DecoderBuffer(0)))); | |
| 96 EXPECT_CALL(demuxer_stream_, SupportsConfigChanges()) | |
| 97 .WillRepeatedly(Return(true)); | |
| 98 AudioParameters out_params(AudioParameters::AUDIO_PCM_LOW_LATENCY, | 89 AudioParameters out_params(AudioParameters::AUDIO_PCM_LOW_LATENCY, |
| 99 kChannelLayout, | 90 kChannelLayout, |
| 100 kOutputSamplesPerSecond, | 91 kOutputSamplesPerSecond, |
| 101 SampleFormatToBytesPerChannel(kSampleFormat) * 8, | 92 SampleFormatToBytesPerChannel(kSampleFormat) * 8, |
| 102 512); | 93 512); |
| 103 ScopedVector<AudioDecoder> decoders; | 94 ScopedVector<AudioDecoder> decoders; |
| 104 decoders.push_back(decoder_); | 95 decoders.push_back(decoder_); |
| 105 renderer_.reset(new AudioRendererImpl(message_loop_.task_runner(), | 96 renderer_.reset(new AudioRendererImpl(message_loop_.task_runner(), |
| 106 sink_.get(), std::move(decoders), | 97 sink_.get(), std::move(decoders), |
| 107 new MediaLog())); | 98 new MediaLog())); |
| 108 renderer_->tick_clock_.reset(tick_clock_); | 99 renderer_->tick_clock_.reset(tick_clock_); |
| 109 tick_clock_->Advance(base::TimeDelta::FromSeconds(1)); | 100 tick_clock_->Advance(base::TimeDelta::FromSeconds(1)); |
| 110 } | 101 } |
| 111 | 102 |
| 112 virtual ~AudioRendererImplTest() { | 103 virtual ~AudioRendererImplTest() { |
| 113 SCOPED_TRACE("~AudioRendererImplTest()"); | 104 SCOPED_TRACE("~AudioRendererImplTest()"); |
| 114 } | 105 } |
| 115 | 106 |
| 107 // Used to save callbacks and run them at a later time. |
| 108 void ConfigureDecoder() { |
| 109 EXPECT_CALL(*decoder_, Decode(_, _)) |
| 110 .WillRepeatedly(Invoke(this, &AudioRendererImplTest::DecodeDecoder)); |
| 111 EXPECT_CALL(*decoder_, Reset(_)) |
| 112 .WillRepeatedly(Invoke(this, &AudioRendererImplTest::ResetDecoder)); |
| 113 } |
| 114 |
| 115 // Mock out demuxer reads. |
| 116 void ConfigureDemuxerStream(bool supports_config_changes) { |
| 117 EXPECT_CALL(demuxer_stream_, Read(_)) |
| 118 .WillRepeatedly( |
| 119 RunCallback<0>(DemuxerStream::kOk, |
| 120 scoped_refptr<DecoderBuffer>(new DecoderBuffer(0)))); |
| 121 EXPECT_CALL(demuxer_stream_, SupportsConfigChanges()) |
| 122 .WillRepeatedly(Return(supports_config_changes)); |
| 123 } |
| 124 |
| 116 // Reconfigures a renderer without config change support using given params. | 125 // Reconfigures a renderer without config change support using given params. |
| 117 void ConfigureBasicRenderer(const AudioParameters& params) { | 126 void ConfigureBasicRenderer(const AudioParameters& params) { |
| 118 hardware_params_ = params; | 127 hardware_params_ = params; |
| 119 sink_ = new FakeAudioRendererSink(hardware_params_); | 128 sink_ = new FakeAudioRendererSink(hardware_params_); |
| 120 decoder_ = new MockAudioDecoder(); | 129 decoder_ = new MockAudioDecoder(); |
| 130 ConfigureDecoder(); |
| 121 ScopedVector<AudioDecoder> decoders; | 131 ScopedVector<AudioDecoder> decoders; |
| 122 decoders.push_back(decoder_); | 132 decoders.push_back(decoder_); |
| 123 renderer_.reset(new AudioRendererImpl(message_loop_.task_runner(), | 133 renderer_.reset(new AudioRendererImpl(message_loop_.task_runner(), |
| 124 sink_.get(), std::move(decoders), | 134 sink_.get(), std::move(decoders), |
| 125 new MediaLog())); | 135 new MediaLog())); |
| 126 testing::Mock::VerifyAndClearExpectations(&demuxer_stream_); | 136 testing::Mock::VerifyAndClearExpectations(&demuxer_stream_); |
| 127 EXPECT_CALL(demuxer_stream_, SupportsConfigChanges()) | 137 ConfigureDemuxerStream(false); |
| 128 .WillRepeatedly(Return(false)); | 138 } |
| 139 |
| 140 // Reconfigures a renderer with config change support using given params. |
| 141 void ConfigureConfigChangeRenderer(const AudioParameters& params, |
| 142 const AudioParameters& hardware_params) { |
| 143 hardware_params_ = hardware_params; |
| 144 sink_ = new FakeAudioRendererSink(hardware_params_); |
| 145 decoder_ = new MockAudioDecoder(); |
| 146 ConfigureDecoder(); |
| 147 ScopedVector<AudioDecoder> decoders; |
| 148 decoders.push_back(decoder_); |
| 149 renderer_.reset(new AudioRendererImpl(message_loop_.task_runner(), |
| 150 sink_.get(), std::move(decoders), |
| 151 new MediaLog())); |
| 152 testing::Mock::VerifyAndClearExpectations(&demuxer_stream_); |
| 153 ConfigureDemuxerStream(true); |
| 129 } | 154 } |
| 130 | 155 |
| 131 void ExpectUnsupportedAudioDecoder() { | 156 void ExpectUnsupportedAudioDecoder() { |
| 132 EXPECT_CALL(*decoder_, Initialize(_, _, _, _)) | 157 EXPECT_CALL(*decoder_, Initialize(_, _, _, _)) |
| 133 .WillOnce(DoAll(SaveArg<3>(&output_cb_), RunCallback<2>(false))); | 158 .WillOnce(DoAll(SaveArg<3>(&output_cb_), RunCallback<2>(false))); |
| 134 } | 159 } |
| 135 | 160 |
| 136 // RendererClient implementation. | 161 // RendererClient implementation. |
| 137 MOCK_METHOD1(OnError, void(PipelineStatus)); | 162 MOCK_METHOD1(OnError, void(PipelineStatus)); |
| 138 void OnEnded() override { | 163 void OnEnded() override { |
| (...skipping 227 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 366 | 391 |
| 367 InputFrames converter_input_frames_left() const { | 392 InputFrames converter_input_frames_left() const { |
| 368 return InputFrames( | 393 return InputFrames( |
| 369 renderer_->buffer_converter_->input_frames_left_for_testing()); | 394 renderer_->buffer_converter_->input_frames_left_for_testing()); |
| 370 } | 395 } |
| 371 | 396 |
| 372 base::TimeDelta CurrentMediaTime() { | 397 base::TimeDelta CurrentMediaTime() { |
| 373 return renderer_->CurrentMediaTime(); | 398 return renderer_->CurrentMediaTime(); |
| 374 } | 399 } |
| 375 | 400 |
| 401 std::vector<bool> channel_mask() const { |
| 402 CHECK(renderer_->algorithm_); |
| 403 return renderer_->algorithm_->channel_mask_for_testing(); |
| 404 } |
| 405 |
| 376 bool ended() const { return ended_; } | 406 bool ended() const { return ended_; } |
| 377 | 407 |
| 378 // Fixture members. | |
| 379 AudioParameters hardware_params_; | |
| 380 base::MessageLoop message_loop_; | |
| 381 std::unique_ptr<AudioRendererImpl> renderer_; | |
| 382 scoped_refptr<FakeAudioRendererSink> sink_; | |
| 383 base::SimpleTestTickClock* tick_clock_; | |
| 384 PipelineStatistics last_statistics_; | |
| 385 | |
| 386 private: | |
| 387 void DecodeDecoder(const scoped_refptr<DecoderBuffer>& buffer, | 408 void DecodeDecoder(const scoped_refptr<DecoderBuffer>& buffer, |
| 388 const AudioDecoder::DecodeCB& decode_cb) { | 409 const AudioDecoder::DecodeCB& decode_cb) { |
| 389 // TODO(scherkus): Make this a DCHECK after threading semantics are fixed. | 410 // TODO(scherkus): Make this a DCHECK after threading semantics are fixed. |
| 390 if (base::MessageLoop::current() != &message_loop_) { | 411 if (base::MessageLoop::current() != &message_loop_) { |
| 391 message_loop_.task_runner()->PostTask( | 412 message_loop_.task_runner()->PostTask( |
| 392 FROM_HERE, base::Bind(&AudioRendererImplTest::DecodeDecoder, | 413 FROM_HERE, base::Bind(&AudioRendererImplTest::DecodeDecoder, |
| 393 base::Unretained(this), buffer, decode_cb)); | 414 base::Unretained(this), buffer, decode_cb)); |
| 394 return; | 415 return; |
| 395 } | 416 } |
| 396 | 417 |
| (...skipping 23 matching lines...) Expand all Loading... |
| 420 if (buffer.get() && !buffer->end_of_stream()) | 441 if (buffer.get() && !buffer->end_of_stream()) |
| 421 output_cb_.Run(buffer); | 442 output_cb_.Run(buffer); |
| 422 base::ResetAndReturn(&decode_cb_).Run(status); | 443 base::ResetAndReturn(&decode_cb_).Run(status); |
| 423 | 444 |
| 424 if (!reset_cb_.is_null()) | 445 if (!reset_cb_.is_null()) |
| 425 base::ResetAndReturn(&reset_cb_).Run(); | 446 base::ResetAndReturn(&reset_cb_).Run(); |
| 426 | 447 |
| 427 base::RunLoop().RunUntilIdle(); | 448 base::RunLoop().RunUntilIdle(); |
| 428 } | 449 } |
| 429 | 450 |
| 451 // Fixture members. |
| 452 AudioParameters hardware_params_; |
| 453 base::MessageLoop message_loop_; |
| 454 std::unique_ptr<AudioRendererImpl> renderer_; |
| 455 scoped_refptr<FakeAudioRendererSink> sink_; |
| 456 base::SimpleTestTickClock* tick_clock_; |
| 457 PipelineStatistics last_statistics_; |
| 458 |
| 430 MockDemuxerStream demuxer_stream_; | 459 MockDemuxerStream demuxer_stream_; |
| 431 MockAudioDecoder* decoder_; | 460 MockAudioDecoder* decoder_; |
| 432 | 461 |
| 433 // Used for satisfying reads. | 462 // Used for satisfying reads. |
| 434 AudioDecoder::OutputCB output_cb_; | 463 AudioDecoder::OutputCB output_cb_; |
| 435 AudioDecoder::DecodeCB decode_cb_; | 464 AudioDecoder::DecodeCB decode_cb_; |
| 436 base::Closure reset_cb_; | 465 base::Closure reset_cb_; |
| 437 std::unique_ptr<AudioTimestampHelper> next_timestamp_; | 466 std::unique_ptr<AudioTimestampHelper> next_timestamp_; |
| 438 | 467 |
| 439 // Run during DecodeDecoder() to unblock WaitForPendingRead(). | 468 // Run during DecodeDecoder() to unblock WaitForPendingRead(). |
| (...skipping 131 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 571 // Verify in the no-config-changes-expected case. | 600 // Verify in the no-config-changes-expected case. |
| 572 ConfigureBasicRenderer(AudioParameters( | 601 ConfigureBasicRenderer(AudioParameters( |
| 573 AudioParameters::AUDIO_PCM_LOW_LATENCY, kChannelLayout, | 602 AudioParameters::AUDIO_PCM_LOW_LATENCY, kChannelLayout, |
| 574 kOutputSamplesPerSecond, SampleFormatToBytesPerChannel(kSampleFormat) * 8, | 603 kOutputSamplesPerSecond, SampleFormatToBytesPerChannel(kSampleFormat) * 8, |
| 575 1024 * 15)); | 604 1024 * 15)); |
| 576 | 605 |
| 577 Initialize(); | 606 Initialize(); |
| 578 EXPECT_GT(buffer_capacity().value, hardware_params_.frames_per_buffer()); | 607 EXPECT_GT(buffer_capacity().value, hardware_params_.frames_per_buffer()); |
| 579 } | 608 } |
| 580 | 609 |
| 610 // Verify that the proper reduced search space is configured for playback rate |
| 611 // changes when upmixing is applied to the input. |
| 612 TEST_F(AudioRendererImplTest, ChannelMask) { |
| 613 AudioParameters hw_params(AudioParameters::AUDIO_PCM_LOW_LATENCY, |
| 614 CHANNEL_LAYOUT_7_1, kOutputSamplesPerSecond, |
| 615 SampleFormatToBytesPerChannel(kSampleFormat) * 8, |
| 616 1024); |
| 617 ConfigureConfigChangeRenderer( |
| 618 AudioParameters(AudioParameters::AUDIO_PCM_LOW_LATENCY, |
| 619 CHANNEL_LAYOUT_STEREO, kOutputSamplesPerSecond, |
| 620 SampleFormatToBytesPerChannel(kSampleFormat) * 8, 1024), |
| 621 hw_params); |
| 622 Initialize(); |
| 623 std::vector<bool> mask = channel_mask(); |
| 624 EXPECT_FALSE(mask.empty()); |
| 625 ASSERT_EQ(mask.size(), static_cast<size_t>(hw_params.channels())); |
| 626 for (int ch = 0; ch < hw_params.channels(); ++ch) { |
| 627 if (ch > 1) |
| 628 ASSERT_FALSE(mask[ch]); |
| 629 else |
| 630 ASSERT_TRUE(mask[ch]); |
| 631 } |
| 632 |
| 633 renderer_->SetMediaTime(base::TimeDelta()); |
| 634 renderer_->StartPlaying(); |
| 635 WaitForPendingRead(); |
| 636 |
| 637 // Force a channel configuration change. |
| 638 scoped_refptr<AudioBuffer> buffer = MakeAudioBuffer<float>( |
| 639 kSampleFormat, hw_params.channel_layout(), hw_params.channels(), |
| 640 kInputSamplesPerSecond, 1.0f, 0.0f, 256, base::TimeDelta()); |
| 641 DeliverBuffer(DecodeStatus::OK, buffer); |
| 642 |
| 643 // All channels should now be enabled. |
| 644 mask = channel_mask(); |
| 645 EXPECT_FALSE(mask.empty()); |
| 646 ASSERT_EQ(mask.size(), static_cast<size_t>(hw_params.channels())); |
| 647 for (int ch = 0; ch < hw_params.channels(); ++ch) |
| 648 ASSERT_TRUE(mask[ch]); |
| 649 } |
| 650 |
| 581 TEST_F(AudioRendererImplTest, Underflow_Flush) { | 651 TEST_F(AudioRendererImplTest, Underflow_Flush) { |
| 582 Initialize(); | 652 Initialize(); |
| 583 Preroll(); | 653 Preroll(); |
| 584 StartTicking(); | 654 StartTicking(); |
| 585 | 655 |
| 586 // Force underflow. | 656 // Force underflow. |
| 587 EXPECT_TRUE(ConsumeBufferedData(frames_buffered())); | 657 EXPECT_TRUE(ConsumeBufferedData(frames_buffered())); |
| 588 WaitForPendingRead(); | 658 WaitForPendingRead(); |
| 589 EXPECT_CALL(*this, OnBufferingStateChange(BUFFERING_HAVE_NOTHING)); | 659 EXPECT_CALL(*this, OnBufferingStateChange(BUFFERING_HAVE_NOTHING)); |
| 590 EXPECT_FALSE(ConsumeBufferedData(OutputFrames(1))); | 660 EXPECT_FALSE(ConsumeBufferedData(OutputFrames(1))); |
| (...skipping 402 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 993 // Advance far enough that we shouldn't be clamped to current time (tested | 1063 // Advance far enough that we shouldn't be clamped to current time (tested |
| 994 // already above). | 1064 // already above). |
| 995 tick_clock_->Advance(kOneSecond); | 1065 tick_clock_->Advance(kOneSecond); |
| 996 EXPECT_EQ( | 1066 EXPECT_EQ( |
| 997 current_time + timestamp_helper.GetFrameDuration(frames_to_consume.value), | 1067 current_time + timestamp_helper.GetFrameDuration(frames_to_consume.value), |
| 998 CurrentMediaWallClockTime(&is_time_moving)); | 1068 CurrentMediaWallClockTime(&is_time_moving)); |
| 999 EXPECT_TRUE(is_time_moving); | 1069 EXPECT_TRUE(is_time_moving); |
| 1000 } | 1070 } |
| 1001 | 1071 |
| 1002 } // namespace media | 1072 } // namespace media |
| OLD | NEW |