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

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