Chromium Code Reviews| 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(); | |
|
DaleCurtis
2014/07/22 00:15:48
Correct, once this returns no further calls to the
| |
| 76 | |
| 77 if (!init_cb_.is_null()) | |
| 78 base::ResetAndReturn(&init_cb_).Run(PIPELINE_ERROR_ABORT); | |
| 73 } | 79 } |
| 74 | 80 |
| 75 void AudioRendererImpl::StartRendering() { | 81 void AudioRendererImpl::StartRendering() { |
| 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 84 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 167 DCHECK_EQ(state_, kFlushed); | 173 DCHECK_EQ(state_, kFlushed); |
| 168 | 174 |
| 169 audio_buffer_stream_->Reset(base::Bind(&AudioRendererImpl::ResetDecoderDone, | 175 audio_buffer_stream_->Reset(base::Bind(&AudioRendererImpl::ResetDecoderDone, |
| 170 weak_factory_.GetWeakPtr())); | 176 weak_factory_.GetWeakPtr())); |
| 171 } | 177 } |
| 172 | 178 |
| 173 void AudioRendererImpl::ResetDecoderDone() { | 179 void AudioRendererImpl::ResetDecoderDone() { |
| 174 DCHECK(task_runner_->BelongsToCurrentThread()); | 180 DCHECK(task_runner_->BelongsToCurrentThread()); |
| 175 { | 181 { |
| 176 base::AutoLock auto_lock(lock_); | 182 base::AutoLock auto_lock(lock_); |
| 177 if (state_ == kStopped) | |
| 178 return; | |
| 179 | 183 |
| 180 DCHECK_EQ(state_, kFlushed); | 184 DCHECK_EQ(state_, kFlushed); |
| 181 DCHECK(!flush_cb_.is_null()); | 185 DCHECK(!flush_cb_.is_null()); |
| 182 | 186 |
| 183 audio_clock_.reset(new AudioClock(audio_parameters_.sample_rate())); | 187 audio_clock_.reset(new AudioClock(audio_parameters_.sample_rate())); |
| 184 received_end_of_stream_ = false; | 188 received_end_of_stream_ = false; |
| 185 rendered_end_of_stream_ = false; | 189 rendered_end_of_stream_ = false; |
| 186 | 190 |
| 187 // Flush() may have been called while underflowed/not fully buffered. | 191 // Flush() may have been called while underflowed/not fully buffered. |
| 188 if (buffering_state_ != BUFFERING_HAVE_NOTHING) | 192 if (buffering_state_ != BUFFERING_HAVE_NOTHING) |
| 189 SetBufferingState_Locked(BUFFERING_HAVE_NOTHING); | 193 SetBufferingState_Locked(BUFFERING_HAVE_NOTHING); |
| 190 | 194 |
| 191 splicer_->Reset(); | 195 splicer_->Reset(); |
| 192 if (buffer_converter_) | 196 if (buffer_converter_) |
| 193 buffer_converter_->Reset(); | 197 buffer_converter_->Reset(); |
| 194 algorithm_->FlushBuffers(); | 198 algorithm_->FlushBuffers(); |
| 195 } | 199 } |
| 196 | 200 |
| 197 // Changes in buffering state are always posted. Flush callback must only be | 201 // Changes in buffering state are always posted. Flush callback must only be |
| 198 // run after buffering state has been set back to nothing. | 202 // run after buffering state has been set back to nothing. |
| 199 task_runner_->PostTask(FROM_HERE, base::ResetAndReturn(&flush_cb_)); | 203 task_runner_->PostTask(FROM_HERE, base::ResetAndReturn(&flush_cb_)); |
| 200 } | 204 } |
| 201 | 205 |
| 202 void AudioRendererImpl::Stop(const base::Closure& callback) { | |
| 203 DVLOG(1) << __FUNCTION__; | |
| 204 DCHECK(task_runner_->BelongsToCurrentThread()); | |
| 205 DCHECK(!callback.is_null()); | |
| 206 | |
| 207 // TODO(scherkus): Consider invalidating |weak_factory_| and replacing | |
| 208 // task-running guards that check |state_| with DCHECK(). | |
| 209 | |
| 210 { | |
| 211 base::AutoLock auto_lock(lock_); | |
| 212 | |
| 213 if (state_ == kStopped) { | |
| 214 task_runner_->PostTask(FROM_HERE, callback); | |
| 215 return; | |
| 216 } | |
| 217 | |
| 218 ChangeState_Locked(kStopped); | |
| 219 algorithm_.reset(); | |
| 220 time_cb_.Reset(); | |
| 221 flush_cb_.Reset(); | |
| 222 } | |
| 223 | |
| 224 if (sink_) { | |
| 225 sink_->Stop(); | |
| 226 sink_ = NULL; | |
| 227 } | |
| 228 | |
| 229 audio_buffer_stream_.reset(); | |
| 230 task_runner_->PostTask(FROM_HERE, callback); | |
| 231 } | |
| 232 | |
| 233 void AudioRendererImpl::StartPlaying() { | 206 void AudioRendererImpl::StartPlaying() { |
| 234 DVLOG(1) << __FUNCTION__; | 207 DVLOG(1) << __FUNCTION__; |
| 235 DCHECK(task_runner_->BelongsToCurrentThread()); | 208 DCHECK(task_runner_->BelongsToCurrentThread()); |
| 236 | 209 |
| 237 base::AutoLock auto_lock(lock_); | 210 base::AutoLock auto_lock(lock_); |
| 238 DCHECK(!sink_playing_); | 211 DCHECK(!sink_playing_); |
| 239 DCHECK_EQ(state_, kFlushed); | 212 DCHECK_EQ(state_, kFlushed); |
| 240 DCHECK_EQ(buffering_state_, BUFFERING_HAVE_NOTHING); | 213 DCHECK_EQ(buffering_state_, BUFFERING_HAVE_NOTHING); |
| 241 DCHECK(!pending_read_) << "Pending read must complete before seeking"; | 214 DCHECK(!pending_read_) << "Pending read must complete before seeking"; |
| 242 | 215 |
| (...skipping 69 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 312 statistics_cb, | 285 statistics_cb, |
| 313 base::Bind(&AudioRendererImpl::OnAudioBufferStreamInitialized, | 286 base::Bind(&AudioRendererImpl::OnAudioBufferStreamInitialized, |
| 314 weak_factory_.GetWeakPtr())); | 287 weak_factory_.GetWeakPtr())); |
| 315 } | 288 } |
| 316 | 289 |
| 317 void AudioRendererImpl::OnAudioBufferStreamInitialized(bool success) { | 290 void AudioRendererImpl::OnAudioBufferStreamInitialized(bool success) { |
| 318 DCHECK(task_runner_->BelongsToCurrentThread()); | 291 DCHECK(task_runner_->BelongsToCurrentThread()); |
| 319 | 292 |
| 320 base::AutoLock auto_lock(lock_); | 293 base::AutoLock auto_lock(lock_); |
| 321 | 294 |
| 322 if (state_ == kStopped) { | |
| 323 base::ResetAndReturn(&init_cb_).Run(PIPELINE_ERROR_ABORT); | |
| 324 return; | |
| 325 } | |
| 326 | |
| 327 if (!success) { | 295 if (!success) { |
| 328 state_ = kUninitialized; | 296 state_ = kUninitialized; |
| 329 base::ResetAndReturn(&init_cb_).Run(DECODER_ERROR_NOT_SUPPORTED); | 297 base::ResetAndReturn(&init_cb_).Run(DECODER_ERROR_NOT_SUPPORTED); |
| 330 return; | 298 return; |
| 331 } | 299 } |
| 332 | 300 |
| 333 if (!audio_parameters_.IsValid()) { | 301 if (!audio_parameters_.IsValid()) { |
| 334 ChangeState_Locked(kUninitialized); | 302 ChangeState_Locked(kUninitialized); |
| 335 base::ResetAndReturn(&init_cb_).Run(PIPELINE_ERROR_INITIALIZATION_FAILED); | 303 base::ResetAndReturn(&init_cb_).Run(PIPELINE_ERROR_INITIALIZATION_FAILED); |
| 336 return; | 304 return; |
| (...skipping 110 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 447 if (trim_time > base::TimeDelta()) { | 415 if (trim_time > base::TimeDelta()) { |
| 448 buffer->TrimStart(buffer->frame_count() * | 416 buffer->TrimStart(buffer->frame_count() * |
| 449 (static_cast<double>(trim_time.InMicroseconds()) / | 417 (static_cast<double>(trim_time.InMicroseconds()) / |
| 450 buffer->duration().InMicroseconds())); | 418 buffer->duration().InMicroseconds())); |
| 451 } | 419 } |
| 452 // If the entire buffer was trimmed, request a new one. | 420 // If the entire buffer was trimmed, request a new one. |
| 453 if (!buffer->frame_count()) | 421 if (!buffer->frame_count()) |
| 454 return true; | 422 return true; |
| 455 } | 423 } |
| 456 | 424 |
| 457 if (state_ != kUninitialized && state_ != kStopped) | 425 if (state_ != kUninitialized) |
| 458 algorithm_->EnqueueBuffer(buffer); | 426 algorithm_->EnqueueBuffer(buffer); |
| 459 } | 427 } |
| 460 | 428 |
| 461 switch (state_) { | 429 switch (state_) { |
| 462 case kUninitialized: | 430 case kUninitialized: |
| 463 case kInitializing: | 431 case kInitializing: |
| 464 case kFlushing: | 432 case kFlushing: |
| 465 NOTREACHED(); | 433 NOTREACHED(); |
| 466 return false; | 434 return false; |
| 467 | 435 |
| 468 case kFlushed: | 436 case kFlushed: |
| 469 DCHECK(!pending_read_); | 437 DCHECK(!pending_read_); |
| 470 return false; | 438 return false; |
| 471 | 439 |
| 472 case kPlaying: | 440 case kPlaying: |
| 473 if (buffer->end_of_stream() || algorithm_->IsQueueFull()) { | 441 if (buffer->end_of_stream() || algorithm_->IsQueueFull()) { |
| 474 if (buffering_state_ == BUFFERING_HAVE_NOTHING) | 442 if (buffering_state_ == BUFFERING_HAVE_NOTHING) |
| 475 SetBufferingState_Locked(BUFFERING_HAVE_ENOUGH); | 443 SetBufferingState_Locked(BUFFERING_HAVE_ENOUGH); |
| 476 return false; | 444 return false; |
| 477 } | 445 } |
| 478 return true; | 446 return true; |
| 479 | |
| 480 case kStopped: | |
| 481 return false; | |
| 482 } | 447 } |
| 483 return false; | 448 return false; |
| 484 } | 449 } |
| 485 | 450 |
| 486 void AudioRendererImpl::AttemptRead() { | 451 void AudioRendererImpl::AttemptRead() { |
| 487 base::AutoLock auto_lock(lock_); | 452 base::AutoLock auto_lock(lock_); |
| 488 AttemptRead_Locked(); | 453 AttemptRead_Locked(); |
| 489 } | 454 } |
| 490 | 455 |
| 491 void AudioRendererImpl::AttemptRead_Locked() { | 456 void AudioRendererImpl::AttemptRead_Locked() { |
| 492 DCHECK(task_runner_->BelongsToCurrentThread()); | 457 DCHECK(task_runner_->BelongsToCurrentThread()); |
| 493 lock_.AssertAcquired(); | 458 lock_.AssertAcquired(); |
| 494 | 459 |
| 495 if (!CanRead_Locked()) | 460 if (!CanRead_Locked()) |
| 496 return; | 461 return; |
| 497 | 462 |
| 498 pending_read_ = true; | 463 pending_read_ = true; |
| 499 audio_buffer_stream_->Read(base::Bind(&AudioRendererImpl::DecodedAudioReady, | 464 audio_buffer_stream_->Read(base::Bind(&AudioRendererImpl::DecodedAudioReady, |
| 500 weak_factory_.GetWeakPtr())); | 465 weak_factory_.GetWeakPtr())); |
| 501 } | 466 } |
| 502 | 467 |
| 503 bool AudioRendererImpl::CanRead_Locked() { | 468 bool AudioRendererImpl::CanRead_Locked() { |
| 504 lock_.AssertAcquired(); | 469 lock_.AssertAcquired(); |
| 505 | 470 |
| 506 switch (state_) { | 471 switch (state_) { |
| 507 case kUninitialized: | 472 case kUninitialized: |
| 508 case kInitializing: | 473 case kInitializing: |
| 509 case kFlushing: | 474 case kFlushing: |
| 510 case kFlushed: | 475 case kFlushed: |
| 511 case kStopped: | |
| 512 return false; | 476 return false; |
| 513 | 477 |
| 514 case kPlaying: | 478 case kPlaying: |
| 515 break; | 479 break; |
| 516 } | 480 } |
| 517 | 481 |
| 518 return !pending_read_ && !received_end_of_stream_ && | 482 return !pending_read_ && !received_end_of_stream_ && |
| 519 !algorithm_->IsQueueFull(); | 483 !algorithm_->IsQueueFull(); |
| 520 } | 484 } |
| 521 | 485 |
| (...skipping 146 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 668 DoFlush_Locked(); | 632 DoFlush_Locked(); |
| 669 return; | 633 return; |
| 670 } | 634 } |
| 671 | 635 |
| 672 error_cb_.Run(status); | 636 error_cb_.Run(status); |
| 673 base::ResetAndReturn(&flush_cb_).Run(); | 637 base::ResetAndReturn(&flush_cb_).Run(); |
| 674 return; | 638 return; |
| 675 | 639 |
| 676 case kFlushed: | 640 case kFlushed: |
| 677 case kPlaying: | 641 case kPlaying: |
| 678 case kStopped: | |
| 679 if (status != PIPELINE_OK) | 642 if (status != PIPELINE_OK) |
| 680 error_cb_.Run(status); | 643 error_cb_.Run(status); |
| 681 return; | 644 return; |
| 682 } | 645 } |
| 683 } | 646 } |
| 684 | 647 |
| 685 void AudioRendererImpl::ChangeState_Locked(State new_state) { | 648 void AudioRendererImpl::ChangeState_Locked(State new_state) { |
| 686 DVLOG(1) << __FUNCTION__ << " : " << state_ << " -> " << new_state; | 649 DVLOG(1) << __FUNCTION__ << " : " << state_ << " -> " << new_state; |
| 687 lock_.AssertAcquired(); | 650 lock_.AssertAcquired(); |
| 688 state_ = new_state; | 651 state_ = new_state; |
| (...skipping 21 matching lines...) Expand all Loading... | |
| 710 << buffering_state; | 673 << buffering_state; |
| 711 DCHECK_NE(buffering_state_, buffering_state); | 674 DCHECK_NE(buffering_state_, buffering_state); |
| 712 lock_.AssertAcquired(); | 675 lock_.AssertAcquired(); |
| 713 buffering_state_ = buffering_state; | 676 buffering_state_ = buffering_state; |
| 714 | 677 |
| 715 task_runner_->PostTask(FROM_HERE, | 678 task_runner_->PostTask(FROM_HERE, |
| 716 base::Bind(buffering_state_cb_, buffering_state_)); | 679 base::Bind(buffering_state_cb_, buffering_state_)); |
| 717 } | 680 } |
| 718 | 681 |
| 719 } // namespace media | 682 } // namespace media |
| OLD | NEW |