Home | History | Annotate | Download | only in filters
      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/message_loop/message_loop_proxy.h"
     16 #include "base/metrics/histogram.h"
     17 #include "media/base/audio_buffer.h"
     18 #include "media/base/audio_splicer.h"
     19 #include "media/base/bind_to_loop.h"
     20 #include "media/base/demuxer_stream.h"
     21 #include "media/filters/audio_decoder_selector.h"
     22 #include "media/filters/decrypting_demuxer_stream.h"
     23 
     24 namespace media {
     25 
     26 namespace {
     27 
     28 enum AudioRendererEvent {
     29   INITIALIZED,
     30   RENDER_ERROR,
     31   MAX_EVENTS
     32 };
     33 
     34 void HistogramRendererEvent(AudioRendererEvent event) {
     35   UMA_HISTOGRAM_ENUMERATION("Media.AudioRendererEvents", event, MAX_EVENTS);
     36 }
     37 
     38 }  // namespace
     39 
     40 AudioRendererImpl::AudioRendererImpl(
     41     const scoped_refptr<base::MessageLoopProxy>& message_loop,
     42     media::AudioRendererSink* sink,
     43     ScopedVector<AudioDecoder> decoders,
     44     const SetDecryptorReadyCB& set_decryptor_ready_cb)
     45     : message_loop_(message_loop),
     46       weak_factory_(this),
     47       sink_(sink),
     48       decoder_selector_(new AudioDecoderSelector(
     49           message_loop, decoders.Pass(), set_decryptor_ready_cb)),
     50       now_cb_(base::Bind(&base::TimeTicks::Now)),
     51       state_(kUninitialized),
     52       sink_playing_(false),
     53       pending_read_(false),
     54       received_end_of_stream_(false),
     55       rendered_end_of_stream_(false),
     56       audio_time_buffered_(kNoTimestamp()),
     57       current_time_(kNoTimestamp()),
     58       underflow_disabled_(false),
     59       preroll_aborted_(false) {
     60 }
     61 
     62 AudioRendererImpl::~AudioRendererImpl() {
     63   // Stop() should have been called and |algorithm_| should have been destroyed.
     64   DCHECK(state_ == kUninitialized || state_ == kStopped);
     65   DCHECK(!algorithm_.get());
     66 }
     67 
     68 void AudioRendererImpl::Play(const base::Closure& callback) {
     69   DCHECK(message_loop_->BelongsToCurrentThread());
     70 
     71   base::AutoLock auto_lock(lock_);
     72   DCHECK_EQ(state_, kPaused);
     73   ChangeState_Locked(kPlaying);
     74   callback.Run();
     75   earliest_end_time_ = now_cb_.Run();
     76 
     77   if (algorithm_->playback_rate() != 0)
     78     DoPlay_Locked();
     79   else
     80     DCHECK(!sink_playing_);
     81 }
     82 
     83 void AudioRendererImpl::DoPlay_Locked() {
     84   DCHECK(message_loop_->BelongsToCurrentThread());
     85   lock_.AssertAcquired();
     86   earliest_end_time_ = now_cb_.Run();
     87 
     88   if ((state_ == kPlaying || state_ == kRebuffering || state_ == kUnderflow) &&
     89       !sink_playing_) {
     90     {
     91       base::AutoUnlock auto_unlock(lock_);
     92       sink_->Play();
     93     }
     94 
     95     sink_playing_ = true;
     96   }
     97 }
     98 
     99 void AudioRendererImpl::Pause(const base::Closure& callback) {
    100   DCHECK(message_loop_->BelongsToCurrentThread());
    101 
    102   base::AutoLock auto_lock(lock_);
    103   DCHECK(state_ == kPlaying || state_ == kUnderflow ||
    104          state_ == kRebuffering) << "state_ == " << state_;
    105   ChangeState_Locked(kPaused);
    106 
    107   DoPause_Locked();
    108 
    109   callback.Run();
    110 }
    111 
    112 void AudioRendererImpl::DoPause_Locked() {
    113   DCHECK(message_loop_->BelongsToCurrentThread());
    114   lock_.AssertAcquired();
    115 
    116   if (sink_playing_) {
    117     {
    118       base::AutoUnlock auto_unlock(lock_);
    119       sink_->Pause();
    120     }
    121     sink_playing_ = false;
    122   }
    123 }
    124 
    125 void AudioRendererImpl::Flush(const base::Closure& callback) {
    126   DCHECK(message_loop_->BelongsToCurrentThread());
    127 
    128   base::AutoLock auto_lock(lock_);
    129   DCHECK_EQ(state_, kPaused);
    130   DCHECK(flush_cb_.is_null());
    131 
    132   flush_cb_ = callback;
    133 
    134   if (pending_read_) {
    135     ChangeState_Locked(kFlushing);
    136     return;
    137   }
    138 
    139   DoFlush_Locked();
    140 }
    141 
    142 void AudioRendererImpl::DoFlush_Locked() {
    143   DCHECK(message_loop_->BelongsToCurrentThread());
    144   lock_.AssertAcquired();
    145 
    146   DCHECK(!pending_read_);
    147   DCHECK_EQ(state_, kPaused);
    148 
    149   if (decrypting_demuxer_stream_) {
    150     decrypting_demuxer_stream_->Reset(BindToCurrentLoop(
    151         base::Bind(&AudioRendererImpl::ResetDecoder, weak_this_)));
    152     return;
    153   }
    154 
    155   ResetDecoder();
    156 }
    157 
    158 void AudioRendererImpl::ResetDecoder() {
    159   DCHECK(message_loop_->BelongsToCurrentThread());
    160   decoder_->Reset(BindToCurrentLoop(
    161       base::Bind(&AudioRendererImpl::ResetDecoderDone, weak_this_)));
    162 }
    163 
    164 void AudioRendererImpl::ResetDecoderDone() {
    165   base::AutoLock auto_lock(lock_);
    166   if (state_ == kStopped)
    167     return;
    168 
    169   DCHECK_EQ(state_, kPaused);
    170   DCHECK(!flush_cb_.is_null());
    171 
    172   audio_time_buffered_ = kNoTimestamp();
    173   current_time_ = kNoTimestamp();
    174   received_end_of_stream_ = false;
    175   rendered_end_of_stream_ = false;
    176   preroll_aborted_ = false;
    177 
    178   earliest_end_time_ = now_cb_.Run();
    179   splicer_->Reset();
    180   algorithm_->FlushBuffers();
    181 
    182   base::ResetAndReturn(&flush_cb_).Run();
    183 }
    184 
    185 void AudioRendererImpl::Stop(const base::Closure& callback) {
    186   DCHECK(message_loop_->BelongsToCurrentThread());
    187   DCHECK(!callback.is_null());
    188 
    189   // TODO(scherkus): Consider invalidating |weak_factory_| and replacing
    190   // task-running guards that check |state_| with DCHECK().
    191 
    192   if (sink_) {
    193     sink_->Stop();
    194     sink_ = NULL;
    195   }
    196 
    197   {
    198     base::AutoLock auto_lock(lock_);
    199     ChangeState_Locked(kStopped);
    200     algorithm_.reset(NULL);
    201     init_cb_.Reset();
    202     underflow_cb_.Reset();
    203     time_cb_.Reset();
    204     flush_cb_.Reset();
    205   }
    206 
    207   callback.Run();
    208 }
    209 
    210 void AudioRendererImpl::Preroll(base::TimeDelta time,
    211                                 const PipelineStatusCB& cb) {
    212   DCHECK(message_loop_->BelongsToCurrentThread());
    213 
    214   base::AutoLock auto_lock(lock_);
    215   DCHECK(!sink_playing_);
    216   DCHECK_EQ(state_, kPaused);
    217   DCHECK(!pending_read_) << "Pending read must complete before seeking";
    218   DCHECK(preroll_cb_.is_null());
    219 
    220   ChangeState_Locked(kPrerolling);
    221   preroll_cb_ = cb;
    222   preroll_timestamp_ = time;
    223 
    224   AttemptRead_Locked();
    225 }
    226 
    227 void AudioRendererImpl::Initialize(DemuxerStream* stream,
    228                                    const PipelineStatusCB& init_cb,
    229                                    const StatisticsCB& statistics_cb,
    230                                    const base::Closure& underflow_cb,
    231                                    const TimeCB& time_cb,
    232                                    const base::Closure& ended_cb,
    233                                    const base::Closure& disabled_cb,
    234                                    const PipelineStatusCB& error_cb) {
    235   DCHECK(message_loop_->BelongsToCurrentThread());
    236   DCHECK(stream);
    237   DCHECK_EQ(stream->type(), DemuxerStream::AUDIO);
    238   DCHECK(!init_cb.is_null());
    239   DCHECK(!statistics_cb.is_null());
    240   DCHECK(!underflow_cb.is_null());
    241   DCHECK(!time_cb.is_null());
    242   DCHECK(!ended_cb.is_null());
    243   DCHECK(!disabled_cb.is_null());
    244   DCHECK(!error_cb.is_null());
    245   DCHECK_EQ(kUninitialized, state_);
    246   DCHECK(sink_);
    247 
    248   weak_this_ = weak_factory_.GetWeakPtr();
    249   init_cb_ = init_cb;
    250   statistics_cb_ = statistics_cb;
    251   underflow_cb_ = underflow_cb;
    252   time_cb_ = time_cb;
    253   ended_cb_ = ended_cb;
    254   disabled_cb_ = disabled_cb;
    255   error_cb_ = error_cb;
    256 
    257   decoder_selector_->SelectAudioDecoder(
    258       stream,
    259       statistics_cb,
    260       base::Bind(&AudioRendererImpl::OnDecoderSelected, weak_this_));
    261 }
    262 
    263 void AudioRendererImpl::OnDecoderSelected(
    264     scoped_ptr<AudioDecoder> decoder,
    265     scoped_ptr<DecryptingDemuxerStream> decrypting_demuxer_stream) {
    266   DCHECK(message_loop_->BelongsToCurrentThread());
    267 
    268   base::AutoLock auto_lock(lock_);
    269   scoped_ptr<AudioDecoderSelector> deleter(decoder_selector_.Pass());
    270 
    271   if (state_ == kStopped) {
    272     DCHECK(!sink_);
    273     return;
    274   }
    275 
    276   if (!decoder) {
    277     base::ResetAndReturn(&init_cb_).Run(DECODER_ERROR_NOT_SUPPORTED);
    278     return;
    279   }
    280 
    281   decoder_ = decoder.Pass();
    282   decrypting_demuxer_stream_ = decrypting_demuxer_stream.Pass();
    283 
    284   int sample_rate = decoder_->samples_per_second();
    285 
    286   // The actual buffer size is controlled via the size of the AudioBus provided
    287   // to Render(), so just choose something reasonable here for looks.
    288   int buffer_size = decoder_->samples_per_second() / 100;
    289   audio_parameters_ = AudioParameters(
    290       AudioParameters::AUDIO_PCM_LOW_LATENCY, decoder_->channel_layout(),
    291       sample_rate, decoder_->bits_per_channel(), buffer_size);
    292   if (!audio_parameters_.IsValid()) {
    293     base::ResetAndReturn(&init_cb_).Run(PIPELINE_ERROR_INITIALIZATION_FAILED);
    294     return;
    295   }
    296 
    297   splicer_.reset(new AudioSplicer(sample_rate));
    298 
    299   // We're all good! Continue initializing the rest of the audio renderer based
    300   // on the decoder format.
    301   algorithm_.reset(new AudioRendererAlgorithm());
    302   algorithm_->Initialize(0, audio_parameters_);
    303 
    304   ChangeState_Locked(kPaused);
    305 
    306   HistogramRendererEvent(INITIALIZED);
    307 
    308   {
    309     base::AutoUnlock auto_unlock(lock_);
    310     sink_->Initialize(audio_parameters_, weak_this_.get());
    311     sink_->Start();
    312 
    313     // Some sinks play on start...
    314     sink_->Pause();
    315   }
    316 
    317   DCHECK(!sink_playing_);
    318 
    319   base::ResetAndReturn(&init_cb_).Run(PIPELINE_OK);
    320 }
    321 
    322 void AudioRendererImpl::ResumeAfterUnderflow() {
    323   DCHECK(message_loop_->BelongsToCurrentThread());
    324   base::AutoLock auto_lock(lock_);
    325   if (state_ == kUnderflow) {
    326     // The "!preroll_aborted_" is a hack. If preroll is aborted, then we
    327     // shouldn't even reach the kUnderflow state to begin with. But for now
    328     // we're just making sure that the audio buffer capacity (i.e. the
    329     // number of bytes that need to be buffered for preroll to complete)
    330     // does not increase due to an aborted preroll.
    331     // TODO(vrk): Fix this bug correctly! (crbug.com/151352)
    332     if (!preroll_aborted_)
    333       algorithm_->IncreaseQueueCapacity();
    334 
    335     ChangeState_Locked(kRebuffering);
    336   }
    337 }
    338 
    339 void AudioRendererImpl::SetVolume(float volume) {
    340   DCHECK(message_loop_->BelongsToCurrentThread());
    341   DCHECK(sink_);
    342   sink_->SetVolume(volume);
    343 }
    344 
    345 void AudioRendererImpl::DecodedAudioReady(
    346     AudioDecoder::Status status,
    347     const scoped_refptr<AudioBuffer>& buffer) {
    348   DVLOG(1) << __FUNCTION__ << "(" << status << ")";
    349   DCHECK(message_loop_->BelongsToCurrentThread());
    350 
    351   base::AutoLock auto_lock(lock_);
    352   DCHECK(state_ != kUninitialized);
    353 
    354   CHECK(pending_read_);
    355   pending_read_ = false;
    356 
    357   if (status == AudioDecoder::kAborted) {
    358     HandleAbortedReadOrDecodeError(false);
    359     return;
    360   }
    361 
    362   if (status == AudioDecoder::kDecodeError) {
    363     HandleAbortedReadOrDecodeError(true);
    364     return;
    365   }
    366 
    367   DCHECK_EQ(status, AudioDecoder::kOk);
    368   DCHECK(buffer.get());
    369 
    370   if (state_ == kFlushing) {
    371     ChangeState_Locked(kPaused);
    372     DoFlush_Locked();
    373     return;
    374   }
    375 
    376   if (!splicer_->AddInput(buffer)) {
    377     HandleAbortedReadOrDecodeError(true);
    378     return;
    379   }
    380 
    381   if (!splicer_->HasNextBuffer()) {
    382     AttemptRead_Locked();
    383     return;
    384   }
    385 
    386   bool need_another_buffer = false;
    387   while (splicer_->HasNextBuffer())
    388     need_another_buffer = HandleSplicerBuffer(splicer_->GetNextBuffer());
    389 
    390   if (!need_another_buffer && !CanRead_Locked())
    391     return;
    392 
    393   AttemptRead_Locked();
    394 }
    395 
    396 bool AudioRendererImpl::HandleSplicerBuffer(
    397     const scoped_refptr<AudioBuffer>& buffer) {
    398   if (buffer->end_of_stream()) {
    399     received_end_of_stream_ = true;
    400 
    401     // Transition to kPlaying if we are currently handling an underflow since
    402     // no more data will be arriving.
    403     if (state_ == kUnderflow || state_ == kRebuffering)
    404       ChangeState_Locked(kPlaying);
    405   } else {
    406     if (state_ == kPrerolling) {
    407       if (IsBeforePrerollTime(buffer))
    408         return true;
    409 
    410       // Trim off any additional time before the preroll timestamp.
    411       const base::TimeDelta trim_time =
    412           preroll_timestamp_ - buffer->timestamp();
    413       if (trim_time > base::TimeDelta()) {
    414         buffer->TrimStart(buffer->frame_count() *
    415                           (static_cast<double>(trim_time.InMicroseconds()) /
    416                            buffer->duration().InMicroseconds()));
    417       }
    418       // If the entire buffer was trimmed, request a new one.
    419       if (!buffer->frame_count())
    420         return true;
    421     }
    422 
    423     if (state_ != kUninitialized && state_ != kStopped)
    424       algorithm_->EnqueueBuffer(buffer);
    425   }
    426 
    427   switch (state_) {
    428     case kUninitialized:
    429     case kFlushing:
    430       NOTREACHED();
    431       return false;
    432 
    433     case kPaused:
    434       DCHECK(!pending_read_);
    435       return false;
    436 
    437     case kPrerolling:
    438       if (!buffer->end_of_stream() && !algorithm_->IsQueueFull())
    439         return true;
    440       ChangeState_Locked(kPaused);
    441       base::ResetAndReturn(&preroll_cb_).Run(PIPELINE_OK);
    442       return false;
    443 
    444     case kPlaying:
    445     case kUnderflow:
    446       return false;
    447 
    448     case kRebuffering:
    449       if (!algorithm_->IsQueueFull())
    450         return true;
    451       ChangeState_Locked(kPlaying);
    452       return false;
    453 
    454     case kStopped:
    455       return false;
    456   }
    457   return false;
    458 }
    459 
    460 void AudioRendererImpl::AttemptRead() {
    461   base::AutoLock auto_lock(lock_);
    462   AttemptRead_Locked();
    463 }
    464 
    465 void AudioRendererImpl::AttemptRead_Locked() {
    466   DCHECK(message_loop_->BelongsToCurrentThread());
    467   lock_.AssertAcquired();
    468 
    469   if (!CanRead_Locked())
    470     return;
    471 
    472   pending_read_ = true;
    473   decoder_->Read(base::Bind(&AudioRendererImpl::DecodedAudioReady, weak_this_));
    474 }
    475 
    476 bool AudioRendererImpl::CanRead_Locked() {
    477   lock_.AssertAcquired();
    478 
    479   switch (state_) {
    480     case kUninitialized:
    481     case kPaused:
    482     case kFlushing:
    483     case kStopped:
    484       return false;
    485 
    486     case kPrerolling:
    487     case kPlaying:
    488     case kUnderflow:
    489     case kRebuffering:
    490       break;
    491   }
    492 
    493   return !pending_read_ && !received_end_of_stream_ &&
    494       !algorithm_->IsQueueFull();
    495 }
    496 
    497 void AudioRendererImpl::SetPlaybackRate(float playback_rate) {
    498   DVLOG(1) << __FUNCTION__ << "(" << playback_rate << ")";
    499   DCHECK(message_loop_->BelongsToCurrentThread());
    500   DCHECK_GE(playback_rate, 0);
    501   DCHECK(sink_);
    502 
    503   base::AutoLock auto_lock(lock_);
    504 
    505   // We have two cases here:
    506   // Play: current_playback_rate == 0 && playback_rate != 0
    507   // Pause: current_playback_rate != 0 && playback_rate == 0
    508   float current_playback_rate = algorithm_->playback_rate();
    509   if (current_playback_rate == 0 && playback_rate != 0)
    510     DoPlay_Locked();
    511   else if (current_playback_rate != 0 && playback_rate == 0)
    512     DoPause_Locked();
    513 
    514   algorithm_->SetPlaybackRate(playback_rate);
    515 }
    516 
    517 bool AudioRendererImpl::IsBeforePrerollTime(
    518     const scoped_refptr<AudioBuffer>& buffer) {
    519   DCHECK_EQ(state_, kPrerolling);
    520   return buffer && !buffer->end_of_stream() &&
    521          (buffer->timestamp() + buffer->duration()) < preroll_timestamp_;
    522 }
    523 
    524 int AudioRendererImpl::Render(AudioBus* audio_bus,
    525                               int audio_delay_milliseconds) {
    526   const int requested_frames = audio_bus->frames();
    527   base::TimeDelta current_time = kNoTimestamp();
    528   base::TimeDelta max_time = kNoTimestamp();
    529   base::TimeDelta playback_delay = base::TimeDelta::FromMilliseconds(
    530       audio_delay_milliseconds);
    531 
    532   int frames_written = 0;
    533   base::Closure underflow_cb;
    534   {
    535     base::AutoLock auto_lock(lock_);
    536 
    537     // Ensure Stop() hasn't destroyed our |algorithm_| on the pipeline thread.
    538     if (!algorithm_)
    539       return 0;
    540 
    541     float playback_rate = algorithm_->playback_rate();
    542     if (playback_rate == 0)
    543       return 0;
    544 
    545     // Mute audio by returning 0 when not playing.
    546     if (state_ != kPlaying)
    547       return 0;
    548 
    549     // We use the following conditions to determine end of playback:
    550     //   1) Algorithm can not fill the audio callback buffer
    551     //   2) We received an end of stream buffer
    552     //   3) We haven't already signalled that we've ended
    553     //   4) Our estimated earliest end time has expired
    554     //
    555     // TODO(enal): we should replace (4) with a check that the browser has no
    556     // more audio data or at least use a delayed callback.
    557     //
    558     // We use the following conditions to determine underflow:
    559     //   1) Algorithm can not fill the audio callback buffer
    560     //   2) We have NOT received an end of stream buffer
    561     //   3) We are in the kPlaying state
    562     //
    563     // Otherwise the buffer has data we can send to the device.
    564     frames_written = algorithm_->FillBuffer(audio_bus, requested_frames);
    565     if (frames_written == 0) {
    566       const base::TimeTicks now = now_cb_.Run();
    567 
    568       if (received_end_of_stream_ && !rendered_end_of_stream_ &&
    569           now >= earliest_end_time_) {
    570         rendered_end_of_stream_ = true;
    571         ended_cb_.Run();
    572       } else if (!received_end_of_stream_ && state_ == kPlaying &&
    573                  !underflow_disabled_) {
    574         ChangeState_Locked(kUnderflow);
    575         underflow_cb = underflow_cb_;
    576       } else {
    577         // We can't write any data this cycle. For example, we may have
    578         // sent all available data to the audio device while not reaching
    579         // |earliest_end_time_|.
    580       }
    581     }
    582 
    583     if (CanRead_Locked()) {
    584       message_loop_->PostTask(FROM_HERE, base::Bind(
    585           &AudioRendererImpl::AttemptRead, weak_this_));
    586     }
    587 
    588     // The |audio_time_buffered_| is the ending timestamp of the last frame
    589     // buffered at the audio device. |playback_delay| is the amount of time
    590     // buffered at the audio device. The current time can be computed by their
    591     // difference.
    592     if (audio_time_buffered_ != kNoTimestamp()) {
    593       // Adjust the delay according to playback rate.
    594       base::TimeDelta adjusted_playback_delay =
    595           base::TimeDelta::FromMicroseconds(ceil(
    596               playback_delay.InMicroseconds() * playback_rate));
    597 
    598       base::TimeDelta previous_time = current_time_;
    599       current_time_ = audio_time_buffered_ - adjusted_playback_delay;
    600 
    601       // Time can change in one of two ways:
    602       //   1) The time of the audio data at the audio device changed, or
    603       //   2) The playback delay value has changed
    604       //
    605       // We only want to set |current_time| (and thus execute |time_cb_|) if
    606       // time has progressed and we haven't signaled end of stream yet.
    607       //
    608       // Why? The current latency of the system results in getting the last call
    609       // to FillBuffer() later than we'd like, which delays firing the 'ended'
    610       // event, which delays the looping/trigging performance of short sound
    611       // effects.
    612       //
    613       // TODO(scherkus): revisit this and switch back to relying on playback
    614       // delay after we've revamped our audio IPC subsystem.
    615       if (current_time_ > previous_time && !rendered_end_of_stream_) {
    616         current_time = current_time_;
    617       }
    618     }
    619 
    620     // The call to FillBuffer() on |algorithm_| has increased the amount of
    621     // buffered audio data. Update the new amount of time buffered.
    622     max_time = algorithm_->GetTime();
    623     audio_time_buffered_ = max_time;
    624 
    625     if (frames_written > 0) {
    626       UpdateEarliestEndTime_Locked(
    627           frames_written, playback_delay, now_cb_.Run());
    628     }
    629   }
    630 
    631   if (current_time != kNoTimestamp() && max_time != kNoTimestamp())
    632     time_cb_.Run(current_time, max_time);
    633 
    634   if (!underflow_cb.is_null())
    635     underflow_cb.Run();
    636 
    637   DCHECK_LE(frames_written, requested_frames);
    638   return frames_written;
    639 }
    640 
    641 void AudioRendererImpl::UpdateEarliestEndTime_Locked(
    642     int frames_filled, const base::TimeDelta& playback_delay,
    643     const base::TimeTicks& time_now) {
    644   DCHECK_GT(frames_filled, 0);
    645 
    646   base::TimeDelta predicted_play_time = base::TimeDelta::FromMicroseconds(
    647       static_cast<float>(frames_filled) * base::Time::kMicrosecondsPerSecond /
    648       audio_parameters_.sample_rate());
    649 
    650   lock_.AssertAcquired();
    651   earliest_end_time_ = std::max(
    652       earliest_end_time_, time_now + playback_delay + predicted_play_time);
    653 }
    654 
    655 void AudioRendererImpl::OnRenderError() {
    656   HistogramRendererEvent(RENDER_ERROR);
    657   disabled_cb_.Run();
    658 }
    659 
    660 void AudioRendererImpl::DisableUnderflowForTesting() {
    661   underflow_disabled_ = true;
    662 }
    663 
    664 void AudioRendererImpl::HandleAbortedReadOrDecodeError(bool is_decode_error) {
    665   lock_.AssertAcquired();
    666 
    667   PipelineStatus status = is_decode_error ? PIPELINE_ERROR_DECODE : PIPELINE_OK;
    668   switch (state_) {
    669     case kUninitialized:
    670       NOTREACHED();
    671       return;
    672     case kPaused:
    673       if (status != PIPELINE_OK)
    674         error_cb_.Run(status);
    675       return;
    676     case kFlushing:
    677       ChangeState_Locked(kPaused);
    678 
    679       if (status == PIPELINE_OK) {
    680         DoFlush_Locked();
    681         return;
    682       }
    683 
    684       error_cb_.Run(status);
    685       base::ResetAndReturn(&flush_cb_).Run();
    686       return;
    687     case kPrerolling:
    688       // This is a signal for abort if it's not an error.
    689       preroll_aborted_ = !is_decode_error;
    690       ChangeState_Locked(kPaused);
    691       base::ResetAndReturn(&preroll_cb_).Run(status);
    692       return;
    693     case kPlaying:
    694     case kUnderflow:
    695     case kRebuffering:
    696     case kStopped:
    697       if (status != PIPELINE_OK)
    698         error_cb_.Run(status);
    699       return;
    700   }
    701 }
    702 
    703 void AudioRendererImpl::ChangeState_Locked(State new_state) {
    704   DVLOG(1) << __FUNCTION__ << " : " << state_ << " -> " << new_state;
    705   lock_.AssertAcquired();
    706   state_ = new_state;
    707 }
    708 
    709 }  // namespace media
    710