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

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

Issue 291093013: Revert of 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
« no previous file with comments | « media/filters/audio_renderer_impl.h ('k') | media/filters/audio_renderer_impl_unittest.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
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 36 matching lines...) Expand 10 before | Expand all | Expand 10 after
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 now_cb_(base::Bind(&base::TimeTicks::Now)), 55 now_cb_(base::Bind(&base::TimeTicks::Now)),
56 state_(kUninitialized), 56 state_(kUninitialized),
57 buffering_state_(BUFFERING_HAVE_NOTHING),
58 rendering_(false), 57 rendering_(false),
59 sink_playing_(false), 58 sink_playing_(false),
60 pending_read_(false), 59 pending_read_(false),
61 received_end_of_stream_(false), 60 received_end_of_stream_(false),
62 rendered_end_of_stream_(false), 61 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_EQ(state_, kPlaying); 95 DCHECK(state_ == kPlaying || state_ == kRebuffering || state_ == kUnderflow)
96 << "state_=" << state_;
96 DCHECK(!sink_playing_); 97 DCHECK(!sink_playing_);
97 DCHECK_NE(algorithm_->playback_rate(), 0); 98 DCHECK_NE(algorithm_->playback_rate(), 0);
98 lock_.AssertAcquired(); 99 lock_.AssertAcquired();
99 100
100 earliest_end_time_ = now_cb_.Run(); 101 earliest_end_time_ = now_cb_.Run();
101 sink_playing_ = true; 102 sink_playing_ = true;
102 103
103 base::AutoUnlock auto_unlock(lock_); 104 base::AutoUnlock auto_unlock(lock_);
104 sink_->Play(); 105 sink_->Play();
105 } 106 }
106 107
107 void AudioRendererImpl::StopRendering() { 108 void AudioRendererImpl::StopRendering() {
108 DVLOG(1) << __FUNCTION__; 109 DVLOG(1) << __FUNCTION__;
109 DCHECK(task_runner_->BelongsToCurrentThread()); 110 DCHECK(task_runner_->BelongsToCurrentThread());
110 DCHECK(rendering_); 111 DCHECK(rendering_);
111 rendering_ = false; 112 rendering_ = false;
112 113
113 base::AutoLock auto_lock(lock_); 114 base::AutoLock auto_lock(lock_);
114 // Rendering should have already been stopped with a zero playback rate. 115 // Rendering should have already been stopped with a zero playback rate.
115 if (algorithm_->playback_rate() == 0) { 116 if (algorithm_->playback_rate() == 0) {
116 DCHECK(!sink_playing_); 117 DCHECK(!sink_playing_);
117 return; 118 return;
118 } 119 }
119 120
120 StopRendering_Locked(); 121 StopRendering_Locked();
121 } 122 }
122 123
123 void AudioRendererImpl::StopRendering_Locked() { 124 void AudioRendererImpl::StopRendering_Locked() {
124 DCHECK(task_runner_->BelongsToCurrentThread()); 125 DCHECK(task_runner_->BelongsToCurrentThread());
125 DCHECK_EQ(state_, kPlaying); 126 DCHECK(state_ == kPlaying || state_ == kRebuffering || state_ == kUnderflow)
127 << "state_=" << state_;
126 DCHECK(sink_playing_); 128 DCHECK(sink_playing_);
127 lock_.AssertAcquired(); 129 lock_.AssertAcquired();
128 130
129 sink_playing_ = false; 131 sink_playing_ = false;
130 132
131 base::AutoUnlock auto_unlock(lock_); 133 base::AutoUnlock auto_unlock(lock_);
132 sink_->Pause(); 134 sink_->Pause();
133 } 135 }
134 136
135 void AudioRendererImpl::Flush(const base::Closure& callback) { 137 void AudioRendererImpl::Flush(const base::Closure& callback) {
136 DVLOG(1) << __FUNCTION__; 138 DVLOG(1) << __FUNCTION__;
137 DCHECK(task_runner_->BelongsToCurrentThread()); 139 DCHECK(task_runner_->BelongsToCurrentThread());
138 140
139 base::AutoLock auto_lock(lock_); 141 base::AutoLock auto_lock(lock_);
140 DCHECK_EQ(state_, kPlaying); 142 DCHECK(state_ == kPlaying || state_ == kRebuffering || state_ == kUnderflow)
143 << "state_=" << state_;
141 DCHECK(flush_cb_.is_null()); 144 DCHECK(flush_cb_.is_null());
142 145
143 flush_cb_ = callback; 146 flush_cb_ = callback;
144 ChangeState_Locked(kFlushing);
145 147
146 if (pending_read_) 148 if (pending_read_) {
149 ChangeState_Locked(kFlushing);
147 return; 150 return;
151 }
148 152
149 ChangeState_Locked(kFlushed); 153 ChangeState_Locked(kFlushed);
150 DoFlush_Locked(); 154 DoFlush_Locked();
151 } 155 }
152 156
153 void AudioRendererImpl::DoFlush_Locked() { 157 void AudioRendererImpl::DoFlush_Locked() {
154 DCHECK(task_runner_->BelongsToCurrentThread()); 158 DCHECK(task_runner_->BelongsToCurrentThread());
155 lock_.AssertAcquired(); 159 lock_.AssertAcquired();
156 160
157 DCHECK(!pending_read_); 161 DCHECK(!pending_read_);
158 DCHECK_EQ(state_, kFlushed); 162 DCHECK_EQ(state_, kFlushed);
159 163
160 audio_buffer_stream_.Reset(base::Bind(&AudioRendererImpl::ResetDecoderDone, 164 audio_buffer_stream_.Reset(base::Bind(&AudioRendererImpl::ResetDecoderDone,
161 weak_factory_.GetWeakPtr())); 165 weak_factory_.GetWeakPtr()));
162 } 166 }
163 167
164 void AudioRendererImpl::ResetDecoderDone() { 168 void AudioRendererImpl::ResetDecoderDone() {
165 DCHECK(task_runner_->BelongsToCurrentThread()); 169 DCHECK(task_runner_->BelongsToCurrentThread());
166 { 170 {
167 base::AutoLock auto_lock(lock_); 171 base::AutoLock auto_lock(lock_);
168 if (state_ == kStopped) 172 if (state_ == kStopped)
169 return; 173 return;
170 174
171 DCHECK_EQ(state_, kFlushed); 175 DCHECK_EQ(state_, kFlushed);
172 DCHECK(!flush_cb_.is_null()); 176 DCHECK(!flush_cb_.is_null());
173 177
174 audio_clock_.reset(new AudioClock(audio_parameters_.sample_rate())); 178 audio_clock_.reset(new AudioClock(audio_parameters_.sample_rate()));
175 received_end_of_stream_ = false; 179 received_end_of_stream_ = false;
176 rendered_end_of_stream_ = false; 180 rendered_end_of_stream_ = false;
177 181 preroll_aborted_ = false;
178 // Flush() may have been called while underflowed/not fully buffered.
179 if (buffering_state_ != BUFFERING_HAVE_NOTHING)
180 SetBufferingState_Locked(BUFFERING_HAVE_NOTHING);
181 182
182 earliest_end_time_ = now_cb_.Run(); 183 earliest_end_time_ = now_cb_.Run();
183 splicer_->Reset(); 184 splicer_->Reset();
184 if (buffer_converter_) 185 if (buffer_converter_)
185 buffer_converter_->Reset(); 186 buffer_converter_->Reset();
186 algorithm_->FlushBuffers(); 187 algorithm_->FlushBuffers();
187 } 188 }
188 base::ResetAndReturn(&flush_cb_).Run(); 189 base::ResetAndReturn(&flush_cb_).Run();
189 } 190 }
190 191
191 void AudioRendererImpl::Stop(const base::Closure& callback) { 192 void AudioRendererImpl::Stop(const base::Closure& callback) {
192 DVLOG(1) << __FUNCTION__; 193 DVLOG(1) << __FUNCTION__;
193 DCHECK(task_runner_->BelongsToCurrentThread()); 194 DCHECK(task_runner_->BelongsToCurrentThread());
194 DCHECK(!callback.is_null()); 195 DCHECK(!callback.is_null());
195 196
196 // TODO(scherkus): Consider invalidating |weak_factory_| and replacing 197 // TODO(scherkus): Consider invalidating |weak_factory_| and replacing
197 // task-running guards that check |state_| with DCHECK(). 198 // task-running guards that check |state_| with DCHECK().
198 199
199 { 200 {
200 base::AutoLock auto_lock(lock_); 201 base::AutoLock auto_lock(lock_);
201 202
202 if (state_ == kStopped) { 203 if (state_ == kStopped) {
203 task_runner_->PostTask(FROM_HERE, callback); 204 task_runner_->PostTask(FROM_HERE, callback);
204 return; 205 return;
205 } 206 }
206 207
207 ChangeState_Locked(kStopped); 208 ChangeState_Locked(kStopped);
208 algorithm_.reset(); 209 algorithm_.reset();
210 underflow_cb_.Reset();
209 time_cb_.Reset(); 211 time_cb_.Reset();
210 flush_cb_.Reset(); 212 flush_cb_.Reset();
211 } 213 }
212 214
213 if (sink_) { 215 if (sink_) {
214 sink_->Stop(); 216 sink_->Stop();
215 sink_ = NULL; 217 sink_ = NULL;
216 } 218 }
217 219
218 audio_buffer_stream_.Stop(callback); 220 audio_buffer_stream_.Stop(callback);
219 } 221 }
220 222
221 void AudioRendererImpl::StartPlayingFrom(base::TimeDelta timestamp) { 223 void AudioRendererImpl::Preroll(base::TimeDelta time,
222 DVLOG(1) << __FUNCTION__ << "(" << timestamp.InMicroseconds() << ")"; 224 const PipelineStatusCB& cb) {
225 DVLOG(1) << __FUNCTION__ << "(" << time.InMicroseconds() << ")";
223 DCHECK(task_runner_->BelongsToCurrentThread()); 226 DCHECK(task_runner_->BelongsToCurrentThread());
224 227
225 base::AutoLock auto_lock(lock_); 228 base::AutoLock auto_lock(lock_);
226 DCHECK(!sink_playing_); 229 DCHECK(!sink_playing_);
227 DCHECK_EQ(state_, kFlushed); 230 DCHECK_EQ(state_, kFlushed);
228 DCHECK_EQ(buffering_state_, BUFFERING_HAVE_NOTHING);
229 DCHECK(!pending_read_) << "Pending read must complete before seeking"; 231 DCHECK(!pending_read_) << "Pending read must complete before seeking";
232 DCHECK(preroll_cb_.is_null());
230 233
231 ChangeState_Locked(kPlaying); 234 ChangeState_Locked(kPrerolling);
232 start_timestamp_ = timestamp; 235 preroll_cb_ = cb;
236 preroll_timestamp_ = time;
233 237
234 AttemptRead_Locked(); 238 AttemptRead_Locked();
235 } 239 }
236 240
237 void AudioRendererImpl::Initialize(DemuxerStream* stream, 241 void AudioRendererImpl::Initialize(DemuxerStream* stream,
238 const PipelineStatusCB& init_cb, 242 const PipelineStatusCB& init_cb,
239 const StatisticsCB& statistics_cb, 243 const StatisticsCB& statistics_cb,
244 const base::Closure& underflow_cb,
240 const TimeCB& time_cb, 245 const TimeCB& time_cb,
241 const BufferingStateCB& buffering_state_cb,
242 const base::Closure& ended_cb, 246 const base::Closure& ended_cb,
243 const PipelineStatusCB& error_cb) { 247 const PipelineStatusCB& error_cb) {
244 DCHECK(task_runner_->BelongsToCurrentThread()); 248 DCHECK(task_runner_->BelongsToCurrentThread());
245 DCHECK(stream); 249 DCHECK(stream);
246 DCHECK_EQ(stream->type(), DemuxerStream::AUDIO); 250 DCHECK_EQ(stream->type(), DemuxerStream::AUDIO);
247 DCHECK(!init_cb.is_null()); 251 DCHECK(!init_cb.is_null());
248 DCHECK(!statistics_cb.is_null()); 252 DCHECK(!statistics_cb.is_null());
253 DCHECK(!underflow_cb.is_null());
249 DCHECK(!time_cb.is_null()); 254 DCHECK(!time_cb.is_null());
250 DCHECK(!buffering_state_cb.is_null());
251 DCHECK(!ended_cb.is_null()); 255 DCHECK(!ended_cb.is_null());
252 DCHECK(!error_cb.is_null()); 256 DCHECK(!error_cb.is_null());
253 DCHECK_EQ(kUninitialized, state_); 257 DCHECK_EQ(kUninitialized, state_);
254 DCHECK(sink_); 258 DCHECK(sink_);
255 259
256 state_ = kInitializing; 260 state_ = kInitializing;
257 261
258 init_cb_ = init_cb; 262 init_cb_ = init_cb;
263 underflow_cb_ = underflow_cb;
259 time_cb_ = time_cb; 264 time_cb_ = time_cb;
260 // Callback can be run from audio callback thread in Render().
261 buffering_state_cb_ = BindToCurrentLoop(buffering_state_cb);
262 ended_cb_ = ended_cb; 265 ended_cb_ = ended_cb;
263 error_cb_ = error_cb; 266 error_cb_ = error_cb;
264 267
265 expecting_config_changes_ = stream->SupportsConfigChanges(); 268 expecting_config_changes_ = stream->SupportsConfigChanges();
266 if (!expecting_config_changes_) { 269 if (!expecting_config_changes_) {
267 // The actual buffer size is controlled via the size of the AudioBus 270 // The actual buffer size is controlled via the size of the AudioBus
268 // provided to Render(), so just choose something reasonable here for looks. 271 // provided to Render(), so just choose something reasonable here for looks.
269 int buffer_size = stream->audio_decoder_config().samples_per_second() / 100; 272 int buffer_size = stream->audio_decoder_config().samples_per_second() / 100;
270 audio_parameters_.Reset( 273 audio_parameters_.Reset(
271 AudioParameters::AUDIO_PCM_LOW_LATENCY, 274 AudioParameters::AUDIO_PCM_LOW_LATENCY,
(...skipping 69 matching lines...) Expand 10 before | Expand all | Expand 10 after
341 344
342 // Some sinks play on start... 345 // Some sinks play on start...
343 sink_->Pause(); 346 sink_->Pause();
344 } 347 }
345 348
346 DCHECK(!sink_playing_); 349 DCHECK(!sink_playing_);
347 350
348 base::ResetAndReturn(&init_cb_).Run(PIPELINE_OK); 351 base::ResetAndReturn(&init_cb_).Run(PIPELINE_OK);
349 } 352 }
350 353
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
351 void AudioRendererImpl::SetVolume(float volume) { 371 void AudioRendererImpl::SetVolume(float volume) {
352 DCHECK(task_runner_->BelongsToCurrentThread()); 372 DCHECK(task_runner_->BelongsToCurrentThread());
353 DCHECK(sink_); 373 DCHECK(sink_);
354 sink_->SetVolume(volume); 374 sink_->SetVolume(volume);
355 } 375 }
356 376
357 void AudioRendererImpl::DecodedAudioReady( 377 void AudioRendererImpl::DecodedAudioReady(
358 AudioBufferStream::Status status, 378 AudioBufferStream::Status status,
359 const scoped_refptr<AudioBuffer>& buffer) { 379 const scoped_refptr<AudioBuffer>& buffer) {
360 DVLOG(2) << __FUNCTION__ << "(" << status << ")"; 380 DVLOG(2) << __FUNCTION__ << "(" << status << ")";
(...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after
402 } 422 }
403 } 423 }
404 424
405 if (!splicer_->HasNextBuffer()) { 425 if (!splicer_->HasNextBuffer()) {
406 AttemptRead_Locked(); 426 AttemptRead_Locked();
407 return; 427 return;
408 } 428 }
409 429
410 bool need_another_buffer = false; 430 bool need_another_buffer = false;
411 while (splicer_->HasNextBuffer()) 431 while (splicer_->HasNextBuffer())
412 need_another_buffer = HandleSplicerBuffer_Locked(splicer_->GetNextBuffer()); 432 need_another_buffer = HandleSplicerBuffer(splicer_->GetNextBuffer());
413 433
414 if (!need_another_buffer && !CanRead_Locked()) 434 if (!need_another_buffer && !CanRead_Locked())
415 return; 435 return;
416 436
417 AttemptRead_Locked(); 437 AttemptRead_Locked();
418 } 438 }
419 439
420 bool AudioRendererImpl::HandleSplicerBuffer_Locked( 440 bool AudioRendererImpl::HandleSplicerBuffer(
421 const scoped_refptr<AudioBuffer>& buffer) { 441 const scoped_refptr<AudioBuffer>& buffer) {
422 lock_.AssertAcquired();
423 if (buffer->end_of_stream()) { 442 if (buffer->end_of_stream()) {
424 received_end_of_stream_ = true; 443 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);
425 } else { 449 } else {
426 if (state_ == kPlaying) { 450 if (state_ == kPrerolling) {
427 if (IsBeforeStartTime(buffer)) 451 if (IsBeforePrerollTime(buffer))
428 return true; 452 return true;
429 453
430 // Trim off any additional time before the start timestamp. 454 // Trim off any additional time before the preroll timestamp.
431 const base::TimeDelta trim_time = start_timestamp_ - buffer->timestamp(); 455 const base::TimeDelta trim_time =
456 preroll_timestamp_ - buffer->timestamp();
432 if (trim_time > base::TimeDelta()) { 457 if (trim_time > base::TimeDelta()) {
433 buffer->TrimStart(buffer->frame_count() * 458 buffer->TrimStart(buffer->frame_count() *
434 (static_cast<double>(trim_time.InMicroseconds()) / 459 (static_cast<double>(trim_time.InMicroseconds()) /
435 buffer->duration().InMicroseconds())); 460 buffer->duration().InMicroseconds()));
436 } 461 }
437 // If the entire buffer was trimmed, request a new one. 462 // If the entire buffer was trimmed, request a new one.
438 if (!buffer->frame_count()) 463 if (!buffer->frame_count())
439 return true; 464 return true;
440 } 465 }
441 466
442 if (state_ != kUninitialized && state_ != kStopped) 467 if (state_ != kUninitialized && state_ != kStopped)
443 algorithm_->EnqueueBuffer(buffer); 468 algorithm_->EnqueueBuffer(buffer);
444 } 469 }
445 470
446 switch (state_) { 471 switch (state_) {
447 case kUninitialized: 472 case kUninitialized:
448 case kInitializing: 473 case kInitializing:
449 case kFlushing: 474 case kFlushing:
450 NOTREACHED(); 475 NOTREACHED();
451 return false; 476 return false;
452 477
453 case kFlushed: 478 case kFlushed:
454 DCHECK(!pending_read_); 479 DCHECK(!pending_read_);
455 return false; 480 return false;
456 481
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
457 case kPlaying: 489 case kPlaying:
458 if (buffer->end_of_stream() || algorithm_->IsQueueFull()) { 490 case kUnderflow:
459 if (buffering_state_ == BUFFERING_HAVE_NOTHING) 491 return false;
460 SetBufferingState_Locked(BUFFERING_HAVE_ENOUGH); 492
461 return false; 493 case kRebuffering:
462 } 494 if (!algorithm_->IsQueueFull())
463 return true; 495 return true;
496 ChangeState_Locked(kPlaying);
497 return false;
464 498
465 case kStopped: 499 case kStopped:
466 return false; 500 return false;
467 } 501 }
468 return false; 502 return false;
469 } 503 }
470 504
471 void AudioRendererImpl::AttemptRead() { 505 void AudioRendererImpl::AttemptRead() {
472 base::AutoLock auto_lock(lock_); 506 base::AutoLock auto_lock(lock_);
473 AttemptRead_Locked(); 507 AttemptRead_Locked();
(...skipping 10 matching lines...) Expand all
484 audio_buffer_stream_.Read(base::Bind(&AudioRendererImpl::DecodedAudioReady, 518 audio_buffer_stream_.Read(base::Bind(&AudioRendererImpl::DecodedAudioReady,
485 weak_factory_.GetWeakPtr())); 519 weak_factory_.GetWeakPtr()));
486 } 520 }
487 521
488 bool AudioRendererImpl::CanRead_Locked() { 522 bool AudioRendererImpl::CanRead_Locked() {
489 lock_.AssertAcquired(); 523 lock_.AssertAcquired();
490 524
491 switch (state_) { 525 switch (state_) {
492 case kUninitialized: 526 case kUninitialized:
493 case kInitializing: 527 case kInitializing:
528 case kFlushed:
494 case kFlushing: 529 case kFlushing:
495 case kFlushed:
496 case kStopped: 530 case kStopped:
497 return false; 531 return false;
498 532
533 case kPrerolling:
499 case kPlaying: 534 case kPlaying:
535 case kUnderflow:
536 case kRebuffering:
500 break; 537 break;
501 } 538 }
502 539
503 return !pending_read_ && !received_end_of_stream_ && 540 return !pending_read_ && !received_end_of_stream_ &&
504 !algorithm_->IsQueueFull(); 541 !algorithm_->IsQueueFull();
505 } 542 }
506 543
507 void AudioRendererImpl::SetPlaybackRate(float playback_rate) { 544 void AudioRendererImpl::SetPlaybackRate(float playback_rate) {
508 DVLOG(1) << __FUNCTION__ << "(" << playback_rate << ")"; 545 DVLOG(1) << __FUNCTION__ << "(" << playback_rate << ")";
509 DCHECK(task_runner_->BelongsToCurrentThread()); 546 DCHECK(task_runner_->BelongsToCurrentThread());
(...skipping 15 matching lines...) Expand all
525 StartRendering_Locked(); 562 StartRendering_Locked();
526 return; 563 return;
527 } 564 }
528 565
529 if (current_playback_rate != 0 && playback_rate == 0) { 566 if (current_playback_rate != 0 && playback_rate == 0) {
530 StopRendering_Locked(); 567 StopRendering_Locked();
531 return; 568 return;
532 } 569 }
533 } 570 }
534 571
535 bool AudioRendererImpl::IsBeforeStartTime( 572 bool AudioRendererImpl::IsBeforePrerollTime(
536 const scoped_refptr<AudioBuffer>& buffer) { 573 const scoped_refptr<AudioBuffer>& buffer) {
537 DCHECK_EQ(state_, kPlaying); 574 DCHECK_EQ(state_, kPrerolling);
538 return buffer && !buffer->end_of_stream() && 575 return buffer && !buffer->end_of_stream() &&
539 (buffer->timestamp() + buffer->duration()) < start_timestamp_; 576 (buffer->timestamp() + buffer->duration()) < preroll_timestamp_;
540 } 577 }
541 578
542 int AudioRendererImpl::Render(AudioBus* audio_bus, 579 int AudioRendererImpl::Render(AudioBus* audio_bus,
543 int audio_delay_milliseconds) { 580 int audio_delay_milliseconds) {
544 const int requested_frames = audio_bus->frames(); 581 const int requested_frames = audio_bus->frames();
545 base::TimeDelta playback_delay = base::TimeDelta::FromMilliseconds( 582 base::TimeDelta playback_delay = base::TimeDelta::FromMilliseconds(
546 audio_delay_milliseconds); 583 audio_delay_milliseconds);
547 const int delay_frames = static_cast<int>(playback_delay.InSecondsF() * 584 const int delay_frames = static_cast<int>(playback_delay.InSecondsF() *
548 audio_parameters_.sample_rate()); 585 audio_parameters_.sample_rate());
549 int frames_written = 0; 586 int frames_written = 0;
550 base::Closure time_cb; 587 base::Closure time_cb;
588 base::Closure underflow_cb;
551 { 589 {
552 base::AutoLock auto_lock(lock_); 590 base::AutoLock auto_lock(lock_);
553 591
554 // Ensure Stop() hasn't destroyed our |algorithm_| on the pipeline thread. 592 // Ensure Stop() hasn't destroyed our |algorithm_| on the pipeline thread.
555 if (!algorithm_) { 593 if (!algorithm_) {
556 audio_clock_->WroteSilence(requested_frames, delay_frames); 594 audio_clock_->WroteSilence(requested_frames, delay_frames);
557 return 0; 595 return 0;
558 } 596 }
559 597
560 float playback_rate = algorithm_->playback_rate(); 598 float playback_rate = algorithm_->playback_rate();
(...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after
594 audio_clock_->WroteSilence(requested_frames - frames_written, delay_frames); 632 audio_clock_->WroteSilence(requested_frames - frames_written, delay_frames);
595 633
596 if (frames_written == 0) { 634 if (frames_written == 0) {
597 const base::TimeTicks now = now_cb_.Run(); 635 const base::TimeTicks now = now_cb_.Run();
598 636
599 if (received_end_of_stream_ && !rendered_end_of_stream_ && 637 if (received_end_of_stream_ && !rendered_end_of_stream_ &&
600 now >= earliest_end_time_) { 638 now >= earliest_end_time_) {
601 rendered_end_of_stream_ = true; 639 rendered_end_of_stream_ = true;
602 ended_cb_.Run(); 640 ended_cb_.Run();
603 } else if (!received_end_of_stream_ && state_ == kPlaying) { 641 } else if (!received_end_of_stream_ && state_ == kPlaying) {
604 if (buffering_state_ != BUFFERING_HAVE_NOTHING) { 642 ChangeState_Locked(kUnderflow);
605 algorithm_->IncreaseQueueCapacity(); 643 underflow_cb = underflow_cb_;
606 SetBufferingState_Locked(BUFFERING_HAVE_NOTHING);
607 }
608 } else { 644 } else {
609 // We can't write any data this cycle. For example, we may have 645 // We can't write any data this cycle. For example, we may have
610 // sent all available data to the audio device while not reaching 646 // sent all available data to the audio device while not reaching
611 // |earliest_end_time_|. 647 // |earliest_end_time_|.
612 } 648 }
613 } 649 }
614 650
615 if (CanRead_Locked()) { 651 if (CanRead_Locked()) {
616 task_runner_->PostTask(FROM_HERE, 652 task_runner_->PostTask(FROM_HERE,
617 base::Bind(&AudioRendererImpl::AttemptRead, 653 base::Bind(&AudioRendererImpl::AttemptRead,
(...skipping 12 matching lines...) Expand all
630 666
631 if (frames_written > 0) { 667 if (frames_written > 0) {
632 UpdateEarliestEndTime_Locked( 668 UpdateEarliestEndTime_Locked(
633 frames_written, playback_delay, now_cb_.Run()); 669 frames_written, playback_delay, now_cb_.Run());
634 } 670 }
635 } 671 }
636 672
637 if (!time_cb.is_null()) 673 if (!time_cb.is_null())
638 time_cb.Run(); 674 time_cb.Run();
639 675
676 if (!underflow_cb.is_null())
677 underflow_cb.Run();
678
640 DCHECK_LE(frames_written, requested_frames); 679 DCHECK_LE(frames_written, requested_frames);
641 return frames_written; 680 return frames_written;
642 } 681 }
643 682
644 void AudioRendererImpl::UpdateEarliestEndTime_Locked( 683 void AudioRendererImpl::UpdateEarliestEndTime_Locked(
645 int frames_filled, const base::TimeDelta& playback_delay, 684 int frames_filled, const base::TimeDelta& playback_delay,
646 const base::TimeTicks& time_now) { 685 const base::TimeTicks& time_now) {
647 DCHECK_GT(frames_filled, 0); 686 DCHECK_GT(frames_filled, 0);
648 687
649 base::TimeDelta predicted_play_time = base::TimeDelta::FromMicroseconds( 688 base::TimeDelta predicted_play_time = base::TimeDelta::FromMicroseconds(
(...skipping 18 matching lines...) Expand all
668 lock_.AssertAcquired(); 707 lock_.AssertAcquired();
669 708
670 PipelineStatus status = is_decode_error ? PIPELINE_ERROR_DECODE : PIPELINE_OK; 709 PipelineStatus status = is_decode_error ? PIPELINE_ERROR_DECODE : PIPELINE_OK;
671 switch (state_) { 710 switch (state_) {
672 case kUninitialized: 711 case kUninitialized:
673 case kInitializing: 712 case kInitializing:
674 NOTREACHED(); 713 NOTREACHED();
675 return; 714 return;
676 case kFlushing: 715 case kFlushing:
677 ChangeState_Locked(kFlushed); 716 ChangeState_Locked(kFlushed);
717
678 if (status == PIPELINE_OK) { 718 if (status == PIPELINE_OK) {
679 DoFlush_Locked(); 719 DoFlush_Locked();
680 return; 720 return;
681 } 721 }
682 722
683 error_cb_.Run(status); 723 error_cb_.Run(status);
684 base::ResetAndReturn(&flush_cb_).Run(); 724 base::ResetAndReturn(&flush_cb_).Run();
685 return; 725 return;
686 726 case kPrerolling:
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;
687 case kFlushed: 732 case kFlushed:
688 case kPlaying: 733 case kPlaying:
734 case kUnderflow:
735 case kRebuffering:
689 case kStopped: 736 case kStopped:
690 if (status != PIPELINE_OK) 737 if (status != PIPELINE_OK)
691 error_cb_.Run(status); 738 error_cb_.Run(status);
692 return; 739 return;
693 } 740 }
694 } 741 }
695 742
696 void AudioRendererImpl::ChangeState_Locked(State new_state) { 743 void AudioRendererImpl::ChangeState_Locked(State new_state) {
697 DVLOG(1) << __FUNCTION__ << " : " << state_ << " -> " << new_state; 744 DVLOG(1) << __FUNCTION__ << " : " << state_ << " -> " << new_state;
698 lock_.AssertAcquired(); 745 lock_.AssertAcquired();
699 state_ = new_state; 746 state_ = new_state;
700 } 747 }
701 748
702 void AudioRendererImpl::OnNewSpliceBuffer(base::TimeDelta splice_timestamp) { 749 void AudioRendererImpl::OnNewSpliceBuffer(base::TimeDelta splice_timestamp) {
703 DCHECK(task_runner_->BelongsToCurrentThread()); 750 DCHECK(task_runner_->BelongsToCurrentThread());
704 splicer_->SetSpliceTimestamp(splice_timestamp); 751 splicer_->SetSpliceTimestamp(splice_timestamp);
705 } 752 }
706 753
707 void AudioRendererImpl::OnConfigChange() { 754 void AudioRendererImpl::OnConfigChange() {
708 DCHECK(task_runner_->BelongsToCurrentThread()); 755 DCHECK(task_runner_->BelongsToCurrentThread());
709 DCHECK(expecting_config_changes_); 756 DCHECK(expecting_config_changes_);
710 buffer_converter_->ResetTimestampState(); 757 buffer_converter_->ResetTimestampState();
711 // Drain flushed buffers from the converter so the AudioSplicer receives all 758 // Drain flushed buffers from the converter so the AudioSplicer receives all
712 // data ahead of any OnNewSpliceBuffer() calls. Since discontinuities should 759 // data ahead of any OnNewSpliceBuffer() calls. Since discontinuities should
713 // only appear after config changes, AddInput() should never fail here. 760 // only appear after config changes, AddInput() should never fail here.
714 while (buffer_converter_->HasNextBuffer()) 761 while (buffer_converter_->HasNextBuffer())
715 CHECK(splicer_->AddInput(buffer_converter_->GetNextBuffer())); 762 CHECK(splicer_->AddInput(buffer_converter_->GetNextBuffer()));
716 } 763 }
717 764
718 void AudioRendererImpl::SetBufferingState_Locked(
719 BufferingState buffering_state) {
720 DVLOG(1) << __FUNCTION__ << " : " << buffering_state_ << " -> "
721 << buffering_state;
722 DCHECK_NE(buffering_state_, buffering_state);
723 lock_.AssertAcquired();
724 buffering_state_ = buffering_state;
725 buffering_state_cb_.Run(buffering_state_);
726 }
727
728 } // namespace media 765 } // namespace media
OLDNEW
« no previous file with comments | « media/filters/audio_renderer_impl.h ('k') | media/filters/audio_renderer_impl_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698