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 3// found in the LICENSE file. 4 5#include "base/bind.h" 6#include "base/callback_helpers.h" 7#include "base/run_loop.h" 8#include "base/strings/stringprintf.h" 9#include "media/base/audio_buffer_converter.h" 10#include "media/base/audio_hardware_config.h" 11#include "media/base/audio_splicer.h" 12#include "media/base/fake_audio_renderer_sink.h" 13#include "media/base/gmock_callback_support.h" 14#include "media/base/mock_filters.h" 15#include "media/base/test_helpers.h" 16#include "media/filters/audio_renderer_impl.h" 17#include "testing/gtest/include/gtest/gtest.h" 18 19using ::base::TimeDelta; 20using ::testing::_; 21using ::testing::Return; 22using ::testing::SaveArg; 23 24namespace media { 25 26namespace { 27 28// Since AudioBufferConverter is used due to different input/output sample 29// rates, define some helper types to differentiate between the two. 30struct InputFrames { 31 explicit InputFrames(int value) : value(value) {} 32 int value; 33}; 34 35struct OutputFrames { 36 explicit OutputFrames(int value) : value(value) {} 37 int value; 38}; 39 40} // namespace 41 42// Constants to specify the type of audio data used. 43static AudioCodec kCodec = kCodecVorbis; 44static SampleFormat kSampleFormat = kSampleFormatPlanarF32; 45static ChannelLayout kChannelLayout = CHANNEL_LAYOUT_STEREO; 46static int kChannelCount = 2; 47static int kChannels = ChannelLayoutToChannelCount(kChannelLayout); 48 49// Use a different output sample rate so the AudioBufferConverter is invoked. 50static int kInputSamplesPerSecond = 5000; 51static int kOutputSamplesPerSecond = 10000; 52 53ACTION_P(EnterPendingDecoderInitStateAction, test) { 54 test->EnterPendingDecoderInitState(arg1); 55} 56 57class AudioRendererImplTest : public ::testing::Test { 58 public: 59 // Give the decoder some non-garbage media properties. 60 AudioRendererImplTest() 61 : hardware_config_(AudioParameters(), AudioParameters()), 62 demuxer_stream_(DemuxerStream::AUDIO), 63 decoder_(new MockAudioDecoder()), 64 ended_(false) { 65 AudioDecoderConfig audio_config(kCodec, 66 kSampleFormat, 67 kChannelLayout, 68 kInputSamplesPerSecond, 69 NULL, 70 0, 71 false); 72 demuxer_stream_.set_audio_decoder_config(audio_config); 73 74 // Used to save callbacks and run them at a later time. 75 EXPECT_CALL(*decoder_, Decode(_, _)) 76 .WillRepeatedly(Invoke(this, &AudioRendererImplTest::DecodeDecoder)); 77 EXPECT_CALL(*decoder_, Reset(_)) 78 .WillRepeatedly(Invoke(this, &AudioRendererImplTest::ResetDecoder)); 79 80 // Mock out demuxer reads. 81 EXPECT_CALL(demuxer_stream_, Read(_)).WillRepeatedly( 82 RunCallback<0>(DemuxerStream::kOk, 83 scoped_refptr<DecoderBuffer>(new DecoderBuffer(0)))); 84 EXPECT_CALL(demuxer_stream_, SupportsConfigChanges()) 85 .WillRepeatedly(Return(true)); 86 AudioParameters out_params(AudioParameters::AUDIO_PCM_LOW_LATENCY, 87 kChannelLayout, 88 kOutputSamplesPerSecond, 89 SampleFormatToBytesPerChannel(kSampleFormat) * 8, 90 512); 91 hardware_config_.UpdateOutputConfig(out_params); 92 ScopedVector<AudioDecoder> decoders; 93 decoders.push_back(decoder_); 94 sink_ = new FakeAudioRendererSink(); 95 renderer_.reset(new AudioRendererImpl(message_loop_.message_loop_proxy(), 96 sink_.get(), 97 decoders.Pass(), 98 SetDecryptorReadyCB(), 99 hardware_config_, 100 new MediaLog())); 101 } 102 103 virtual ~AudioRendererImplTest() { 104 SCOPED_TRACE("~AudioRendererImplTest()"); 105 } 106 107 void ExpectUnsupportedAudioDecoder() { 108 EXPECT_CALL(*decoder_, Initialize(_, _, _)) 109 .WillOnce(DoAll(SaveArg<2>(&output_cb_), 110 RunCallback<1>(DECODER_ERROR_NOT_SUPPORTED))); 111 } 112 113 MOCK_METHOD1(OnStatistics, void(const PipelineStatistics&)); 114 MOCK_METHOD1(OnBufferingStateChange, void(BufferingState)); 115 MOCK_METHOD1(OnError, void(PipelineStatus)); 116 117 void InitializeRenderer(const PipelineStatusCB& pipeline_status_cb) { 118 renderer_->Initialize( 119 &demuxer_stream_, 120 pipeline_status_cb, 121 base::Bind(&AudioRendererImplTest::OnStatistics, 122 base::Unretained(this)), 123 base::Bind(&AudioRendererImplTest::OnBufferingStateChange, 124 base::Unretained(this)), 125 base::Bind(&AudioRendererImplTest::OnEnded, 126 base::Unretained(this)), 127 base::Bind(&AudioRendererImplTest::OnError, 128 base::Unretained(this))); 129 } 130 131 void Initialize() { 132 EXPECT_CALL(*decoder_, Initialize(_, _, _)) 133 .WillOnce(DoAll(SaveArg<2>(&output_cb_), 134 RunCallback<1>(PIPELINE_OK))); 135 InitializeWithStatus(PIPELINE_OK); 136 137 next_timestamp_.reset(new AudioTimestampHelper(kInputSamplesPerSecond)); 138 } 139 140 void InitializeWithStatus(PipelineStatus expected) { 141 SCOPED_TRACE(base::StringPrintf("InitializeWithStatus(%d)", expected)); 142 143 WaitableMessageLoopEvent event; 144 InitializeRenderer(event.GetPipelineStatusCB()); 145 event.RunAndWaitForStatus(expected); 146 147 // We should have no reads. 148 EXPECT_TRUE(decode_cb_.is_null()); 149 } 150 151 void InitializeAndDestroy() { 152 EXPECT_CALL(*decoder_, Initialize(_, _, _)) 153 .WillOnce(RunCallback<1>(PIPELINE_OK)); 154 155 WaitableMessageLoopEvent event; 156 InitializeRenderer(event.GetPipelineStatusCB()); 157 158 // Destroy the |renderer_| before we let the MessageLoop run, this simulates 159 // an interleaving in which we end up destroying the |renderer_| while the 160 // OnDecoderSelected callback is in flight. 161 renderer_.reset(); 162 event.RunAndWaitForStatus(PIPELINE_ERROR_ABORT); 163 } 164 165 void InitializeAndDestroyDuringDecoderInit() { 166 EXPECT_CALL(*decoder_, Initialize(_, _, _)) 167 .WillOnce(EnterPendingDecoderInitStateAction(this)); 168 169 WaitableMessageLoopEvent event; 170 InitializeRenderer(event.GetPipelineStatusCB()); 171 base::RunLoop().RunUntilIdle(); 172 DCHECK(!init_decoder_cb_.is_null()); 173 174 renderer_.reset(); 175 event.RunAndWaitForStatus(PIPELINE_ERROR_ABORT); 176 } 177 178 void EnterPendingDecoderInitState(PipelineStatusCB cb) { 179 init_decoder_cb_ = cb; 180 } 181 182 void FlushDuringPendingRead() { 183 SCOPED_TRACE("FlushDuringPendingRead()"); 184 WaitableMessageLoopEvent flush_event; 185 renderer_->Flush(flush_event.GetClosure()); 186 SatisfyPendingRead(InputFrames(256)); 187 flush_event.RunAndWait(); 188 189 EXPECT_FALSE(IsReadPending()); 190 } 191 192 void Preroll() { 193 Preroll(0, PIPELINE_OK); 194 } 195 196 void Preroll(int timestamp_ms, PipelineStatus expected) { 197 SCOPED_TRACE(base::StringPrintf("Preroll(%d, %d)", timestamp_ms, expected)); 198 199 TimeDelta timestamp = TimeDelta::FromMilliseconds(timestamp_ms); 200 next_timestamp_->SetBaseTimestamp(timestamp); 201 202 // Fill entire buffer to complete prerolling. 203 renderer_->SetMediaTime(timestamp); 204 renderer_->StartPlaying(); 205 WaitForPendingRead(); 206 EXPECT_CALL(*this, OnBufferingStateChange(BUFFERING_HAVE_ENOUGH)); 207 DeliverRemainingAudio(); 208 } 209 210 void StartTicking() { 211 renderer_->StartTicking(); 212 renderer_->SetPlaybackRate(1.0f); 213 } 214 215 void StopTicking() { renderer_->StopTicking(); } 216 217 bool IsReadPending() const { 218 return !decode_cb_.is_null(); 219 } 220 221 void WaitForPendingRead() { 222 SCOPED_TRACE("WaitForPendingRead()"); 223 if (!decode_cb_.is_null()) 224 return; 225 226 DCHECK(wait_for_pending_decode_cb_.is_null()); 227 228 WaitableMessageLoopEvent event; 229 wait_for_pending_decode_cb_ = event.GetClosure(); 230 event.RunAndWait(); 231 232 DCHECK(!decode_cb_.is_null()); 233 DCHECK(wait_for_pending_decode_cb_.is_null()); 234 } 235 236 // Delivers decoded frames to |renderer_|. 237 void SatisfyPendingRead(InputFrames frames) { 238 CHECK_GT(frames.value, 0); 239 CHECK(!decode_cb_.is_null()); 240 241 scoped_refptr<AudioBuffer> buffer = 242 MakeAudioBuffer<float>(kSampleFormat, 243 kChannelLayout, 244 kChannelCount, 245 kInputSamplesPerSecond, 246 1.0f, 247 0.0f, 248 frames.value, 249 next_timestamp_->GetTimestamp()); 250 next_timestamp_->AddFrames(frames.value); 251 252 DeliverBuffer(AudioDecoder::kOk, buffer); 253 } 254 255 void DeliverEndOfStream() { 256 DCHECK(!decode_cb_.is_null()); 257 258 // Return EOS buffer to trigger EOS frame. 259 EXPECT_CALL(demuxer_stream_, Read(_)) 260 .WillOnce(RunCallback<0>(DemuxerStream::kOk, 261 DecoderBuffer::CreateEOSBuffer())); 262 263 // Satify pending |decode_cb_| to trigger a new DemuxerStream::Read(). 264 message_loop_.PostTask( 265 FROM_HERE, 266 base::Bind(base::ResetAndReturn(&decode_cb_), AudioDecoder::kOk)); 267 268 WaitForPendingRead(); 269 270 message_loop_.PostTask( 271 FROM_HERE, 272 base::Bind(base::ResetAndReturn(&decode_cb_), AudioDecoder::kOk)); 273 274 base::RunLoop().RunUntilIdle(); 275 } 276 277 // Delivers frames until |renderer_|'s internal buffer is full and no longer 278 // has pending reads. 279 void DeliverRemainingAudio() { 280 while (frames_remaining_in_buffer().value > 0) { 281 SatisfyPendingRead(InputFrames(256)); 282 } 283 } 284 285 // Attempts to consume |requested_frames| frames from |renderer_|'s internal 286 // buffer. Returns true if and only if all of |requested_frames| were able 287 // to be consumed. 288 bool ConsumeBufferedData(OutputFrames requested_frames) { 289 scoped_ptr<AudioBus> bus = 290 AudioBus::Create(kChannels, requested_frames.value); 291 int frames_read = 0; 292 EXPECT_TRUE(sink_->Render(bus.get(), 0, &frames_read)); 293 return frames_read == requested_frames.value; 294 } 295 296 OutputFrames frames_buffered() { 297 return OutputFrames(renderer_->algorithm_->frames_buffered()); 298 } 299 300 OutputFrames buffer_capacity() { 301 return OutputFrames(renderer_->algorithm_->QueueCapacity()); 302 } 303 304 OutputFrames frames_remaining_in_buffer() { 305 // This can happen if too much data was delivered, in which case the buffer 306 // will accept the data but not increase capacity. 307 if (frames_buffered().value > buffer_capacity().value) { 308 return OutputFrames(0); 309 } 310 return OutputFrames(buffer_capacity().value - frames_buffered().value); 311 } 312 313 void force_config_change() { 314 renderer_->OnConfigChange(); 315 } 316 317 InputFrames converter_input_frames_left() const { 318 return InputFrames( 319 renderer_->buffer_converter_->input_frames_left_for_testing()); 320 } 321 322 bool splicer_has_next_buffer() const { 323 return renderer_->splicer_->HasNextBuffer(); 324 } 325 326 base::TimeDelta CurrentMediaTime() { 327 return renderer_->CurrentMediaTime(); 328 } 329 330 bool ended() const { return ended_; } 331 332 // Fixture members. 333 base::MessageLoop message_loop_; 334 scoped_ptr<AudioRendererImpl> renderer_; 335 scoped_refptr<FakeAudioRendererSink> sink_; 336 AudioHardwareConfig hardware_config_; 337 338 private: 339 void DecodeDecoder(const scoped_refptr<DecoderBuffer>& buffer, 340 const AudioDecoder::DecodeCB& decode_cb) { 341 // TODO(scherkus): Make this a DCHECK after threading semantics are fixed. 342 if (base::MessageLoop::current() != &message_loop_) { 343 message_loop_.PostTask(FROM_HERE, base::Bind( 344 &AudioRendererImplTest::DecodeDecoder, 345 base::Unretained(this), buffer, decode_cb)); 346 return; 347 } 348 349 CHECK(decode_cb_.is_null()) << "Overlapping decodes are not permitted"; 350 decode_cb_ = decode_cb; 351 352 // Wake up WaitForPendingRead() if needed. 353 if (!wait_for_pending_decode_cb_.is_null()) 354 base::ResetAndReturn(&wait_for_pending_decode_cb_).Run(); 355 } 356 357 void ResetDecoder(const base::Closure& reset_cb) { 358 if (!decode_cb_.is_null()) { 359 // |reset_cb| will be called in DeliverBuffer(), after the decoder is 360 // flushed. 361 reset_cb_ = reset_cb; 362 return; 363 } 364 365 message_loop_.PostTask(FROM_HERE, reset_cb); 366 } 367 368 void DeliverBuffer(AudioDecoder::Status status, 369 const scoped_refptr<AudioBuffer>& buffer) { 370 CHECK(!decode_cb_.is_null()); 371 if (buffer.get() && !buffer->end_of_stream()) 372 output_cb_.Run(buffer); 373 base::ResetAndReturn(&decode_cb_).Run(status); 374 375 if (!reset_cb_.is_null()) 376 base::ResetAndReturn(&reset_cb_).Run(); 377 378 base::RunLoop().RunUntilIdle(); 379 } 380 381 void OnEnded() { 382 CHECK(!ended_); 383 ended_ = true; 384 } 385 386 MockDemuxerStream demuxer_stream_; 387 MockAudioDecoder* decoder_; 388 389 // Used for satisfying reads. 390 AudioDecoder::OutputCB output_cb_; 391 AudioDecoder::DecodeCB decode_cb_; 392 base::Closure reset_cb_; 393 scoped_ptr<AudioTimestampHelper> next_timestamp_; 394 395 // Run during DecodeDecoder() to unblock WaitForPendingRead(). 396 base::Closure wait_for_pending_decode_cb_; 397 398 PipelineStatusCB init_decoder_cb_; 399 bool ended_; 400 401 DISALLOW_COPY_AND_ASSIGN(AudioRendererImplTest); 402}; 403 404TEST_F(AudioRendererImplTest, Initialize_Successful) { 405 Initialize(); 406} 407 408TEST_F(AudioRendererImplTest, Initialize_DecoderInitFailure) { 409 ExpectUnsupportedAudioDecoder(); 410 InitializeWithStatus(DECODER_ERROR_NOT_SUPPORTED); 411} 412 413TEST_F(AudioRendererImplTest, Preroll) { 414 Initialize(); 415 Preroll(); 416} 417 418TEST_F(AudioRendererImplTest, StartTicking) { 419 Initialize(); 420 Preroll(); 421 StartTicking(); 422 423 // Drain internal buffer, we should have a pending read. 424 EXPECT_TRUE(ConsumeBufferedData(frames_buffered())); 425 WaitForPendingRead(); 426} 427 428TEST_F(AudioRendererImplTest, EndOfStream) { 429 Initialize(); 430 Preroll(); 431 StartTicking(); 432 433 // Drain internal buffer, we should have a pending read. 434 EXPECT_TRUE(ConsumeBufferedData(frames_buffered())); 435 WaitForPendingRead(); 436 437 // Forcefully trigger underflow. 438 EXPECT_FALSE(ConsumeBufferedData(OutputFrames(1))); 439 EXPECT_CALL(*this, OnBufferingStateChange(BUFFERING_HAVE_NOTHING)); 440 441 // Fulfill the read with an end-of-stream buffer. Doing so should change our 442 // buffering state so playback resumes. 443 EXPECT_CALL(*this, OnBufferingStateChange(BUFFERING_HAVE_ENOUGH)); 444 DeliverEndOfStream(); 445 446 // Consume all remaining data. We shouldn't have signal ended yet. 447 EXPECT_TRUE(ConsumeBufferedData(frames_buffered())); 448 base::RunLoop().RunUntilIdle(); 449 EXPECT_FALSE(ended()); 450 451 // Ended should trigger on next render call. 452 EXPECT_FALSE(ConsumeBufferedData(OutputFrames(1))); 453 base::RunLoop().RunUntilIdle(); 454 EXPECT_TRUE(ended()); 455} 456 457TEST_F(AudioRendererImplTest, Underflow) { 458 Initialize(); 459 Preroll(); 460 StartTicking(); 461 462 // Drain internal buffer, we should have a pending read. 463 EXPECT_TRUE(ConsumeBufferedData(frames_buffered())); 464 WaitForPendingRead(); 465 466 // Verify the next FillBuffer() call triggers a buffering state change 467 // update. 468 EXPECT_CALL(*this, OnBufferingStateChange(BUFFERING_HAVE_NOTHING)); 469 EXPECT_FALSE(ConsumeBufferedData(OutputFrames(1))); 470 471 // Verify we're still not getting audio data. 472 EXPECT_EQ(0, frames_buffered().value); 473 EXPECT_FALSE(ConsumeBufferedData(OutputFrames(1))); 474 475 // Deliver enough data to have enough for buffering. 476 EXPECT_CALL(*this, OnBufferingStateChange(BUFFERING_HAVE_ENOUGH)); 477 DeliverRemainingAudio(); 478 479 // Verify we're getting audio data. 480 EXPECT_TRUE(ConsumeBufferedData(OutputFrames(1))); 481} 482 483TEST_F(AudioRendererImplTest, Underflow_CapacityResetsAfterFlush) { 484 Initialize(); 485 Preroll(); 486 StartTicking(); 487 488 // Drain internal buffer, we should have a pending read. 489 EXPECT_TRUE(ConsumeBufferedData(frames_buffered())); 490 WaitForPendingRead(); 491 492 // Verify the next FillBuffer() call triggers the underflow callback 493 // since the decoder hasn't delivered any data after it was drained. 494 OutputFrames initial_capacity = buffer_capacity(); 495 EXPECT_CALL(*this, OnBufferingStateChange(BUFFERING_HAVE_NOTHING)); 496 EXPECT_FALSE(ConsumeBufferedData(OutputFrames(1))); 497 498 // Verify that the buffer capacity increased as a result of underflowing. 499 EXPECT_GT(buffer_capacity().value, initial_capacity.value); 500 501 // Verify that the buffer capacity is restored to the |initial_capacity|. 502 FlushDuringPendingRead(); 503 EXPECT_EQ(buffer_capacity().value, initial_capacity.value); 504} 505 506TEST_F(AudioRendererImplTest, Underflow_Flush) { 507 Initialize(); 508 Preroll(); 509 StartTicking(); 510 511 // Force underflow. 512 EXPECT_TRUE(ConsumeBufferedData(frames_buffered())); 513 WaitForPendingRead(); 514 EXPECT_CALL(*this, OnBufferingStateChange(BUFFERING_HAVE_NOTHING)); 515 EXPECT_FALSE(ConsumeBufferedData(OutputFrames(1))); 516 WaitForPendingRead(); 517 StopTicking(); 518 519 // We shouldn't expect another buffering state change when flushing. 520 FlushDuringPendingRead(); 521} 522 523TEST_F(AudioRendererImplTest, PendingRead_Flush) { 524 Initialize(); 525 526 Preroll(); 527 StartTicking(); 528 529 // Partially drain internal buffer so we get a pending read. 530 EXPECT_TRUE(ConsumeBufferedData(OutputFrames(256))); 531 WaitForPendingRead(); 532 533 StopTicking(); 534 535 EXPECT_TRUE(IsReadPending()); 536 537 // Flush and expect to be notified that we have nothing. 538 EXPECT_CALL(*this, OnBufferingStateChange(BUFFERING_HAVE_NOTHING)); 539 FlushDuringPendingRead(); 540 541 // Preroll again to a different timestamp and verify it completed normally. 542 Preroll(1000, PIPELINE_OK); 543} 544 545TEST_F(AudioRendererImplTest, PendingRead_Destroy) { 546 Initialize(); 547 548 Preroll(); 549 StartTicking(); 550 551 // Partially drain internal buffer so we get a pending read. 552 EXPECT_TRUE(ConsumeBufferedData(OutputFrames(256))); 553 WaitForPendingRead(); 554 555 StopTicking(); 556 557 EXPECT_TRUE(IsReadPending()); 558 559 renderer_.reset(); 560} 561 562TEST_F(AudioRendererImplTest, PendingFlush_Destroy) { 563 Initialize(); 564 565 Preroll(); 566 StartTicking(); 567 568 // Partially drain internal buffer so we get a pending read. 569 EXPECT_TRUE(ConsumeBufferedData(OutputFrames(256))); 570 WaitForPendingRead(); 571 572 StopTicking(); 573 574 EXPECT_TRUE(IsReadPending()); 575 576 // Start flushing. 577 WaitableMessageLoopEvent flush_event; 578 renderer_->Flush(flush_event.GetClosure()); 579 580 EXPECT_CALL(*this, OnBufferingStateChange(BUFFERING_HAVE_NOTHING)); 581 SatisfyPendingRead(InputFrames(256)); 582 583 renderer_.reset(); 584} 585 586TEST_F(AudioRendererImplTest, InitializeThenDestroy) { 587 InitializeAndDestroy(); 588} 589 590TEST_F(AudioRendererImplTest, InitializeThenDestroyDuringDecoderInit) { 591 InitializeAndDestroyDuringDecoderInit(); 592} 593 594TEST_F(AudioRendererImplTest, ConfigChangeDrainsConverter) { 595 Initialize(); 596 Preroll(); 597 StartTicking(); 598 599 // Drain internal buffer, we should have a pending read. 600 EXPECT_TRUE(ConsumeBufferedData(frames_buffered())); 601 WaitForPendingRead(); 602 603 // Deliver a little bit of data. Use an odd data size to ensure there is data 604 // left in the AudioBufferConverter. Ensure no buffers are in the splicer. 605 SatisfyPendingRead(InputFrames(2053)); 606 EXPECT_FALSE(splicer_has_next_buffer()); 607 EXPECT_GT(converter_input_frames_left().value, 0); 608 609 // Force a config change and then ensure all buffered data has been put into 610 // the splicer. 611 force_config_change(); 612 EXPECT_TRUE(splicer_has_next_buffer()); 613 EXPECT_EQ(0, converter_input_frames_left().value); 614} 615 616TEST_F(AudioRendererImplTest, TimeUpdatesOnFirstBuffer) { 617 Initialize(); 618 Preroll(); 619 StartTicking(); 620 621 AudioTimestampHelper timestamp_helper(kOutputSamplesPerSecond); 622 timestamp_helper.SetBaseTimestamp(base::TimeDelta()); 623 624 // Time should be the starting timestamp as nothing's been consumed yet. 625 EXPECT_EQ(timestamp_helper.GetTimestamp(), CurrentMediaTime()); 626 627 // Consume some audio data. 628 OutputFrames frames_to_consume(frames_buffered().value / 2); 629 EXPECT_TRUE(ConsumeBufferedData(frames_to_consume)); 630 WaitForPendingRead(); 631 632 // Time shouldn't change just yet because we've only sent the initial audio 633 // data to the hardware. 634 EXPECT_EQ(timestamp_helper.GetTimestamp(), CurrentMediaTime()); 635 636 // Consume some more audio data. 637 frames_to_consume = frames_buffered(); 638 EXPECT_TRUE(ConsumeBufferedData(frames_to_consume)); 639 640 // Now time should change now that the audio hardware has called back. 641 timestamp_helper.AddFrames(frames_to_consume.value); 642 EXPECT_EQ(timestamp_helper.GetTimestamp(), CurrentMediaTime()); 643} 644 645TEST_F(AudioRendererImplTest, ImmediateEndOfStream) { 646 Initialize(); 647 { 648 SCOPED_TRACE("Preroll()"); 649 renderer_->StartPlaying(); 650 WaitForPendingRead(); 651 EXPECT_CALL(*this, OnBufferingStateChange(BUFFERING_HAVE_ENOUGH)); 652 DeliverEndOfStream(); 653 } 654 StartTicking(); 655 656 // Read a single frame. We shouldn't be able to satisfy it. 657 EXPECT_FALSE(ended()); 658 EXPECT_FALSE(ConsumeBufferedData(OutputFrames(1))); 659 base::RunLoop().RunUntilIdle(); 660 EXPECT_TRUE(ended()); 661} 662 663TEST_F(AudioRendererImplTest, OnRenderErrorCausesDecodeError) { 664 Initialize(); 665 Preroll(); 666 StartTicking(); 667 668 EXPECT_CALL(*this, OnError(PIPELINE_ERROR_DECODE)); 669 sink_->OnRenderError(); 670 base::RunLoop().RunUntilIdle(); 671} 672 673// Test for AudioRendererImpl calling Pause()/Play() on the sink when the 674// playback rate is set to zero and non-zero. 675TEST_F(AudioRendererImplTest, SetPlaybackRate) { 676 Initialize(); 677 Preroll(); 678 679 // Rendering hasn't started. Sink should always be paused. 680 EXPECT_EQ(FakeAudioRendererSink::kPaused, sink_->state()); 681 renderer_->SetPlaybackRate(0.0f); 682 EXPECT_EQ(FakeAudioRendererSink::kPaused, sink_->state()); 683 renderer_->SetPlaybackRate(1.0f); 684 EXPECT_EQ(FakeAudioRendererSink::kPaused, sink_->state()); 685 686 // Rendering has started with non-zero rate. Rate changes will affect sink 687 // state. 688 renderer_->StartTicking(); 689 EXPECT_EQ(FakeAudioRendererSink::kPlaying, sink_->state()); 690 renderer_->SetPlaybackRate(0.0f); 691 EXPECT_EQ(FakeAudioRendererSink::kPaused, sink_->state()); 692 renderer_->SetPlaybackRate(1.0f); 693 EXPECT_EQ(FakeAudioRendererSink::kPlaying, sink_->state()); 694 695 // Rendering has stopped. Sink should be paused. 696 renderer_->StopTicking(); 697 EXPECT_EQ(FakeAudioRendererSink::kPaused, sink_->state()); 698 699 // Start rendering with zero playback rate. Sink should be paused until 700 // non-zero rate is set. 701 renderer_->SetPlaybackRate(0.0f); 702 renderer_->StartTicking(); 703 EXPECT_EQ(FakeAudioRendererSink::kPaused, sink_->state()); 704 renderer_->SetPlaybackRate(1.0f); 705 EXPECT_EQ(FakeAudioRendererSink::kPlaying, sink_->state()); 706} 707 708} // namespace media 709