Switch TestFrameNavigationObserver to DidCommitProvisionalLoadForFrame.
[chromium-blink-merge.git] / media / renderers / audio_renderer_impl.cc
blobfe439e25b4edbc2baadd629bd759f8770d5fef82
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.
5 #include "media/renderers/audio_renderer_impl.h"
7 #include <math.h>
9 #include <algorithm>
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"
26 namespace media {
28 namespace {
30 enum AudioRendererEvent {
31 INITIALIZED,
32 RENDER_ERROR,
33 RENDER_EVENT_MAX = RENDER_ERROR,
36 void HistogramRendererEvent(AudioRendererEvent event) {
37 UMA_HISTOGRAM_ENUMERATION(
38 "Media.AudioRendererEvents", event, RENDER_EVENT_MAX + 1);
41 } // namespace
43 AudioRendererImpl::AudioRendererImpl(
44 const scoped_refptr<base::SingleThreadTaskRunner>& task_runner,
45 media::AudioRendererSink* sink,
46 ScopedVector<AudioDecoder> decoders,
47 const AudioHardwareConfig& hardware_config,
48 const scoped_refptr<MediaLog>& media_log)
49 : task_runner_(task_runner),
50 expecting_config_changes_(false),
51 sink_(sink),
52 audio_buffer_stream_(
53 new AudioBufferStream(task_runner, decoders.Pass(), media_log)),
54 hardware_config_(hardware_config),
55 playback_rate_(0.0),
56 state_(kUninitialized),
57 buffering_state_(BUFFERING_HAVE_NOTHING),
58 rendering_(false),
59 sink_playing_(false),
60 pending_read_(false),
61 received_end_of_stream_(false),
62 rendered_end_of_stream_(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()));
70 AudioRendererImpl::~AudioRendererImpl() {
71 DVLOG(1) << __FUNCTION__;
72 DCHECK(task_runner_->BelongsToCurrentThread());
74 // If Render() is in progress, this call will wait for Render() to finish.
75 // After this call, the |sink_| will not call back into |this| anymore.
76 sink_->Stop();
78 if (!init_cb_.is_null())
79 base::ResetAndReturn(&init_cb_).Run(PIPELINE_ERROR_ABORT);
82 void AudioRendererImpl::StartTicking() {
83 DVLOG(1) << __FUNCTION__;
84 DCHECK(task_runner_->BelongsToCurrentThread());
85 DCHECK(!rendering_);
86 rendering_ = true;
88 base::AutoLock auto_lock(lock_);
89 // Wait for an eventual call to SetPlaybackRate() to start rendering.
90 if (playback_rate_ == 0) {
91 DCHECK(!sink_playing_);
92 return;
95 StartRendering_Locked();
98 void AudioRendererImpl::StartRendering_Locked() {
99 DVLOG(1) << __FUNCTION__;
100 DCHECK(task_runner_->BelongsToCurrentThread());
101 DCHECK_EQ(state_, kPlaying);
102 DCHECK(!sink_playing_);
103 DCHECK_NE(playback_rate_, 0.0);
104 lock_.AssertAcquired();
106 sink_playing_ = true;
108 base::AutoUnlock auto_unlock(lock_);
109 sink_->Play();
112 void AudioRendererImpl::StopTicking() {
113 DVLOG(1) << __FUNCTION__;
114 DCHECK(task_runner_->BelongsToCurrentThread());
115 DCHECK(rendering_);
116 rendering_ = false;
118 base::AutoLock auto_lock(lock_);
119 // Rendering should have already been stopped with a zero playback rate.
120 if (playback_rate_ == 0) {
121 DCHECK(!sink_playing_);
122 return;
125 StopRendering_Locked();
128 void AudioRendererImpl::StopRendering_Locked() {
129 DCHECK(task_runner_->BelongsToCurrentThread());
130 DCHECK_EQ(state_, kPlaying);
131 DCHECK(sink_playing_);
132 lock_.AssertAcquired();
134 sink_playing_ = false;
136 base::AutoUnlock auto_unlock(lock_);
137 sink_->Pause();
140 void AudioRendererImpl::SetMediaTime(base::TimeDelta time) {
141 DVLOG(1) << __FUNCTION__ << "(" << time << ")";
142 DCHECK(task_runner_->BelongsToCurrentThread());
144 base::AutoLock auto_lock(lock_);
145 DCHECK(!rendering_);
146 DCHECK_EQ(state_, kFlushed);
148 start_timestamp_ = time;
149 ended_timestamp_ = kInfiniteDuration();
150 last_render_ticks_ = base::TimeTicks();
151 first_packet_timestamp_ = kNoTimestamp();
152 audio_clock_.reset(new AudioClock(time, audio_parameters_.sample_rate()));
155 base::TimeDelta AudioRendererImpl::CurrentMediaTime() {
156 // In practice the Render() method is called with a high enough frequency
157 // that returning only the front timestamp is good enough and also prevents
158 // returning values that go backwards in time.
159 base::TimeDelta current_media_time;
161 base::AutoLock auto_lock(lock_);
162 current_media_time = audio_clock_->front_timestamp();
165 DVLOG(2) << __FUNCTION__ << ": " << current_media_time;
166 return current_media_time;
169 bool AudioRendererImpl::GetWallClockTimes(
170 const std::vector<base::TimeDelta>& media_timestamps,
171 std::vector<base::TimeTicks>* wall_clock_times) {
172 base::AutoLock auto_lock(lock_);
173 if (last_render_ticks_.is_null() || !playback_rate_ ||
174 buffering_state_ != BUFFERING_HAVE_ENOUGH || !sink_playing_) {
175 return false;
178 DCHECK(wall_clock_times->empty());
179 wall_clock_times->reserve(media_timestamps.size());
180 for (const auto& media_timestamp : media_timestamps) {
181 base::TimeDelta base_time;
182 if (media_timestamp < audio_clock_->front_timestamp()) {
183 // See notes about |media_time| values less than |base_time| in TimeSource
184 // header.
185 base_time = audio_clock_->front_timestamp();
186 } else if (media_timestamp > audio_clock_->back_timestamp()) {
187 base_time = audio_clock_->back_timestamp();
188 } else {
189 // No need to estimate time, so return the actual wallclock time.
190 wall_clock_times->push_back(
191 last_render_ticks_ +
192 audio_clock_->TimeUntilPlayback(media_timestamp));
193 continue;
196 // In practice, most calls will be estimates given the relatively small
197 // window in which clients can get the actual time.
198 wall_clock_times->push_back(
199 last_render_ticks_ + audio_clock_->TimeUntilPlayback(base_time) +
200 base::TimeDelta::FromMicroseconds(
201 (media_timestamp - base_time).InMicroseconds() / playback_rate_));
203 return true;
206 TimeSource* AudioRendererImpl::GetTimeSource() {
207 return this;
210 void AudioRendererImpl::Flush(const base::Closure& callback) {
211 DVLOG(1) << __FUNCTION__;
212 DCHECK(task_runner_->BelongsToCurrentThread());
214 base::AutoLock auto_lock(lock_);
215 DCHECK_EQ(state_, kPlaying);
216 DCHECK(flush_cb_.is_null());
218 flush_cb_ = callback;
219 ChangeState_Locked(kFlushing);
221 if (pending_read_)
222 return;
224 ChangeState_Locked(kFlushed);
225 DoFlush_Locked();
228 void AudioRendererImpl::DoFlush_Locked() {
229 DCHECK(task_runner_->BelongsToCurrentThread());
230 lock_.AssertAcquired();
232 DCHECK(!pending_read_);
233 DCHECK_EQ(state_, kFlushed);
235 audio_buffer_stream_->Reset(base::Bind(&AudioRendererImpl::ResetDecoderDone,
236 weak_factory_.GetWeakPtr()));
239 void AudioRendererImpl::ResetDecoderDone() {
240 DCHECK(task_runner_->BelongsToCurrentThread());
242 base::AutoLock auto_lock(lock_);
244 DCHECK_EQ(state_, kFlushed);
245 DCHECK(!flush_cb_.is_null());
247 received_end_of_stream_ = false;
248 rendered_end_of_stream_ = false;
250 // Flush() may have been called while underflowed/not fully buffered.
251 if (buffering_state_ != BUFFERING_HAVE_NOTHING)
252 SetBufferingState_Locked(BUFFERING_HAVE_NOTHING);
254 splicer_->Reset();
255 if (buffer_converter_)
256 buffer_converter_->Reset();
257 algorithm_->FlushBuffers();
260 // Changes in buffering state are always posted. Flush callback must only be
261 // run after buffering state has been set back to nothing.
262 task_runner_->PostTask(FROM_HERE, base::ResetAndReturn(&flush_cb_));
265 void AudioRendererImpl::StartPlaying() {
266 DVLOG(1) << __FUNCTION__;
267 DCHECK(task_runner_->BelongsToCurrentThread());
269 base::AutoLock auto_lock(lock_);
270 DCHECK(!sink_playing_);
271 DCHECK_EQ(state_, kFlushed);
272 DCHECK_EQ(buffering_state_, BUFFERING_HAVE_NOTHING);
273 DCHECK(!pending_read_) << "Pending read must complete before seeking";
275 ChangeState_Locked(kPlaying);
276 AttemptRead_Locked();
279 void AudioRendererImpl::Initialize(
280 DemuxerStream* stream,
281 const PipelineStatusCB& init_cb,
282 const SetDecryptorReadyCB& set_decryptor_ready_cb,
283 const StatisticsCB& statistics_cb,
284 const BufferingStateCB& buffering_state_cb,
285 const base::Closure& ended_cb,
286 const PipelineStatusCB& error_cb,
287 const base::Closure& waiting_for_decryption_key_cb) {
288 DVLOG(1) << __FUNCTION__;
289 DCHECK(task_runner_->BelongsToCurrentThread());
290 DCHECK(stream);
291 DCHECK_EQ(stream->type(), DemuxerStream::AUDIO);
292 DCHECK(!init_cb.is_null());
293 DCHECK(!statistics_cb.is_null());
294 DCHECK(!buffering_state_cb.is_null());
295 DCHECK(!ended_cb.is_null());
296 DCHECK(!error_cb.is_null());
297 DCHECK_EQ(kUninitialized, state_);
298 DCHECK(sink_.get());
300 state_ = kInitializing;
302 // Always post |init_cb_| because |this| could be destroyed if initialization
303 // failed.
304 init_cb_ = BindToCurrentLoop(init_cb);
306 buffering_state_cb_ = buffering_state_cb;
307 ended_cb_ = ended_cb;
308 error_cb_ = error_cb;
310 const AudioParameters& hw_params = hardware_config_.GetOutputConfig();
311 expecting_config_changes_ = stream->SupportsConfigChanges();
312 if (!expecting_config_changes_ || !hw_params.IsValid()) {
313 // The actual buffer size is controlled via the size of the AudioBus
314 // provided to Render(), so just choose something reasonable here for looks.
315 int buffer_size = stream->audio_decoder_config().samples_per_second() / 100;
316 audio_parameters_.Reset(
317 AudioParameters::AUDIO_PCM_LOW_LATENCY,
318 stream->audio_decoder_config().channel_layout(),
319 ChannelLayoutToChannelCount(
320 stream->audio_decoder_config().channel_layout()),
321 stream->audio_decoder_config().samples_per_second(),
322 stream->audio_decoder_config().bits_per_channel(),
323 buffer_size);
324 buffer_converter_.reset();
325 } else {
326 audio_parameters_.Reset(
327 hw_params.format(),
328 // Always use the source's channel layout and channel count to avoid
329 // premature downmixing (http://crbug.com/379288), platform specific
330 // issues around channel layouts (http://crbug.com/266674), and
331 // unnecessary upmixing overhead.
332 stream->audio_decoder_config().channel_layout(),
333 ChannelLayoutToChannelCount(
334 stream->audio_decoder_config().channel_layout()),
335 hw_params.sample_rate(),
336 hw_params.bits_per_sample(),
337 hardware_config_.GetHighLatencyBufferSize());
340 audio_clock_.reset(
341 new AudioClock(base::TimeDelta(), audio_parameters_.sample_rate()));
343 audio_buffer_stream_->Initialize(
344 stream, base::Bind(&AudioRendererImpl::OnAudioBufferStreamInitialized,
345 weak_factory_.GetWeakPtr()),
346 set_decryptor_ready_cb, statistics_cb, waiting_for_decryption_key_cb);
349 void AudioRendererImpl::OnAudioBufferStreamInitialized(bool success) {
350 DVLOG(1) << __FUNCTION__ << ": " << success;
351 DCHECK(task_runner_->BelongsToCurrentThread());
353 base::AutoLock auto_lock(lock_);
355 if (!success) {
356 state_ = kUninitialized;
357 base::ResetAndReturn(&init_cb_).Run(DECODER_ERROR_NOT_SUPPORTED);
358 return;
361 if (!audio_parameters_.IsValid()) {
362 DVLOG(1) << __FUNCTION__ << ": Invalid audio parameters: "
363 << audio_parameters_.AsHumanReadableString();
364 ChangeState_Locked(kUninitialized);
365 base::ResetAndReturn(&init_cb_).Run(PIPELINE_ERROR_INITIALIZATION_FAILED);
366 return;
369 if (expecting_config_changes_)
370 buffer_converter_.reset(new AudioBufferConverter(audio_parameters_));
371 splicer_.reset(new AudioSplicer(audio_parameters_.sample_rate()));
373 // We're all good! Continue initializing the rest of the audio renderer
374 // based on the decoder format.
375 algorithm_.reset(new AudioRendererAlgorithm());
376 algorithm_->Initialize(audio_parameters_);
378 ChangeState_Locked(kFlushed);
380 HistogramRendererEvent(INITIALIZED);
383 base::AutoUnlock auto_unlock(lock_);
384 sink_->Initialize(audio_parameters_, this);
385 sink_->Start();
387 // Some sinks play on start...
388 sink_->Pause();
391 DCHECK(!sink_playing_);
392 base::ResetAndReturn(&init_cb_).Run(PIPELINE_OK);
395 void AudioRendererImpl::SetVolume(float volume) {
396 DCHECK(task_runner_->BelongsToCurrentThread());
397 DCHECK(sink_.get());
398 sink_->SetVolume(volume);
401 void AudioRendererImpl::DecodedAudioReady(
402 AudioBufferStream::Status status,
403 const scoped_refptr<AudioBuffer>& buffer) {
404 DVLOG(2) << __FUNCTION__ << "(" << status << ")";
405 DCHECK(task_runner_->BelongsToCurrentThread());
407 base::AutoLock auto_lock(lock_);
408 DCHECK(state_ != kUninitialized);
410 CHECK(pending_read_);
411 pending_read_ = false;
413 if (status == AudioBufferStream::ABORTED ||
414 status == AudioBufferStream::DEMUXER_READ_ABORTED) {
415 HandleAbortedReadOrDecodeError(false);
416 return;
419 if (status == AudioBufferStream::DECODE_ERROR) {
420 HandleAbortedReadOrDecodeError(true);
421 return;
424 DCHECK_EQ(status, AudioBufferStream::OK);
425 DCHECK(buffer.get());
427 if (state_ == kFlushing) {
428 ChangeState_Locked(kFlushed);
429 DoFlush_Locked();
430 return;
433 if (expecting_config_changes_) {
434 DCHECK(buffer_converter_);
435 buffer_converter_->AddInput(buffer);
436 while (buffer_converter_->HasNextBuffer()) {
437 if (!splicer_->AddInput(buffer_converter_->GetNextBuffer())) {
438 HandleAbortedReadOrDecodeError(true);
439 return;
442 } else {
443 if (!splicer_->AddInput(buffer)) {
444 HandleAbortedReadOrDecodeError(true);
445 return;
449 if (!splicer_->HasNextBuffer()) {
450 AttemptRead_Locked();
451 return;
454 bool need_another_buffer = false;
455 while (splicer_->HasNextBuffer())
456 need_another_buffer = HandleSplicerBuffer_Locked(splicer_->GetNextBuffer());
458 if (!need_another_buffer && !CanRead_Locked())
459 return;
461 AttemptRead_Locked();
464 bool AudioRendererImpl::HandleSplicerBuffer_Locked(
465 const scoped_refptr<AudioBuffer>& buffer) {
466 lock_.AssertAcquired();
467 if (buffer->end_of_stream()) {
468 received_end_of_stream_ = true;
469 } else {
470 if (state_ == kPlaying) {
471 if (IsBeforeStartTime(buffer))
472 return true;
474 // Trim off any additional time before the start timestamp.
475 const base::TimeDelta trim_time = start_timestamp_ - buffer->timestamp();
476 if (trim_time > base::TimeDelta()) {
477 buffer->TrimStart(buffer->frame_count() *
478 (static_cast<double>(trim_time.InMicroseconds()) /
479 buffer->duration().InMicroseconds()));
481 // If the entire buffer was trimmed, request a new one.
482 if (!buffer->frame_count())
483 return true;
486 if (state_ != kUninitialized)
487 algorithm_->EnqueueBuffer(buffer);
490 // Store the timestamp of the first packet so we know when to start actual
491 // audio playback.
492 if (first_packet_timestamp_ == kNoTimestamp())
493 first_packet_timestamp_ = buffer->timestamp();
495 switch (state_) {
496 case kUninitialized:
497 case kInitializing:
498 case kFlushing:
499 NOTREACHED();
500 return false;
502 case kFlushed:
503 DCHECK(!pending_read_);
504 return false;
506 case kPlaying:
507 if (buffer->end_of_stream() || algorithm_->IsQueueFull()) {
508 if (buffering_state_ == BUFFERING_HAVE_NOTHING)
509 SetBufferingState_Locked(BUFFERING_HAVE_ENOUGH);
510 return false;
512 return true;
514 return false;
517 void AudioRendererImpl::AttemptRead() {
518 base::AutoLock auto_lock(lock_);
519 AttemptRead_Locked();
522 void AudioRendererImpl::AttemptRead_Locked() {
523 DCHECK(task_runner_->BelongsToCurrentThread());
524 lock_.AssertAcquired();
526 if (!CanRead_Locked())
527 return;
529 pending_read_ = true;
530 audio_buffer_stream_->Read(base::Bind(&AudioRendererImpl::DecodedAudioReady,
531 weak_factory_.GetWeakPtr()));
534 bool AudioRendererImpl::CanRead_Locked() {
535 lock_.AssertAcquired();
537 switch (state_) {
538 case kUninitialized:
539 case kInitializing:
540 case kFlushing:
541 case kFlushed:
542 return false;
544 case kPlaying:
545 break;
548 return !pending_read_ && !received_end_of_stream_ &&
549 !algorithm_->IsQueueFull();
552 void AudioRendererImpl::SetPlaybackRate(double playback_rate) {
553 DVLOG(1) << __FUNCTION__ << "(" << playback_rate << ")";
554 DCHECK(task_runner_->BelongsToCurrentThread());
555 DCHECK_GE(playback_rate, 0);
556 DCHECK(sink_.get());
558 base::AutoLock auto_lock(lock_);
560 // We have two cases here:
561 // Play: current_playback_rate == 0 && playback_rate != 0
562 // Pause: current_playback_rate != 0 && playback_rate == 0
563 double current_playback_rate = playback_rate_;
564 playback_rate_ = playback_rate;
566 if (!rendering_)
567 return;
569 if (current_playback_rate == 0 && playback_rate != 0) {
570 StartRendering_Locked();
571 return;
574 if (current_playback_rate != 0 && playback_rate == 0) {
575 StopRendering_Locked();
576 return;
580 bool AudioRendererImpl::IsBeforeStartTime(
581 const scoped_refptr<AudioBuffer>& buffer) {
582 DCHECK_EQ(state_, kPlaying);
583 return buffer.get() && !buffer->end_of_stream() &&
584 (buffer->timestamp() + buffer->duration()) < start_timestamp_;
587 int AudioRendererImpl::Render(AudioBus* audio_bus,
588 int audio_delay_milliseconds) {
589 const int requested_frames = audio_bus->frames();
590 base::TimeDelta playback_delay = base::TimeDelta::FromMilliseconds(
591 audio_delay_milliseconds);
592 const int delay_frames = static_cast<int>(playback_delay.InSecondsF() *
593 audio_parameters_.sample_rate());
594 int frames_written = 0;
596 base::AutoLock auto_lock(lock_);
597 last_render_ticks_ = base::TimeTicks::Now();
599 // Ensure Stop() hasn't destroyed our |algorithm_| on the pipeline thread.
600 if (!algorithm_) {
601 audio_clock_->WroteAudio(
602 0, requested_frames, delay_frames, playback_rate_);
603 return 0;
606 if (playback_rate_ == 0) {
607 audio_clock_->WroteAudio(
608 0, requested_frames, delay_frames, playback_rate_);
609 return 0;
612 // Mute audio by returning 0 when not playing.
613 if (state_ != kPlaying) {
614 audio_clock_->WroteAudio(
615 0, requested_frames, delay_frames, playback_rate_);
616 return 0;
619 // Delay playback by writing silence if we haven't reached the first
620 // timestamp yet; this can occur if the video starts before the audio.
621 if (algorithm_->frames_buffered() > 0) {
622 DCHECK(first_packet_timestamp_ != kNoTimestamp());
623 const base::TimeDelta play_delay =
624 first_packet_timestamp_ - audio_clock_->back_timestamp();
625 if (play_delay > base::TimeDelta()) {
626 DCHECK_EQ(frames_written, 0);
627 frames_written =
628 std::min(static_cast<int>(play_delay.InSecondsF() *
629 audio_parameters_.sample_rate()),
630 requested_frames);
631 audio_bus->ZeroFramesPartial(0, frames_written);
634 // If there's any space left, actually render the audio; this is where the
635 // aural magic happens.
636 if (frames_written < requested_frames) {
637 frames_written += algorithm_->FillBuffer(
638 audio_bus, frames_written, requested_frames - frames_written,
639 playback_rate_);
643 // We use the following conditions to determine end of playback:
644 // 1) Algorithm can not fill the audio callback buffer
645 // 2) We received an end of stream buffer
646 // 3) We haven't already signalled that we've ended
647 // 4) We've played all known audio data sent to hardware
649 // We use the following conditions to determine underflow:
650 // 1) Algorithm can not fill the audio callback buffer
651 // 2) We have NOT received an end of stream buffer
652 // 3) We are in the kPlaying state
654 // Otherwise the buffer has data we can send to the device.
656 // Per the TimeSource API the media time should always increase even after
657 // we've rendered all known audio data. Doing so simplifies scenarios where
658 // we have other sources of media data that need to be scheduled after audio
659 // data has ended.
661 // That being said, we don't want to advance time when underflowed as we
662 // know more decoded frames will eventually arrive. If we did, we would
663 // throw things out of sync when said decoded frames arrive.
664 int frames_after_end_of_stream = 0;
665 if (frames_written == 0) {
666 if (received_end_of_stream_) {
667 if (ended_timestamp_ == kInfiniteDuration())
668 ended_timestamp_ = audio_clock_->back_timestamp();
669 frames_after_end_of_stream = requested_frames;
670 } else if (state_ == kPlaying &&
671 buffering_state_ != BUFFERING_HAVE_NOTHING) {
672 algorithm_->IncreaseQueueCapacity();
673 SetBufferingState_Locked(BUFFERING_HAVE_NOTHING);
677 audio_clock_->WroteAudio(frames_written + frames_after_end_of_stream,
678 requested_frames,
679 delay_frames,
680 playback_rate_);
682 if (CanRead_Locked()) {
683 task_runner_->PostTask(FROM_HERE,
684 base::Bind(&AudioRendererImpl::AttemptRead,
685 weak_factory_.GetWeakPtr()));
688 if (audio_clock_->front_timestamp() >= ended_timestamp_ &&
689 !rendered_end_of_stream_) {
690 rendered_end_of_stream_ = true;
691 task_runner_->PostTask(FROM_HERE, ended_cb_);
695 DCHECK_LE(frames_written, requested_frames);
696 return frames_written;
699 void AudioRendererImpl::OnRenderError() {
700 // UMA data tells us this happens ~0.01% of the time. Trigger an error instead
701 // of trying to gracefully fall back to a fake sink. It's very likely
702 // OnRenderError() should be removed and the audio stack handle errors without
703 // notifying clients. See http://crbug.com/234708 for details.
704 HistogramRendererEvent(RENDER_ERROR);
705 // Post to |task_runner_| as this is called on the audio callback thread.
706 task_runner_->PostTask(FROM_HERE,
707 base::Bind(error_cb_, PIPELINE_ERROR_DECODE));
710 void AudioRendererImpl::HandleAbortedReadOrDecodeError(bool is_decode_error) {
711 DCHECK(task_runner_->BelongsToCurrentThread());
712 lock_.AssertAcquired();
714 PipelineStatus status = is_decode_error ? PIPELINE_ERROR_DECODE : PIPELINE_OK;
715 switch (state_) {
716 case kUninitialized:
717 case kInitializing:
718 NOTREACHED();
719 return;
720 case kFlushing:
721 ChangeState_Locked(kFlushed);
722 if (status == PIPELINE_OK) {
723 DoFlush_Locked();
724 return;
727 error_cb_.Run(status);
728 base::ResetAndReturn(&flush_cb_).Run();
729 return;
731 case kFlushed:
732 case kPlaying:
733 if (status != PIPELINE_OK)
734 error_cb_.Run(status);
735 return;
739 void AudioRendererImpl::ChangeState_Locked(State new_state) {
740 DVLOG(1) << __FUNCTION__ << " : " << state_ << " -> " << new_state;
741 lock_.AssertAcquired();
742 state_ = new_state;
745 void AudioRendererImpl::OnNewSpliceBuffer(base::TimeDelta splice_timestamp) {
746 DCHECK(task_runner_->BelongsToCurrentThread());
747 splicer_->SetSpliceTimestamp(splice_timestamp);
750 void AudioRendererImpl::OnConfigChange() {
751 DCHECK(task_runner_->BelongsToCurrentThread());
752 DCHECK(expecting_config_changes_);
753 buffer_converter_->ResetTimestampState();
754 // Drain flushed buffers from the converter so the AudioSplicer receives all
755 // data ahead of any OnNewSpliceBuffer() calls. Since discontinuities should
756 // only appear after config changes, AddInput() should never fail here.
757 while (buffer_converter_->HasNextBuffer())
758 CHECK(splicer_->AddInput(buffer_converter_->GetNextBuffer()));
761 void AudioRendererImpl::SetBufferingState_Locked(
762 BufferingState buffering_state) {
763 DVLOG(1) << __FUNCTION__ << " : " << buffering_state_ << " -> "
764 << buffering_state;
765 DCHECK_NE(buffering_state_, buffering_state);
766 lock_.AssertAcquired();
767 buffering_state_ = buffering_state;
769 task_runner_->PostTask(FROM_HERE,
770 base::Bind(buffering_state_cb_, buffering_state_));
773 } // namespace media