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 "media/filters/audio_renderer_impl.h" 6 7 #include <math.h> 8 9 #include <algorithm> 10 11 #include "base/bind.h" 12 #include "base/callback.h" 13 #include "base/callback_helpers.h" 14 #include "base/logging.h" 15 #include "base/metrics/histogram.h" 16 #include "base/single_thread_task_runner.h" 17 #include "media/base/audio_buffer.h" 18 #include "media/base/audio_buffer_converter.h" 19 #include "media/base/audio_hardware_config.h" 20 #include "media/base/audio_splicer.h" 21 #include "media/base/bind_to_current_loop.h" 22 #include "media/base/demuxer_stream.h" 23 #include "media/filters/audio_clock.h" 24 #include "media/filters/decrypting_demuxer_stream.h" 25 26 namespace media { 27 28 namespace { 29 30 enum AudioRendererEvent { 31 INITIALIZED, 32 RENDER_ERROR, 33 RENDER_EVENT_MAX = RENDER_ERROR, 34 }; 35 36 void HistogramRendererEvent(AudioRendererEvent event) { 37 UMA_HISTOGRAM_ENUMERATION( 38 "Media.AudioRendererEvents", event, RENDER_EVENT_MAX + 1); 39 } 40 41 } // namespace 42 43 AudioRendererImpl::AudioRendererImpl( 44 const scoped_refptr<base::SingleThreadTaskRunner>& task_runner, 45 media::AudioRendererSink* sink, 46 ScopedVector<AudioDecoder> decoders, 47 const SetDecryptorReadyCB& set_decryptor_ready_cb, 48 AudioHardwareConfig* hardware_config) 49 : task_runner_(task_runner), 50 sink_(sink), 51 audio_buffer_stream_(task_runner, 52 decoders.Pass(), 53 set_decryptor_ready_cb), 54 hardware_config_(hardware_config), 55 now_cb_(base::Bind(&base::TimeTicks::Now)), 56 state_(kUninitialized), 57 rendering_(false), 58 sink_playing_(false), 59 pending_read_(false), 60 received_end_of_stream_(false), 61 rendered_end_of_stream_(false), 62 preroll_aborted_(false), 63 weak_factory_(this) { 64 audio_buffer_stream_.set_splice_observer(base::Bind( 65 &AudioRendererImpl::OnNewSpliceBuffer, weak_factory_.GetWeakPtr())); 66 audio_buffer_stream_.set_config_change_observer(base::Bind( 67 &AudioRendererImpl::OnConfigChange, weak_factory_.GetWeakPtr())); 68 } 69 70 AudioRendererImpl::~AudioRendererImpl() { 71 // Stop() should have been called and |algorithm_| should have been destroyed. 72 DCHECK(state_ == kUninitialized || state_ == kStopped); 73 DCHECK(!algorithm_.get()); 74 } 75 76 void AudioRendererImpl::StartRendering() { 77 DVLOG(1) << __FUNCTION__; 78 DCHECK(task_runner_->BelongsToCurrentThread()); 79 DCHECK(!rendering_); 80 rendering_ = true; 81 82 base::AutoLock auto_lock(lock_); 83 // Wait for an eventual call to SetPlaybackRate() to start rendering. 84 if (algorithm_->playback_rate() == 0) { 85 DCHECK(!sink_playing_); 86 return; 87 } 88 89 StartRendering_Locked(); 90 } 91 92 void AudioRendererImpl::StartRendering_Locked() { 93 DVLOG(1) << __FUNCTION__; 94 DCHECK(task_runner_->BelongsToCurrentThread()); 95 DCHECK(state_ == kPlaying || state_ == kRebuffering || state_ == kUnderflow) 96 << "state_=" << state_; 97 DCHECK(!sink_playing_); 98 DCHECK_NE(algorithm_->playback_rate(), 0); 99 lock_.AssertAcquired(); 100 101 earliest_end_time_ = now_cb_.Run(); 102 sink_playing_ = true; 103 104 base::AutoUnlock auto_unlock(lock_); 105 sink_->Play(); 106 } 107 108 void AudioRendererImpl::StopRendering() { 109 DVLOG(1) << __FUNCTION__; 110 DCHECK(task_runner_->BelongsToCurrentThread()); 111 DCHECK(rendering_); 112 rendering_ = false; 113 114 base::AutoLock auto_lock(lock_); 115 // Rendering should have already been stopped with a zero playback rate. 116 if (algorithm_->playback_rate() == 0) { 117 DCHECK(!sink_playing_); 118 return; 119 } 120 121 StopRendering_Locked(); 122 } 123 124 void AudioRendererImpl::StopRendering_Locked() { 125 DCHECK(task_runner_->BelongsToCurrentThread()); 126 DCHECK(state_ == kPlaying || state_ == kRebuffering || state_ == kUnderflow) 127 << "state_=" << state_; 128 DCHECK(sink_playing_); 129 lock_.AssertAcquired(); 130 131 sink_playing_ = false; 132 133 base::AutoUnlock auto_unlock(lock_); 134 sink_->Pause(); 135 } 136 137 void AudioRendererImpl::Flush(const base::Closure& callback) { 138 DVLOG(1) << __FUNCTION__; 139 DCHECK(task_runner_->BelongsToCurrentThread()); 140 141 base::AutoLock auto_lock(lock_); 142 DCHECK(state_ == kPlaying || state_ == kRebuffering || state_ == kUnderflow) 143 << "state_=" << state_; 144 DCHECK(flush_cb_.is_null()); 145 146 flush_cb_ = callback; 147 148 if (pending_read_) { 149 ChangeState_Locked(kFlushing); 150 return; 151 } 152 153 ChangeState_Locked(kFlushed); 154 DoFlush_Locked(); 155 } 156 157 void AudioRendererImpl::DoFlush_Locked() { 158 DCHECK(task_runner_->BelongsToCurrentThread()); 159 lock_.AssertAcquired(); 160 161 DCHECK(!pending_read_); 162 DCHECK_EQ(state_, kFlushed); 163 164 audio_buffer_stream_.Reset(base::Bind(&AudioRendererImpl::ResetDecoderDone, 165 weak_factory_.GetWeakPtr())); 166 } 167 168 void AudioRendererImpl::ResetDecoderDone() { 169 DCHECK(task_runner_->BelongsToCurrentThread()); 170 { 171 base::AutoLock auto_lock(lock_); 172 if (state_ == kStopped) 173 return; 174 175 DCHECK_EQ(state_, kFlushed); 176 DCHECK(!flush_cb_.is_null()); 177 178 audio_clock_.reset(new AudioClock(audio_parameters_.sample_rate())); 179 received_end_of_stream_ = false; 180 rendered_end_of_stream_ = false; 181 preroll_aborted_ = false; 182 183 earliest_end_time_ = now_cb_.Run(); 184 splicer_->Reset(); 185 if (buffer_converter_) 186 buffer_converter_->Reset(); 187 algorithm_->FlushBuffers(); 188 } 189 base::ResetAndReturn(&flush_cb_).Run(); 190 } 191 192 void AudioRendererImpl::Stop(const base::Closure& callback) { 193 DVLOG(1) << __FUNCTION__; 194 DCHECK(task_runner_->BelongsToCurrentThread()); 195 DCHECK(!callback.is_null()); 196 197 // TODO(scherkus): Consider invalidating |weak_factory_| and replacing 198 // task-running guards that check |state_| with DCHECK(). 199 200 { 201 base::AutoLock auto_lock(lock_); 202 203 if (state_ == kStopped) { 204 task_runner_->PostTask(FROM_HERE, callback); 205 return; 206 } 207 208 ChangeState_Locked(kStopped); 209 algorithm_.reset(); 210 underflow_cb_.Reset(); 211 time_cb_.Reset(); 212 flush_cb_.Reset(); 213 } 214 215 if (sink_) { 216 sink_->Stop(); 217 sink_ = NULL; 218 } 219 220 audio_buffer_stream_.Stop(callback); 221 } 222 223 void AudioRendererImpl::Preroll(base::TimeDelta time, 224 const PipelineStatusCB& cb) { 225 DVLOG(1) << __FUNCTION__ << "(" << time.InMicroseconds() << ")"; 226 DCHECK(task_runner_->BelongsToCurrentThread()); 227 228 base::AutoLock auto_lock(lock_); 229 DCHECK(!sink_playing_); 230 DCHECK_EQ(state_, kFlushed); 231 DCHECK(!pending_read_) << "Pending read must complete before seeking"; 232 DCHECK(preroll_cb_.is_null()); 233 234 ChangeState_Locked(kPrerolling); 235 preroll_cb_ = cb; 236 preroll_timestamp_ = time; 237 238 AttemptRead_Locked(); 239 } 240 241 void AudioRendererImpl::Initialize(DemuxerStream* stream, 242 const PipelineStatusCB& init_cb, 243 const StatisticsCB& statistics_cb, 244 const base::Closure& underflow_cb, 245 const TimeCB& time_cb, 246 const base::Closure& ended_cb, 247 const PipelineStatusCB& error_cb) { 248 DCHECK(task_runner_->BelongsToCurrentThread()); 249 DCHECK(stream); 250 DCHECK_EQ(stream->type(), DemuxerStream::AUDIO); 251 DCHECK(!init_cb.is_null()); 252 DCHECK(!statistics_cb.is_null()); 253 DCHECK(!underflow_cb.is_null()); 254 DCHECK(!time_cb.is_null()); 255 DCHECK(!ended_cb.is_null()); 256 DCHECK(!error_cb.is_null()); 257 DCHECK_EQ(kUninitialized, state_); 258 DCHECK(sink_); 259 260 state_ = kInitializing; 261 262 init_cb_ = init_cb; 263 underflow_cb_ = underflow_cb; 264 time_cb_ = time_cb; 265 ended_cb_ = ended_cb; 266 error_cb_ = error_cb; 267 268 expecting_config_changes_ = stream->SupportsConfigChanges(); 269 if (!expecting_config_changes_) { 270 // The actual buffer size is controlled via the size of the AudioBus 271 // provided to Render(), so just choose something reasonable here for looks. 272 int buffer_size = stream->audio_decoder_config().samples_per_second() / 100; 273 audio_parameters_.Reset( 274 AudioParameters::AUDIO_PCM_LOW_LATENCY, 275 stream->audio_decoder_config().channel_layout(), 276 ChannelLayoutToChannelCount( 277 stream->audio_decoder_config().channel_layout()), 278 0, 279 stream->audio_decoder_config().samples_per_second(), 280 stream->audio_decoder_config().bits_per_channel(), 281 buffer_size); 282 buffer_converter_.reset(); 283 } else { 284 // TODO(rileya): Support hardware config changes 285 const AudioParameters& hw_params = hardware_config_->GetOutputConfig(); 286 audio_parameters_.Reset( 287 hw_params.format(), 288 // Always use the source's channel layout and channel count to avoid 289 // premature downmixing (http://crbug.com/379288), platform specific 290 // issues around channel layouts (http://crbug.com/266674), and 291 // unnecessary upmixing overhead. 292 stream->audio_decoder_config().channel_layout(), 293 ChannelLayoutToChannelCount( 294 stream->audio_decoder_config().channel_layout()), 295 hw_params.input_channels(), 296 hw_params.sample_rate(), 297 hw_params.bits_per_sample(), 298 hardware_config_->GetHighLatencyBufferSize()); 299 } 300 301 audio_clock_.reset(new AudioClock(audio_parameters_.sample_rate())); 302 303 audio_buffer_stream_.Initialize( 304 stream, 305 false, 306 statistics_cb, 307 base::Bind(&AudioRendererImpl::OnAudioBufferStreamInitialized, 308 weak_factory_.GetWeakPtr())); 309 } 310 311 void AudioRendererImpl::OnAudioBufferStreamInitialized(bool success) { 312 DCHECK(task_runner_->BelongsToCurrentThread()); 313 314 base::AutoLock auto_lock(lock_); 315 316 if (state_ == kStopped) { 317 base::ResetAndReturn(&init_cb_).Run(PIPELINE_ERROR_ABORT); 318 return; 319 } 320 321 if (!success) { 322 state_ = kUninitialized; 323 base::ResetAndReturn(&init_cb_).Run(DECODER_ERROR_NOT_SUPPORTED); 324 return; 325 } 326 327 if (!audio_parameters_.IsValid()) { 328 ChangeState_Locked(kUninitialized); 329 base::ResetAndReturn(&init_cb_).Run(PIPELINE_ERROR_INITIALIZATION_FAILED); 330 return; 331 } 332 333 if (expecting_config_changes_) 334 buffer_converter_.reset(new AudioBufferConverter(audio_parameters_)); 335 splicer_.reset(new AudioSplicer(audio_parameters_.sample_rate())); 336 337 // We're all good! Continue initializing the rest of the audio renderer 338 // based on the decoder format. 339 algorithm_.reset(new AudioRendererAlgorithm()); 340 algorithm_->Initialize(0, audio_parameters_); 341 342 ChangeState_Locked(kFlushed); 343 344 HistogramRendererEvent(INITIALIZED); 345 346 { 347 base::AutoUnlock auto_unlock(lock_); 348 sink_->Initialize(audio_parameters_, this); 349 sink_->Start(); 350 351 // Some sinks play on start... 352 sink_->Pause(); 353 } 354 355 DCHECK(!sink_playing_); 356 357 base::ResetAndReturn(&init_cb_).Run(PIPELINE_OK); 358 } 359 360 void AudioRendererImpl::ResumeAfterUnderflow() { 361 DCHECK(task_runner_->BelongsToCurrentThread()); 362 base::AutoLock auto_lock(lock_); 363 if (state_ == kUnderflow) { 364 // The "!preroll_aborted_" is a hack. If preroll is aborted, then we 365 // shouldn't even reach the kUnderflow state to begin with. But for now 366 // we're just making sure that the audio buffer capacity (i.e. the 367 // number of bytes that need to be buffered for preroll to complete) 368 // does not increase due to an aborted preroll. 369 // TODO(vrk): Fix this bug correctly! (crbug.com/151352) 370 if (!preroll_aborted_) 371 algorithm_->IncreaseQueueCapacity(); 372 373 ChangeState_Locked(kRebuffering); 374 } 375 } 376 377 void AudioRendererImpl::SetVolume(float volume) { 378 DCHECK(task_runner_->BelongsToCurrentThread()); 379 DCHECK(sink_); 380 sink_->SetVolume(volume); 381 } 382 383 void AudioRendererImpl::DecodedAudioReady( 384 AudioBufferStream::Status status, 385 const scoped_refptr<AudioBuffer>& buffer) { 386 DVLOG(2) << __FUNCTION__ << "(" << status << ")"; 387 DCHECK(task_runner_->BelongsToCurrentThread()); 388 389 base::AutoLock auto_lock(lock_); 390 DCHECK(state_ != kUninitialized); 391 392 CHECK(pending_read_); 393 pending_read_ = false; 394 395 if (status == AudioBufferStream::ABORTED || 396 status == AudioBufferStream::DEMUXER_READ_ABORTED) { 397 HandleAbortedReadOrDecodeError(false); 398 return; 399 } 400 401 if (status == AudioBufferStream::DECODE_ERROR) { 402 HandleAbortedReadOrDecodeError(true); 403 return; 404 } 405 406 DCHECK_EQ(status, AudioBufferStream::OK); 407 DCHECK(buffer.get()); 408 409 if (state_ == kFlushing) { 410 ChangeState_Locked(kFlushed); 411 DoFlush_Locked(); 412 return; 413 } 414 415 if (expecting_config_changes_) { 416 DCHECK(buffer_converter_); 417 buffer_converter_->AddInput(buffer); 418 while (buffer_converter_->HasNextBuffer()) { 419 if (!splicer_->AddInput(buffer_converter_->GetNextBuffer())) { 420 HandleAbortedReadOrDecodeError(true); 421 return; 422 } 423 } 424 } else { 425 if (!splicer_->AddInput(buffer)) { 426 HandleAbortedReadOrDecodeError(true); 427 return; 428 } 429 } 430 431 if (!splicer_->HasNextBuffer()) { 432 AttemptRead_Locked(); 433 return; 434 } 435 436 bool need_another_buffer = false; 437 while (splicer_->HasNextBuffer()) 438 need_another_buffer = HandleSplicerBuffer(splicer_->GetNextBuffer()); 439 440 if (!need_another_buffer && !CanRead_Locked()) 441 return; 442 443 AttemptRead_Locked(); 444 } 445 446 bool AudioRendererImpl::HandleSplicerBuffer( 447 const scoped_refptr<AudioBuffer>& buffer) { 448 if (buffer->end_of_stream()) { 449 received_end_of_stream_ = true; 450 451 // Transition to kPlaying if we are currently handling an underflow since 452 // no more data will be arriving. 453 if (state_ == kUnderflow || state_ == kRebuffering) 454 ChangeState_Locked(kPlaying); 455 } else { 456 if (state_ == kPrerolling) { 457 if (IsBeforePrerollTime(buffer)) 458 return true; 459 460 // Trim off any additional time before the preroll timestamp. 461 const base::TimeDelta trim_time = 462 preroll_timestamp_ - buffer->timestamp(); 463 if (trim_time > base::TimeDelta()) { 464 buffer->TrimStart(buffer->frame_count() * 465 (static_cast<double>(trim_time.InMicroseconds()) / 466 buffer->duration().InMicroseconds())); 467 } 468 // If the entire buffer was trimmed, request a new one. 469 if (!buffer->frame_count()) 470 return true; 471 } 472 473 if (state_ != kUninitialized && state_ != kStopped) 474 algorithm_->EnqueueBuffer(buffer); 475 } 476 477 switch (state_) { 478 case kUninitialized: 479 case kInitializing: 480 case kFlushing: 481 NOTREACHED(); 482 return false; 483 484 case kFlushed: 485 DCHECK(!pending_read_); 486 return false; 487 488 case kPrerolling: 489 if (!buffer->end_of_stream() && !algorithm_->IsQueueFull()) 490 return true; 491 ChangeState_Locked(kPlaying); 492 base::ResetAndReturn(&preroll_cb_).Run(PIPELINE_OK); 493 return false; 494 495 case kPlaying: 496 case kUnderflow: 497 return false; 498 499 case kRebuffering: 500 if (!algorithm_->IsQueueFull()) 501 return true; 502 ChangeState_Locked(kPlaying); 503 return false; 504 505 case kStopped: 506 return false; 507 } 508 return false; 509 } 510 511 void AudioRendererImpl::AttemptRead() { 512 base::AutoLock auto_lock(lock_); 513 AttemptRead_Locked(); 514 } 515 516 void AudioRendererImpl::AttemptRead_Locked() { 517 DCHECK(task_runner_->BelongsToCurrentThread()); 518 lock_.AssertAcquired(); 519 520 if (!CanRead_Locked()) 521 return; 522 523 pending_read_ = true; 524 audio_buffer_stream_.Read(base::Bind(&AudioRendererImpl::DecodedAudioReady, 525 weak_factory_.GetWeakPtr())); 526 } 527 528 bool AudioRendererImpl::CanRead_Locked() { 529 lock_.AssertAcquired(); 530 531 switch (state_) { 532 case kUninitialized: 533 case kInitializing: 534 case kFlushed: 535 case kFlushing: 536 case kStopped: 537 return false; 538 539 case kPrerolling: 540 case kPlaying: 541 case kUnderflow: 542 case kRebuffering: 543 break; 544 } 545 546 return !pending_read_ && !received_end_of_stream_ && 547 !algorithm_->IsQueueFull(); 548 } 549 550 void AudioRendererImpl::SetPlaybackRate(float playback_rate) { 551 DVLOG(1) << __FUNCTION__ << "(" << playback_rate << ")"; 552 DCHECK(task_runner_->BelongsToCurrentThread()); 553 DCHECK_GE(playback_rate, 0); 554 DCHECK(sink_); 555 556 base::AutoLock auto_lock(lock_); 557 558 // We have two cases here: 559 // Play: current_playback_rate == 0 && playback_rate != 0 560 // Pause: current_playback_rate != 0 && playback_rate == 0 561 float current_playback_rate = algorithm_->playback_rate(); 562 algorithm_->SetPlaybackRate(playback_rate); 563 564 if (!rendering_) 565 return; 566 567 if (current_playback_rate == 0 && playback_rate != 0) { 568 StartRendering_Locked(); 569 return; 570 } 571 572 if (current_playback_rate != 0 && playback_rate == 0) { 573 StopRendering_Locked(); 574 return; 575 } 576 } 577 578 bool AudioRendererImpl::IsBeforePrerollTime( 579 const scoped_refptr<AudioBuffer>& buffer) { 580 DCHECK_EQ(state_, kPrerolling); 581 return buffer && !buffer->end_of_stream() && 582 (buffer->timestamp() + buffer->duration()) < preroll_timestamp_; 583 } 584 585 int AudioRendererImpl::Render(AudioBus* audio_bus, 586 int audio_delay_milliseconds) { 587 const int requested_frames = audio_bus->frames(); 588 base::TimeDelta playback_delay = base::TimeDelta::FromMilliseconds( 589 audio_delay_milliseconds); 590 const int delay_frames = static_cast<int>(playback_delay.InSecondsF() * 591 audio_parameters_.sample_rate()); 592 int frames_written = 0; 593 base::Closure time_cb; 594 base::Closure underflow_cb; 595 { 596 base::AutoLock auto_lock(lock_); 597 598 // Ensure Stop() hasn't destroyed our |algorithm_| on the pipeline thread. 599 if (!algorithm_) { 600 audio_clock_->WroteSilence(requested_frames, delay_frames); 601 return 0; 602 } 603 604 float playback_rate = algorithm_->playback_rate(); 605 if (playback_rate == 0) { 606 audio_clock_->WroteSilence(requested_frames, delay_frames); 607 return 0; 608 } 609 610 // Mute audio by returning 0 when not playing. 611 if (state_ != kPlaying) { 612 audio_clock_->WroteSilence(requested_frames, delay_frames); 613 return 0; 614 } 615 616 // We use the following conditions to determine end of playback: 617 // 1) Algorithm can not fill the audio callback buffer 618 // 2) We received an end of stream buffer 619 // 3) We haven't already signalled that we've ended 620 // 4) Our estimated earliest end time has expired 621 // 622 // TODO(enal): we should replace (4) with a check that the browser has no 623 // more audio data or at least use a delayed callback. 624 // 625 // We use the following conditions to determine underflow: 626 // 1) Algorithm can not fill the audio callback buffer 627 // 2) We have NOT received an end of stream buffer 628 // 3) We are in the kPlaying state 629 // 630 // Otherwise the buffer has data we can send to the device. 631 const base::TimeDelta media_timestamp_before_filling = 632 audio_clock_->CurrentMediaTimestamp(); 633 if (algorithm_->frames_buffered() > 0) { 634 frames_written = algorithm_->FillBuffer(audio_bus, requested_frames); 635 audio_clock_->WroteAudio( 636 frames_written, delay_frames, playback_rate, algorithm_->GetTime()); 637 } 638 audio_clock_->WroteSilence(requested_frames - frames_written, delay_frames); 639 640 if (frames_written == 0) { 641 const base::TimeTicks now = now_cb_.Run(); 642 643 if (received_end_of_stream_ && !rendered_end_of_stream_ && 644 now >= earliest_end_time_) { 645 rendered_end_of_stream_ = true; 646 ended_cb_.Run(); 647 } else if (!received_end_of_stream_ && state_ == kPlaying) { 648 ChangeState_Locked(kUnderflow); 649 underflow_cb = underflow_cb_; 650 } else { 651 // We can't write any data this cycle. For example, we may have 652 // sent all available data to the audio device while not reaching 653 // |earliest_end_time_|. 654 } 655 } 656 657 if (CanRead_Locked()) { 658 task_runner_->PostTask(FROM_HERE, 659 base::Bind(&AudioRendererImpl::AttemptRead, 660 weak_factory_.GetWeakPtr())); 661 } 662 663 // We only want to execute |time_cb_| if time has progressed and we haven't 664 // signaled end of stream yet. 665 if (media_timestamp_before_filling != 666 audio_clock_->CurrentMediaTimestamp() && 667 !rendered_end_of_stream_) { 668 time_cb = base::Bind(time_cb_, 669 audio_clock_->CurrentMediaTimestamp(), 670 audio_clock_->last_endpoint_timestamp()); 671 } 672 673 if (frames_written > 0) { 674 UpdateEarliestEndTime_Locked( 675 frames_written, playback_delay, now_cb_.Run()); 676 } 677 } 678 679 if (!time_cb.is_null()) 680 task_runner_->PostTask(FROM_HERE, time_cb); 681 682 if (!underflow_cb.is_null()) 683 underflow_cb.Run(); 684 685 DCHECK_LE(frames_written, requested_frames); 686 return frames_written; 687 } 688 689 void AudioRendererImpl::UpdateEarliestEndTime_Locked( 690 int frames_filled, const base::TimeDelta& playback_delay, 691 const base::TimeTicks& time_now) { 692 DCHECK_GT(frames_filled, 0); 693 694 base::TimeDelta predicted_play_time = base::TimeDelta::FromMicroseconds( 695 static_cast<float>(frames_filled) * base::Time::kMicrosecondsPerSecond / 696 audio_parameters_.sample_rate()); 697 698 lock_.AssertAcquired(); 699 earliest_end_time_ = std::max( 700 earliest_end_time_, time_now + playback_delay + predicted_play_time); 701 } 702 703 void AudioRendererImpl::OnRenderError() { 704 // UMA data tells us this happens ~0.01% of the time. Trigger an error instead 705 // of trying to gracefully fall back to a fake sink. It's very likely 706 // OnRenderError() should be removed and the audio stack handle errors without 707 // notifying clients. See http://crbug.com/234708 for details. 708 HistogramRendererEvent(RENDER_ERROR); 709 error_cb_.Run(PIPELINE_ERROR_DECODE); 710 } 711 712 void AudioRendererImpl::HandleAbortedReadOrDecodeError(bool is_decode_error) { 713 lock_.AssertAcquired(); 714 715 PipelineStatus status = is_decode_error ? PIPELINE_ERROR_DECODE : PIPELINE_OK; 716 switch (state_) { 717 case kUninitialized: 718 case kInitializing: 719 NOTREACHED(); 720 return; 721 case kFlushing: 722 ChangeState_Locked(kFlushed); 723 724 if (status == PIPELINE_OK) { 725 DoFlush_Locked(); 726 return; 727 } 728 729 error_cb_.Run(status); 730 base::ResetAndReturn(&flush_cb_).Run(); 731 return; 732 case kPrerolling: 733 // This is a signal for abort if it's not an error. 734 preroll_aborted_ = !is_decode_error; 735 ChangeState_Locked(kPlaying); 736 base::ResetAndReturn(&preroll_cb_).Run(status); 737 return; 738 case kFlushed: 739 case kPlaying: 740 case kUnderflow: 741 case kRebuffering: 742 case kStopped: 743 if (status != PIPELINE_OK) 744 error_cb_.Run(status); 745 return; 746 } 747 } 748 749 void AudioRendererImpl::ChangeState_Locked(State new_state) { 750 DVLOG(1) << __FUNCTION__ << " : " << state_ << " -> " << new_state; 751 lock_.AssertAcquired(); 752 state_ = new_state; 753 } 754 755 void AudioRendererImpl::OnNewSpliceBuffer(base::TimeDelta splice_timestamp) { 756 DCHECK(task_runner_->BelongsToCurrentThread()); 757 splicer_->SetSpliceTimestamp(splice_timestamp); 758 } 759 760 void AudioRendererImpl::OnConfigChange() { 761 DCHECK(task_runner_->BelongsToCurrentThread()); 762 DCHECK(expecting_config_changes_); 763 buffer_converter_->ResetTimestampState(); 764 // Drain flushed buffers from the converter so the AudioSplicer receives all 765 // data ahead of any OnNewSpliceBuffer() calls. Since discontinuities should 766 // only appear after config changes, AddInput() should never fail here. 767 while (buffer_converter_->HasNextBuffer()) 768 CHECK(splicer_->AddInput(buffer_converter_->GetNextBuffer())); 769 } 770 771 } // namespace media 772