OLD | NEW |
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 49 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
60 received_end_of_stream_(false), | 60 received_end_of_stream_(false), |
61 rendered_end_of_stream_(false), | 61 rendered_end_of_stream_(false), |
62 weak_factory_(this) { | 62 weak_factory_(this) { |
63 audio_buffer_stream_->set_splice_observer(base::Bind( | 63 audio_buffer_stream_->set_splice_observer(base::Bind( |
64 &AudioRendererImpl::OnNewSpliceBuffer, weak_factory_.GetWeakPtr())); | 64 &AudioRendererImpl::OnNewSpliceBuffer, weak_factory_.GetWeakPtr())); |
65 audio_buffer_stream_->set_config_change_observer(base::Bind( | 65 audio_buffer_stream_->set_config_change_observer(base::Bind( |
66 &AudioRendererImpl::OnConfigChange, weak_factory_.GetWeakPtr())); | 66 &AudioRendererImpl::OnConfigChange, weak_factory_.GetWeakPtr())); |
67 } | 67 } |
68 | 68 |
69 AudioRendererImpl::~AudioRendererImpl() { | 69 AudioRendererImpl::~AudioRendererImpl() { |
70 // Stop() should have been called and |algorithm_| should have been destroyed. | 70 DVLOG(1) << __FUNCTION__; |
71 DCHECK(state_ == kUninitialized || state_ == kStopped); | 71 DCHECK(task_runner_->BelongsToCurrentThread()); |
72 DCHECK(!algorithm_.get()); | 72 |
| 73 // If Render() is in progress, this call will wait for Render() to finish. |
| 74 // After this call, the |sink_| will not call back into |this| anymore. |
| 75 sink_->Stop(); |
| 76 |
| 77 if (!init_cb_.is_null()) |
| 78 base::ResetAndReturn(&init_cb_).Run(PIPELINE_ERROR_ABORT); |
73 } | 79 } |
74 | 80 |
75 void AudioRendererImpl::StartTicking() { | 81 void AudioRendererImpl::StartTicking() { |
76 DVLOG(1) << __FUNCTION__; | 82 DVLOG(1) << __FUNCTION__; |
77 DCHECK(task_runner_->BelongsToCurrentThread()); | 83 DCHECK(task_runner_->BelongsToCurrentThread()); |
78 DCHECK(!rendering_); | 84 DCHECK(!rendering_); |
79 rendering_ = true; | 85 rendering_ = true; |
80 | 86 |
81 base::AutoLock auto_lock(lock_); | 87 base::AutoLock auto_lock(lock_); |
82 // Wait for an eventual call to SetPlaybackRate() to start rendering. | 88 // Wait for an eventual call to SetPlaybackRate() to start rendering. |
(...skipping 99 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
182 DCHECK_EQ(state_, kFlushed); | 188 DCHECK_EQ(state_, kFlushed); |
183 | 189 |
184 audio_buffer_stream_->Reset(base::Bind(&AudioRendererImpl::ResetDecoderDone, | 190 audio_buffer_stream_->Reset(base::Bind(&AudioRendererImpl::ResetDecoderDone, |
185 weak_factory_.GetWeakPtr())); | 191 weak_factory_.GetWeakPtr())); |
186 } | 192 } |
187 | 193 |
188 void AudioRendererImpl::ResetDecoderDone() { | 194 void AudioRendererImpl::ResetDecoderDone() { |
189 DCHECK(task_runner_->BelongsToCurrentThread()); | 195 DCHECK(task_runner_->BelongsToCurrentThread()); |
190 { | 196 { |
191 base::AutoLock auto_lock(lock_); | 197 base::AutoLock auto_lock(lock_); |
192 if (state_ == kStopped) | |
193 return; | |
194 | 198 |
195 DCHECK_EQ(state_, kFlushed); | 199 DCHECK_EQ(state_, kFlushed); |
196 DCHECK(!flush_cb_.is_null()); | 200 DCHECK(!flush_cb_.is_null()); |
197 | 201 |
198 audio_clock_.reset(new AudioClock(audio_parameters_.sample_rate())); | 202 audio_clock_.reset(new AudioClock(audio_parameters_.sample_rate())); |
199 received_end_of_stream_ = false; | 203 received_end_of_stream_ = false; |
200 rendered_end_of_stream_ = false; | 204 rendered_end_of_stream_ = false; |
201 | 205 |
202 // Flush() may have been called while underflowed/not fully buffered. | 206 // Flush() may have been called while underflowed/not fully buffered. |
203 if (buffering_state_ != BUFFERING_HAVE_NOTHING) | 207 if (buffering_state_ != BUFFERING_HAVE_NOTHING) |
204 SetBufferingState_Locked(BUFFERING_HAVE_NOTHING); | 208 SetBufferingState_Locked(BUFFERING_HAVE_NOTHING); |
205 | 209 |
206 splicer_->Reset(); | 210 splicer_->Reset(); |
207 if (buffer_converter_) | 211 if (buffer_converter_) |
208 buffer_converter_->Reset(); | 212 buffer_converter_->Reset(); |
209 algorithm_->FlushBuffers(); | 213 algorithm_->FlushBuffers(); |
210 } | 214 } |
211 | 215 |
212 // Changes in buffering state are always posted. Flush callback must only be | 216 // Changes in buffering state are always posted. Flush callback must only be |
213 // run after buffering state has been set back to nothing. | 217 // run after buffering state has been set back to nothing. |
214 task_runner_->PostTask(FROM_HERE, base::ResetAndReturn(&flush_cb_)); | 218 task_runner_->PostTask(FROM_HERE, base::ResetAndReturn(&flush_cb_)); |
215 } | 219 } |
216 | 220 |
217 void AudioRendererImpl::Stop(const base::Closure& callback) { | |
218 DVLOG(1) << __FUNCTION__; | |
219 DCHECK(task_runner_->BelongsToCurrentThread()); | |
220 DCHECK(!callback.is_null()); | |
221 | |
222 // TODO(scherkus): Consider invalidating |weak_factory_| and replacing | |
223 // task-running guards that check |state_| with DCHECK(). | |
224 | |
225 { | |
226 base::AutoLock auto_lock(lock_); | |
227 | |
228 if (state_ == kStopped) { | |
229 task_runner_->PostTask(FROM_HERE, callback); | |
230 return; | |
231 } | |
232 | |
233 ChangeState_Locked(kStopped); | |
234 algorithm_.reset(); | |
235 time_cb_.Reset(); | |
236 flush_cb_.Reset(); | |
237 } | |
238 | |
239 if (sink_) { | |
240 sink_->Stop(); | |
241 sink_ = NULL; | |
242 } | |
243 | |
244 audio_buffer_stream_.reset(); | |
245 task_runner_->PostTask(FROM_HERE, callback); | |
246 } | |
247 | |
248 void AudioRendererImpl::StartPlaying() { | 221 void AudioRendererImpl::StartPlaying() { |
249 DVLOG(1) << __FUNCTION__; | 222 DVLOG(1) << __FUNCTION__; |
250 DCHECK(task_runner_->BelongsToCurrentThread()); | 223 DCHECK(task_runner_->BelongsToCurrentThread()); |
251 | 224 |
252 base::AutoLock auto_lock(lock_); | 225 base::AutoLock auto_lock(lock_); |
253 DCHECK(!sink_playing_); | 226 DCHECK(!sink_playing_); |
254 DCHECK_EQ(state_, kFlushed); | 227 DCHECK_EQ(state_, kFlushed); |
255 DCHECK_EQ(buffering_state_, BUFFERING_HAVE_NOTHING); | 228 DCHECK_EQ(buffering_state_, BUFFERING_HAVE_NOTHING); |
256 DCHECK(!pending_read_) << "Pending read must complete before seeking"; | 229 DCHECK(!pending_read_) << "Pending read must complete before seeking"; |
257 | 230 |
(...skipping 69 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
327 statistics_cb, | 300 statistics_cb, |
328 base::Bind(&AudioRendererImpl::OnAudioBufferStreamInitialized, | 301 base::Bind(&AudioRendererImpl::OnAudioBufferStreamInitialized, |
329 weak_factory_.GetWeakPtr())); | 302 weak_factory_.GetWeakPtr())); |
330 } | 303 } |
331 | 304 |
332 void AudioRendererImpl::OnAudioBufferStreamInitialized(bool success) { | 305 void AudioRendererImpl::OnAudioBufferStreamInitialized(bool success) { |
333 DCHECK(task_runner_->BelongsToCurrentThread()); | 306 DCHECK(task_runner_->BelongsToCurrentThread()); |
334 | 307 |
335 base::AutoLock auto_lock(lock_); | 308 base::AutoLock auto_lock(lock_); |
336 | 309 |
337 if (state_ == kStopped) { | |
338 base::ResetAndReturn(&init_cb_).Run(PIPELINE_ERROR_ABORT); | |
339 return; | |
340 } | |
341 | |
342 if (!success) { | 310 if (!success) { |
343 state_ = kUninitialized; | 311 state_ = kUninitialized; |
344 base::ResetAndReturn(&init_cb_).Run(DECODER_ERROR_NOT_SUPPORTED); | 312 base::ResetAndReturn(&init_cb_).Run(DECODER_ERROR_NOT_SUPPORTED); |
345 return; | 313 return; |
346 } | 314 } |
347 | 315 |
348 if (!audio_parameters_.IsValid()) { | 316 if (!audio_parameters_.IsValid()) { |
349 ChangeState_Locked(kUninitialized); | 317 ChangeState_Locked(kUninitialized); |
350 base::ResetAndReturn(&init_cb_).Run(PIPELINE_ERROR_INITIALIZATION_FAILED); | 318 base::ResetAndReturn(&init_cb_).Run(PIPELINE_ERROR_INITIALIZATION_FAILED); |
351 return; | 319 return; |
(...skipping 110 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
462 if (trim_time > base::TimeDelta()) { | 430 if (trim_time > base::TimeDelta()) { |
463 buffer->TrimStart(buffer->frame_count() * | 431 buffer->TrimStart(buffer->frame_count() * |
464 (static_cast<double>(trim_time.InMicroseconds()) / | 432 (static_cast<double>(trim_time.InMicroseconds()) / |
465 buffer->duration().InMicroseconds())); | 433 buffer->duration().InMicroseconds())); |
466 } | 434 } |
467 // If the entire buffer was trimmed, request a new one. | 435 // If the entire buffer was trimmed, request a new one. |
468 if (!buffer->frame_count()) | 436 if (!buffer->frame_count()) |
469 return true; | 437 return true; |
470 } | 438 } |
471 | 439 |
472 if (state_ != kUninitialized && state_ != kStopped) | 440 if (state_ != kUninitialized) |
473 algorithm_->EnqueueBuffer(buffer); | 441 algorithm_->EnqueueBuffer(buffer); |
474 } | 442 } |
475 | 443 |
476 switch (state_) { | 444 switch (state_) { |
477 case kUninitialized: | 445 case kUninitialized: |
478 case kInitializing: | 446 case kInitializing: |
479 case kFlushing: | 447 case kFlushing: |
480 NOTREACHED(); | 448 NOTREACHED(); |
481 return false; | 449 return false; |
482 | 450 |
483 case kFlushed: | 451 case kFlushed: |
484 DCHECK(!pending_read_); | 452 DCHECK(!pending_read_); |
485 return false; | 453 return false; |
486 | 454 |
487 case kPlaying: | 455 case kPlaying: |
488 if (buffer->end_of_stream() || algorithm_->IsQueueFull()) { | 456 if (buffer->end_of_stream() || algorithm_->IsQueueFull()) { |
489 if (buffering_state_ == BUFFERING_HAVE_NOTHING) | 457 if (buffering_state_ == BUFFERING_HAVE_NOTHING) |
490 SetBufferingState_Locked(BUFFERING_HAVE_ENOUGH); | 458 SetBufferingState_Locked(BUFFERING_HAVE_ENOUGH); |
491 return false; | 459 return false; |
492 } | 460 } |
493 return true; | 461 return true; |
494 | |
495 case kStopped: | |
496 return false; | |
497 } | 462 } |
498 return false; | 463 return false; |
499 } | 464 } |
500 | 465 |
501 void AudioRendererImpl::AttemptRead() { | 466 void AudioRendererImpl::AttemptRead() { |
502 base::AutoLock auto_lock(lock_); | 467 base::AutoLock auto_lock(lock_); |
503 AttemptRead_Locked(); | 468 AttemptRead_Locked(); |
504 } | 469 } |
505 | 470 |
506 void AudioRendererImpl::AttemptRead_Locked() { | 471 void AudioRendererImpl::AttemptRead_Locked() { |
507 DCHECK(task_runner_->BelongsToCurrentThread()); | 472 DCHECK(task_runner_->BelongsToCurrentThread()); |
508 lock_.AssertAcquired(); | 473 lock_.AssertAcquired(); |
509 | 474 |
510 if (!CanRead_Locked()) | 475 if (!CanRead_Locked()) |
511 return; | 476 return; |
512 | 477 |
513 pending_read_ = true; | 478 pending_read_ = true; |
514 audio_buffer_stream_->Read(base::Bind(&AudioRendererImpl::DecodedAudioReady, | 479 audio_buffer_stream_->Read(base::Bind(&AudioRendererImpl::DecodedAudioReady, |
515 weak_factory_.GetWeakPtr())); | 480 weak_factory_.GetWeakPtr())); |
516 } | 481 } |
517 | 482 |
518 bool AudioRendererImpl::CanRead_Locked() { | 483 bool AudioRendererImpl::CanRead_Locked() { |
519 lock_.AssertAcquired(); | 484 lock_.AssertAcquired(); |
520 | 485 |
521 switch (state_) { | 486 switch (state_) { |
522 case kUninitialized: | 487 case kUninitialized: |
523 case kInitializing: | 488 case kInitializing: |
524 case kFlushing: | 489 case kFlushing: |
525 case kFlushed: | 490 case kFlushed: |
526 case kStopped: | |
527 return false; | 491 return false; |
528 | 492 |
529 case kPlaying: | 493 case kPlaying: |
530 break; | 494 break; |
531 } | 495 } |
532 | 496 |
533 return !pending_read_ && !received_end_of_stream_ && | 497 return !pending_read_ && !received_end_of_stream_ && |
534 !algorithm_->IsQueueFull(); | 498 !algorithm_->IsQueueFull(); |
535 } | 499 } |
536 | 500 |
(...skipping 146 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
683 DoFlush_Locked(); | 647 DoFlush_Locked(); |
684 return; | 648 return; |
685 } | 649 } |
686 | 650 |
687 error_cb_.Run(status); | 651 error_cb_.Run(status); |
688 base::ResetAndReturn(&flush_cb_).Run(); | 652 base::ResetAndReturn(&flush_cb_).Run(); |
689 return; | 653 return; |
690 | 654 |
691 case kFlushed: | 655 case kFlushed: |
692 case kPlaying: | 656 case kPlaying: |
693 case kStopped: | |
694 if (status != PIPELINE_OK) | 657 if (status != PIPELINE_OK) |
695 error_cb_.Run(status); | 658 error_cb_.Run(status); |
696 return; | 659 return; |
697 } | 660 } |
698 } | 661 } |
699 | 662 |
700 void AudioRendererImpl::ChangeState_Locked(State new_state) { | 663 void AudioRendererImpl::ChangeState_Locked(State new_state) { |
701 DVLOG(1) << __FUNCTION__ << " : " << state_ << " -> " << new_state; | 664 DVLOG(1) << __FUNCTION__ << " : " << state_ << " -> " << new_state; |
702 lock_.AssertAcquired(); | 665 lock_.AssertAcquired(); |
703 state_ = new_state; | 666 state_ = new_state; |
(...skipping 21 matching lines...) Expand all Loading... |
725 << buffering_state; | 688 << buffering_state; |
726 DCHECK_NE(buffering_state_, buffering_state); | 689 DCHECK_NE(buffering_state_, buffering_state); |
727 lock_.AssertAcquired(); | 690 lock_.AssertAcquired(); |
728 buffering_state_ = buffering_state; | 691 buffering_state_ = buffering_state; |
729 | 692 |
730 task_runner_->PostTask(FROM_HERE, | 693 task_runner_->PostTask(FROM_HERE, |
731 base::Bind(buffering_state_cb_, buffering_state_)); | 694 base::Bind(buffering_state_cb_, buffering_state_)); |
732 } | 695 } |
733 | 696 |
734 } // namespace media | 697 } // namespace media |
OLD | NEW |