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"
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 "base/time/default_tick_clock.h"
18 #include "media/base/audio_buffer.h"
19 #include "media/base/audio_buffer_converter.h"
20 #include "media/base/audio_hardware_config.h"
21 #include "media/base/audio_splicer.h"
22 #include "media/base/bind_to_current_loop.h"
23 #include "media/base/demuxer_stream.h"
24 #include "media/base/media_log.h"
25 #include "media/filters/audio_clock.h"
26 #include "media/filters/decrypting_demuxer_stream.h"
32 enum AudioRendererEvent
{
35 RENDER_EVENT_MAX
= RENDER_ERROR
,
38 void HistogramRendererEvent(AudioRendererEvent event
) {
39 UMA_HISTOGRAM_ENUMERATION(
40 "Media.AudioRendererEvents", event
, RENDER_EVENT_MAX
+ 1);
45 AudioRendererImpl::AudioRendererImpl(
46 const scoped_refptr
<base::SingleThreadTaskRunner
>& task_runner
,
47 media::AudioRendererSink
* sink
,
48 ScopedVector
<AudioDecoder
> decoders
,
49 const AudioHardwareConfig
& hardware_config
,
50 const scoped_refptr
<MediaLog
>& media_log
)
51 : task_runner_(task_runner
),
52 expecting_config_changes_(false),
55 new AudioBufferStream(task_runner
, decoders
.Pass(), media_log
)),
56 hardware_config_(hardware_config
),
57 media_log_(media_log
),
58 tick_clock_(new base::DefaultTickClock()),
60 state_(kUninitialized
),
61 buffering_state_(BUFFERING_HAVE_NOTHING
),
65 received_end_of_stream_(false),
66 rendered_end_of_stream_(false),
68 audio_buffer_stream_
->set_splice_observer(base::Bind(
69 &AudioRendererImpl::OnNewSpliceBuffer
, weak_factory_
.GetWeakPtr()));
70 audio_buffer_stream_
->set_config_change_observer(base::Bind(
71 &AudioRendererImpl::OnConfigChange
, weak_factory_
.GetWeakPtr()));
74 AudioRendererImpl::~AudioRendererImpl() {
75 DVLOG(1) << __FUNCTION__
;
76 DCHECK(task_runner_
->BelongsToCurrentThread());
78 // If Render() is in progress, this call will wait for Render() to finish.
79 // After this call, the |sink_| will not call back into |this| anymore.
82 if (!init_cb_
.is_null())
83 base::ResetAndReturn(&init_cb_
).Run(PIPELINE_ERROR_ABORT
);
86 void AudioRendererImpl::StartTicking() {
87 DVLOG(1) << __FUNCTION__
;
88 DCHECK(task_runner_
->BelongsToCurrentThread());
92 base::AutoLock
auto_lock(lock_
);
93 // Wait for an eventual call to SetPlaybackRate() to start rendering.
94 if (playback_rate_
== 0) {
95 DCHECK(!sink_playing_
);
99 StartRendering_Locked();
102 void AudioRendererImpl::StartRendering_Locked() {
103 DVLOG(1) << __FUNCTION__
;
104 DCHECK(task_runner_
->BelongsToCurrentThread());
105 DCHECK_EQ(state_
, kPlaying
);
106 DCHECK(!sink_playing_
);
107 DCHECK_NE(playback_rate_
, 0.0);
108 lock_
.AssertAcquired();
110 sink_playing_
= true;
112 base::AutoUnlock
auto_unlock(lock_
);
116 void AudioRendererImpl::StopTicking() {
117 DVLOG(1) << __FUNCTION__
;
118 DCHECK(task_runner_
->BelongsToCurrentThread());
122 base::AutoLock
auto_lock(lock_
);
123 // Rendering should have already been stopped with a zero playback rate.
124 if (playback_rate_
== 0) {
125 DCHECK(!sink_playing_
);
129 StopRendering_Locked();
132 void AudioRendererImpl::StopRendering_Locked() {
133 DCHECK(task_runner_
->BelongsToCurrentThread());
134 DCHECK_EQ(state_
, kPlaying
);
135 DCHECK(sink_playing_
);
136 lock_
.AssertAcquired();
138 sink_playing_
= false;
140 base::AutoUnlock
auto_unlock(lock_
);
142 stop_rendering_time_
= last_render_time_
;
145 void AudioRendererImpl::SetMediaTime(base::TimeDelta time
) {
146 DVLOG(1) << __FUNCTION__
<< "(" << time
<< ")";
147 DCHECK(task_runner_
->BelongsToCurrentThread());
149 base::AutoLock
auto_lock(lock_
);
151 DCHECK_EQ(state_
, kFlushed
);
153 start_timestamp_
= time
;
154 ended_timestamp_
= kInfiniteDuration();
155 last_render_time_
= stop_rendering_time_
= base::TimeTicks();
156 first_packet_timestamp_
= kNoTimestamp();
157 audio_clock_
.reset(new AudioClock(time
, audio_parameters_
.sample_rate()));
160 base::TimeDelta
AudioRendererImpl::CurrentMediaTime() {
161 // In practice the Render() method is called with a high enough frequency
162 // that returning only the front timestamp is good enough and also prevents
163 // returning values that go backwards in time.
164 base::TimeDelta current_media_time
;
166 base::AutoLock
auto_lock(lock_
);
167 current_media_time
= audio_clock_
->front_timestamp();
170 DVLOG(2) << __FUNCTION__
<< ": " << current_media_time
;
171 return current_media_time
;
174 bool AudioRendererImpl::GetWallClockTimes(
175 const std::vector
<base::TimeDelta
>& media_timestamps
,
176 std::vector
<base::TimeTicks
>* wall_clock_times
) {
177 base::AutoLock
auto_lock(lock_
);
178 DCHECK(wall_clock_times
->empty());
180 // When playback is paused (rate is zero), assume a rate of 1.0.
181 const double playback_rate
= playback_rate_
? playback_rate_
: 1.0;
182 const bool is_time_moving
= sink_playing_
&& playback_rate_
&&
183 !last_render_time_
.is_null() &&
184 stop_rendering_time_
.is_null();
186 // Pre-compute the time until playback of the audio buffer extents, since
187 // these values are frequently used below.
188 const base::TimeDelta time_until_front
=
189 audio_clock_
->TimeUntilPlayback(audio_clock_
->front_timestamp());
190 const base::TimeDelta time_until_back
=
191 audio_clock_
->TimeUntilPlayback(audio_clock_
->back_timestamp());
193 if (media_timestamps
.empty()) {
194 // Return the current media time as a wall clock time while accounting for
195 // frames which may be in the process of play out.
196 wall_clock_times
->push_back(std::min(
197 std::max(tick_clock_
->NowTicks(), last_render_time_
+ time_until_front
),
198 last_render_time_
+ time_until_back
));
199 return is_time_moving
;
202 wall_clock_times
->reserve(media_timestamps
.size());
203 for (const auto& media_timestamp
: media_timestamps
) {
204 // When time was or is moving and the requested media timestamp is within
205 // range of played out audio, we can provide an exact conversion.
206 if (!last_render_time_
.is_null() &&
207 media_timestamp
>= audio_clock_
->front_timestamp() &&
208 media_timestamp
<= audio_clock_
->back_timestamp()) {
209 wall_clock_times
->push_back(
210 last_render_time_
+ audio_clock_
->TimeUntilPlayback(media_timestamp
));
214 base::TimeDelta base_timestamp
, time_until_playback
;
215 if (media_timestamp
< audio_clock_
->front_timestamp()) {
216 base_timestamp
= audio_clock_
->front_timestamp();
217 time_until_playback
= time_until_front
;
219 base_timestamp
= audio_clock_
->back_timestamp();
220 time_until_playback
= time_until_back
;
223 // In practice, most calls will be estimates given the relatively small
224 // window in which clients can get the actual time.
225 wall_clock_times
->push_back(last_render_time_
+ time_until_playback
+
226 (media_timestamp
- base_timestamp
) /
230 return is_time_moving
;
233 TimeSource
* AudioRendererImpl::GetTimeSource() {
237 void AudioRendererImpl::Flush(const base::Closure
& callback
) {
238 DVLOG(1) << __FUNCTION__
;
239 DCHECK(task_runner_
->BelongsToCurrentThread());
241 base::AutoLock
auto_lock(lock_
);
242 DCHECK_EQ(state_
, kPlaying
);
243 DCHECK(flush_cb_
.is_null());
245 flush_cb_
= callback
;
246 ChangeState_Locked(kFlushing
);
251 ChangeState_Locked(kFlushed
);
255 void AudioRendererImpl::DoFlush_Locked() {
256 DCHECK(task_runner_
->BelongsToCurrentThread());
257 lock_
.AssertAcquired();
259 DCHECK(!pending_read_
);
260 DCHECK_EQ(state_
, kFlushed
);
262 audio_buffer_stream_
->Reset(base::Bind(&AudioRendererImpl::ResetDecoderDone
,
263 weak_factory_
.GetWeakPtr()));
266 void AudioRendererImpl::ResetDecoderDone() {
267 DCHECK(task_runner_
->BelongsToCurrentThread());
269 base::AutoLock
auto_lock(lock_
);
271 DCHECK_EQ(state_
, kFlushed
);
272 DCHECK(!flush_cb_
.is_null());
274 received_end_of_stream_
= false;
275 rendered_end_of_stream_
= false;
277 // Flush() may have been called while underflowed/not fully buffered.
278 if (buffering_state_
!= BUFFERING_HAVE_NOTHING
)
279 SetBufferingState_Locked(BUFFERING_HAVE_NOTHING
);
282 if (buffer_converter_
)
283 buffer_converter_
->Reset();
284 algorithm_
->FlushBuffers();
287 // Changes in buffering state are always posted. Flush callback must only be
288 // run after buffering state has been set back to nothing.
289 task_runner_
->PostTask(FROM_HERE
, base::ResetAndReturn(&flush_cb_
));
292 void AudioRendererImpl::StartPlaying() {
293 DVLOG(1) << __FUNCTION__
;
294 DCHECK(task_runner_
->BelongsToCurrentThread());
296 base::AutoLock
auto_lock(lock_
);
297 DCHECK(!sink_playing_
);
298 DCHECK_EQ(state_
, kFlushed
);
299 DCHECK_EQ(buffering_state_
, BUFFERING_HAVE_NOTHING
);
300 DCHECK(!pending_read_
) << "Pending read must complete before seeking";
302 ChangeState_Locked(kPlaying
);
303 AttemptRead_Locked();
306 void AudioRendererImpl::Initialize(
307 DemuxerStream
* stream
,
308 const PipelineStatusCB
& init_cb
,
309 const SetDecryptorReadyCB
& set_decryptor_ready_cb
,
310 const StatisticsCB
& statistics_cb
,
311 const BufferingStateCB
& buffering_state_cb
,
312 const base::Closure
& ended_cb
,
313 const PipelineStatusCB
& error_cb
,
314 const base::Closure
& waiting_for_decryption_key_cb
) {
315 DVLOG(1) << __FUNCTION__
;
316 DCHECK(task_runner_
->BelongsToCurrentThread());
318 DCHECK_EQ(stream
->type(), DemuxerStream::AUDIO
);
319 DCHECK(!init_cb
.is_null());
320 DCHECK(!statistics_cb
.is_null());
321 DCHECK(!buffering_state_cb
.is_null());
322 DCHECK(!ended_cb
.is_null());
323 DCHECK(!error_cb
.is_null());
324 DCHECK_EQ(kUninitialized
, state_
);
327 state_
= kInitializing
;
329 // Always post |init_cb_| because |this| could be destroyed if initialization
331 init_cb_
= BindToCurrentLoop(init_cb
);
333 buffering_state_cb_
= buffering_state_cb
;
334 ended_cb_
= ended_cb
;
335 error_cb_
= error_cb
;
337 const AudioParameters
& hw_params
= hardware_config_
.GetOutputConfig();
338 expecting_config_changes_
= stream
->SupportsConfigChanges();
339 if (!expecting_config_changes_
|| !hw_params
.IsValid()) {
340 // The actual buffer size is controlled via the size of the AudioBus
341 // provided to Render(), so just choose something reasonable here for looks.
342 int buffer_size
= stream
->audio_decoder_config().samples_per_second() / 100;
343 audio_parameters_
.Reset(
344 AudioParameters::AUDIO_PCM_LOW_LATENCY
,
345 stream
->audio_decoder_config().channel_layout(),
346 ChannelLayoutToChannelCount(
347 stream
->audio_decoder_config().channel_layout()),
348 stream
->audio_decoder_config().samples_per_second(),
349 stream
->audio_decoder_config().bits_per_channel(),
351 buffer_converter_
.reset();
353 audio_parameters_
.Reset(
355 // Always use the source's channel layout and channel count to avoid
356 // premature downmixing (http://crbug.com/379288), platform specific
357 // issues around channel layouts (http://crbug.com/266674), and
358 // unnecessary upmixing overhead.
359 stream
->audio_decoder_config().channel_layout(),
360 ChannelLayoutToChannelCount(
361 stream
->audio_decoder_config().channel_layout()),
362 hw_params
.sample_rate(),
363 hw_params
.bits_per_sample(),
364 hardware_config_
.GetHighLatencyBufferSize());
368 new AudioClock(base::TimeDelta(), audio_parameters_
.sample_rate()));
370 audio_buffer_stream_
->Initialize(
371 stream
, base::Bind(&AudioRendererImpl::OnAudioBufferStreamInitialized
,
372 weak_factory_
.GetWeakPtr()),
373 set_decryptor_ready_cb
, statistics_cb
, waiting_for_decryption_key_cb
);
376 void AudioRendererImpl::OnAudioBufferStreamInitialized(bool success
) {
377 DVLOG(1) << __FUNCTION__
<< ": " << success
;
378 DCHECK(task_runner_
->BelongsToCurrentThread());
380 base::AutoLock
auto_lock(lock_
);
383 state_
= kUninitialized
;
384 base::ResetAndReturn(&init_cb_
).Run(DECODER_ERROR_NOT_SUPPORTED
);
388 if (!audio_parameters_
.IsValid()) {
389 DVLOG(1) << __FUNCTION__
<< ": Invalid audio parameters: "
390 << audio_parameters_
.AsHumanReadableString();
391 ChangeState_Locked(kUninitialized
);
392 base::ResetAndReturn(&init_cb_
).Run(PIPELINE_ERROR_INITIALIZATION_FAILED
);
396 if (expecting_config_changes_
)
397 buffer_converter_
.reset(new AudioBufferConverter(audio_parameters_
));
398 splicer_
.reset(new AudioSplicer(audio_parameters_
.sample_rate(), media_log_
));
400 // We're all good! Continue initializing the rest of the audio renderer
401 // based on the decoder format.
402 algorithm_
.reset(new AudioRendererAlgorithm());
403 algorithm_
->Initialize(audio_parameters_
);
405 ChangeState_Locked(kFlushed
);
407 HistogramRendererEvent(INITIALIZED
);
410 base::AutoUnlock
auto_unlock(lock_
);
411 sink_
->Initialize(audio_parameters_
, this);
414 // Some sinks play on start...
418 DCHECK(!sink_playing_
);
419 base::ResetAndReturn(&init_cb_
).Run(PIPELINE_OK
);
422 void AudioRendererImpl::SetVolume(float volume
) {
423 DCHECK(task_runner_
->BelongsToCurrentThread());
425 sink_
->SetVolume(volume
);
428 void AudioRendererImpl::DecodedAudioReady(
429 AudioBufferStream::Status status
,
430 const scoped_refptr
<AudioBuffer
>& buffer
) {
431 DVLOG(2) << __FUNCTION__
<< "(" << status
<< ")";
432 DCHECK(task_runner_
->BelongsToCurrentThread());
434 base::AutoLock
auto_lock(lock_
);
435 DCHECK(state_
!= kUninitialized
);
437 CHECK(pending_read_
);
438 pending_read_
= false;
440 if (status
== AudioBufferStream::ABORTED
||
441 status
== AudioBufferStream::DEMUXER_READ_ABORTED
) {
442 HandleAbortedReadOrDecodeError(false);
446 if (status
== AudioBufferStream::DECODE_ERROR
) {
447 HandleAbortedReadOrDecodeError(true);
451 DCHECK_EQ(status
, AudioBufferStream::OK
);
452 DCHECK(buffer
.get());
454 if (state_
== kFlushing
) {
455 ChangeState_Locked(kFlushed
);
460 if (expecting_config_changes_
) {
461 DCHECK(buffer_converter_
);
462 buffer_converter_
->AddInput(buffer
);
463 while (buffer_converter_
->HasNextBuffer()) {
464 if (!splicer_
->AddInput(buffer_converter_
->GetNextBuffer())) {
465 HandleAbortedReadOrDecodeError(true);
470 if (!splicer_
->AddInput(buffer
)) {
471 HandleAbortedReadOrDecodeError(true);
476 if (!splicer_
->HasNextBuffer()) {
477 AttemptRead_Locked();
481 bool need_another_buffer
= false;
482 while (splicer_
->HasNextBuffer())
483 need_another_buffer
= HandleSplicerBuffer_Locked(splicer_
->GetNextBuffer());
485 if (!need_another_buffer
&& !CanRead_Locked())
488 AttemptRead_Locked();
491 bool AudioRendererImpl::HandleSplicerBuffer_Locked(
492 const scoped_refptr
<AudioBuffer
>& buffer
) {
493 lock_
.AssertAcquired();
494 if (buffer
->end_of_stream()) {
495 received_end_of_stream_
= true;
497 if (state_
== kPlaying
) {
498 if (IsBeforeStartTime(buffer
))
501 // Trim off any additional time before the start timestamp.
502 const base::TimeDelta trim_time
= start_timestamp_
- buffer
->timestamp();
503 if (trim_time
> base::TimeDelta()) {
504 buffer
->TrimStart(buffer
->frame_count() *
505 (static_cast<double>(trim_time
.InMicroseconds()) /
506 buffer
->duration().InMicroseconds()));
508 // If the entire buffer was trimmed, request a new one.
509 if (!buffer
->frame_count())
513 if (state_
!= kUninitialized
)
514 algorithm_
->EnqueueBuffer(buffer
);
517 // Store the timestamp of the first packet so we know when to start actual
519 if (first_packet_timestamp_
== kNoTimestamp())
520 first_packet_timestamp_
= buffer
->timestamp();
530 DCHECK(!pending_read_
);
534 if (buffer
->end_of_stream() || algorithm_
->IsQueueFull()) {
535 if (buffering_state_
== BUFFERING_HAVE_NOTHING
)
536 SetBufferingState_Locked(BUFFERING_HAVE_ENOUGH
);
544 void AudioRendererImpl::AttemptRead() {
545 base::AutoLock
auto_lock(lock_
);
546 AttemptRead_Locked();
549 void AudioRendererImpl::AttemptRead_Locked() {
550 DCHECK(task_runner_
->BelongsToCurrentThread());
551 lock_
.AssertAcquired();
553 if (!CanRead_Locked())
556 pending_read_
= true;
557 audio_buffer_stream_
->Read(base::Bind(&AudioRendererImpl::DecodedAudioReady
,
558 weak_factory_
.GetWeakPtr()));
561 bool AudioRendererImpl::CanRead_Locked() {
562 lock_
.AssertAcquired();
575 return !pending_read_
&& !received_end_of_stream_
&&
576 !algorithm_
->IsQueueFull();
579 void AudioRendererImpl::SetPlaybackRate(double playback_rate
) {
580 DVLOG(1) << __FUNCTION__
<< "(" << playback_rate
<< ")";
581 DCHECK(task_runner_
->BelongsToCurrentThread());
582 DCHECK_GE(playback_rate
, 0);
585 base::AutoLock
auto_lock(lock_
);
587 // We have two cases here:
588 // Play: current_playback_rate == 0 && playback_rate != 0
589 // Pause: current_playback_rate != 0 && playback_rate == 0
590 double current_playback_rate
= playback_rate_
;
591 playback_rate_
= playback_rate
;
596 if (current_playback_rate
== 0 && playback_rate
!= 0) {
597 StartRendering_Locked();
601 if (current_playback_rate
!= 0 && playback_rate
== 0) {
602 StopRendering_Locked();
607 bool AudioRendererImpl::IsBeforeStartTime(
608 const scoped_refptr
<AudioBuffer
>& buffer
) {
609 DCHECK_EQ(state_
, kPlaying
);
610 return buffer
.get() && !buffer
->end_of_stream() &&
611 (buffer
->timestamp() + buffer
->duration()) < start_timestamp_
;
614 int AudioRendererImpl::Render(AudioBus
* audio_bus
,
615 int audio_delay_milliseconds
) {
616 const int requested_frames
= audio_bus
->frames();
617 base::TimeDelta playback_delay
= base::TimeDelta::FromMilliseconds(
618 audio_delay_milliseconds
);
619 const int delay_frames
= static_cast<int>(playback_delay
.InSecondsF() *
620 audio_parameters_
.sample_rate());
621 int frames_written
= 0;
623 base::AutoLock
auto_lock(lock_
);
624 last_render_time_
= tick_clock_
->NowTicks();
626 if (!stop_rendering_time_
.is_null()) {
627 audio_clock_
->CompensateForSuspendedWrites(
628 last_render_time_
- stop_rendering_time_
, delay_frames
);
629 stop_rendering_time_
= base::TimeTicks();
632 // Ensure Stop() hasn't destroyed our |algorithm_| on the pipeline thread.
634 audio_clock_
->WroteAudio(
635 0, requested_frames
, delay_frames
, playback_rate_
);
639 if (playback_rate_
== 0) {
640 audio_clock_
->WroteAudio(
641 0, requested_frames
, delay_frames
, playback_rate_
);
645 // Mute audio by returning 0 when not playing.
646 if (state_
!= kPlaying
) {
647 audio_clock_
->WroteAudio(
648 0, requested_frames
, delay_frames
, playback_rate_
);
652 // Delay playback by writing silence if we haven't reached the first
653 // timestamp yet; this can occur if the video starts before the audio.
654 if (algorithm_
->frames_buffered() > 0) {
655 DCHECK(first_packet_timestamp_
!= kNoTimestamp());
656 const base::TimeDelta play_delay
=
657 first_packet_timestamp_
- audio_clock_
->back_timestamp();
658 if (play_delay
> base::TimeDelta()) {
659 DCHECK_EQ(frames_written
, 0);
661 std::min(static_cast<int>(play_delay
.InSecondsF() *
662 audio_parameters_
.sample_rate()),
664 audio_bus
->ZeroFramesPartial(0, frames_written
);
667 // If there's any space left, actually render the audio; this is where the
668 // aural magic happens.
669 if (frames_written
< requested_frames
) {
670 frames_written
+= algorithm_
->FillBuffer(
671 audio_bus
, frames_written
, requested_frames
- frames_written
,
676 // We use the following conditions to determine end of playback:
677 // 1) Algorithm can not fill the audio callback buffer
678 // 2) We received an end of stream buffer
679 // 3) We haven't already signalled that we've ended
680 // 4) We've played all known audio data sent to hardware
682 // We use the following conditions to determine underflow:
683 // 1) Algorithm can not fill the audio callback buffer
684 // 2) We have NOT received an end of stream buffer
685 // 3) We are in the kPlaying state
687 // Otherwise the buffer has data we can send to the device.
689 // Per the TimeSource API the media time should always increase even after
690 // we've rendered all known audio data. Doing so simplifies scenarios where
691 // we have other sources of media data that need to be scheduled after audio
694 // That being said, we don't want to advance time when underflowed as we
695 // know more decoded frames will eventually arrive. If we did, we would
696 // throw things out of sync when said decoded frames arrive.
697 int frames_after_end_of_stream
= 0;
698 if (frames_written
== 0) {
699 if (received_end_of_stream_
) {
700 if (ended_timestamp_
== kInfiniteDuration())
701 ended_timestamp_
= audio_clock_
->back_timestamp();
702 frames_after_end_of_stream
= requested_frames
;
703 } else if (state_
== kPlaying
&&
704 buffering_state_
!= BUFFERING_HAVE_NOTHING
) {
705 algorithm_
->IncreaseQueueCapacity();
706 SetBufferingState_Locked(BUFFERING_HAVE_NOTHING
);
710 audio_clock_
->WroteAudio(frames_written
+ frames_after_end_of_stream
,
715 if (CanRead_Locked()) {
716 task_runner_
->PostTask(FROM_HERE
,
717 base::Bind(&AudioRendererImpl::AttemptRead
,
718 weak_factory_
.GetWeakPtr()));
721 if (audio_clock_
->front_timestamp() >= ended_timestamp_
&&
722 !rendered_end_of_stream_
) {
723 rendered_end_of_stream_
= true;
724 task_runner_
->PostTask(FROM_HERE
, ended_cb_
);
728 DCHECK_LE(frames_written
, requested_frames
);
729 return frames_written
;
732 void AudioRendererImpl::OnRenderError() {
733 // UMA data tells us this happens ~0.01% of the time. Trigger an error instead
734 // of trying to gracefully fall back to a fake sink. It's very likely
735 // OnRenderError() should be removed and the audio stack handle errors without
736 // notifying clients. See http://crbug.com/234708 for details.
737 HistogramRendererEvent(RENDER_ERROR
);
739 MEDIA_LOG(ERROR
, media_log_
) << "audio render error";
741 // Post to |task_runner_| as this is called on the audio callback thread.
742 task_runner_
->PostTask(FROM_HERE
,
743 base::Bind(error_cb_
, PIPELINE_ERROR_DECODE
));
746 void AudioRendererImpl::HandleAbortedReadOrDecodeError(bool is_decode_error
) {
747 DCHECK(task_runner_
->BelongsToCurrentThread());
748 lock_
.AssertAcquired();
750 PipelineStatus status
= is_decode_error
? PIPELINE_ERROR_DECODE
: PIPELINE_OK
;
757 ChangeState_Locked(kFlushed
);
758 if (status
== PIPELINE_OK
) {
763 MEDIA_LOG(ERROR
, media_log_
) << "audio decode error during flushing";
764 error_cb_
.Run(status
);
765 base::ResetAndReturn(&flush_cb_
).Run();
770 if (status
!= PIPELINE_OK
) {
771 MEDIA_LOG(ERROR
, media_log_
) << "audio decode error during playing";
772 error_cb_
.Run(status
);
778 void AudioRendererImpl::ChangeState_Locked(State new_state
) {
779 DVLOG(1) << __FUNCTION__
<< " : " << state_
<< " -> " << new_state
;
780 lock_
.AssertAcquired();
784 void AudioRendererImpl::OnNewSpliceBuffer(base::TimeDelta splice_timestamp
) {
785 DCHECK(task_runner_
->BelongsToCurrentThread());
786 splicer_
->SetSpliceTimestamp(splice_timestamp
);
789 void AudioRendererImpl::OnConfigChange() {
790 DCHECK(task_runner_
->BelongsToCurrentThread());
791 DCHECK(expecting_config_changes_
);
792 buffer_converter_
->ResetTimestampState();
793 // Drain flushed buffers from the converter so the AudioSplicer receives all
794 // data ahead of any OnNewSpliceBuffer() calls. Since discontinuities should
795 // only appear after config changes, AddInput() should never fail here.
796 while (buffer_converter_
->HasNextBuffer())
797 CHECK(splicer_
->AddInput(buffer_converter_
->GetNextBuffer()));
800 void AudioRendererImpl::SetBufferingState_Locked(
801 BufferingState buffering_state
) {
802 DVLOG(1) << __FUNCTION__
<< " : " << buffering_state_
<< " -> "
804 DCHECK_NE(buffering_state_
, buffering_state
);
805 lock_
.AssertAcquired();
806 buffering_state_
= buffering_state
;
808 task_runner_
->PostTask(FROM_HERE
,
809 base::Bind(buffering_state_cb_
, buffering_state_
));