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