• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
HistogramRendererEvent(AudioRendererEvent event)36 void HistogramRendererEvent(AudioRendererEvent event) {
37   UMA_HISTOGRAM_ENUMERATION(
38       "Media.AudioRendererEvents", event, RENDER_EVENT_MAX + 1);
39 }
40 
41 }  // namespace
42 
AudioRendererImpl(const scoped_refptr<base::SingleThreadTaskRunner> & task_runner,media::AudioRendererSink * sink,ScopedVector<AudioDecoder> decoders,const SetDecryptorReadyCB & set_decryptor_ready_cb,AudioHardwareConfig * hardware_config)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     AudioHardwareConfig* hardware_config)
49     : task_runner_(task_runner),
50       sink_(sink),
51       audio_buffer_stream_(task_runner,
52                            decoders.Pass(),
53                            set_decryptor_ready_cb),
54       hardware_config_(hardware_config),
55       now_cb_(base::Bind(&base::TimeTicks::Now)),
56       state_(kUninitialized),
57       rendering_(false),
58       sink_playing_(false),
59       pending_read_(false),
60       received_end_of_stream_(false),
61       rendered_end_of_stream_(false),
62       preroll_aborted_(false),
63       weak_factory_(this) {
64   audio_buffer_stream_.set_splice_observer(base::Bind(
65       &AudioRendererImpl::OnNewSpliceBuffer, weak_factory_.GetWeakPtr()));
66   audio_buffer_stream_.set_config_change_observer(base::Bind(
67       &AudioRendererImpl::OnConfigChange, weak_factory_.GetWeakPtr()));
68 }
69 
~AudioRendererImpl()70 AudioRendererImpl::~AudioRendererImpl() {
71   // Stop() should have been called and |algorithm_| should have been destroyed.
72   DCHECK(state_ == kUninitialized || state_ == kStopped);
73   DCHECK(!algorithm_.get());
74 }
75 
StartRendering()76 void AudioRendererImpl::StartRendering() {
77   DVLOG(1) << __FUNCTION__;
78   DCHECK(task_runner_->BelongsToCurrentThread());
79   DCHECK(!rendering_);
80   rendering_ = true;
81 
82   base::AutoLock auto_lock(lock_);
83   // Wait for an eventual call to SetPlaybackRate() to start rendering.
84   if (algorithm_->playback_rate() == 0) {
85     DCHECK(!sink_playing_);
86     return;
87   }
88 
89   StartRendering_Locked();
90 }
91 
StartRendering_Locked()92 void AudioRendererImpl::StartRendering_Locked() {
93   DVLOG(1) << __FUNCTION__;
94   DCHECK(task_runner_->BelongsToCurrentThread());
95   DCHECK(state_ == kPlaying || state_ == kRebuffering || state_ == kUnderflow)
96       << "state_=" << state_;
97   DCHECK(!sink_playing_);
98   DCHECK_NE(algorithm_->playback_rate(), 0);
99   lock_.AssertAcquired();
100 
101   earliest_end_time_ = now_cb_.Run();
102   sink_playing_ = true;
103 
104   base::AutoUnlock auto_unlock(lock_);
105   sink_->Play();
106 }
107 
StopRendering()108 void AudioRendererImpl::StopRendering() {
109   DVLOG(1) << __FUNCTION__;
110   DCHECK(task_runner_->BelongsToCurrentThread());
111   DCHECK(rendering_);
112   rendering_ = false;
113 
114   base::AutoLock auto_lock(lock_);
115   // Rendering should have already been stopped with a zero playback rate.
116   if (algorithm_->playback_rate() == 0) {
117     DCHECK(!sink_playing_);
118     return;
119   }
120 
121   StopRendering_Locked();
122 }
123 
StopRendering_Locked()124 void AudioRendererImpl::StopRendering_Locked() {
125   DCHECK(task_runner_->BelongsToCurrentThread());
126   DCHECK(state_ == kPlaying || state_ == kRebuffering || state_ == kUnderflow)
127       << "state_=" << state_;
128   DCHECK(sink_playing_);
129   lock_.AssertAcquired();
130 
131   sink_playing_ = false;
132 
133   base::AutoUnlock auto_unlock(lock_);
134   sink_->Pause();
135 }
136 
Flush(const base::Closure & callback)137 void AudioRendererImpl::Flush(const base::Closure& callback) {
138   DVLOG(1) << __FUNCTION__;
139   DCHECK(task_runner_->BelongsToCurrentThread());
140 
141   base::AutoLock auto_lock(lock_);
142   DCHECK(state_ == kPlaying || state_ == kRebuffering || state_ == kUnderflow)
143       << "state_=" << state_;
144   DCHECK(flush_cb_.is_null());
145 
146   flush_cb_ = callback;
147 
148   if (pending_read_) {
149     ChangeState_Locked(kFlushing);
150     return;
151   }
152 
153   ChangeState_Locked(kFlushed);
154   DoFlush_Locked();
155 }
156 
DoFlush_Locked()157 void AudioRendererImpl::DoFlush_Locked() {
158   DCHECK(task_runner_->BelongsToCurrentThread());
159   lock_.AssertAcquired();
160 
161   DCHECK(!pending_read_);
162   DCHECK_EQ(state_, kFlushed);
163 
164   audio_buffer_stream_.Reset(base::Bind(&AudioRendererImpl::ResetDecoderDone,
165                                         weak_factory_.GetWeakPtr()));
166 }
167 
ResetDecoderDone()168 void AudioRendererImpl::ResetDecoderDone() {
169   DCHECK(task_runner_->BelongsToCurrentThread());
170   {
171     base::AutoLock auto_lock(lock_);
172     if (state_ == kStopped)
173       return;
174 
175     DCHECK_EQ(state_, kFlushed);
176     DCHECK(!flush_cb_.is_null());
177 
178     audio_clock_.reset(new AudioClock(audio_parameters_.sample_rate()));
179     received_end_of_stream_ = false;
180     rendered_end_of_stream_ = false;
181     preroll_aborted_ = false;
182 
183     earliest_end_time_ = now_cb_.Run();
184     splicer_->Reset();
185     if (buffer_converter_)
186       buffer_converter_->Reset();
187     algorithm_->FlushBuffers();
188   }
189   base::ResetAndReturn(&flush_cb_).Run();
190 }
191 
Stop(const base::Closure & callback)192 void AudioRendererImpl::Stop(const base::Closure& callback) {
193   DVLOG(1) << __FUNCTION__;
194   DCHECK(task_runner_->BelongsToCurrentThread());
195   DCHECK(!callback.is_null());
196 
197   // TODO(scherkus): Consider invalidating |weak_factory_| and replacing
198   // task-running guards that check |state_| with DCHECK().
199 
200   {
201     base::AutoLock auto_lock(lock_);
202 
203     if (state_ == kStopped) {
204       task_runner_->PostTask(FROM_HERE, callback);
205       return;
206     }
207 
208     ChangeState_Locked(kStopped);
209     algorithm_.reset();
210     underflow_cb_.Reset();
211     time_cb_.Reset();
212     flush_cb_.Reset();
213   }
214 
215   if (sink_) {
216     sink_->Stop();
217     sink_ = NULL;
218   }
219 
220   audio_buffer_stream_.Stop(callback);
221 }
222 
Preroll(base::TimeDelta time,const PipelineStatusCB & cb)223 void AudioRendererImpl::Preroll(base::TimeDelta time,
224                                 const PipelineStatusCB& cb) {
225   DVLOG(1) << __FUNCTION__ << "(" << time.InMicroseconds() << ")";
226   DCHECK(task_runner_->BelongsToCurrentThread());
227 
228   base::AutoLock auto_lock(lock_);
229   DCHECK(!sink_playing_);
230   DCHECK_EQ(state_, kFlushed);
231   DCHECK(!pending_read_) << "Pending read must complete before seeking";
232   DCHECK(preroll_cb_.is_null());
233 
234   ChangeState_Locked(kPrerolling);
235   preroll_cb_ = cb;
236   preroll_timestamp_ = time;
237 
238   AttemptRead_Locked();
239 }
240 
Initialize(DemuxerStream * stream,const PipelineStatusCB & init_cb,const StatisticsCB & statistics_cb,const base::Closure & underflow_cb,const TimeCB & time_cb,const base::Closure & ended_cb,const PipelineStatusCB & error_cb)241 void AudioRendererImpl::Initialize(DemuxerStream* stream,
242                                    const PipelineStatusCB& init_cb,
243                                    const StatisticsCB& statistics_cb,
244                                    const base::Closure& underflow_cb,
245                                    const TimeCB& time_cb,
246                                    const base::Closure& ended_cb,
247                                    const PipelineStatusCB& error_cb) {
248   DCHECK(task_runner_->BelongsToCurrentThread());
249   DCHECK(stream);
250   DCHECK_EQ(stream->type(), DemuxerStream::AUDIO);
251   DCHECK(!init_cb.is_null());
252   DCHECK(!statistics_cb.is_null());
253   DCHECK(!underflow_cb.is_null());
254   DCHECK(!time_cb.is_null());
255   DCHECK(!ended_cb.is_null());
256   DCHECK(!error_cb.is_null());
257   DCHECK_EQ(kUninitialized, state_);
258   DCHECK(sink_);
259 
260   state_ = kInitializing;
261 
262   init_cb_ = init_cb;
263   underflow_cb_ = underflow_cb;
264   time_cb_ = time_cb;
265   ended_cb_ = ended_cb;
266   error_cb_ = error_cb;
267 
268   expecting_config_changes_ = stream->SupportsConfigChanges();
269   if (!expecting_config_changes_) {
270     // The actual buffer size is controlled via the size of the AudioBus
271     // provided to Render(), so just choose something reasonable here for looks.
272     int buffer_size = stream->audio_decoder_config().samples_per_second() / 100;
273     audio_parameters_.Reset(
274         AudioParameters::AUDIO_PCM_LOW_LATENCY,
275         stream->audio_decoder_config().channel_layout(),
276         ChannelLayoutToChannelCount(
277             stream->audio_decoder_config().channel_layout()),
278         0,
279         stream->audio_decoder_config().samples_per_second(),
280         stream->audio_decoder_config().bits_per_channel(),
281         buffer_size);
282     buffer_converter_.reset();
283   } else {
284     // TODO(rileya): Support hardware config changes
285     const AudioParameters& hw_params = hardware_config_->GetOutputConfig();
286     audio_parameters_.Reset(
287         hw_params.format(),
288         // Always use the source's channel layout and channel count to avoid
289         // premature downmixing (http://crbug.com/379288), platform specific
290         // issues around channel layouts (http://crbug.com/266674), and
291         // unnecessary upmixing overhead.
292         stream->audio_decoder_config().channel_layout(),
293         ChannelLayoutToChannelCount(
294             stream->audio_decoder_config().channel_layout()),
295         hw_params.input_channels(),
296         hw_params.sample_rate(),
297         hw_params.bits_per_sample(),
298         hardware_config_->GetHighLatencyBufferSize());
299   }
300 
301   audio_clock_.reset(new AudioClock(audio_parameters_.sample_rate()));
302 
303   audio_buffer_stream_.Initialize(
304       stream,
305       false,
306       statistics_cb,
307       base::Bind(&AudioRendererImpl::OnAudioBufferStreamInitialized,
308                  weak_factory_.GetWeakPtr()));
309 }
310 
OnAudioBufferStreamInitialized(bool success)311 void AudioRendererImpl::OnAudioBufferStreamInitialized(bool success) {
312   DCHECK(task_runner_->BelongsToCurrentThread());
313 
314   base::AutoLock auto_lock(lock_);
315 
316   if (state_ == kStopped) {
317     base::ResetAndReturn(&init_cb_).Run(PIPELINE_ERROR_ABORT);
318     return;
319   }
320 
321   if (!success) {
322     state_ = kUninitialized;
323     base::ResetAndReturn(&init_cb_).Run(DECODER_ERROR_NOT_SUPPORTED);
324     return;
325   }
326 
327   if (!audio_parameters_.IsValid()) {
328     ChangeState_Locked(kUninitialized);
329     base::ResetAndReturn(&init_cb_).Run(PIPELINE_ERROR_INITIALIZATION_FAILED);
330     return;
331   }
332 
333   if (expecting_config_changes_)
334     buffer_converter_.reset(new AudioBufferConverter(audio_parameters_));
335   splicer_.reset(new AudioSplicer(audio_parameters_.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(kFlushed);
343 
344   HistogramRendererEvent(INITIALIZED);
345 
346   {
347     base::AutoUnlock auto_unlock(lock_);
348     sink_->Initialize(audio_parameters_, this);
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 
ResumeAfterUnderflow()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 
SetVolume(float volume)377 void AudioRendererImpl::SetVolume(float volume) {
378   DCHECK(task_runner_->BelongsToCurrentThread());
379   DCHECK(sink_);
380   sink_->SetVolume(volume);
381 }
382 
DecodedAudioReady(AudioBufferStream::Status status,const scoped_refptr<AudioBuffer> & buffer)383 void AudioRendererImpl::DecodedAudioReady(
384     AudioBufferStream::Status status,
385     const scoped_refptr<AudioBuffer>& buffer) {
386   DVLOG(2) << __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 == AudioBufferStream::ABORTED ||
396       status == AudioBufferStream::DEMUXER_READ_ABORTED) {
397     HandleAbortedReadOrDecodeError(false);
398     return;
399   }
400 
401   if (status == AudioBufferStream::DECODE_ERROR) {
402     HandleAbortedReadOrDecodeError(true);
403     return;
404   }
405 
406   DCHECK_EQ(status, AudioBufferStream::OK);
407   DCHECK(buffer.get());
408 
409   if (state_ == kFlushing) {
410     ChangeState_Locked(kFlushed);
411     DoFlush_Locked();
412     return;
413   }
414 
415   if (expecting_config_changes_) {
416     DCHECK(buffer_converter_);
417     buffer_converter_->AddInput(buffer);
418     while (buffer_converter_->HasNextBuffer()) {
419       if (!splicer_->AddInput(buffer_converter_->GetNextBuffer())) {
420         HandleAbortedReadOrDecodeError(true);
421         return;
422       }
423     }
424   } else {
425     if (!splicer_->AddInput(buffer)) {
426       HandleAbortedReadOrDecodeError(true);
427       return;
428     }
429   }
430 
431   if (!splicer_->HasNextBuffer()) {
432     AttemptRead_Locked();
433     return;
434   }
435 
436   bool need_another_buffer = false;
437   while (splicer_->HasNextBuffer())
438     need_another_buffer = HandleSplicerBuffer(splicer_->GetNextBuffer());
439 
440   if (!need_another_buffer && !CanRead_Locked())
441     return;
442 
443   AttemptRead_Locked();
444 }
445 
HandleSplicerBuffer(const scoped_refptr<AudioBuffer> & buffer)446 bool AudioRendererImpl::HandleSplicerBuffer(
447     const scoped_refptr<AudioBuffer>& buffer) {
448   if (buffer->end_of_stream()) {
449     received_end_of_stream_ = true;
450 
451     // Transition to kPlaying if we are currently handling an underflow since
452     // no more data will be arriving.
453     if (state_ == kUnderflow || state_ == kRebuffering)
454       ChangeState_Locked(kPlaying);
455   } else {
456     if (state_ == kPrerolling) {
457       if (IsBeforePrerollTime(buffer))
458         return true;
459 
460       // Trim off any additional time before the preroll timestamp.
461       const base::TimeDelta trim_time =
462           preroll_timestamp_ - buffer->timestamp();
463       if (trim_time > base::TimeDelta()) {
464         buffer->TrimStart(buffer->frame_count() *
465                           (static_cast<double>(trim_time.InMicroseconds()) /
466                            buffer->duration().InMicroseconds()));
467       }
468       // If the entire buffer was trimmed, request a new one.
469       if (!buffer->frame_count())
470         return true;
471     }
472 
473     if (state_ != kUninitialized && state_ != kStopped)
474       algorithm_->EnqueueBuffer(buffer);
475   }
476 
477   switch (state_) {
478     case kUninitialized:
479     case kInitializing:
480     case kFlushing:
481       NOTREACHED();
482       return false;
483 
484     case kFlushed:
485       DCHECK(!pending_read_);
486       return false;
487 
488     case kPrerolling:
489       if (!buffer->end_of_stream() && !algorithm_->IsQueueFull())
490         return true;
491       ChangeState_Locked(kPlaying);
492       base::ResetAndReturn(&preroll_cb_).Run(PIPELINE_OK);
493       return false;
494 
495     case kPlaying:
496     case kUnderflow:
497       return false;
498 
499     case kRebuffering:
500       if (!algorithm_->IsQueueFull())
501         return true;
502       ChangeState_Locked(kPlaying);
503       return false;
504 
505     case kStopped:
506       return false;
507   }
508   return false;
509 }
510 
AttemptRead()511 void AudioRendererImpl::AttemptRead() {
512   base::AutoLock auto_lock(lock_);
513   AttemptRead_Locked();
514 }
515 
AttemptRead_Locked()516 void AudioRendererImpl::AttemptRead_Locked() {
517   DCHECK(task_runner_->BelongsToCurrentThread());
518   lock_.AssertAcquired();
519 
520   if (!CanRead_Locked())
521     return;
522 
523   pending_read_ = true;
524   audio_buffer_stream_.Read(base::Bind(&AudioRendererImpl::DecodedAudioReady,
525                                        weak_factory_.GetWeakPtr()));
526 }
527 
CanRead_Locked()528 bool AudioRendererImpl::CanRead_Locked() {
529   lock_.AssertAcquired();
530 
531   switch (state_) {
532     case kUninitialized:
533     case kInitializing:
534     case kFlushed:
535     case kFlushing:
536     case kStopped:
537       return false;
538 
539     case kPrerolling:
540     case kPlaying:
541     case kUnderflow:
542     case kRebuffering:
543       break;
544   }
545 
546   return !pending_read_ && !received_end_of_stream_ &&
547       !algorithm_->IsQueueFull();
548 }
549 
SetPlaybackRate(float playback_rate)550 void AudioRendererImpl::SetPlaybackRate(float playback_rate) {
551   DVLOG(1) << __FUNCTION__ << "(" << playback_rate << ")";
552   DCHECK(task_runner_->BelongsToCurrentThread());
553   DCHECK_GE(playback_rate, 0);
554   DCHECK(sink_);
555 
556   base::AutoLock auto_lock(lock_);
557 
558   // We have two cases here:
559   // Play: current_playback_rate == 0 && playback_rate != 0
560   // Pause: current_playback_rate != 0 && playback_rate == 0
561   float current_playback_rate = algorithm_->playback_rate();
562   algorithm_->SetPlaybackRate(playback_rate);
563 
564   if (!rendering_)
565     return;
566 
567   if (current_playback_rate == 0 && playback_rate != 0) {
568     StartRendering_Locked();
569     return;
570   }
571 
572   if (current_playback_rate != 0 && playback_rate == 0) {
573     StopRendering_Locked();
574     return;
575   }
576 }
577 
IsBeforePrerollTime(const scoped_refptr<AudioBuffer> & buffer)578 bool AudioRendererImpl::IsBeforePrerollTime(
579     const scoped_refptr<AudioBuffer>& buffer) {
580   DCHECK_EQ(state_, kPrerolling);
581   return buffer && !buffer->end_of_stream() &&
582          (buffer->timestamp() + buffer->duration()) < preroll_timestamp_;
583 }
584 
Render(AudioBus * audio_bus,int audio_delay_milliseconds)585 int AudioRendererImpl::Render(AudioBus* audio_bus,
586                               int audio_delay_milliseconds) {
587   const int requested_frames = audio_bus->frames();
588   base::TimeDelta playback_delay = base::TimeDelta::FromMilliseconds(
589       audio_delay_milliseconds);
590   const int delay_frames = static_cast<int>(playback_delay.InSecondsF() *
591                                             audio_parameters_.sample_rate());
592   int frames_written = 0;
593   base::Closure time_cb;
594   base::Closure underflow_cb;
595   {
596     base::AutoLock auto_lock(lock_);
597 
598     // Ensure Stop() hasn't destroyed our |algorithm_| on the pipeline thread.
599     if (!algorithm_) {
600       audio_clock_->WroteSilence(requested_frames, delay_frames);
601       return 0;
602     }
603 
604     float playback_rate = algorithm_->playback_rate();
605     if (playback_rate == 0) {
606       audio_clock_->WroteSilence(requested_frames, delay_frames);
607       return 0;
608     }
609 
610     // Mute audio by returning 0 when not playing.
611     if (state_ != kPlaying) {
612       audio_clock_->WroteSilence(requested_frames, delay_frames);
613       return 0;
614     }
615 
616     // We use the following conditions to determine end of playback:
617     //   1) Algorithm can not fill the audio callback buffer
618     //   2) We received an end of stream buffer
619     //   3) We haven't already signalled that we've ended
620     //   4) Our estimated earliest end time has expired
621     //
622     // TODO(enal): we should replace (4) with a check that the browser has no
623     // more audio data or at least use a delayed callback.
624     //
625     // We use the following conditions to determine underflow:
626     //   1) Algorithm can not fill the audio callback buffer
627     //   2) We have NOT received an end of stream buffer
628     //   3) We are in the kPlaying state
629     //
630     // Otherwise the buffer has data we can send to the device.
631     const base::TimeDelta media_timestamp_before_filling =
632         audio_clock_->CurrentMediaTimestamp();
633     if (algorithm_->frames_buffered() > 0) {
634       frames_written = algorithm_->FillBuffer(audio_bus, requested_frames);
635       audio_clock_->WroteAudio(
636           frames_written, delay_frames, playback_rate, algorithm_->GetTime());
637     }
638     audio_clock_->WroteSilence(requested_frames - frames_written, delay_frames);
639 
640     if (frames_written == 0) {
641       const base::TimeTicks now = now_cb_.Run();
642 
643       if (received_end_of_stream_ && !rendered_end_of_stream_ &&
644           now >= earliest_end_time_) {
645         rendered_end_of_stream_ = true;
646         ended_cb_.Run();
647       } else if (!received_end_of_stream_ && state_ == kPlaying) {
648         ChangeState_Locked(kUnderflow);
649         underflow_cb = underflow_cb_;
650       } else {
651         // We can't write any data this cycle. For example, we may have
652         // sent all available data to the audio device while not reaching
653         // |earliest_end_time_|.
654       }
655     }
656 
657     if (CanRead_Locked()) {
658       task_runner_->PostTask(FROM_HERE,
659                              base::Bind(&AudioRendererImpl::AttemptRead,
660                                         weak_factory_.GetWeakPtr()));
661     }
662 
663     // We only want to execute |time_cb_| if time has progressed and we haven't
664     // signaled end of stream yet.
665     if (media_timestamp_before_filling !=
666             audio_clock_->CurrentMediaTimestamp() &&
667         !rendered_end_of_stream_) {
668       time_cb = base::Bind(time_cb_,
669                            audio_clock_->CurrentMediaTimestamp(),
670                            audio_clock_->last_endpoint_timestamp());
671     }
672 
673     if (frames_written > 0) {
674       UpdateEarliestEndTime_Locked(
675           frames_written, playback_delay, now_cb_.Run());
676     }
677   }
678 
679   if (!time_cb.is_null())
680     task_runner_->PostTask(FROM_HERE, time_cb);
681 
682   if (!underflow_cb.is_null())
683     underflow_cb.Run();
684 
685   DCHECK_LE(frames_written, requested_frames);
686   return frames_written;
687 }
688 
UpdateEarliestEndTime_Locked(int frames_filled,const base::TimeDelta & playback_delay,const base::TimeTicks & time_now)689 void AudioRendererImpl::UpdateEarliestEndTime_Locked(
690     int frames_filled, const base::TimeDelta& playback_delay,
691     const base::TimeTicks& time_now) {
692   DCHECK_GT(frames_filled, 0);
693 
694   base::TimeDelta predicted_play_time = base::TimeDelta::FromMicroseconds(
695       static_cast<float>(frames_filled) * base::Time::kMicrosecondsPerSecond /
696       audio_parameters_.sample_rate());
697 
698   lock_.AssertAcquired();
699   earliest_end_time_ = std::max(
700       earliest_end_time_, time_now + playback_delay + predicted_play_time);
701 }
702 
OnRenderError()703 void AudioRendererImpl::OnRenderError() {
704   // UMA data tells us this happens ~0.01% of the time. Trigger an error instead
705   // of trying to gracefully fall back to a fake sink. It's very likely
706   // OnRenderError() should be removed and the audio stack handle errors without
707   // notifying clients. See http://crbug.com/234708 for details.
708   HistogramRendererEvent(RENDER_ERROR);
709   error_cb_.Run(PIPELINE_ERROR_DECODE);
710 }
711 
HandleAbortedReadOrDecodeError(bool is_decode_error)712 void AudioRendererImpl::HandleAbortedReadOrDecodeError(bool is_decode_error) {
713   lock_.AssertAcquired();
714 
715   PipelineStatus status = is_decode_error ? PIPELINE_ERROR_DECODE : PIPELINE_OK;
716   switch (state_) {
717     case kUninitialized:
718     case kInitializing:
719       NOTREACHED();
720       return;
721     case kFlushing:
722       ChangeState_Locked(kFlushed);
723 
724       if (status == PIPELINE_OK) {
725         DoFlush_Locked();
726         return;
727       }
728 
729       error_cb_.Run(status);
730       base::ResetAndReturn(&flush_cb_).Run();
731       return;
732     case kPrerolling:
733       // This is a signal for abort if it's not an error.
734       preroll_aborted_ = !is_decode_error;
735       ChangeState_Locked(kPlaying);
736       base::ResetAndReturn(&preroll_cb_).Run(status);
737       return;
738     case kFlushed:
739     case kPlaying:
740     case kUnderflow:
741     case kRebuffering:
742     case kStopped:
743       if (status != PIPELINE_OK)
744         error_cb_.Run(status);
745       return;
746   }
747 }
748 
ChangeState_Locked(State new_state)749 void AudioRendererImpl::ChangeState_Locked(State new_state) {
750   DVLOG(1) << __FUNCTION__ << " : " << state_ << " -> " << new_state;
751   lock_.AssertAcquired();
752   state_ = new_state;
753 }
754 
OnNewSpliceBuffer(base::TimeDelta splice_timestamp)755 void AudioRendererImpl::OnNewSpliceBuffer(base::TimeDelta splice_timestamp) {
756   DCHECK(task_runner_->BelongsToCurrentThread());
757   splicer_->SetSpliceTimestamp(splice_timestamp);
758 }
759 
OnConfigChange()760 void AudioRendererImpl::OnConfigChange() {
761   DCHECK(task_runner_->BelongsToCurrentThread());
762   DCHECK(expecting_config_changes_);
763   buffer_converter_->ResetTimestampState();
764   // Drain flushed buffers from the converter so the AudioSplicer receives all
765   // data ahead of any OnNewSpliceBuffer() calls.  Since discontinuities should
766   // only appear after config changes, AddInput() should never fail here.
767   while (buffer_converter_->HasNextBuffer())
768     CHECK(splicer_->AddInput(buffer_converter_->GetNextBuffer()));
769 }
770 
771 }  // namespace media
772