Upstream version 10.39.225.0
[platform/framework/web/crosswalk.git] / src / media / filters / audio_renderer_impl.cc
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     const AudioHardwareConfig& hardware_config,
49     const scoped_refptr<MediaLog>& media_log)
50     : task_runner_(task_runner),
51       expecting_config_changes_(false),
52       sink_(sink),
53       audio_buffer_stream_(new AudioBufferStream(task_runner,
54                                                  decoders.Pass(),
55                                                  set_decryptor_ready_cb,
56                                                  media_log)),
57       hardware_config_(hardware_config),
58       playback_rate_(0),
59       state_(kUninitialized),
60       buffering_state_(BUFFERING_HAVE_NOTHING),
61       rendering_(false),
62       sink_playing_(false),
63       pending_read_(false),
64       received_end_of_stream_(false),
65       rendered_end_of_stream_(false),
66       weak_factory_(this) {
67   audio_buffer_stream_->set_splice_observer(base::Bind(
68       &AudioRendererImpl::OnNewSpliceBuffer, weak_factory_.GetWeakPtr()));
69   audio_buffer_stream_->set_config_change_observer(base::Bind(
70       &AudioRendererImpl::OnConfigChange, weak_factory_.GetWeakPtr()));
71 }
72
73 AudioRendererImpl::~AudioRendererImpl() {
74   DVLOG(1) << __FUNCTION__;
75   DCHECK(task_runner_->BelongsToCurrentThread());
76
77   // If Render() is in progress, this call will wait for Render() to finish.
78   // After this call, the |sink_| will not call back into |this| anymore.
79   sink_->Stop();
80
81   if (!init_cb_.is_null())
82     base::ResetAndReturn(&init_cb_).Run(PIPELINE_ERROR_ABORT);
83 }
84
85 void AudioRendererImpl::StartTicking() {
86   DVLOG(1) << __FUNCTION__;
87   DCHECK(task_runner_->BelongsToCurrentThread());
88   DCHECK(!rendering_);
89   rendering_ = true;
90
91   base::AutoLock auto_lock(lock_);
92   // Wait for an eventual call to SetPlaybackRate() to start rendering.
93   if (playback_rate_ == 0) {
94     DCHECK(!sink_playing_);
95     return;
96   }
97
98   StartRendering_Locked();
99 }
100
101 void AudioRendererImpl::StartRendering_Locked() {
102   DVLOG(1) << __FUNCTION__;
103   DCHECK(task_runner_->BelongsToCurrentThread());
104   DCHECK_EQ(state_, kPlaying);
105   DCHECK(!sink_playing_);
106   DCHECK_NE(playback_rate_, 0);
107   lock_.AssertAcquired();
108
109   sink_playing_ = true;
110
111   base::AutoUnlock auto_unlock(lock_);
112   sink_->Play();
113 }
114
115 void AudioRendererImpl::StopTicking() {
116   DVLOG(1) << __FUNCTION__;
117   DCHECK(task_runner_->BelongsToCurrentThread());
118   DCHECK(rendering_);
119   rendering_ = false;
120
121   base::AutoLock auto_lock(lock_);
122   // Rendering should have already been stopped with a zero playback rate.
123   if (playback_rate_ == 0) {
124     DCHECK(!sink_playing_);
125     return;
126   }
127
128   StopRendering_Locked();
129 }
130
131 void AudioRendererImpl::StopRendering_Locked() {
132   DCHECK(task_runner_->BelongsToCurrentThread());
133   DCHECK_EQ(state_, kPlaying);
134   DCHECK(sink_playing_);
135   lock_.AssertAcquired();
136
137   sink_playing_ = false;
138
139   base::AutoUnlock auto_unlock(lock_);
140   sink_->Pause();
141 }
142
143 void AudioRendererImpl::SetMediaTime(base::TimeDelta time) {
144   DVLOG(1) << __FUNCTION__ << "(" << time.InMicroseconds() << ")";
145   DCHECK(task_runner_->BelongsToCurrentThread());
146
147   base::AutoLock auto_lock(lock_);
148   DCHECK(!rendering_);
149   DCHECK_EQ(state_, kFlushed);
150
151   start_timestamp_ = time;
152   ended_timestamp_ = kInfiniteDuration();
153   last_render_ticks_ = base::TimeTicks();
154   audio_clock_.reset(new AudioClock(time, audio_parameters_.sample_rate()));
155 }
156
157 base::TimeDelta AudioRendererImpl::CurrentMediaTime() {
158   DVLOG(2) << __FUNCTION__;
159
160   // In practice the Render() method is called with a high enough frequency
161   // that returning only the front timestamp is good enough and also prevents
162   // returning values that go backwards in time.
163   base::AutoLock auto_lock(lock_);
164   return audio_clock_->front_timestamp();
165 }
166
167 base::TimeDelta AudioRendererImpl::CurrentMediaTimeForSyncingVideo() {
168   DVLOG(2) << __FUNCTION__;
169
170   base::AutoLock auto_lock(lock_);
171   if (last_render_ticks_.is_null())
172     return audio_clock_->front_timestamp();
173
174   return audio_clock_->TimestampSinceWriting(base::TimeTicks::Now() -
175                                              last_render_ticks_);
176 }
177
178 TimeSource* AudioRendererImpl::GetTimeSource() {
179   return this;
180 }
181
182 void AudioRendererImpl::Flush(const base::Closure& callback) {
183   DVLOG(1) << __FUNCTION__;
184   DCHECK(task_runner_->BelongsToCurrentThread());
185
186   base::AutoLock auto_lock(lock_);
187   DCHECK_EQ(state_, kPlaying);
188   DCHECK(flush_cb_.is_null());
189
190   flush_cb_ = callback;
191   ChangeState_Locked(kFlushing);
192
193   if (pending_read_)
194     return;
195
196   ChangeState_Locked(kFlushed);
197   DoFlush_Locked();
198 }
199
200 void AudioRendererImpl::DoFlush_Locked() {
201   DCHECK(task_runner_->BelongsToCurrentThread());
202   lock_.AssertAcquired();
203
204   DCHECK(!pending_read_);
205   DCHECK_EQ(state_, kFlushed);
206
207   audio_buffer_stream_->Reset(base::Bind(&AudioRendererImpl::ResetDecoderDone,
208                                          weak_factory_.GetWeakPtr()));
209 }
210
211 void AudioRendererImpl::ResetDecoderDone() {
212   DCHECK(task_runner_->BelongsToCurrentThread());
213   {
214     base::AutoLock auto_lock(lock_);
215
216     DCHECK_EQ(state_, kFlushed);
217     DCHECK(!flush_cb_.is_null());
218
219     received_end_of_stream_ = false;
220     rendered_end_of_stream_ = false;
221
222     // Flush() may have been called while underflowed/not fully buffered.
223     if (buffering_state_ != BUFFERING_HAVE_NOTHING)
224       SetBufferingState_Locked(BUFFERING_HAVE_NOTHING);
225
226     splicer_->Reset();
227     if (buffer_converter_)
228       buffer_converter_->Reset();
229     algorithm_->FlushBuffers();
230   }
231
232   // Changes in buffering state are always posted. Flush callback must only be
233   // run after buffering state has been set back to nothing.
234   task_runner_->PostTask(FROM_HERE, base::ResetAndReturn(&flush_cb_));
235 }
236
237 void AudioRendererImpl::StartPlaying() {
238   DVLOG(1) << __FUNCTION__;
239   DCHECK(task_runner_->BelongsToCurrentThread());
240
241   base::AutoLock auto_lock(lock_);
242   DCHECK(!sink_playing_);
243   DCHECK_EQ(state_, kFlushed);
244   DCHECK_EQ(buffering_state_, BUFFERING_HAVE_NOTHING);
245   DCHECK(!pending_read_) << "Pending read must complete before seeking";
246
247   ChangeState_Locked(kPlaying);
248   AttemptRead_Locked();
249 }
250
251 void AudioRendererImpl::Initialize(DemuxerStream* stream,
252                                    const PipelineStatusCB& init_cb,
253                                    const StatisticsCB& statistics_cb,
254                                    const BufferingStateCB& buffering_state_cb,
255                                    const base::Closure& ended_cb,
256                                    const PipelineStatusCB& error_cb) {
257   DCHECK(task_runner_->BelongsToCurrentThread());
258   DCHECK(stream);
259   DCHECK_EQ(stream->type(), DemuxerStream::AUDIO);
260   DCHECK(!init_cb.is_null());
261   DCHECK(!statistics_cb.is_null());
262   DCHECK(!buffering_state_cb.is_null());
263   DCHECK(!ended_cb.is_null());
264   DCHECK(!error_cb.is_null());
265   DCHECK_EQ(kUninitialized, state_);
266   DCHECK(sink_.get());
267
268   state_ = kInitializing;
269
270   // Always post |init_cb_| because |this| could be destroyed if initialization
271   // failed.
272   init_cb_ = BindToCurrentLoop(init_cb);
273
274   buffering_state_cb_ = buffering_state_cb;
275   ended_cb_ = ended_cb;
276   error_cb_ = error_cb;
277
278   expecting_config_changes_ = stream->SupportsConfigChanges();
279   if (!expecting_config_changes_) {
280     // The actual buffer size is controlled via the size of the AudioBus
281     // provided to Render(), so just choose something reasonable here for looks.
282     int buffer_size = stream->audio_decoder_config().samples_per_second() / 100;
283     audio_parameters_.Reset(
284         AudioParameters::AUDIO_PCM_LOW_LATENCY,
285         stream->audio_decoder_config().channel_layout(),
286         ChannelLayoutToChannelCount(
287             stream->audio_decoder_config().channel_layout()),
288         stream->audio_decoder_config().samples_per_second(),
289         stream->audio_decoder_config().bits_per_channel(),
290         buffer_size);
291     buffer_converter_.reset();
292   } else {
293     // TODO(rileya): Support hardware config changes
294     const AudioParameters& hw_params = hardware_config_.GetOutputConfig();
295     audio_parameters_.Reset(
296         hw_params.format(),
297         // Always use the source's channel layout and channel count to avoid
298         // premature downmixing (http://crbug.com/379288), platform specific
299         // issues around channel layouts (http://crbug.com/266674), and
300         // unnecessary upmixing overhead.
301         stream->audio_decoder_config().channel_layout(),
302         ChannelLayoutToChannelCount(
303             stream->audio_decoder_config().channel_layout()),
304         hw_params.sample_rate(),
305         hw_params.bits_per_sample(),
306         hardware_config_.GetHighLatencyBufferSize());
307   }
308
309   audio_clock_.reset(
310       new AudioClock(base::TimeDelta(), audio_parameters_.sample_rate()));
311
312   audio_buffer_stream_->Initialize(
313       stream,
314       false,
315       statistics_cb,
316       base::Bind(&AudioRendererImpl::OnAudioBufferStreamInitialized,
317                  weak_factory_.GetWeakPtr()));
318 }
319
320 void AudioRendererImpl::OnAudioBufferStreamInitialized(bool success) {
321   DCHECK(task_runner_->BelongsToCurrentThread());
322
323   base::AutoLock auto_lock(lock_);
324
325   if (!success) {
326     state_ = kUninitialized;
327     base::ResetAndReturn(&init_cb_).Run(DECODER_ERROR_NOT_SUPPORTED);
328     return;
329   }
330
331   if (!audio_parameters_.IsValid()) {
332     ChangeState_Locked(kUninitialized);
333     base::ResetAndReturn(&init_cb_).Run(PIPELINE_ERROR_INITIALIZATION_FAILED);
334     return;
335   }
336
337   if (expecting_config_changes_)
338     buffer_converter_.reset(new AudioBufferConverter(audio_parameters_));
339   splicer_.reset(new AudioSplicer(audio_parameters_.sample_rate()));
340
341   // We're all good! Continue initializing the rest of the audio renderer
342   // based on the decoder format.
343   algorithm_.reset(new AudioRendererAlgorithm());
344   algorithm_->Initialize(audio_parameters_);
345
346   ChangeState_Locked(kFlushed);
347
348   HistogramRendererEvent(INITIALIZED);
349
350   {
351     base::AutoUnlock auto_unlock(lock_);
352     sink_->Initialize(audio_parameters_, this);
353     sink_->Start();
354
355     // Some sinks play on start...
356     sink_->Pause();
357   }
358
359   DCHECK(!sink_playing_);
360   base::ResetAndReturn(&init_cb_).Run(PIPELINE_OK);
361 }
362
363 void AudioRendererImpl::SetVolume(float volume) {
364   DCHECK(task_runner_->BelongsToCurrentThread());
365   DCHECK(sink_.get());
366   sink_->SetVolume(volume);
367 }
368
369 void AudioRendererImpl::DecodedAudioReady(
370     AudioBufferStream::Status status,
371     const scoped_refptr<AudioBuffer>& buffer) {
372   DVLOG(2) << __FUNCTION__ << "(" << status << ")";
373   DCHECK(task_runner_->BelongsToCurrentThread());
374
375   base::AutoLock auto_lock(lock_);
376   DCHECK(state_ != kUninitialized);
377
378   CHECK(pending_read_);
379   pending_read_ = false;
380
381   if (status == AudioBufferStream::ABORTED ||
382       status == AudioBufferStream::DEMUXER_READ_ABORTED) {
383     HandleAbortedReadOrDecodeError(false);
384     return;
385   }
386
387   if (status == AudioBufferStream::DECODE_ERROR) {
388     HandleAbortedReadOrDecodeError(true);
389     return;
390   }
391
392   DCHECK_EQ(status, AudioBufferStream::OK);
393   DCHECK(buffer.get());
394
395   if (state_ == kFlushing) {
396     ChangeState_Locked(kFlushed);
397     DoFlush_Locked();
398     return;
399   }
400
401   if (expecting_config_changes_) {
402     DCHECK(buffer_converter_);
403     buffer_converter_->AddInput(buffer);
404     while (buffer_converter_->HasNextBuffer()) {
405       if (!splicer_->AddInput(buffer_converter_->GetNextBuffer())) {
406         HandleAbortedReadOrDecodeError(true);
407         return;
408       }
409     }
410   } else {
411     if (!splicer_->AddInput(buffer)) {
412       HandleAbortedReadOrDecodeError(true);
413       return;
414     }
415   }
416
417   if (!splicer_->HasNextBuffer()) {
418     AttemptRead_Locked();
419     return;
420   }
421
422   bool need_another_buffer = false;
423   while (splicer_->HasNextBuffer())
424     need_another_buffer = HandleSplicerBuffer_Locked(splicer_->GetNextBuffer());
425
426   if (!need_another_buffer && !CanRead_Locked())
427     return;
428
429   AttemptRead_Locked();
430 }
431
432 bool AudioRendererImpl::HandleSplicerBuffer_Locked(
433     const scoped_refptr<AudioBuffer>& buffer) {
434   lock_.AssertAcquired();
435   if (buffer->end_of_stream()) {
436     received_end_of_stream_ = true;
437   } else {
438     if (state_ == kPlaying) {
439       if (IsBeforeStartTime(buffer))
440         return true;
441
442       // Trim off any additional time before the start timestamp.
443       const base::TimeDelta trim_time = start_timestamp_ - buffer->timestamp();
444       if (trim_time > base::TimeDelta()) {
445         buffer->TrimStart(buffer->frame_count() *
446                           (static_cast<double>(trim_time.InMicroseconds()) /
447                            buffer->duration().InMicroseconds()));
448       }
449       // If the entire buffer was trimmed, request a new one.
450       if (!buffer->frame_count())
451         return true;
452     }
453
454     if (state_ != kUninitialized)
455       algorithm_->EnqueueBuffer(buffer);
456   }
457
458   switch (state_) {
459     case kUninitialized:
460     case kInitializing:
461     case kFlushing:
462       NOTREACHED();
463       return false;
464
465     case kFlushed:
466       DCHECK(!pending_read_);
467       return false;
468
469     case kPlaying:
470       if (buffer->end_of_stream() || algorithm_->IsQueueFull()) {
471         if (buffering_state_ == BUFFERING_HAVE_NOTHING)
472           SetBufferingState_Locked(BUFFERING_HAVE_ENOUGH);
473         return false;
474       }
475       return true;
476   }
477   return false;
478 }
479
480 void AudioRendererImpl::AttemptRead() {
481   base::AutoLock auto_lock(lock_);
482   AttemptRead_Locked();
483 }
484
485 void AudioRendererImpl::AttemptRead_Locked() {
486   DCHECK(task_runner_->BelongsToCurrentThread());
487   lock_.AssertAcquired();
488
489   if (!CanRead_Locked())
490     return;
491
492   pending_read_ = true;
493   audio_buffer_stream_->Read(base::Bind(&AudioRendererImpl::DecodedAudioReady,
494                                         weak_factory_.GetWeakPtr()));
495 }
496
497 bool AudioRendererImpl::CanRead_Locked() {
498   lock_.AssertAcquired();
499
500   switch (state_) {
501     case kUninitialized:
502     case kInitializing:
503     case kFlushing:
504     case kFlushed:
505       return false;
506
507     case kPlaying:
508       break;
509   }
510
511   return !pending_read_ && !received_end_of_stream_ &&
512       !algorithm_->IsQueueFull();
513 }
514
515 void AudioRendererImpl::SetPlaybackRate(float playback_rate) {
516   DVLOG(1) << __FUNCTION__ << "(" << playback_rate << ")";
517   DCHECK(task_runner_->BelongsToCurrentThread());
518   DCHECK_GE(playback_rate, 0);
519   DCHECK(sink_.get());
520
521   base::AutoLock auto_lock(lock_);
522
523   // We have two cases here:
524   // Play: current_playback_rate == 0 && playback_rate != 0
525   // Pause: current_playback_rate != 0 && playback_rate == 0
526   float current_playback_rate = playback_rate_;
527   playback_rate_ = playback_rate;
528
529   if (!rendering_)
530     return;
531
532   if (current_playback_rate == 0 && playback_rate != 0) {
533     StartRendering_Locked();
534     return;
535   }
536
537   if (current_playback_rate != 0 && playback_rate == 0) {
538     StopRendering_Locked();
539     return;
540   }
541 }
542
543 bool AudioRendererImpl::IsBeforeStartTime(
544     const scoped_refptr<AudioBuffer>& buffer) {
545   DCHECK_EQ(state_, kPlaying);
546   return buffer.get() && !buffer->end_of_stream() &&
547          (buffer->timestamp() + buffer->duration()) < start_timestamp_;
548 }
549
550 int AudioRendererImpl::Render(AudioBus* audio_bus,
551                               int audio_delay_milliseconds) {
552   const int requested_frames = audio_bus->frames();
553   base::TimeDelta playback_delay = base::TimeDelta::FromMilliseconds(
554       audio_delay_milliseconds);
555   const int delay_frames = static_cast<int>(playback_delay.InSecondsF() *
556                                             audio_parameters_.sample_rate());
557   int frames_written = 0;
558   {
559     base::AutoLock auto_lock(lock_);
560     last_render_ticks_ = base::TimeTicks::Now();
561
562     // Ensure Stop() hasn't destroyed our |algorithm_| on the pipeline thread.
563     if (!algorithm_) {
564       audio_clock_->WroteAudio(
565           0, requested_frames, delay_frames, playback_rate_);
566       return 0;
567     }
568
569     if (playback_rate_ == 0) {
570       audio_clock_->WroteAudio(
571           0, requested_frames, delay_frames, playback_rate_);
572       return 0;
573     }
574
575     // Mute audio by returning 0 when not playing.
576     if (state_ != kPlaying) {
577       audio_clock_->WroteAudio(
578           0, requested_frames, delay_frames, playback_rate_);
579       return 0;
580     }
581
582     // We use the following conditions to determine end of playback:
583     //   1) Algorithm can not fill the audio callback buffer
584     //   2) We received an end of stream buffer
585     //   3) We haven't already signalled that we've ended
586     //   4) We've played all known audio data sent to hardware
587     //
588     // We use the following conditions to determine underflow:
589     //   1) Algorithm can not fill the audio callback buffer
590     //   2) We have NOT received an end of stream buffer
591     //   3) We are in the kPlaying state
592     //
593     // Otherwise the buffer has data we can send to the device.
594     if (algorithm_->frames_buffered() > 0) {
595       frames_written =
596           algorithm_->FillBuffer(audio_bus, requested_frames, playback_rate_);
597     }
598
599     // Per the TimeSource API the media time should always increase even after
600     // we've rendered all known audio data. Doing so simplifies scenarios where
601     // we have other sources of media data that need to be scheduled after audio
602     // data has ended.
603     //
604     // That being said, we don't want to advance time when underflowed as we
605     // know more decoded frames will eventually arrive. If we did, we would
606     // throw things out of sync when said decoded frames arrive.
607     int frames_after_end_of_stream = 0;
608     if (frames_written == 0) {
609       if (received_end_of_stream_) {
610         if (ended_timestamp_ == kInfiniteDuration())
611           ended_timestamp_ = audio_clock_->back_timestamp();
612         frames_after_end_of_stream = requested_frames;
613       } else if (state_ == kPlaying &&
614                  buffering_state_ != BUFFERING_HAVE_NOTHING) {
615         algorithm_->IncreaseQueueCapacity();
616         SetBufferingState_Locked(BUFFERING_HAVE_NOTHING);
617       }
618     }
619
620     audio_clock_->WroteAudio(frames_written + frames_after_end_of_stream,
621                              requested_frames,
622                              delay_frames,
623                              playback_rate_);
624
625     if (CanRead_Locked()) {
626       task_runner_->PostTask(FROM_HERE,
627                              base::Bind(&AudioRendererImpl::AttemptRead,
628                                         weak_factory_.GetWeakPtr()));
629     }
630
631     if (audio_clock_->front_timestamp() >= ended_timestamp_ &&
632         !rendered_end_of_stream_) {
633       rendered_end_of_stream_ = true;
634       task_runner_->PostTask(FROM_HERE, ended_cb_);
635     }
636   }
637
638   DCHECK_LE(frames_written, requested_frames);
639   return frames_written;
640 }
641
642 void AudioRendererImpl::OnRenderError() {
643   // UMA data tells us this happens ~0.01% of the time. Trigger an error instead
644   // of trying to gracefully fall back to a fake sink. It's very likely
645   // OnRenderError() should be removed and the audio stack handle errors without
646   // notifying clients. See http://crbug.com/234708 for details.
647   HistogramRendererEvent(RENDER_ERROR);
648   // Post to |task_runner_| as this is called on the audio callback thread.
649   task_runner_->PostTask(FROM_HERE,
650                          base::Bind(error_cb_, PIPELINE_ERROR_DECODE));
651 }
652
653 void AudioRendererImpl::HandleAbortedReadOrDecodeError(bool is_decode_error) {
654   DCHECK(task_runner_->BelongsToCurrentThread());
655   lock_.AssertAcquired();
656
657   PipelineStatus status = is_decode_error ? PIPELINE_ERROR_DECODE : PIPELINE_OK;
658   switch (state_) {
659     case kUninitialized:
660     case kInitializing:
661       NOTREACHED();
662       return;
663     case kFlushing:
664       ChangeState_Locked(kFlushed);
665       if (status == PIPELINE_OK) {
666         DoFlush_Locked();
667         return;
668       }
669
670       error_cb_.Run(status);
671       base::ResetAndReturn(&flush_cb_).Run();
672       return;
673
674     case kFlushed:
675     case kPlaying:
676       if (status != PIPELINE_OK)
677         error_cb_.Run(status);
678       return;
679   }
680 }
681
682 void AudioRendererImpl::ChangeState_Locked(State new_state) {
683   DVLOG(1) << __FUNCTION__ << " : " << state_ << " -> " << new_state;
684   lock_.AssertAcquired();
685   state_ = new_state;
686 }
687
688 void AudioRendererImpl::OnNewSpliceBuffer(base::TimeDelta splice_timestamp) {
689   DCHECK(task_runner_->BelongsToCurrentThread());
690   splicer_->SetSpliceTimestamp(splice_timestamp);
691 }
692
693 void AudioRendererImpl::OnConfigChange() {
694   DCHECK(task_runner_->BelongsToCurrentThread());
695   DCHECK(expecting_config_changes_);
696   buffer_converter_->ResetTimestampState();
697   // Drain flushed buffers from the converter so the AudioSplicer receives all
698   // data ahead of any OnNewSpliceBuffer() calls.  Since discontinuities should
699   // only appear after config changes, AddInput() should never fail here.
700   while (buffer_converter_->HasNextBuffer())
701     CHECK(splicer_->AddInput(buffer_converter_->GetNextBuffer()));
702 }
703
704 void AudioRendererImpl::SetBufferingState_Locked(
705     BufferingState buffering_state) {
706   DVLOG(1) << __FUNCTION__ << " : " << buffering_state_ << " -> "
707            << buffering_state;
708   DCHECK_NE(buffering_state_, buffering_state);
709   lock_.AssertAcquired();
710   buffering_state_ = buffering_state;
711
712   task_runner_->PostTask(FROM_HERE,
713                          base::Bind(buffering_state_cb_, buffering_state_));
714 }
715
716 }  // namespace media