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