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
26namespace media {
27
28namespace {
29
30enum AudioRendererEvent {
31  INITIALIZED,
32  RENDER_ERROR,
33  RENDER_EVENT_MAX = RENDER_ERROR,
34};
35
36void HistogramRendererEvent(AudioRendererEvent event) {
37  UMA_HISTOGRAM_ENUMERATION(
38      "Media.AudioRendererEvents", event, RENDER_EVENT_MAX + 1);
39}
40
41}  // namespace
42
43AudioRendererImpl::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
73AudioRendererImpl::~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
85void 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
101void 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
115void 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
131void 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
143void 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
157base::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
167base::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
178TimeSource* AudioRendererImpl::GetTimeSource() {
179  return this;
180}
181
182void 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
200void 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
211void 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
237void 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
251void 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
320void 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
363void AudioRendererImpl::SetVolume(float volume) {
364  DCHECK(task_runner_->BelongsToCurrentThread());
365  DCHECK(sink_.get());
366  sink_->SetVolume(volume);
367}
368
369void 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
432bool 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
480void AudioRendererImpl::AttemptRead() {
481  base::AutoLock auto_lock(lock_);
482  AttemptRead_Locked();
483}
484
485void 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
497bool 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
515void 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
543bool 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
550int 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
642void 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
653void 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
682void AudioRendererImpl::ChangeState_Locked(State new_state) {
683  DVLOG(1) << __FUNCTION__ << " : " << state_ << " -> " << new_state;
684  lock_.AssertAcquired();
685  state_ = new_state;
686}
687
688void AudioRendererImpl::OnNewSpliceBuffer(base::TimeDelta splice_timestamp) {
689  DCHECK(task_runner_->BelongsToCurrentThread());
690  splicer_->SetSpliceTimestamp(splice_timestamp);
691}
692
693void 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
704void 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
717