| 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 |