Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(127)

Side by Side Diff: media/filters/audio_renderer_impl.cc

Issue 284763002: Update AudioRenderer API to fire changes in BufferingState. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Created 6 years, 7 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. 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 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "media/filters/audio_renderer_impl.h" 5 #include "media/filters/audio_renderer_impl.h"
6 6
7 #include <math.h> 7 #include <math.h>
8 8
9 #include <algorithm> 9 #include <algorithm>
10 10
(...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after
45 media::AudioRendererSink* sink, 45 media::AudioRendererSink* sink,
46 ScopedVector<AudioDecoder> decoders, 46 ScopedVector<AudioDecoder> decoders,
47 const SetDecryptorReadyCB& set_decryptor_ready_cb, 47 const SetDecryptorReadyCB& set_decryptor_ready_cb,
48 AudioHardwareConfig* hardware_config) 48 AudioHardwareConfig* hardware_config)
49 : task_runner_(task_runner), 49 : task_runner_(task_runner),
50 sink_(sink), 50 sink_(sink),
51 audio_buffer_stream_(task_runner, 51 audio_buffer_stream_(task_runner,
52 decoders.Pass(), 52 decoders.Pass(),
53 set_decryptor_ready_cb), 53 set_decryptor_ready_cb),
54 hardware_config_(hardware_config), 54 hardware_config_(hardware_config),
55 buffering_state_(BUFFERING_HAVE_NOTHING),
55 now_cb_(base::Bind(&base::TimeTicks::Now)), 56 now_cb_(base::Bind(&base::TimeTicks::Now)),
56 state_(kUninitialized), 57 state_(kUninitialized),
57 rendering_(false), 58 rendering_(false),
58 sink_playing_(false), 59 sink_playing_(false),
59 pending_read_(false), 60 pending_read_(false),
60 received_end_of_stream_(false), 61 received_end_of_stream_(false),
61 rendered_end_of_stream_(false), 62 rendered_end_of_stream_(false),
62 underflow_disabled_(false),
63 preroll_aborted_(false),
64 weak_factory_(this) { 63 weak_factory_(this) {
65 audio_buffer_stream_.set_splice_observer(base::Bind( 64 audio_buffer_stream_.set_splice_observer(base::Bind(
66 &AudioRendererImpl::OnNewSpliceBuffer, weak_factory_.GetWeakPtr())); 65 &AudioRendererImpl::OnNewSpliceBuffer, weak_factory_.GetWeakPtr()));
67 audio_buffer_stream_.set_config_change_observer(base::Bind( 66 audio_buffer_stream_.set_config_change_observer(base::Bind(
68 &AudioRendererImpl::OnConfigChange, weak_factory_.GetWeakPtr())); 67 &AudioRendererImpl::OnConfigChange, weak_factory_.GetWeakPtr()));
69 } 68 }
70 69
71 AudioRendererImpl::~AudioRendererImpl() { 70 AudioRendererImpl::~AudioRendererImpl() {
72 // Stop() should have been called and |algorithm_| should have been destroyed. 71 // Stop() should have been called and |algorithm_| should have been destroyed.
73 DCHECK(state_ == kUninitialized || state_ == kStopped); 72 DCHECK(state_ == kUninitialized || state_ == kStopped);
(...skipping 12 matching lines...) Expand all
86 DCHECK(!sink_playing_); 85 DCHECK(!sink_playing_);
87 return; 86 return;
88 } 87 }
89 88
90 StartRendering_Locked(); 89 StartRendering_Locked();
91 } 90 }
92 91
93 void AudioRendererImpl::StartRendering_Locked() { 92 void AudioRendererImpl::StartRendering_Locked() {
94 DVLOG(1) << __FUNCTION__; 93 DVLOG(1) << __FUNCTION__;
95 DCHECK(task_runner_->BelongsToCurrentThread()); 94 DCHECK(task_runner_->BelongsToCurrentThread());
96 DCHECK(state_ == kPlaying || state_ == kRebuffering || state_ == kUnderflow) 95 DCHECK_EQ(state_, kPlaying);
97 << "state_=" << state_;
98 DCHECK(!sink_playing_); 96 DCHECK(!sink_playing_);
99 DCHECK_NE(algorithm_->playback_rate(), 0); 97 DCHECK_NE(algorithm_->playback_rate(), 0);
100 lock_.AssertAcquired(); 98 lock_.AssertAcquired();
101 99
102 earliest_end_time_ = now_cb_.Run(); 100 earliest_end_time_ = now_cb_.Run();
103 sink_playing_ = true; 101 sink_playing_ = true;
104 102
105 base::AutoUnlock auto_unlock(lock_); 103 base::AutoUnlock auto_unlock(lock_);
106 sink_->Play(); 104 sink_->Play();
107 } 105 }
108 106
109 void AudioRendererImpl::StopRendering() { 107 void AudioRendererImpl::StopRendering() {
110 DVLOG(1) << __FUNCTION__; 108 DVLOG(1) << __FUNCTION__;
111 DCHECK(task_runner_->BelongsToCurrentThread()); 109 DCHECK(task_runner_->BelongsToCurrentThread());
112 DCHECK(rendering_); 110 DCHECK(rendering_);
113 rendering_ = false; 111 rendering_ = false;
114 112
115 base::AutoLock auto_lock(lock_); 113 base::AutoLock auto_lock(lock_);
116 // Rendering should have already been stopped with a zero playback rate. 114 // Rendering should have already been stopped with a zero playback rate.
117 if (algorithm_->playback_rate() == 0) { 115 if (algorithm_->playback_rate() == 0) {
118 DCHECK(!sink_playing_); 116 DCHECK(!sink_playing_);
119 return; 117 return;
120 } 118 }
121 119
122 StopRendering_Locked(); 120 StopRendering_Locked();
123 } 121 }
124 122
125 void AudioRendererImpl::StopRendering_Locked() { 123 void AudioRendererImpl::StopRendering_Locked() {
126 DCHECK(task_runner_->BelongsToCurrentThread()); 124 DCHECK(task_runner_->BelongsToCurrentThread());
127 DCHECK(state_ == kPlaying || state_ == kRebuffering || state_ == kUnderflow) 125 DCHECK_EQ(state_, kPlaying);
128 << "state_=" << state_;
129 DCHECK(sink_playing_); 126 DCHECK(sink_playing_);
130 lock_.AssertAcquired(); 127 lock_.AssertAcquired();
131 128
132 sink_playing_ = false; 129 sink_playing_ = false;
133 130
134 base::AutoUnlock auto_unlock(lock_); 131 base::AutoUnlock auto_unlock(lock_);
135 sink_->Pause(); 132 sink_->Pause();
136 } 133 }
137 134
138 void AudioRendererImpl::Flush(const base::Closure& callback) { 135 void AudioRendererImpl::Flush(const base::Closure& callback) {
136 DVLOG(1) << __FUNCTION__;
139 DCHECK(task_runner_->BelongsToCurrentThread()); 137 DCHECK(task_runner_->BelongsToCurrentThread());
140 138
141 base::AutoLock auto_lock(lock_); 139 base::AutoLock auto_lock(lock_);
142 DCHECK_EQ(state_, kPlaying); 140 DCHECK_EQ(state_, kPlaying);
143 DCHECK(flush_cb_.is_null()); 141 DCHECK(flush_cb_.is_null());
144 142
145 flush_cb_ = callback; 143 flush_cb_ = callback;
144 ChangeState_Locked(kFlushing);
146 145
147 if (pending_read_) { 146 if (pending_read_)
148 ChangeState_Locked(kFlushing);
149 return; 147 return;
150 }
151 148
152 ChangeState_Locked(kFlushed); 149 ChangeState_Locked(kFlushed);
153 DoFlush_Locked(); 150 DoFlush_Locked();
154 } 151 }
155 152
156 void AudioRendererImpl::DoFlush_Locked() { 153 void AudioRendererImpl::DoFlush_Locked() {
157 DCHECK(task_runner_->BelongsToCurrentThread()); 154 DCHECK(task_runner_->BelongsToCurrentThread());
158 lock_.AssertAcquired(); 155 lock_.AssertAcquired();
159 156
160 DCHECK(!pending_read_); 157 DCHECK(!pending_read_);
161 DCHECK_EQ(state_, kFlushed); 158 DCHECK_EQ(state_, kFlushed);
162 159
163 audio_buffer_stream_.Reset(base::Bind(&AudioRendererImpl::ResetDecoderDone, 160 audio_buffer_stream_.Reset(base::Bind(&AudioRendererImpl::ResetDecoderDone,
164 weak_factory_.GetWeakPtr())); 161 weak_factory_.GetWeakPtr()));
165 } 162 }
166 163
167 void AudioRendererImpl::ResetDecoderDone() { 164 void AudioRendererImpl::ResetDecoderDone() {
168 DCHECK(task_runner_->BelongsToCurrentThread()); 165 DCHECK(task_runner_->BelongsToCurrentThread());
169 { 166 {
170 base::AutoLock auto_lock(lock_); 167 base::AutoLock auto_lock(lock_);
171 if (state_ == kStopped) 168 if (state_ == kStopped)
172 return; 169 return;
173 170
174 DCHECK_EQ(state_, kFlushed); 171 DCHECK_EQ(state_, kFlushed);
175 DCHECK(!flush_cb_.is_null()); 172 DCHECK(!flush_cb_.is_null());
176 173
177 audio_clock_.reset(new AudioClock(audio_parameters_.sample_rate())); 174 audio_clock_.reset(new AudioClock(audio_parameters_.sample_rate()));
175 buffering_state_ = BUFFERING_HAVE_NOTHING;
178 received_end_of_stream_ = false; 176 received_end_of_stream_ = false;
179 rendered_end_of_stream_ = false; 177 rendered_end_of_stream_ = false;
180 preroll_aborted_ = false;
181 178
182 earliest_end_time_ = now_cb_.Run(); 179 earliest_end_time_ = now_cb_.Run();
183 splicer_->Reset(); 180 splicer_->Reset();
184 if (buffer_converter_) 181 if (buffer_converter_)
185 buffer_converter_->Reset(); 182 buffer_converter_->Reset();
186 algorithm_->FlushBuffers(); 183 algorithm_->FlushBuffers();
184
185 ChangeState_Locked(kFlushed);
acolwell GONE FROM CHROMIUM 2014/05/13 20:44:27 Why do we need this? The DCHECK on line 171 indica
scherkus (not reviewing) 2014/05/15 23:28:43 Done.
187 } 186 }
188 base::ResetAndReturn(&flush_cb_).Run(); 187 base::ResetAndReturn(&flush_cb_).Run();
189 } 188 }
190 189
191 void AudioRendererImpl::Stop(const base::Closure& callback) { 190 void AudioRendererImpl::Stop(const base::Closure& callback) {
192 DCHECK(task_runner_->BelongsToCurrentThread()); 191 DCHECK(task_runner_->BelongsToCurrentThread());
193 DCHECK(!callback.is_null()); 192 DCHECK(!callback.is_null());
194 193
195 // TODO(scherkus): Consider invalidating |weak_factory_| and replacing 194 // TODO(scherkus): Consider invalidating |weak_factory_| and replacing
196 // task-running guards that check |state_| with DCHECK(). 195 // task-running guards that check |state_| with DCHECK().
197 196
198 { 197 {
199 base::AutoLock auto_lock(lock_); 198 base::AutoLock auto_lock(lock_);
200 199
201 if (state_ == kStopped) { 200 if (state_ == kStopped) {
202 task_runner_->PostTask(FROM_HERE, callback); 201 task_runner_->PostTask(FROM_HERE, callback);
203 return; 202 return;
204 } 203 }
205 204
206 ChangeState_Locked(kStopped); 205 ChangeState_Locked(kStopped);
207 algorithm_.reset(); 206 algorithm_.reset();
208 underflow_cb_.Reset();
209 time_cb_.Reset(); 207 time_cb_.Reset();
210 flush_cb_.Reset(); 208 flush_cb_.Reset();
211 } 209 }
212 210
213 if (sink_) { 211 if (sink_) {
214 sink_->Stop(); 212 sink_->Stop();
215 sink_ = NULL; 213 sink_ = NULL;
216 } 214 }
217 215
218 audio_buffer_stream_.Stop(callback); 216 audio_buffer_stream_.Stop(callback);
219 } 217 }
220 218
221 void AudioRendererImpl::Preroll(base::TimeDelta time, 219 void AudioRendererImpl::StartPlayingFrom(base::TimeDelta timestamp) {
222 const PipelineStatusCB& cb) { 220 DVLOG(1) << __FUNCTION__ << "(" << timestamp.InMicroseconds() << ")";
223 DCHECK(task_runner_->BelongsToCurrentThread()); 221 DCHECK(task_runner_->BelongsToCurrentThread());
224 222
225 base::AutoLock auto_lock(lock_); 223 base::AutoLock auto_lock(lock_);
226 DCHECK(!sink_playing_); 224 DCHECK(!sink_playing_);
227 DCHECK_EQ(state_, kFlushed); 225 DCHECK_EQ(state_, kFlushed);
226 DCHECK_EQ(buffering_state_, BUFFERING_HAVE_NOTHING);
228 DCHECK(!pending_read_) << "Pending read must complete before seeking"; 227 DCHECK(!pending_read_) << "Pending read must complete before seeking";
229 DCHECK(preroll_cb_.is_null());
230 228
231 ChangeState_Locked(kPrerolling); 229 ChangeState_Locked(kPlaying);
232 preroll_cb_ = cb; 230 start_timestamp_ = timestamp;
233 preroll_timestamp_ = time;
234 231
235 AttemptRead_Locked(); 232 AttemptRead_Locked();
236 } 233 }
237 234
238 void AudioRendererImpl::Initialize(DemuxerStream* stream, 235 void AudioRendererImpl::Initialize(DemuxerStream* stream,
239 const PipelineStatusCB& init_cb, 236 const PipelineStatusCB& init_cb,
240 const StatisticsCB& statistics_cb, 237 const StatisticsCB& statistics_cb,
241 const base::Closure& underflow_cb,
242 const TimeCB& time_cb, 238 const TimeCB& time_cb,
239 const BufferingStateCB& buffering_state_cb,
243 const base::Closure& ended_cb, 240 const base::Closure& ended_cb,
244 const PipelineStatusCB& error_cb) { 241 const PipelineStatusCB& error_cb) {
245 DCHECK(task_runner_->BelongsToCurrentThread()); 242 DCHECK(task_runner_->BelongsToCurrentThread());
246 DCHECK(stream); 243 DCHECK(stream);
247 DCHECK_EQ(stream->type(), DemuxerStream::AUDIO); 244 DCHECK_EQ(stream->type(), DemuxerStream::AUDIO);
248 DCHECK(!init_cb.is_null()); 245 DCHECK(!init_cb.is_null());
249 DCHECK(!statistics_cb.is_null()); 246 DCHECK(!statistics_cb.is_null());
250 DCHECK(!underflow_cb.is_null());
251 DCHECK(!time_cb.is_null()); 247 DCHECK(!time_cb.is_null());
248 DCHECK(!buffering_state_cb.is_null());
252 DCHECK(!ended_cb.is_null()); 249 DCHECK(!ended_cb.is_null());
253 DCHECK(!error_cb.is_null()); 250 DCHECK(!error_cb.is_null());
254 DCHECK_EQ(kUninitialized, state_); 251 DCHECK_EQ(kUninitialized, state_);
255 DCHECK(sink_); 252 DCHECK(sink_);
256 253
257 state_ = kInitializing; 254 state_ = kInitializing;
258 255
259 init_cb_ = init_cb; 256 init_cb_ = init_cb;
260 underflow_cb_ = underflow_cb;
261 time_cb_ = time_cb; 257 time_cb_ = time_cb;
258 buffering_state_cb_ = buffering_state_cb;
262 ended_cb_ = ended_cb; 259 ended_cb_ = ended_cb;
263 error_cb_ = error_cb; 260 error_cb_ = error_cb;
264 261
265 expecting_config_changes_ = stream->SupportsConfigChanges(); 262 expecting_config_changes_ = stream->SupportsConfigChanges();
266 if (!expecting_config_changes_) { 263 if (!expecting_config_changes_) {
267 // The actual buffer size is controlled via the size of the AudioBus 264 // The actual buffer size is controlled via the size of the AudioBus
268 // provided to Render(), so just choose something reasonable here for looks. 265 // provided to Render(), so just choose something reasonable here for looks.
269 int buffer_size = stream->audio_decoder_config().samples_per_second() / 100; 266 int buffer_size = stream->audio_decoder_config().samples_per_second() / 100;
270 audio_parameters_.Reset( 267 audio_parameters_.Reset(
271 AudioParameters::AUDIO_PCM_LOW_LATENCY, 268 AudioParameters::AUDIO_PCM_LOW_LATENCY,
(...skipping 69 matching lines...) Expand 10 before | Expand all | Expand 10 after
341 338
342 // Some sinks play on start... 339 // Some sinks play on start...
343 sink_->Pause(); 340 sink_->Pause();
344 } 341 }
345 342
346 DCHECK(!sink_playing_); 343 DCHECK(!sink_playing_);
347 344
348 base::ResetAndReturn(&init_cb_).Run(PIPELINE_OK); 345 base::ResetAndReturn(&init_cb_).Run(PIPELINE_OK);
349 } 346 }
350 347
351 void AudioRendererImpl::ResumeAfterUnderflow() {
352 DCHECK(task_runner_->BelongsToCurrentThread());
353 base::AutoLock auto_lock(lock_);
354 if (state_ == kUnderflow) {
355 // The "!preroll_aborted_" is a hack. If preroll is aborted, then we
356 // shouldn't even reach the kUnderflow state to begin with. But for now
357 // we're just making sure that the audio buffer capacity (i.e. the
358 // number of bytes that need to be buffered for preroll to complete)
359 // does not increase due to an aborted preroll.
360 // TODO(vrk): Fix this bug correctly! (crbug.com/151352)
361 if (!preroll_aborted_)
362 algorithm_->IncreaseQueueCapacity();
363
364 ChangeState_Locked(kRebuffering);
365 }
366 }
367
368 void AudioRendererImpl::SetVolume(float volume) { 348 void AudioRendererImpl::SetVolume(float volume) {
369 DCHECK(task_runner_->BelongsToCurrentThread()); 349 DCHECK(task_runner_->BelongsToCurrentThread());
370 DCHECK(sink_); 350 DCHECK(sink_);
371 sink_->SetVolume(volume); 351 sink_->SetVolume(volume);
372 } 352 }
373 353
374 void AudioRendererImpl::DecodedAudioReady( 354 void AudioRendererImpl::DecodedAudioReady(
375 AudioBufferStream::Status status, 355 AudioBufferStream::Status status,
376 const scoped_refptr<AudioBuffer>& buffer) { 356 const scoped_refptr<AudioBuffer>& buffer) {
377 DVLOG(2) << __FUNCTION__ << "(" << status << ")"; 357 DVLOG(2) << __FUNCTION__ << "(" << status << ")";
(...skipping 53 matching lines...) Expand 10 before | Expand all | Expand 10 after
431 if (!need_another_buffer && !CanRead_Locked()) 411 if (!need_another_buffer && !CanRead_Locked())
432 return; 412 return;
433 413
434 AttemptRead_Locked(); 414 AttemptRead_Locked();
435 } 415 }
436 416
437 bool AudioRendererImpl::HandleSplicerBuffer( 417 bool AudioRendererImpl::HandleSplicerBuffer(
438 const scoped_refptr<AudioBuffer>& buffer) { 418 const scoped_refptr<AudioBuffer>& buffer) {
439 if (buffer->end_of_stream()) { 419 if (buffer->end_of_stream()) {
440 received_end_of_stream_ = true; 420 received_end_of_stream_ = true;
441
442 // Transition to kPlaying if we are currently handling an underflow since
443 // no more data will be arriving.
444 if (state_ == kUnderflow || state_ == kRebuffering)
445 ChangeState_Locked(kPlaying);
446 } else { 421 } else {
447 if (state_ == kPrerolling) { 422 if (state_ == kPlaying) {
448 if (IsBeforePrerollTime(buffer)) 423 if (IsBeforeStartTime(buffer))
449 return true; 424 return true;
450 425
451 // Trim off any additional time before the preroll timestamp. 426 // Trim off any additional time before the start timestamp.
452 const base::TimeDelta trim_time = 427 const base::TimeDelta trim_time = start_timestamp_ - buffer->timestamp();
453 preroll_timestamp_ - buffer->timestamp();
454 if (trim_time > base::TimeDelta()) { 428 if (trim_time > base::TimeDelta()) {
455 buffer->TrimStart(buffer->frame_count() * 429 buffer->TrimStart(buffer->frame_count() *
456 (static_cast<double>(trim_time.InMicroseconds()) / 430 (static_cast<double>(trim_time.InMicroseconds()) /
457 buffer->duration().InMicroseconds())); 431 buffer->duration().InMicroseconds()));
458 } 432 }
459 // If the entire buffer was trimmed, request a new one. 433 // If the entire buffer was trimmed, request a new one.
460 if (!buffer->frame_count()) 434 if (!buffer->frame_count())
461 return true; 435 return true;
462 } 436 }
463 437
464 if (state_ != kUninitialized && state_ != kStopped) 438 if (state_ != kUninitialized && state_ != kStopped)
465 algorithm_->EnqueueBuffer(buffer); 439 algorithm_->EnqueueBuffer(buffer);
466 } 440 }
467 441
468 switch (state_) { 442 switch (state_) {
469 case kUninitialized: 443 case kUninitialized:
470 case kInitializing: 444 case kInitializing:
471 case kFlushing: 445 case kFlushing:
472 NOTREACHED(); 446 NOTREACHED();
473 return false; 447 return false;
474 448
475 case kFlushed: 449 case kFlushed:
476 DCHECK(!pending_read_); 450 DCHECK(!pending_read_);
477 return false; 451 return false;
478 452
479 case kPrerolling:
480 if (!buffer->end_of_stream() && !algorithm_->IsQueueFull())
481 return true;
482 ChangeState_Locked(kPlaying);
483 base::ResetAndReturn(&preroll_cb_).Run(PIPELINE_OK);
484 return false;
485
486 case kPlaying: 453 case kPlaying:
487 case kUnderflow: 454 if (buffer->end_of_stream() || algorithm_->IsQueueFull()) {
488 return false; 455 if (buffering_state_ == BUFFERING_HAVE_NOTHING) {
489 456 buffering_state_ = BUFFERING_HAVE_ENOUGH;
490 case kRebuffering: 457 buffering_state_cb_.Run(BUFFERING_HAVE_ENOUGH);
491 if (!algorithm_->IsQueueFull()) 458 }
492 return true; 459 return false;
493 ChangeState_Locked(kPlaying); 460 }
494 return false; 461 return true;
495 462
496 case kStopped: 463 case kStopped:
497 return false; 464 return false;
498 } 465 }
499 return false; 466 return false;
500 } 467 }
501 468
502 void AudioRendererImpl::AttemptRead() { 469 void AudioRendererImpl::AttemptRead() {
503 base::AutoLock auto_lock(lock_); 470 base::AutoLock auto_lock(lock_);
504 AttemptRead_Locked(); 471 AttemptRead_Locked();
(...skipping 10 matching lines...) Expand all
515 audio_buffer_stream_.Read(base::Bind(&AudioRendererImpl::DecodedAudioReady, 482 audio_buffer_stream_.Read(base::Bind(&AudioRendererImpl::DecodedAudioReady,
516 weak_factory_.GetWeakPtr())); 483 weak_factory_.GetWeakPtr()));
517 } 484 }
518 485
519 bool AudioRendererImpl::CanRead_Locked() { 486 bool AudioRendererImpl::CanRead_Locked() {
520 lock_.AssertAcquired(); 487 lock_.AssertAcquired();
521 488
522 switch (state_) { 489 switch (state_) {
523 case kUninitialized: 490 case kUninitialized:
524 case kInitializing: 491 case kInitializing:
492 case kFlushing:
525 case kFlushed: 493 case kFlushed:
526 case kFlushing:
527 case kStopped: 494 case kStopped:
528 return false; 495 return false;
529 496
530 case kPrerolling:
531 case kPlaying: 497 case kPlaying:
532 case kUnderflow:
533 case kRebuffering:
534 break; 498 break;
535 } 499 }
536 500
537 return !pending_read_ && !received_end_of_stream_ && 501 return !pending_read_ && !received_end_of_stream_ &&
538 !algorithm_->IsQueueFull(); 502 !algorithm_->IsQueueFull();
539 } 503 }
540 504
541 void AudioRendererImpl::SetPlaybackRate(float playback_rate) { 505 void AudioRendererImpl::SetPlaybackRate(float playback_rate) {
542 DVLOG(1) << __FUNCTION__ << "(" << playback_rate << ")"; 506 DVLOG(1) << __FUNCTION__ << "(" << playback_rate << ")";
543 DCHECK(task_runner_->BelongsToCurrentThread()); 507 DCHECK(task_runner_->BelongsToCurrentThread());
(...skipping 15 matching lines...) Expand all
559 StartRendering_Locked(); 523 StartRendering_Locked();
560 return; 524 return;
561 } 525 }
562 526
563 if (current_playback_rate != 0 && playback_rate == 0) { 527 if (current_playback_rate != 0 && playback_rate == 0) {
564 StopRendering_Locked(); 528 StopRendering_Locked();
565 return; 529 return;
566 } 530 }
567 } 531 }
568 532
569 bool AudioRendererImpl::IsBeforePrerollTime( 533 bool AudioRendererImpl::IsBeforeStartTime(
570 const scoped_refptr<AudioBuffer>& buffer) { 534 const scoped_refptr<AudioBuffer>& buffer) {
571 DCHECK_EQ(state_, kPrerolling); 535 DCHECK_EQ(state_, kPlaying);
572 return buffer && !buffer->end_of_stream() && 536 return buffer && !buffer->end_of_stream() &&
573 (buffer->timestamp() + buffer->duration()) < preroll_timestamp_; 537 (buffer->timestamp() + buffer->duration()) < start_timestamp_;
574 } 538 }
575 539
576 int AudioRendererImpl::Render(AudioBus* audio_bus, 540 int AudioRendererImpl::Render(AudioBus* audio_bus,
577 int audio_delay_milliseconds) { 541 int audio_delay_milliseconds) {
578 const int requested_frames = audio_bus->frames(); 542 const int requested_frames = audio_bus->frames();
579 base::TimeDelta playback_delay = base::TimeDelta::FromMilliseconds( 543 base::TimeDelta playback_delay = base::TimeDelta::FromMilliseconds(
580 audio_delay_milliseconds); 544 audio_delay_milliseconds);
581 const int delay_frames = static_cast<int>(playback_delay.InSecondsF() * 545 const int delay_frames = static_cast<int>(playback_delay.InSecondsF() *
582 audio_parameters_.sample_rate()); 546 audio_parameters_.sample_rate());
583 int frames_written = 0; 547 int frames_written = 0;
584 base::Closure time_cb; 548 base::Closure time_cb;
585 base::Closure underflow_cb;
586 { 549 {
587 base::AutoLock auto_lock(lock_); 550 base::AutoLock auto_lock(lock_);
588 551
589 // Ensure Stop() hasn't destroyed our |algorithm_| on the pipeline thread. 552 // Ensure Stop() hasn't destroyed our |algorithm_| on the pipeline thread.
590 if (!algorithm_) { 553 if (!algorithm_) {
591 audio_clock_->WroteSilence(requested_frames, delay_frames); 554 audio_clock_->WroteSilence(requested_frames, delay_frames);
592 return 0; 555 return 0;
593 } 556 }
594 557
595 float playback_rate = algorithm_->playback_rate(); 558 float playback_rate = algorithm_->playback_rate();
(...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after
628 } 591 }
629 audio_clock_->WroteSilence(requested_frames - frames_written, delay_frames); 592 audio_clock_->WroteSilence(requested_frames - frames_written, delay_frames);
630 593
631 if (frames_written == 0) { 594 if (frames_written == 0) {
632 const base::TimeTicks now = now_cb_.Run(); 595 const base::TimeTicks now = now_cb_.Run();
633 596
634 if (received_end_of_stream_ && !rendered_end_of_stream_ && 597 if (received_end_of_stream_ && !rendered_end_of_stream_ &&
635 now >= earliest_end_time_) { 598 now >= earliest_end_time_) {
636 rendered_end_of_stream_ = true; 599 rendered_end_of_stream_ = true;
637 ended_cb_.Run(); 600 ended_cb_.Run();
638 } else if (!received_end_of_stream_ && state_ == kPlaying && 601 } else if (!received_end_of_stream_ && state_ == kPlaying) {
639 !underflow_disabled_) { 602 if (buffering_state_ != BUFFERING_HAVE_NOTHING) {
640 ChangeState_Locked(kUnderflow); 603 algorithm_->IncreaseQueueCapacity();
641 underflow_cb = underflow_cb_; 604 buffering_state_ = BUFFERING_HAVE_NOTHING;
605 buffering_state_cb_.Run(BUFFERING_HAVE_NOTHING);
606 }
642 } else { 607 } else {
643 // We can't write any data this cycle. For example, we may have 608 // We can't write any data this cycle. For example, we may have
644 // sent all available data to the audio device while not reaching 609 // sent all available data to the audio device while not reaching
645 // |earliest_end_time_|. 610 // |earliest_end_time_|.
646 } 611 }
647 } 612 }
648 613
649 if (CanRead_Locked()) { 614 if (CanRead_Locked()) {
650 task_runner_->PostTask(FROM_HERE, 615 task_runner_->PostTask(FROM_HERE,
651 base::Bind(&AudioRendererImpl::AttemptRead, 616 base::Bind(&AudioRendererImpl::AttemptRead,
(...skipping 12 matching lines...) Expand all
664 629
665 if (frames_written > 0) { 630 if (frames_written > 0) {
666 UpdateEarliestEndTime_Locked( 631 UpdateEarliestEndTime_Locked(
667 frames_written, playback_delay, now_cb_.Run()); 632 frames_written, playback_delay, now_cb_.Run());
668 } 633 }
669 } 634 }
670 635
671 if (!time_cb.is_null()) 636 if (!time_cb.is_null())
672 time_cb.Run(); 637 time_cb.Run();
673 638
674 if (!underflow_cb.is_null())
675 underflow_cb.Run();
676
677 DCHECK_LE(frames_written, requested_frames); 639 DCHECK_LE(frames_written, requested_frames);
678 return frames_written; 640 return frames_written;
679 } 641 }
680 642
681 void AudioRendererImpl::UpdateEarliestEndTime_Locked( 643 void AudioRendererImpl::UpdateEarliestEndTime_Locked(
682 int frames_filled, const base::TimeDelta& playback_delay, 644 int frames_filled, const base::TimeDelta& playback_delay,
683 const base::TimeTicks& time_now) { 645 const base::TimeTicks& time_now) {
684 DCHECK_GT(frames_filled, 0); 646 DCHECK_GT(frames_filled, 0);
685 647
686 base::TimeDelta predicted_play_time = base::TimeDelta::FromMicroseconds( 648 base::TimeDelta predicted_play_time = base::TimeDelta::FromMicroseconds(
687 static_cast<float>(frames_filled) * base::Time::kMicrosecondsPerSecond / 649 static_cast<float>(frames_filled) * base::Time::kMicrosecondsPerSecond /
688 audio_parameters_.sample_rate()); 650 audio_parameters_.sample_rate());
689 651
690 lock_.AssertAcquired(); 652 lock_.AssertAcquired();
691 earliest_end_time_ = std::max( 653 earliest_end_time_ = std::max(
692 earliest_end_time_, time_now + playback_delay + predicted_play_time); 654 earliest_end_time_, time_now + playback_delay + predicted_play_time);
693 } 655 }
694 656
695 void AudioRendererImpl::OnRenderError() { 657 void AudioRendererImpl::OnRenderError() {
696 // UMA data tells us this happens ~0.01% of the time. Trigger an error instead 658 // UMA data tells us this happens ~0.01% of the time. Trigger an error instead
697 // of trying to gracefully fall back to a fake sink. It's very likely 659 // of trying to gracefully fall back to a fake sink. It's very likely
698 // OnRenderError() should be removed and the audio stack handle errors without 660 // OnRenderError() should be removed and the audio stack handle errors without
699 // notifying clients. See http://crbug.com/234708 for details. 661 // notifying clients. See http://crbug.com/234708 for details.
700 HistogramRendererEvent(RENDER_ERROR); 662 HistogramRendererEvent(RENDER_ERROR);
701 error_cb_.Run(PIPELINE_ERROR_DECODE); 663 error_cb_.Run(PIPELINE_ERROR_DECODE);
702 } 664 }
703 665
704 void AudioRendererImpl::DisableUnderflowForTesting() {
705 underflow_disabled_ = true;
706 }
707
708 void AudioRendererImpl::HandleAbortedReadOrDecodeError(bool is_decode_error) { 666 void AudioRendererImpl::HandleAbortedReadOrDecodeError(bool is_decode_error) {
709 lock_.AssertAcquired(); 667 lock_.AssertAcquired();
710 668
711 PipelineStatus status = is_decode_error ? PIPELINE_ERROR_DECODE : PIPELINE_OK; 669 PipelineStatus status = is_decode_error ? PIPELINE_ERROR_DECODE : PIPELINE_OK;
712 switch (state_) { 670 switch (state_) {
713 case kUninitialized: 671 case kUninitialized:
714 case kInitializing: 672 case kInitializing:
715 NOTREACHED(); 673 NOTREACHED();
716 return; 674 return;
717 case kFlushing: 675 case kFlushing:
718 ChangeState_Locked(kFlushed); 676 ChangeState_Locked(kFlushed);
719
720 if (status == PIPELINE_OK) { 677 if (status == PIPELINE_OK) {
721 DoFlush_Locked(); 678 DoFlush_Locked();
722 return; 679 return;
723 } 680 }
724 681
725 error_cb_.Run(status); 682 error_cb_.Run(status);
726 base::ResetAndReturn(&flush_cb_).Run(); 683 base::ResetAndReturn(&flush_cb_).Run();
727 return; 684 return;
728 case kPrerolling: 685
729 // This is a signal for abort if it's not an error.
730 preroll_aborted_ = !is_decode_error;
731 ChangeState_Locked(kPlaying);
732 base::ResetAndReturn(&preroll_cb_).Run(status);
733 return;
734 case kFlushed: 686 case kFlushed:
735 case kPlaying: 687 case kPlaying:
736 case kUnderflow:
737 case kRebuffering:
738 case kStopped: 688 case kStopped:
739 if (status != PIPELINE_OK) 689 if (status != PIPELINE_OK)
740 error_cb_.Run(status); 690 error_cb_.Run(status);
741 return; 691 return;
742 } 692 }
743 } 693 }
744 694
745 void AudioRendererImpl::ChangeState_Locked(State new_state) { 695 void AudioRendererImpl::ChangeState_Locked(State new_state) {
746 DVLOG(1) << __FUNCTION__ << " : " << state_ << " -> " << new_state; 696 DVLOG(1) << __FUNCTION__ << " : " << state_ << " -> " << new_state;
747 lock_.AssertAcquired(); 697 lock_.AssertAcquired();
(...skipping 10 matching lines...) Expand all
758 DCHECK(expecting_config_changes_); 708 DCHECK(expecting_config_changes_);
759 buffer_converter_->ResetTimestampState(); 709 buffer_converter_->ResetTimestampState();
760 // Drain flushed buffers from the converter so the AudioSplicer receives all 710 // Drain flushed buffers from the converter so the AudioSplicer receives all
761 // data ahead of any OnNewSpliceBuffer() calls. Since discontinuities should 711 // data ahead of any OnNewSpliceBuffer() calls. Since discontinuities should
762 // only appear after config changes, AddInput() should never fail here. 712 // only appear after config changes, AddInput() should never fail here.
763 while (buffer_converter_->HasNextBuffer()) 713 while (buffer_converter_->HasNextBuffer())
764 CHECK(splicer_->AddInput(buffer_converter_->GetNextBuffer())); 714 CHECK(splicer_->AddInput(buffer_converter_->GetNextBuffer()));
765 } 715 }
766 716
767 } // namespace media 717 } // namespace media
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698