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)); | |
129 } | 138 } |
130 | 139 |
131 // Reconfigures a renderer with config change support using given params. | 140 // Reconfigures a renderer with config change support using given params. |
132 void ConfigureConfigChangeRenderer(const AudioParameters& params, | 141 void ConfigureConfigChangeRenderer(const AudioParameters& params, |
133 const AudioParameters& hardware_params) { | 142 const AudioParameters& hardware_params) { |
134 hardware_params_ = hardware_params; | 143 hardware_params_ = hardware_params; |
135 sink_ = new FakeAudioRendererSink(hardware_params_); | 144 sink_ = new FakeAudioRendererSink(hardware_params_); |
136 decoder_ = new MockAudioDecoder(); | 145 decoder_ = new MockAudioDecoder(); |
| 146 ConfigureDecoder(); |
137 ScopedVector<AudioDecoder> decoders; | 147 ScopedVector<AudioDecoder> decoders; |
138 decoders.push_back(decoder_); | 148 decoders.push_back(decoder_); |
139 renderer_.reset(new AudioRendererImpl(message_loop_.task_runner(), | 149 renderer_.reset(new AudioRendererImpl(message_loop_.task_runner(), |
140 sink_.get(), std::move(decoders), | 150 sink_.get(), std::move(decoders), |
141 new MediaLog())); | 151 new MediaLog())); |
142 testing::Mock::VerifyAndClearExpectations(&demuxer_stream_); | 152 testing::Mock::VerifyAndClearExpectations(&demuxer_stream_); |
143 EXPECT_CALL(demuxer_stream_, SupportsConfigChanges()) | 153 ConfigureDemuxerStream(true); |
144 .WillRepeatedly(Return(true)); | |
145 } | 154 } |
146 | 155 |
147 void ExpectUnsupportedAudioDecoder() { | 156 void ExpectUnsupportedAudioDecoder() { |
148 EXPECT_CALL(*decoder_, Initialize(_, _, _, _)) | 157 EXPECT_CALL(*decoder_, Initialize(_, _, _, _)) |
149 .WillOnce(DoAll(SaveArg<3>(&output_cb_), RunCallback<2>(false))); | 158 .WillOnce(DoAll(SaveArg<3>(&output_cb_), RunCallback<2>(false))); |
150 } | 159 } |
151 | 160 |
152 // RendererClient implementation. | 161 // RendererClient implementation. |
153 MOCK_METHOD1(OnError, void(PipelineStatus)); | 162 MOCK_METHOD1(OnError, void(PipelineStatus)); |
154 void OnEnded() override { | 163 void OnEnded() override { |
(...skipping 227 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
382 | 391 |
383 InputFrames converter_input_frames_left() const { | 392 InputFrames converter_input_frames_left() const { |
384 return InputFrames( | 393 return InputFrames( |
385 renderer_->buffer_converter_->input_frames_left_for_testing()); | 394 renderer_->buffer_converter_->input_frames_left_for_testing()); |
386 } | 395 } |
387 | 396 |
388 base::TimeDelta CurrentMediaTime() { | 397 base::TimeDelta CurrentMediaTime() { |
389 return renderer_->CurrentMediaTime(); | 398 return renderer_->CurrentMediaTime(); |
390 } | 399 } |
391 | 400 |
392 std::vector<bool> channel_mask() const { return renderer_->channel_mask_; } | 401 std::vector<bool> channel_mask() const { |
| 402 CHECK(renderer_->algorithm_); |
| 403 return renderer_->algorithm_->channel_mask_for_testing(); |
| 404 } |
393 | 405 |
394 bool ended() const { return ended_; } | 406 bool ended() const { return ended_; } |
395 | 407 |
396 // Fixture members. | |
397 AudioParameters hardware_params_; | |
398 base::MessageLoop message_loop_; | |
399 std::unique_ptr<AudioRendererImpl> renderer_; | |
400 scoped_refptr<FakeAudioRendererSink> sink_; | |
401 base::SimpleTestTickClock* tick_clock_; | |
402 PipelineStatistics last_statistics_; | |
403 | |
404 private: | |
405 void DecodeDecoder(const scoped_refptr<DecoderBuffer>& buffer, | 408 void DecodeDecoder(const scoped_refptr<DecoderBuffer>& buffer, |
406 const AudioDecoder::DecodeCB& decode_cb) { | 409 const AudioDecoder::DecodeCB& decode_cb) { |
407 // TODO(scherkus): Make this a DCHECK after threading semantics are fixed. | 410 // TODO(scherkus): Make this a DCHECK after threading semantics are fixed. |
408 if (base::MessageLoop::current() != &message_loop_) { | 411 if (base::MessageLoop::current() != &message_loop_) { |
409 message_loop_.task_runner()->PostTask( | 412 message_loop_.task_runner()->PostTask( |
410 FROM_HERE, base::Bind(&AudioRendererImplTest::DecodeDecoder, | 413 FROM_HERE, base::Bind(&AudioRendererImplTest::DecodeDecoder, |
411 base::Unretained(this), buffer, decode_cb)); | 414 base::Unretained(this), buffer, decode_cb)); |
412 return; | 415 return; |
413 } | 416 } |
414 | 417 |
(...skipping 23 matching lines...) Expand all Loading... |
438 if (buffer.get() && !buffer->end_of_stream()) | 441 if (buffer.get() && !buffer->end_of_stream()) |
439 output_cb_.Run(buffer); | 442 output_cb_.Run(buffer); |
440 base::ResetAndReturn(&decode_cb_).Run(status); | 443 base::ResetAndReturn(&decode_cb_).Run(status); |
441 | 444 |
442 if (!reset_cb_.is_null()) | 445 if (!reset_cb_.is_null()) |
443 base::ResetAndReturn(&reset_cb_).Run(); | 446 base::ResetAndReturn(&reset_cb_).Run(); |
444 | 447 |
445 base::RunLoop().RunUntilIdle(); | 448 base::RunLoop().RunUntilIdle(); |
446 } | 449 } |
447 | 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 |
448 MockDemuxerStream demuxer_stream_; | 459 MockDemuxerStream demuxer_stream_; |
449 MockAudioDecoder* decoder_; | 460 MockAudioDecoder* decoder_; |
450 | 461 |
451 // Used for satisfying reads. | 462 // Used for satisfying reads. |
452 AudioDecoder::OutputCB output_cb_; | 463 AudioDecoder::OutputCB output_cb_; |
453 AudioDecoder::DecodeCB decode_cb_; | 464 AudioDecoder::DecodeCB decode_cb_; |
454 base::Closure reset_cb_; | 465 base::Closure reset_cb_; |
455 std::unique_ptr<AudioTimestampHelper> next_timestamp_; | 466 std::unique_ptr<AudioTimestampHelper> next_timestamp_; |
456 | 467 |
457 // Run during DecodeDecoder() to unblock WaitForPendingRead(). | 468 // Run during DecodeDecoder() to unblock WaitForPendingRead(). |
(...skipping 134 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
592 kOutputSamplesPerSecond, SampleFormatToBytesPerChannel(kSampleFormat) * 8, | 603 kOutputSamplesPerSecond, SampleFormatToBytesPerChannel(kSampleFormat) * 8, |
593 1024 * 15)); | 604 1024 * 15)); |
594 | 605 |
595 Initialize(); | 606 Initialize(); |
596 EXPECT_GT(buffer_capacity().value, hardware_params_.frames_per_buffer()); | 607 EXPECT_GT(buffer_capacity().value, hardware_params_.frames_per_buffer()); |
597 } | 608 } |
598 | 609 |
599 // Verify that the proper reduced search space is configured for playback rate | 610 // Verify that the proper reduced search space is configured for playback rate |
600 // changes when upmixing is applied to the input. | 611 // changes when upmixing is applied to the input. |
601 TEST_F(AudioRendererImplTest, ChannelMask) { | 612 TEST_F(AudioRendererImplTest, ChannelMask) { |
602 Initialize(); | |
603 AudioParameters hw_params(AudioParameters::AUDIO_PCM_LOW_LATENCY, | 613 AudioParameters hw_params(AudioParameters::AUDIO_PCM_LOW_LATENCY, |
604 CHANNEL_LAYOUT_7_1, kOutputSamplesPerSecond, | 614 CHANNEL_LAYOUT_7_1, kOutputSamplesPerSecond, |
605 SampleFormatToBytesPerChannel(kSampleFormat) * 8, | 615 SampleFormatToBytesPerChannel(kSampleFormat) * 8, |
606 1024); | 616 1024); |
607 ConfigureConfigChangeRenderer( | 617 ConfigureConfigChangeRenderer( |
608 AudioParameters(AudioParameters::AUDIO_PCM_LOW_LATENCY, | 618 AudioParameters(AudioParameters::AUDIO_PCM_LOW_LATENCY, |
609 CHANNEL_LAYOUT_STEREO, kOutputSamplesPerSecond, | 619 CHANNEL_LAYOUT_STEREO, kOutputSamplesPerSecond, |
610 SampleFormatToBytesPerChannel(kSampleFormat) * 8, 1024), | 620 SampleFormatToBytesPerChannel(kSampleFormat) * 8, 1024), |
611 hw_params); | 621 hw_params); |
| 622 Initialize(); |
612 std::vector<bool> mask = channel_mask(); | 623 std::vector<bool> mask = channel_mask(); |
613 EXPECT_TRUE(mask.empty()); | |
614 Initialize(); | |
615 mask = channel_mask(); | |
616 EXPECT_FALSE(mask.empty()); | 624 EXPECT_FALSE(mask.empty()); |
| 625 ASSERT_EQ(mask.size(), static_cast<size_t>(hw_params.channels())); |
617 for (int ch = 0; ch < hw_params.channels(); ++ch) { | 626 for (int ch = 0; ch < hw_params.channels(); ++ch) { |
618 if (ch > 1) | 627 if (ch > 1) |
619 ASSERT_FALSE(mask[ch]); | 628 ASSERT_FALSE(mask[ch]); |
620 else | 629 else |
621 ASSERT_TRUE(mask[ch]); | 630 ASSERT_TRUE(mask[ch]); |
622 } | 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]); |
623 } | 649 } |
624 | 650 |
625 TEST_F(AudioRendererImplTest, Underflow_Flush) { | 651 TEST_F(AudioRendererImplTest, Underflow_Flush) { |
626 Initialize(); | 652 Initialize(); |
627 Preroll(); | 653 Preroll(); |
628 StartTicking(); | 654 StartTicking(); |
629 | 655 |
630 // Force underflow. | 656 // Force underflow. |
631 EXPECT_TRUE(ConsumeBufferedData(frames_buffered())); | 657 EXPECT_TRUE(ConsumeBufferedData(frames_buffered())); |
632 WaitForPendingRead(); | 658 WaitForPendingRead(); |
(...skipping 404 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1037 // 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 |
1038 // already above). | 1064 // already above). |
1039 tick_clock_->Advance(kOneSecond); | 1065 tick_clock_->Advance(kOneSecond); |
1040 EXPECT_EQ( | 1066 EXPECT_EQ( |
1041 current_time + timestamp_helper.GetFrameDuration(frames_to_consume.value), | 1067 current_time + timestamp_helper.GetFrameDuration(frames_to_consume.value), |
1042 CurrentMediaWallClockTime(&is_time_moving)); | 1068 CurrentMediaWallClockTime(&is_time_moving)); |
1043 EXPECT_TRUE(is_time_moving); | 1069 EXPECT_TRUE(is_time_moving); |
1044 } | 1070 } |
1045 | 1071 |
1046 } // namespace media | 1072 } // namespace media |
OLD | NEW |