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

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: rebase 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 preroll_aborted_(false),
63 weak_factory_(this) { 63 weak_factory_(this) {
64 audio_buffer_stream_.set_splice_observer(base::Bind( 64 audio_buffer_stream_.set_splice_observer(base::Bind(
65 &AudioRendererImpl::OnNewSpliceBuffer, weak_factory_.GetWeakPtr())); 65 &AudioRendererImpl::OnNewSpliceBuffer, weak_factory_.GetWeakPtr()));
66 audio_buffer_stream_.set_config_change_observer(base::Bind( 66 audio_buffer_stream_.set_config_change_observer(base::Bind(
67 &AudioRendererImpl::OnConfigChange, weak_factory_.GetWeakPtr())); 67 &AudioRendererImpl::OnConfigChange, weak_factory_.GetWeakPtr()));
68 } 68 }
69 69
70 AudioRendererImpl::~AudioRendererImpl() { 70 AudioRendererImpl::~AudioRendererImpl() {
71 // Stop() should have been called and |algorithm_| should have been destroyed. 71 // Stop() should have been called and |algorithm_| should have been destroyed.
72 DCHECK(state_ == kUninitialized || state_ == kStopped); 72 DCHECK(state_ == kUninitialized || state_ == kStopped);
(...skipping 12 matching lines...) Expand all
85 DCHECK(!sink_playing_); 85 DCHECK(!sink_playing_);
86 return; 86 return;
87 } 87 }
88 88
89 StartRendering_Locked(); 89 StartRendering_Locked();
90 } 90 }
91 91
92 void AudioRendererImpl::StartRendering_Locked() { 92 void AudioRendererImpl::StartRendering_Locked() {
93 DVLOG(1) << __FUNCTION__; 93 DVLOG(1) << __FUNCTION__;
94 DCHECK(task_runner_->BelongsToCurrentThread()); 94 DCHECK(task_runner_->BelongsToCurrentThread());
95 DCHECK(state_ == kPlaying || state_ == kRebuffering || state_ == kUnderflow) 95 DCHECK_EQ(state_, kPlaying);
96 << "state_=" << state_;
97 DCHECK(!sink_playing_); 96 DCHECK(!sink_playing_);
98 DCHECK_NE(algorithm_->playback_rate(), 0); 97 DCHECK_NE(algorithm_->playback_rate(), 0);
99 lock_.AssertAcquired(); 98 lock_.AssertAcquired();
100 99
101 earliest_end_time_ = now_cb_.Run(); 100 earliest_end_time_ = now_cb_.Run();
102 sink_playing_ = true; 101 sink_playing_ = true;
103 102
104 base::AutoUnlock auto_unlock(lock_); 103 base::AutoUnlock auto_unlock(lock_);
105 sink_->Play(); 104 sink_->Play();
106 } 105 }
107 106
108 void AudioRendererImpl::StopRendering() { 107 void AudioRendererImpl::StopRendering() {
109 DVLOG(1) << __FUNCTION__; 108 DVLOG(1) << __FUNCTION__;
110 DCHECK(task_runner_->BelongsToCurrentThread()); 109 DCHECK(task_runner_->BelongsToCurrentThread());
111 DCHECK(rendering_); 110 DCHECK(rendering_);
112 rendering_ = false; 111 rendering_ = false;
113 112
114 base::AutoLock auto_lock(lock_); 113 base::AutoLock auto_lock(lock_);
115 // Rendering should have already been stopped with a zero playback rate. 114 // Rendering should have already been stopped with a zero playback rate.
116 if (algorithm_->playback_rate() == 0) { 115 if (algorithm_->playback_rate() == 0) {
117 DCHECK(!sink_playing_); 116 DCHECK(!sink_playing_);
118 return; 117 return;
119 } 118 }
120 119
121 StopRendering_Locked(); 120 StopRendering_Locked();
122 } 121 }
123 122
124 void AudioRendererImpl::StopRendering_Locked() { 123 void AudioRendererImpl::StopRendering_Locked() {
125 DCHECK(task_runner_->BelongsToCurrentThread()); 124 DCHECK(task_runner_->BelongsToCurrentThread());
126 DCHECK(state_ == kPlaying || state_ == kRebuffering || state_ == kUnderflow) 125 DCHECK_EQ(state_, kPlaying);
127 << "state_=" << state_;
128 DCHECK(sink_playing_); 126 DCHECK(sink_playing_);
129 lock_.AssertAcquired(); 127 lock_.AssertAcquired();
130 128
131 sink_playing_ = false; 129 sink_playing_ = false;
132 130
133 base::AutoUnlock auto_unlock(lock_); 131 base::AutoUnlock auto_unlock(lock_);
134 sink_->Pause(); 132 sink_->Pause();
135 } 133 }
136 134
137 void AudioRendererImpl::Flush(const base::Closure& callback) { 135 void AudioRendererImpl::Flush(const base::Closure& callback) {
138 DVLOG(1) << __FUNCTION__; 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(state_ == kPlaying || state_ == kRebuffering || state_ == kUnderflow) 140 DCHECK_EQ(state_, kPlaying);
143 << "state_=" << state_;
144 DCHECK(flush_cb_.is_null()); 141 DCHECK(flush_cb_.is_null());
145 142
146 flush_cb_ = callback; 143 flush_cb_ = callback;
144 ChangeState_Locked(kFlushing);
147 145
148 if (pending_read_) { 146 if (pending_read_)
149 ChangeState_Locked(kFlushing);
150 return; 147 return;
151 }
152 148
153 ChangeState_Locked(kFlushed); 149 ChangeState_Locked(kFlushed);
154 DoFlush_Locked(); 150 DoFlush_Locked();
155 } 151 }
156 152
157 void AudioRendererImpl::DoFlush_Locked() { 153 void AudioRendererImpl::DoFlush_Locked() {
158 DCHECK(task_runner_->BelongsToCurrentThread()); 154 DCHECK(task_runner_->BelongsToCurrentThread());
159 lock_.AssertAcquired(); 155 lock_.AssertAcquired();
160 156
161 DCHECK(!pending_read_); 157 DCHECK(!pending_read_);
162 DCHECK_EQ(state_, kFlushed); 158 DCHECK_EQ(state_, kFlushed);
163 159
164 audio_buffer_stream_.Reset(base::Bind(&AudioRendererImpl::ResetDecoderDone, 160 audio_buffer_stream_.Reset(base::Bind(&AudioRendererImpl::ResetDecoderDone,
165 weak_factory_.GetWeakPtr())); 161 weak_factory_.GetWeakPtr()));
166 } 162 }
167 163
168 void AudioRendererImpl::ResetDecoderDone() { 164 void AudioRendererImpl::ResetDecoderDone() {
169 DCHECK(task_runner_->BelongsToCurrentThread()); 165 DCHECK(task_runner_->BelongsToCurrentThread());
170 { 166 {
171 base::AutoLock auto_lock(lock_); 167 base::AutoLock auto_lock(lock_);
172 if (state_ == kStopped) 168 if (state_ == kStopped)
173 return; 169 return;
174 170
175 DCHECK_EQ(state_, kFlushed); 171 DCHECK_EQ(state_, kFlushed);
176 DCHECK(!flush_cb_.is_null()); 172 DCHECK(!flush_cb_.is_null());
177 173
178 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;
acolwell GONE FROM CHROMIUM 2014/05/16 17:25:08 Why don't we dispatch a callback in this case? The
scherkus (not reviewing) 2014/05/22 17:49:12 as discussed offline ... updated API docs + impls
179 received_end_of_stream_ = false; 176 received_end_of_stream_ = false;
180 rendered_end_of_stream_ = false; 177 rendered_end_of_stream_ = false;
181 preroll_aborted_ = false;
182 178
183 earliest_end_time_ = now_cb_.Run(); 179 earliest_end_time_ = now_cb_.Run();
184 splicer_->Reset(); 180 splicer_->Reset();
185 if (buffer_converter_) 181 if (buffer_converter_)
186 buffer_converter_->Reset(); 182 buffer_converter_->Reset();
187 algorithm_->FlushBuffers(); 183 algorithm_->FlushBuffers();
188 } 184 }
189 base::ResetAndReturn(&flush_cb_).Run(); 185 base::ResetAndReturn(&flush_cb_).Run();
190 } 186 }
191 187
192 void AudioRendererImpl::Stop(const base::Closure& callback) { 188 void AudioRendererImpl::Stop(const base::Closure& callback) {
193 DVLOG(1) << __FUNCTION__; 189 DVLOG(1) << __FUNCTION__;
194 DCHECK(task_runner_->BelongsToCurrentThread()); 190 DCHECK(task_runner_->BelongsToCurrentThread());
195 DCHECK(!callback.is_null()); 191 DCHECK(!callback.is_null());
196 192
197 // TODO(scherkus): Consider invalidating |weak_factory_| and replacing 193 // TODO(scherkus): Consider invalidating |weak_factory_| and replacing
198 // task-running guards that check |state_| with DCHECK(). 194 // task-running guards that check |state_| with DCHECK().
199 195
200 { 196 {
201 base::AutoLock auto_lock(lock_); 197 base::AutoLock auto_lock(lock_);
202 198
203 if (state_ == kStopped) { 199 if (state_ == kStopped) {
204 task_runner_->PostTask(FROM_HERE, callback); 200 task_runner_->PostTask(FROM_HERE, callback);
205 return; 201 return;
206 } 202 }
207 203
208 ChangeState_Locked(kStopped); 204 ChangeState_Locked(kStopped);
209 algorithm_.reset(); 205 algorithm_.reset();
210 underflow_cb_.Reset();
211 time_cb_.Reset(); 206 time_cb_.Reset();
212 flush_cb_.Reset(); 207 flush_cb_.Reset();
213 } 208 }
214 209
215 if (sink_) { 210 if (sink_) {
216 sink_->Stop(); 211 sink_->Stop();
217 sink_ = NULL; 212 sink_ = NULL;
218 } 213 }
219 214
220 audio_buffer_stream_.Stop(callback); 215 audio_buffer_stream_.Stop(callback);
221 } 216 }
222 217
223 void AudioRendererImpl::Preroll(base::TimeDelta time, 218 void AudioRendererImpl::StartPlayingFrom(base::TimeDelta timestamp) {
224 const PipelineStatusCB& cb) { 219 DVLOG(1) << __FUNCTION__ << "(" << timestamp.InMicroseconds() << ")";
225 DVLOG(1) << __FUNCTION__ << "(" << time.InMicroseconds() << ")";
226 DCHECK(task_runner_->BelongsToCurrentThread()); 220 DCHECK(task_runner_->BelongsToCurrentThread());
227 221
228 base::AutoLock auto_lock(lock_); 222 base::AutoLock auto_lock(lock_);
229 DCHECK(!sink_playing_); 223 DCHECK(!sink_playing_);
230 DCHECK_EQ(state_, kFlushed); 224 DCHECK_EQ(state_, kFlushed);
225 DCHECK_EQ(buffering_state_, BUFFERING_HAVE_NOTHING);
231 DCHECK(!pending_read_) << "Pending read must complete before seeking"; 226 DCHECK(!pending_read_) << "Pending read must complete before seeking";
232 DCHECK(preroll_cb_.is_null());
233 227
234 ChangeState_Locked(kPrerolling); 228 ChangeState_Locked(kPlaying);
235 preroll_cb_ = cb; 229 start_timestamp_ = timestamp;
236 preroll_timestamp_ = time;
237 230
238 AttemptRead_Locked(); 231 AttemptRead_Locked();
239 } 232 }
240 233
241 void AudioRendererImpl::Initialize(DemuxerStream* stream, 234 void AudioRendererImpl::Initialize(DemuxerStream* stream,
242 const PipelineStatusCB& init_cb, 235 const PipelineStatusCB& init_cb,
243 const StatisticsCB& statistics_cb, 236 const StatisticsCB& statistics_cb,
244 const base::Closure& underflow_cb,
245 const TimeCB& time_cb, 237 const TimeCB& time_cb,
238 const BufferingStateCB& buffering_state_cb,
246 const base::Closure& ended_cb, 239 const base::Closure& ended_cb,
247 const PipelineStatusCB& error_cb) { 240 const PipelineStatusCB& error_cb) {
248 DCHECK(task_runner_->BelongsToCurrentThread()); 241 DCHECK(task_runner_->BelongsToCurrentThread());
249 DCHECK(stream); 242 DCHECK(stream);
250 DCHECK_EQ(stream->type(), DemuxerStream::AUDIO); 243 DCHECK_EQ(stream->type(), DemuxerStream::AUDIO);
251 DCHECK(!init_cb.is_null()); 244 DCHECK(!init_cb.is_null());
252 DCHECK(!statistics_cb.is_null()); 245 DCHECK(!statistics_cb.is_null());
253 DCHECK(!underflow_cb.is_null());
254 DCHECK(!time_cb.is_null()); 246 DCHECK(!time_cb.is_null());
247 DCHECK(!buffering_state_cb.is_null());
255 DCHECK(!ended_cb.is_null()); 248 DCHECK(!ended_cb.is_null());
256 DCHECK(!error_cb.is_null()); 249 DCHECK(!error_cb.is_null());
257 DCHECK_EQ(kUninitialized, state_); 250 DCHECK_EQ(kUninitialized, state_);
258 DCHECK(sink_); 251 DCHECK(sink_);
259 252
260 state_ = kInitializing; 253 state_ = kInitializing;
261 254
262 init_cb_ = init_cb; 255 init_cb_ = init_cb;
263 underflow_cb_ = underflow_cb;
264 time_cb_ = time_cb; 256 time_cb_ = time_cb;
257 // TODO(scherkus): Enforce AudioRendererImpl to call on right thread.
acolwell GONE FROM CHROMIUM 2014/05/16 17:25:08 Is this still a TODO? It looks like you are ensuri
scherkus (not reviewing) 2014/05/22 17:49:12 yeah .. I guess so :\ would rather have ARI be si
258 buffering_state_cb_ = BindToCurrentLoop(buffering_state_cb);
265 ended_cb_ = ended_cb; 259 ended_cb_ = ended_cb;
266 error_cb_ = error_cb; 260 error_cb_ = error_cb;
267 261
268 expecting_config_changes_ = stream->SupportsConfigChanges(); 262 expecting_config_changes_ = stream->SupportsConfigChanges();
269 if (!expecting_config_changes_) { 263 if (!expecting_config_changes_) {
270 // 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
271 // provided to Render(), so just choose something reasonable here for looks. 265 // provided to Render(), so just choose something reasonable here for looks.
272 int buffer_size = stream->audio_decoder_config().samples_per_second() / 100; 266 int buffer_size = stream->audio_decoder_config().samples_per_second() / 100;
273 audio_parameters_.Reset( 267 audio_parameters_.Reset(
274 AudioParameters::AUDIO_PCM_LOW_LATENCY, 268 AudioParameters::AUDIO_PCM_LOW_LATENCY,
(...skipping 69 matching lines...) Expand 10 before | Expand all | Expand 10 after
344 338
345 // Some sinks play on start... 339 // Some sinks play on start...
346 sink_->Pause(); 340 sink_->Pause();
347 } 341 }
348 342
349 DCHECK(!sink_playing_); 343 DCHECK(!sink_playing_);
350 344
351 base::ResetAndReturn(&init_cb_).Run(PIPELINE_OK); 345 base::ResetAndReturn(&init_cb_).Run(PIPELINE_OK);
352 } 346 }
353 347
354 void AudioRendererImpl::ResumeAfterUnderflow() {
355 DCHECK(task_runner_->BelongsToCurrentThread());
356 base::AutoLock auto_lock(lock_);
357 if (state_ == kUnderflow) {
358 // The "!preroll_aborted_" is a hack. If preroll is aborted, then we
359 // shouldn't even reach the kUnderflow state to begin with. But for now
360 // we're just making sure that the audio buffer capacity (i.e. the
361 // number of bytes that need to be buffered for preroll to complete)
362 // does not increase due to an aborted preroll.
363 // TODO(vrk): Fix this bug correctly! (crbug.com/151352)
364 if (!preroll_aborted_)
365 algorithm_->IncreaseQueueCapacity();
366
367 ChangeState_Locked(kRebuffering);
368 }
369 }
370
371 void AudioRendererImpl::SetVolume(float volume) { 348 void AudioRendererImpl::SetVolume(float volume) {
372 DCHECK(task_runner_->BelongsToCurrentThread()); 349 DCHECK(task_runner_->BelongsToCurrentThread());
373 DCHECK(sink_); 350 DCHECK(sink_);
374 sink_->SetVolume(volume); 351 sink_->SetVolume(volume);
375 } 352 }
376 353
377 void AudioRendererImpl::DecodedAudioReady( 354 void AudioRendererImpl::DecodedAudioReady(
378 AudioBufferStream::Status status, 355 AudioBufferStream::Status status,
379 const scoped_refptr<AudioBuffer>& buffer) { 356 const scoped_refptr<AudioBuffer>& buffer) {
380 DVLOG(2) << __FUNCTION__ << "(" << status << ")"; 357 DVLOG(2) << __FUNCTION__ << "(" << status << ")";
(...skipping 51 matching lines...) Expand 10 before | Expand all | Expand 10 after
432 need_another_buffer = HandleSplicerBuffer(splicer_->GetNextBuffer()); 409 need_another_buffer = HandleSplicerBuffer(splicer_->GetNextBuffer());
433 410
434 if (!need_another_buffer && !CanRead_Locked()) 411 if (!need_another_buffer && !CanRead_Locked())
435 return; 412 return;
436 413
437 AttemptRead_Locked(); 414 AttemptRead_Locked();
438 } 415 }
439 416
440 bool AudioRendererImpl::HandleSplicerBuffer( 417 bool AudioRendererImpl::HandleSplicerBuffer(
441 const scoped_refptr<AudioBuffer>& buffer) { 418 const scoped_refptr<AudioBuffer>& buffer) {
442 if (buffer->end_of_stream()) { 419 if (buffer->end_of_stream()) {
acolwell GONE FROM CHROMIUM 2014/05/16 17:25:08 nit: add lock_.AssertAcquired() and possibly _Lock
scherkus (not reviewing) 2014/05/22 17:49:12 Done.
443 received_end_of_stream_ = true; 420 received_end_of_stream_ = true;
444
445 // Transition to kPlaying if we are currently handling an underflow since
446 // no more data will be arriving.
447 if (state_ == kUnderflow || state_ == kRebuffering)
448 ChangeState_Locked(kPlaying);
449 } else { 421 } else {
450 if (state_ == kPrerolling) { 422 if (state_ == kPlaying) {
451 if (IsBeforePrerollTime(buffer)) 423 if (IsBeforeStartTime(buffer))
452 return true; 424 return true;
453 425
454 // Trim off any additional time before the preroll timestamp. 426 // Trim off any additional time before the start timestamp.
455 const base::TimeDelta trim_time = 427 const base::TimeDelta trim_time = start_timestamp_ - buffer->timestamp();
456 preroll_timestamp_ - buffer->timestamp();
457 if (trim_time > base::TimeDelta()) { 428 if (trim_time > base::TimeDelta()) {
458 buffer->TrimStart(buffer->frame_count() * 429 buffer->TrimStart(buffer->frame_count() *
459 (static_cast<double>(trim_time.InMicroseconds()) / 430 (static_cast<double>(trim_time.InMicroseconds()) /
460 buffer->duration().InMicroseconds())); 431 buffer->duration().InMicroseconds()));
461 } 432 }
462 // If the entire buffer was trimmed, request a new one. 433 // If the entire buffer was trimmed, request a new one.
463 if (!buffer->frame_count()) 434 if (!buffer->frame_count())
464 return true; 435 return true;
465 } 436 }
466 437
467 if (state_ != kUninitialized && state_ != kStopped) 438 if (state_ != kUninitialized && state_ != kStopped)
468 algorithm_->EnqueueBuffer(buffer); 439 algorithm_->EnqueueBuffer(buffer);
469 } 440 }
470 441
471 switch (state_) { 442 switch (state_) {
472 case kUninitialized: 443 case kUninitialized:
473 case kInitializing: 444 case kInitializing:
474 case kFlushing: 445 case kFlushing:
475 NOTREACHED(); 446 NOTREACHED();
476 return false; 447 return false;
477 448
478 case kFlushed: 449 case kFlushed:
479 DCHECK(!pending_read_); 450 DCHECK(!pending_read_);
480 return false; 451 return false;
481 452
482 case kPrerolling:
483 if (!buffer->end_of_stream() && !algorithm_->IsQueueFull())
484 return true;
485 ChangeState_Locked(kPlaying);
486 base::ResetAndReturn(&preroll_cb_).Run(PIPELINE_OK);
487 return false;
488
489 case kPlaying: 453 case kPlaying:
490 case kUnderflow: 454 if (buffer->end_of_stream() || algorithm_->IsQueueFull()) {
491 return false; 455 if (buffering_state_ == BUFFERING_HAVE_NOTHING) {
492 456 buffering_state_ = BUFFERING_HAVE_ENOUGH;
493 case kRebuffering: 457 buffering_state_cb_.Run(BUFFERING_HAVE_ENOUGH);
acolwell GONE FROM CHROMIUM 2014/05/16 17:25:08 nit: Put these 2 operations in a SetBufferingState
scherkus (not reviewing) 2014/05/22 17:49:12 Done.
494 if (!algorithm_->IsQueueFull()) 458 }
495 return true; 459 return false;
496 ChangeState_Locked(kPlaying); 460 }
497 return false; 461 return true;
498 462
499 case kStopped: 463 case kStopped:
500 return false; 464 return false;
501 } 465 }
502 return false; 466 return false;
503 } 467 }
504 468
505 void AudioRendererImpl::AttemptRead() { 469 void AudioRendererImpl::AttemptRead() {
506 base::AutoLock auto_lock(lock_); 470 base::AutoLock auto_lock(lock_);
507 AttemptRead_Locked(); 471 AttemptRead_Locked();
(...skipping 10 matching lines...) Expand all
518 audio_buffer_stream_.Read(base::Bind(&AudioRendererImpl::DecodedAudioReady, 482 audio_buffer_stream_.Read(base::Bind(&AudioRendererImpl::DecodedAudioReady,
519 weak_factory_.GetWeakPtr())); 483 weak_factory_.GetWeakPtr()));
520 } 484 }
521 485
522 bool AudioRendererImpl::CanRead_Locked() { 486 bool AudioRendererImpl::CanRead_Locked() {
523 lock_.AssertAcquired(); 487 lock_.AssertAcquired();
524 488
525 switch (state_) { 489 switch (state_) {
526 case kUninitialized: 490 case kUninitialized:
527 case kInitializing: 491 case kInitializing:
492 case kFlushing:
528 case kFlushed: 493 case kFlushed:
529 case kFlushing:
530 case kStopped: 494 case kStopped:
531 return false; 495 return false;
532 496
533 case kPrerolling:
534 case kPlaying: 497 case kPlaying:
535 case kUnderflow:
536 case kRebuffering:
537 break; 498 break;
538 } 499 }
539 500
540 return !pending_read_ && !received_end_of_stream_ && 501 return !pending_read_ && !received_end_of_stream_ &&
541 !algorithm_->IsQueueFull(); 502 !algorithm_->IsQueueFull();
542 } 503 }
543 504
544 void AudioRendererImpl::SetPlaybackRate(float playback_rate) { 505 void AudioRendererImpl::SetPlaybackRate(float playback_rate) {
545 DVLOG(1) << __FUNCTION__ << "(" << playback_rate << ")"; 506 DVLOG(1) << __FUNCTION__ << "(" << playback_rate << ")";
546 DCHECK(task_runner_->BelongsToCurrentThread()); 507 DCHECK(task_runner_->BelongsToCurrentThread());
(...skipping 15 matching lines...) Expand all
562 StartRendering_Locked(); 523 StartRendering_Locked();
563 return; 524 return;
564 } 525 }
565 526
566 if (current_playback_rate != 0 && playback_rate == 0) { 527 if (current_playback_rate != 0 && playback_rate == 0) {
567 StopRendering_Locked(); 528 StopRendering_Locked();
568 return; 529 return;
569 } 530 }
570 } 531 }
571 532
572 bool AudioRendererImpl::IsBeforePrerollTime( 533 bool AudioRendererImpl::IsBeforeStartTime(
573 const scoped_refptr<AudioBuffer>& buffer) { 534 const scoped_refptr<AudioBuffer>& buffer) {
574 DCHECK_EQ(state_, kPrerolling); 535 DCHECK_EQ(state_, kPlaying);
575 return buffer && !buffer->end_of_stream() && 536 return buffer && !buffer->end_of_stream() &&
576 (buffer->timestamp() + buffer->duration()) < preroll_timestamp_; 537 (buffer->timestamp() + buffer->duration()) < start_timestamp_;
577 } 538 }
578 539
579 int AudioRendererImpl::Render(AudioBus* audio_bus, 540 int AudioRendererImpl::Render(AudioBus* audio_bus,
580 int audio_delay_milliseconds) { 541 int audio_delay_milliseconds) {
581 const int requested_frames = audio_bus->frames(); 542 const int requested_frames = audio_bus->frames();
582 base::TimeDelta playback_delay = base::TimeDelta::FromMilliseconds( 543 base::TimeDelta playback_delay = base::TimeDelta::FromMilliseconds(
583 audio_delay_milliseconds); 544 audio_delay_milliseconds);
584 const int delay_frames = static_cast<int>(playback_delay.InSecondsF() * 545 const int delay_frames = static_cast<int>(playback_delay.InSecondsF() *
585 audio_parameters_.sample_rate()); 546 audio_parameters_.sample_rate());
586 int frames_written = 0; 547 int frames_written = 0;
587 base::Closure time_cb; 548 base::Closure time_cb;
588 base::Closure underflow_cb;
589 { 549 {
590 base::AutoLock auto_lock(lock_); 550 base::AutoLock auto_lock(lock_);
591 551
592 // Ensure Stop() hasn't destroyed our |algorithm_| on the pipeline thread. 552 // Ensure Stop() hasn't destroyed our |algorithm_| on the pipeline thread.
593 if (!algorithm_) { 553 if (!algorithm_) {
594 audio_clock_->WroteSilence(requested_frames, delay_frames); 554 audio_clock_->WroteSilence(requested_frames, delay_frames);
595 return 0; 555 return 0;
596 } 556 }
597 557
598 float playback_rate = algorithm_->playback_rate(); 558 float playback_rate = algorithm_->playback_rate();
(...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after
632 audio_clock_->WroteSilence(requested_frames - frames_written, delay_frames); 592 audio_clock_->WroteSilence(requested_frames - frames_written, delay_frames);
633 593
634 if (frames_written == 0) { 594 if (frames_written == 0) {
635 const base::TimeTicks now = now_cb_.Run(); 595 const base::TimeTicks now = now_cb_.Run();
636 596
637 if (received_end_of_stream_ && !rendered_end_of_stream_ && 597 if (received_end_of_stream_ && !rendered_end_of_stream_ &&
638 now >= earliest_end_time_) { 598 now >= earliest_end_time_) {
639 rendered_end_of_stream_ = true; 599 rendered_end_of_stream_ = true;
640 ended_cb_.Run(); 600 ended_cb_.Run();
641 } else if (!received_end_of_stream_ && state_ == kPlaying) { 601 } else if (!received_end_of_stream_ && state_ == kPlaying) {
642 ChangeState_Locked(kUnderflow); 602 if (buffering_state_ != BUFFERING_HAVE_NOTHING) {
643 underflow_cb = underflow_cb_; 603 algorithm_->IncreaseQueueCapacity();
604 buffering_state_ = BUFFERING_HAVE_NOTHING;
605 buffering_state_cb_.Run(BUFFERING_HAVE_NOTHING);
606 }
644 } else { 607 } else {
645 // 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
646 // sent all available data to the audio device while not reaching 609 // sent all available data to the audio device while not reaching
647 // |earliest_end_time_|. 610 // |earliest_end_time_|.
648 } 611 }
649 } 612 }
650 613
651 if (CanRead_Locked()) { 614 if (CanRead_Locked()) {
652 task_runner_->PostTask(FROM_HERE, 615 task_runner_->PostTask(FROM_HERE,
653 base::Bind(&AudioRendererImpl::AttemptRead, 616 base::Bind(&AudioRendererImpl::AttemptRead,
(...skipping 12 matching lines...) Expand all
666 629
667 if (frames_written > 0) { 630 if (frames_written > 0) {
668 UpdateEarliestEndTime_Locked( 631 UpdateEarliestEndTime_Locked(
669 frames_written, playback_delay, now_cb_.Run()); 632 frames_written, playback_delay, now_cb_.Run());
670 } 633 }
671 } 634 }
672 635
673 if (!time_cb.is_null()) 636 if (!time_cb.is_null())
674 time_cb.Run(); 637 time_cb.Run();
675 638
676 if (!underflow_cb.is_null())
677 underflow_cb.Run();
678
679 DCHECK_LE(frames_written, requested_frames); 639 DCHECK_LE(frames_written, requested_frames);
680 return frames_written; 640 return frames_written;
681 } 641 }
682 642
683 void AudioRendererImpl::UpdateEarliestEndTime_Locked( 643 void AudioRendererImpl::UpdateEarliestEndTime_Locked(
684 int frames_filled, const base::TimeDelta& playback_delay, 644 int frames_filled, const base::TimeDelta& playback_delay,
685 const base::TimeTicks& time_now) { 645 const base::TimeTicks& time_now) {
686 DCHECK_GT(frames_filled, 0); 646 DCHECK_GT(frames_filled, 0);
687 647
688 base::TimeDelta predicted_play_time = base::TimeDelta::FromMicroseconds( 648 base::TimeDelta predicted_play_time = base::TimeDelta::FromMicroseconds(
(...skipping 18 matching lines...) Expand all
707 lock_.AssertAcquired(); 667 lock_.AssertAcquired();
708 668
709 PipelineStatus status = is_decode_error ? PIPELINE_ERROR_DECODE : PIPELINE_OK; 669 PipelineStatus status = is_decode_error ? PIPELINE_ERROR_DECODE : PIPELINE_OK;
710 switch (state_) { 670 switch (state_) {
711 case kUninitialized: 671 case kUninitialized:
712 case kInitializing: 672 case kInitializing:
713 NOTREACHED(); 673 NOTREACHED();
714 return; 674 return;
715 case kFlushing: 675 case kFlushing:
716 ChangeState_Locked(kFlushed); 676 ChangeState_Locked(kFlushed);
717
718 if (status == PIPELINE_OK) { 677 if (status == PIPELINE_OK) {
719 DoFlush_Locked(); 678 DoFlush_Locked();
720 return; 679 return;
721 } 680 }
722 681
723 error_cb_.Run(status); 682 error_cb_.Run(status);
724 base::ResetAndReturn(&flush_cb_).Run(); 683 base::ResetAndReturn(&flush_cb_).Run();
725 return; 684 return;
726 case kPrerolling: 685
727 // This is a signal for abort if it's not an error.
728 preroll_aborted_ = !is_decode_error;
729 ChangeState_Locked(kPlaying);
730 base::ResetAndReturn(&preroll_cb_).Run(status);
731 return;
732 case kFlushed: 686 case kFlushed:
733 case kPlaying: 687 case kPlaying:
734 case kUnderflow:
735 case kRebuffering:
736 case kStopped: 688 case kStopped:
737 if (status != PIPELINE_OK) 689 if (status != PIPELINE_OK)
738 error_cb_.Run(status); 690 error_cb_.Run(status);
739 return; 691 return;
740 } 692 }
741 } 693 }
742 694
743 void AudioRendererImpl::ChangeState_Locked(State new_state) { 695 void AudioRendererImpl::ChangeState_Locked(State new_state) {
744 DVLOG(1) << __FUNCTION__ << " : " << state_ << " -> " << new_state; 696 DVLOG(1) << __FUNCTION__ << " : " << state_ << " -> " << new_state;
745 lock_.AssertAcquired(); 697 lock_.AssertAcquired();
(...skipping 10 matching lines...) Expand all
756 DCHECK(expecting_config_changes_); 708 DCHECK(expecting_config_changes_);
757 buffer_converter_->ResetTimestampState(); 709 buffer_converter_->ResetTimestampState();
758 // Drain flushed buffers from the converter so the AudioSplicer receives all 710 // Drain flushed buffers from the converter so the AudioSplicer receives all
759 // data ahead of any OnNewSpliceBuffer() calls. Since discontinuities should 711 // data ahead of any OnNewSpliceBuffer() calls. Since discontinuities should
760 // only appear after config changes, AddInput() should never fail here. 712 // only appear after config changes, AddInput() should never fail here.
761 while (buffer_converter_->HasNextBuffer()) 713 while (buffer_converter_->HasNextBuffer())
762 CHECK(splicer_->AddInput(buffer_converter_->GetNextBuffer())); 714 CHECK(splicer_->AddInput(buffer_converter_->GetNextBuffer()));
763 } 715 }
764 716
765 } // namespace media 717 } // namespace media
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698