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 (sink_) { | |
| 74 // If Render() is in process, this call will wait for Render() to finish. | |
|
scherkus (not reviewing)
2014/07/21 23:38:20
s/process/progress/?
xhwang
2014/07/21 23:56:33
Done.
| |
| 75 // After this call, the |sink_| will not call back into |this| anymore. | |
| 76 sink_->Stop(); | |
| 77 sink_ = NULL; | |
|
scherkus (not reviewing)
2014/07/21 23:38:20
is this required to force the ref-count to zero? i
xhwang
2014/07/21 23:56:33
Probably not needed. The ref-count will be dropped
| |
| 78 } | |
| 79 | |
| 80 if (!init_cb_.is_null()) | |
| 81 base::ResetAndReturn(&init_cb_).Run(PIPELINE_ERROR_ABORT); | |
| 73 } | 82 } |
| 74 | 83 |
| 75 void AudioRendererImpl::StartRendering() { | 84 void AudioRendererImpl::StartRendering() { |
| 76 DVLOG(1) << __FUNCTION__; | 85 DVLOG(1) << __FUNCTION__; |
| 77 DCHECK(task_runner_->BelongsToCurrentThread()); | 86 DCHECK(task_runner_->BelongsToCurrentThread()); |
| 78 DCHECK(!rendering_); | 87 DCHECK(!rendering_); |
| 79 rendering_ = true; | 88 rendering_ = true; |
| 80 | 89 |
| 81 base::AutoLock auto_lock(lock_); | 90 base::AutoLock auto_lock(lock_); |
| 82 // Wait for an eventual call to SetPlaybackRate() to start rendering. | 91 // Wait for an eventual call to SetPlaybackRate() to start rendering. |
| (...skipping 73 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 156 DCHECK_EQ(state_, kFlushed); | 165 DCHECK_EQ(state_, kFlushed); |
| 157 | 166 |
| 158 audio_buffer_stream_->Reset(base::Bind(&AudioRendererImpl::ResetDecoderDone, | 167 audio_buffer_stream_->Reset(base::Bind(&AudioRendererImpl::ResetDecoderDone, |
| 159 weak_factory_.GetWeakPtr())); | 168 weak_factory_.GetWeakPtr())); |
| 160 } | 169 } |
| 161 | 170 |
| 162 void AudioRendererImpl::ResetDecoderDone() { | 171 void AudioRendererImpl::ResetDecoderDone() { |
| 163 DCHECK(task_runner_->BelongsToCurrentThread()); | 172 DCHECK(task_runner_->BelongsToCurrentThread()); |
| 164 { | 173 { |
| 165 base::AutoLock auto_lock(lock_); | 174 base::AutoLock auto_lock(lock_); |
| 166 if (state_ == kStopped) | |
| 167 return; | |
| 168 | 175 |
| 169 DCHECK_EQ(state_, kFlushed); | 176 DCHECK_EQ(state_, kFlushed); |
| 170 DCHECK(!flush_cb_.is_null()); | 177 DCHECK(!flush_cb_.is_null()); |
| 171 | 178 |
| 172 audio_clock_.reset(new AudioClock(audio_parameters_.sample_rate())); | 179 audio_clock_.reset(new AudioClock(audio_parameters_.sample_rate())); |
| 173 received_end_of_stream_ = false; | 180 received_end_of_stream_ = false; |
| 174 rendered_end_of_stream_ = false; | 181 rendered_end_of_stream_ = false; |
| 175 | 182 |
| 176 // Flush() may have been called while underflowed/not fully buffered. | 183 // Flush() may have been called while underflowed/not fully buffered. |
| 177 if (buffering_state_ != BUFFERING_HAVE_NOTHING) | 184 if (buffering_state_ != BUFFERING_HAVE_NOTHING) |
| 178 SetBufferingState_Locked(BUFFERING_HAVE_NOTHING); | 185 SetBufferingState_Locked(BUFFERING_HAVE_NOTHING); |
| 179 | 186 |
| 180 splicer_->Reset(); | 187 splicer_->Reset(); |
| 181 if (buffer_converter_) | 188 if (buffer_converter_) |
| 182 buffer_converter_->Reset(); | 189 buffer_converter_->Reset(); |
| 183 algorithm_->FlushBuffers(); | 190 algorithm_->FlushBuffers(); |
| 184 } | 191 } |
| 185 | 192 |
| 186 // Changes in buffering state are always posted. Flush callback must only be | 193 // Changes in buffering state are always posted. Flush callback must only be |
| 187 // run after buffering state has been set back to nothing. | 194 // run after buffering state has been set back to nothing. |
| 188 task_runner_->PostTask(FROM_HERE, base::ResetAndReturn(&flush_cb_)); | 195 task_runner_->PostTask(FROM_HERE, base::ResetAndReturn(&flush_cb_)); |
| 189 } | 196 } |
| 190 | 197 |
| 191 void AudioRendererImpl::Stop(const base::Closure& callback) { | |
| 192 DVLOG(1) << __FUNCTION__; | |
| 193 DCHECK(task_runner_->BelongsToCurrentThread()); | |
| 194 DCHECK(!callback.is_null()); | |
| 195 | |
| 196 // TODO(scherkus): Consider invalidating |weak_factory_| and replacing | |
| 197 // task-running guards that check |state_| with DCHECK(). | |
| 198 | |
| 199 { | |
| 200 base::AutoLock auto_lock(lock_); | |
| 201 | |
| 202 if (state_ == kStopped) { | |
| 203 task_runner_->PostTask(FROM_HERE, callback); | |
| 204 return; | |
| 205 } | |
| 206 | |
| 207 ChangeState_Locked(kStopped); | |
| 208 algorithm_.reset(); | |
| 209 time_cb_.Reset(); | |
| 210 flush_cb_.Reset(); | |
| 211 } | |
| 212 | |
| 213 if (sink_) { | |
| 214 sink_->Stop(); | |
| 215 sink_ = NULL; | |
| 216 } | |
| 217 | |
| 218 audio_buffer_stream_.reset(); | |
| 219 task_runner_->PostTask(FROM_HERE, callback); | |
| 220 } | |
| 221 | |
| 222 void AudioRendererImpl::StartPlayingFrom(base::TimeDelta timestamp) { | 198 void AudioRendererImpl::StartPlayingFrom(base::TimeDelta timestamp) { |
| 223 DVLOG(1) << __FUNCTION__ << "(" << timestamp.InMicroseconds() << ")"; | 199 DVLOG(1) << __FUNCTION__ << "(" << timestamp.InMicroseconds() << ")"; |
| 224 DCHECK(task_runner_->BelongsToCurrentThread()); | 200 DCHECK(task_runner_->BelongsToCurrentThread()); |
| 225 | 201 |
| 226 base::AutoLock auto_lock(lock_); | 202 base::AutoLock auto_lock(lock_); |
| 227 DCHECK(!sink_playing_); | 203 DCHECK(!sink_playing_); |
| 228 DCHECK_EQ(state_, kFlushed); | 204 DCHECK_EQ(state_, kFlushed); |
| 229 DCHECK_EQ(buffering_state_, BUFFERING_HAVE_NOTHING); | 205 DCHECK_EQ(buffering_state_, BUFFERING_HAVE_NOTHING); |
| 230 DCHECK(!pending_read_) << "Pending read must complete before seeking"; | 206 DCHECK(!pending_read_) << "Pending read must complete before seeking"; |
| 231 | 207 |
| (...skipping 71 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 303 statistics_cb, | 279 statistics_cb, |
| 304 base::Bind(&AudioRendererImpl::OnAudioBufferStreamInitialized, | 280 base::Bind(&AudioRendererImpl::OnAudioBufferStreamInitialized, |
| 305 weak_factory_.GetWeakPtr())); | 281 weak_factory_.GetWeakPtr())); |
| 306 } | 282 } |
| 307 | 283 |
| 308 void AudioRendererImpl::OnAudioBufferStreamInitialized(bool success) { | 284 void AudioRendererImpl::OnAudioBufferStreamInitialized(bool success) { |
| 309 DCHECK(task_runner_->BelongsToCurrentThread()); | 285 DCHECK(task_runner_->BelongsToCurrentThread()); |
| 310 | 286 |
| 311 base::AutoLock auto_lock(lock_); | 287 base::AutoLock auto_lock(lock_); |
| 312 | 288 |
| 313 if (state_ == kStopped) { | |
| 314 base::ResetAndReturn(&init_cb_).Run(PIPELINE_ERROR_ABORT); | |
| 315 return; | |
| 316 } | |
| 317 | |
| 318 if (!success) { | 289 if (!success) { |
| 319 state_ = kUninitialized; | 290 state_ = kUninitialized; |
| 320 base::ResetAndReturn(&init_cb_).Run(DECODER_ERROR_NOT_SUPPORTED); | 291 base::ResetAndReturn(&init_cb_).Run(DECODER_ERROR_NOT_SUPPORTED); |
| 321 return; | 292 return; |
| 322 } | 293 } |
| 323 | 294 |
| 324 if (!audio_parameters_.IsValid()) { | 295 if (!audio_parameters_.IsValid()) { |
| 325 ChangeState_Locked(kUninitialized); | 296 ChangeState_Locked(kUninitialized); |
| 326 base::ResetAndReturn(&init_cb_).Run(PIPELINE_ERROR_INITIALIZATION_FAILED); | 297 base::ResetAndReturn(&init_cb_).Run(PIPELINE_ERROR_INITIALIZATION_FAILED); |
| 327 return; | 298 return; |
| (...skipping 110 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 438 if (trim_time > base::TimeDelta()) { | 409 if (trim_time > base::TimeDelta()) { |
| 439 buffer->TrimStart(buffer->frame_count() * | 410 buffer->TrimStart(buffer->frame_count() * |
| 440 (static_cast<double>(trim_time.InMicroseconds()) / | 411 (static_cast<double>(trim_time.InMicroseconds()) / |
| 441 buffer->duration().InMicroseconds())); | 412 buffer->duration().InMicroseconds())); |
| 442 } | 413 } |
| 443 // If the entire buffer was trimmed, request a new one. | 414 // If the entire buffer was trimmed, request a new one. |
| 444 if (!buffer->frame_count()) | 415 if (!buffer->frame_count()) |
| 445 return true; | 416 return true; |
| 446 } | 417 } |
| 447 | 418 |
| 448 if (state_ != kUninitialized && state_ != kStopped) | 419 if (state_ != kUninitialized) |
| 449 algorithm_->EnqueueBuffer(buffer); | 420 algorithm_->EnqueueBuffer(buffer); |
| 450 } | 421 } |
| 451 | 422 |
| 452 switch (state_) { | 423 switch (state_) { |
| 453 case kUninitialized: | 424 case kUninitialized: |
| 454 case kInitializing: | 425 case kInitializing: |
| 455 case kFlushing: | 426 case kFlushing: |
| 456 NOTREACHED(); | 427 NOTREACHED(); |
| 457 return false; | 428 return false; |
| 458 | 429 |
| 459 case kFlushed: | 430 case kFlushed: |
| 460 DCHECK(!pending_read_); | 431 DCHECK(!pending_read_); |
| 461 return false; | 432 return false; |
| 462 | 433 |
| 463 case kPlaying: | 434 case kPlaying: |
| 464 if (buffer->end_of_stream() || algorithm_->IsQueueFull()) { | 435 if (buffer->end_of_stream() || algorithm_->IsQueueFull()) { |
| 465 if (buffering_state_ == BUFFERING_HAVE_NOTHING) | 436 if (buffering_state_ == BUFFERING_HAVE_NOTHING) |
| 466 SetBufferingState_Locked(BUFFERING_HAVE_ENOUGH); | 437 SetBufferingState_Locked(BUFFERING_HAVE_ENOUGH); |
| 467 return false; | 438 return false; |
| 468 } | 439 } |
| 469 return true; | 440 return true; |
| 470 | |
| 471 case kStopped: | |
| 472 return false; | |
| 473 } | 441 } |
| 474 return false; | 442 return false; |
| 475 } | 443 } |
| 476 | 444 |
| 477 void AudioRendererImpl::AttemptRead() { | 445 void AudioRendererImpl::AttemptRead() { |
| 478 base::AutoLock auto_lock(lock_); | 446 base::AutoLock auto_lock(lock_); |
| 479 AttemptRead_Locked(); | 447 AttemptRead_Locked(); |
| 480 } | 448 } |
| 481 | 449 |
| 482 void AudioRendererImpl::AttemptRead_Locked() { | 450 void AudioRendererImpl::AttemptRead_Locked() { |
| 483 DCHECK(task_runner_->BelongsToCurrentThread()); | 451 DCHECK(task_runner_->BelongsToCurrentThread()); |
| 484 lock_.AssertAcquired(); | 452 lock_.AssertAcquired(); |
| 485 | 453 |
| 486 if (!CanRead_Locked()) | 454 if (!CanRead_Locked()) |
| 487 return; | 455 return; |
| 488 | 456 |
| 489 pending_read_ = true; | 457 pending_read_ = true; |
| 490 audio_buffer_stream_->Read(base::Bind(&AudioRendererImpl::DecodedAudioReady, | 458 audio_buffer_stream_->Read(base::Bind(&AudioRendererImpl::DecodedAudioReady, |
| 491 weak_factory_.GetWeakPtr())); | 459 weak_factory_.GetWeakPtr())); |
| 492 } | 460 } |
| 493 | 461 |
| 494 bool AudioRendererImpl::CanRead_Locked() { | 462 bool AudioRendererImpl::CanRead_Locked() { |
| 495 lock_.AssertAcquired(); | 463 lock_.AssertAcquired(); |
| 496 | 464 |
| 497 switch (state_) { | 465 switch (state_) { |
| 498 case kUninitialized: | 466 case kUninitialized: |
| 499 case kInitializing: | 467 case kInitializing: |
| 500 case kFlushing: | 468 case kFlushing: |
| 501 case kFlushed: | 469 case kFlushed: |
| 502 case kStopped: | |
| 503 return false; | 470 return false; |
| 504 | 471 |
| 505 case kPlaying: | 472 case kPlaying: |
| 506 break; | 473 break; |
| 507 } | 474 } |
| 508 | 475 |
| 509 return !pending_read_ && !received_end_of_stream_ && | 476 return !pending_read_ && !received_end_of_stream_ && |
| 510 !algorithm_->IsQueueFull(); | 477 !algorithm_->IsQueueFull(); |
| 511 } | 478 } |
| 512 | 479 |
| (...skipping 146 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 659 DoFlush_Locked(); | 626 DoFlush_Locked(); |
| 660 return; | 627 return; |
| 661 } | 628 } |
| 662 | 629 |
| 663 error_cb_.Run(status); | 630 error_cb_.Run(status); |
| 664 base::ResetAndReturn(&flush_cb_).Run(); | 631 base::ResetAndReturn(&flush_cb_).Run(); |
| 665 return; | 632 return; |
| 666 | 633 |
| 667 case kFlushed: | 634 case kFlushed: |
| 668 case kPlaying: | 635 case kPlaying: |
| 669 case kStopped: | |
| 670 if (status != PIPELINE_OK) | 636 if (status != PIPELINE_OK) |
| 671 error_cb_.Run(status); | 637 error_cb_.Run(status); |
| 672 return; | 638 return; |
| 673 } | 639 } |
| 674 } | 640 } |
| 675 | 641 |
| 676 void AudioRendererImpl::ChangeState_Locked(State new_state) { | 642 void AudioRendererImpl::ChangeState_Locked(State new_state) { |
| 677 DVLOG(1) << __FUNCTION__ << " : " << state_ << " -> " << new_state; | 643 DVLOG(1) << __FUNCTION__ << " : " << state_ << " -> " << new_state; |
| 678 lock_.AssertAcquired(); | 644 lock_.AssertAcquired(); |
| 679 state_ = new_state; | 645 state_ = new_state; |
| (...skipping 21 matching lines...) Expand all Loading... | |
| 701 << buffering_state; | 667 << buffering_state; |
| 702 DCHECK_NE(buffering_state_, buffering_state); | 668 DCHECK_NE(buffering_state_, buffering_state); |
| 703 lock_.AssertAcquired(); | 669 lock_.AssertAcquired(); |
| 704 buffering_state_ = buffering_state; | 670 buffering_state_ = buffering_state; |
| 705 | 671 |
| 706 task_runner_->PostTask(FROM_HERE, | 672 task_runner_->PostTask(FROM_HERE, |
| 707 base::Bind(buffering_state_cb_, buffering_state_)); | 673 base::Bind(buffering_state_cb_, buffering_state_)); |
| 708 } | 674 } |
| 709 | 675 |
| 710 } // namespace media | 676 } // namespace media |
| OLD | NEW |