| 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 34 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 45 media::AudioRendererSink* sink, | 45 media::AudioRendererSink* sink, |
| 46 ScopedVector<AudioDecoder> decoders, | 46 ScopedVector<AudioDecoder> decoders, |
| 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_(new AudioBufferStream(task_runner, | 51 audio_buffer_stream_(new AudioBufferStream(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 playback_rate_(0), |
| 55 state_(kUninitialized), | 56 state_(kUninitialized), |
| 56 buffering_state_(BUFFERING_HAVE_NOTHING), | 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 weak_factory_(this) { | 63 weak_factory_(this) { |
| 63 audio_buffer_stream_->set_splice_observer(base::Bind( | 64 audio_buffer_stream_->set_splice_observer(base::Bind( |
| 64 &AudioRendererImpl::OnNewSpliceBuffer, weak_factory_.GetWeakPtr())); | 65 &AudioRendererImpl::OnNewSpliceBuffer, weak_factory_.GetWeakPtr())); |
| 65 audio_buffer_stream_->set_config_change_observer(base::Bind( | 66 audio_buffer_stream_->set_config_change_observer(base::Bind( |
| 66 &AudioRendererImpl::OnConfigChange, weak_factory_.GetWeakPtr())); | 67 &AudioRendererImpl::OnConfigChange, weak_factory_.GetWeakPtr())); |
| 67 } | 68 } |
| 68 | 69 |
| 69 AudioRendererImpl::~AudioRendererImpl() { | 70 AudioRendererImpl::~AudioRendererImpl() { |
| 70 // Stop() should have been called and |algorithm_| should have been destroyed. | 71 // Stop() should have been called and |algorithm_| should have been destroyed. |
| 71 DCHECK(state_ == kUninitialized || state_ == kStopped); | 72 DCHECK(state_ == kUninitialized || state_ == kStopped); |
| 72 DCHECK(!algorithm_.get()); | 73 DCHECK(!algorithm_.get()); |
| 73 } | 74 } |
| 74 | 75 |
| 75 void AudioRendererImpl::StartRendering() { | 76 void AudioRendererImpl::StartRendering() { |
| 76 DVLOG(1) << __FUNCTION__; | 77 DVLOG(1) << __FUNCTION__; |
| 77 DCHECK(task_runner_->BelongsToCurrentThread()); | 78 DCHECK(task_runner_->BelongsToCurrentThread()); |
| 78 DCHECK(!rendering_); | 79 DCHECK(!rendering_); |
| 79 rendering_ = true; | 80 rendering_ = true; |
| 80 | 81 |
| 81 base::AutoLock auto_lock(lock_); | 82 base::AutoLock auto_lock(lock_); |
| 82 // Wait for an eventual call to SetPlaybackRate() to start rendering. | 83 // Wait for an eventual call to SetPlaybackRate() to start rendering. |
| 83 if (algorithm_->playback_rate() == 0) { | 84 if (playback_rate_ == 0) { |
| 84 DCHECK(!sink_playing_); | 85 DCHECK(!sink_playing_); |
| 85 return; | 86 return; |
| 86 } | 87 } |
| 87 | 88 |
| 88 StartRendering_Locked(); | 89 StartRendering_Locked(); |
| 89 } | 90 } |
| 90 | 91 |
| 91 void AudioRendererImpl::StartRendering_Locked() { | 92 void AudioRendererImpl::StartRendering_Locked() { |
| 92 DVLOG(1) << __FUNCTION__; | 93 DVLOG(1) << __FUNCTION__; |
| 93 DCHECK(task_runner_->BelongsToCurrentThread()); | 94 DCHECK(task_runner_->BelongsToCurrentThread()); |
| 94 DCHECK_EQ(state_, kPlaying); | 95 DCHECK_EQ(state_, kPlaying); |
| 95 DCHECK(!sink_playing_); | 96 DCHECK(!sink_playing_); |
| 96 DCHECK_NE(algorithm_->playback_rate(), 0); | 97 DCHECK_NE(playback_rate_, 0); |
| 97 lock_.AssertAcquired(); | 98 lock_.AssertAcquired(); |
| 98 | 99 |
| 99 sink_playing_ = true; | 100 sink_playing_ = true; |
| 100 | 101 |
| 101 base::AutoUnlock auto_unlock(lock_); | 102 base::AutoUnlock auto_unlock(lock_); |
| 102 sink_->Play(); | 103 sink_->Play(); |
| 103 } | 104 } |
| 104 | 105 |
| 105 void AudioRendererImpl::StopRendering() { | 106 void AudioRendererImpl::StopRendering() { |
| 106 DVLOG(1) << __FUNCTION__; | 107 DVLOG(1) << __FUNCTION__; |
| 107 DCHECK(task_runner_->BelongsToCurrentThread()); | 108 DCHECK(task_runner_->BelongsToCurrentThread()); |
| 108 DCHECK(rendering_); | 109 DCHECK(rendering_); |
| 109 rendering_ = false; | 110 rendering_ = false; |
| 110 | 111 |
| 111 base::AutoLock auto_lock(lock_); | 112 base::AutoLock auto_lock(lock_); |
| 112 // Rendering should have already been stopped with a zero playback rate. | 113 // Rendering should have already been stopped with a zero playback rate. |
| 113 if (algorithm_->playback_rate() == 0) { | 114 if (playback_rate_ == 0) { |
| 114 DCHECK(!sink_playing_); | 115 DCHECK(!sink_playing_); |
| 115 return; | 116 return; |
| 116 } | 117 } |
| 117 | 118 |
| 118 StopRendering_Locked(); | 119 StopRendering_Locked(); |
| 119 } | 120 } |
| 120 | 121 |
| 121 void AudioRendererImpl::StopRendering_Locked() { | 122 void AudioRendererImpl::StopRendering_Locked() { |
| 122 DCHECK(task_runner_->BelongsToCurrentThread()); | 123 DCHECK(task_runner_->BelongsToCurrentThread()); |
| 123 DCHECK_EQ(state_, kPlaying); | 124 DCHECK_EQ(state_, kPlaying); |
| (...skipping 212 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 336 return; | 337 return; |
| 337 } | 338 } |
| 338 | 339 |
| 339 if (expecting_config_changes_) | 340 if (expecting_config_changes_) |
| 340 buffer_converter_.reset(new AudioBufferConverter(audio_parameters_)); | 341 buffer_converter_.reset(new AudioBufferConverter(audio_parameters_)); |
| 341 splicer_.reset(new AudioSplicer(audio_parameters_.sample_rate())); | 342 splicer_.reset(new AudioSplicer(audio_parameters_.sample_rate())); |
| 342 | 343 |
| 343 // We're all good! Continue initializing the rest of the audio renderer | 344 // We're all good! Continue initializing the rest of the audio renderer |
| 344 // based on the decoder format. | 345 // based on the decoder format. |
| 345 algorithm_.reset(new AudioRendererAlgorithm()); | 346 algorithm_.reset(new AudioRendererAlgorithm()); |
| 346 algorithm_->Initialize(0, audio_parameters_); | 347 algorithm_->Initialize(audio_parameters_); |
| 347 | 348 |
| 348 ChangeState_Locked(kFlushed); | 349 ChangeState_Locked(kFlushed); |
| 349 | 350 |
| 350 HistogramRendererEvent(INITIALIZED); | 351 HistogramRendererEvent(INITIALIZED); |
| 351 | 352 |
| 352 { | 353 { |
| 353 base::AutoUnlock auto_unlock(lock_); | 354 base::AutoUnlock auto_unlock(lock_); |
| 354 sink_->Initialize(audio_parameters_, this); | 355 sink_->Initialize(audio_parameters_, this); |
| 355 sink_->Start(); | 356 sink_->Start(); |
| 356 | 357 |
| (...skipping 166 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 523 DVLOG(1) << __FUNCTION__ << "(" << playback_rate << ")"; | 524 DVLOG(1) << __FUNCTION__ << "(" << playback_rate << ")"; |
| 524 DCHECK(task_runner_->BelongsToCurrentThread()); | 525 DCHECK(task_runner_->BelongsToCurrentThread()); |
| 525 DCHECK_GE(playback_rate, 0); | 526 DCHECK_GE(playback_rate, 0); |
| 526 DCHECK(sink_); | 527 DCHECK(sink_); |
| 527 | 528 |
| 528 base::AutoLock auto_lock(lock_); | 529 base::AutoLock auto_lock(lock_); |
| 529 | 530 |
| 530 // We have two cases here: | 531 // We have two cases here: |
| 531 // Play: current_playback_rate == 0 && playback_rate != 0 | 532 // Play: current_playback_rate == 0 && playback_rate != 0 |
| 532 // Pause: current_playback_rate != 0 && playback_rate == 0 | 533 // Pause: current_playback_rate != 0 && playback_rate == 0 |
| 533 float current_playback_rate = algorithm_->playback_rate(); | 534 float current_playback_rate = playback_rate_; |
| 534 algorithm_->SetPlaybackRate(playback_rate); | 535 playback_rate_ = playback_rate; |
| 535 | 536 |
| 536 if (!rendering_) | 537 if (!rendering_) |
| 537 return; | 538 return; |
| 538 | 539 |
| 539 if (current_playback_rate == 0 && playback_rate != 0) { | 540 if (current_playback_rate == 0 && playback_rate != 0) { |
| 540 StartRendering_Locked(); | 541 StartRendering_Locked(); |
| 541 return; | 542 return; |
| 542 } | 543 } |
| 543 | 544 |
| 544 if (current_playback_rate != 0 && playback_rate == 0) { | 545 if (current_playback_rate != 0 && playback_rate == 0) { |
| (...skipping 20 matching lines...) Expand all Loading... |
| 565 base::Closure time_cb; | 566 base::Closure time_cb; |
| 566 { | 567 { |
| 567 base::AutoLock auto_lock(lock_); | 568 base::AutoLock auto_lock(lock_); |
| 568 | 569 |
| 569 // Ensure Stop() hasn't destroyed our |algorithm_| on the pipeline thread. | 570 // Ensure Stop() hasn't destroyed our |algorithm_| on the pipeline thread. |
| 570 if (!algorithm_) { | 571 if (!algorithm_) { |
| 571 audio_clock_->WroteSilence(requested_frames, delay_frames); | 572 audio_clock_->WroteSilence(requested_frames, delay_frames); |
| 572 return 0; | 573 return 0; |
| 573 } | 574 } |
| 574 | 575 |
| 575 float playback_rate = algorithm_->playback_rate(); | 576 if (playback_rate_ == 0) { |
| 576 if (playback_rate == 0) { | |
| 577 audio_clock_->WroteSilence(requested_frames, delay_frames); | 577 audio_clock_->WroteSilence(requested_frames, delay_frames); |
| 578 return 0; | 578 return 0; |
| 579 } | 579 } |
| 580 | 580 |
| 581 // Mute audio by returning 0 when not playing. | 581 // Mute audio by returning 0 when not playing. |
| 582 if (state_ != kPlaying) { | 582 if (state_ != kPlaying) { |
| 583 audio_clock_->WroteSilence(requested_frames, delay_frames); | 583 audio_clock_->WroteSilence(requested_frames, delay_frames); |
| 584 return 0; | 584 return 0; |
| 585 } | 585 } |
| 586 | 586 |
| 587 // We use the following conditions to determine end of playback: | 587 // We use the following conditions to determine end of playback: |
| 588 // 1) Algorithm can not fill the audio callback buffer | 588 // 1) Algorithm can not fill the audio callback buffer |
| 589 // 2) We received an end of stream buffer | 589 // 2) We received an end of stream buffer |
| 590 // 3) We haven't already signalled that we've ended | 590 // 3) We haven't already signalled that we've ended |
| 591 // 4) We've played all known audio data sent to hardware | 591 // 4) We've played all known audio data sent to hardware |
| 592 // | 592 // |
| 593 // We use the following conditions to determine underflow: | 593 // We use the following conditions to determine underflow: |
| 594 // 1) Algorithm can not fill the audio callback buffer | 594 // 1) Algorithm can not fill the audio callback buffer |
| 595 // 2) We have NOT received an end of stream buffer | 595 // 2) We have NOT received an end of stream buffer |
| 596 // 3) We are in the kPlaying state | 596 // 3) We are in the kPlaying state |
| 597 // | 597 // |
| 598 // Otherwise the buffer has data we can send to the device. | 598 // Otherwise the buffer has data we can send to the device. |
| 599 const base::TimeDelta media_timestamp_before_filling = | 599 const base::TimeDelta media_timestamp_before_filling = |
| 600 audio_clock_->CurrentMediaTimestamp(base::TimeDelta()); | 600 audio_clock_->CurrentMediaTimestamp(base::TimeDelta()); |
| 601 if (algorithm_->frames_buffered() > 0) { | 601 if (algorithm_->frames_buffered() > 0) { |
| 602 frames_written = algorithm_->FillBuffer(audio_bus, requested_frames); | 602 frames_written = |
| 603 algorithm_->FillBuffer(audio_bus, requested_frames, playback_rate_); |
| 603 audio_clock_->WroteAudio( | 604 audio_clock_->WroteAudio( |
| 604 frames_written, delay_frames, playback_rate, algorithm_->GetTime()); | 605 frames_written, delay_frames, playback_rate_, algorithm_->GetTime()); |
| 605 } | 606 } |
| 606 audio_clock_->WroteSilence(requested_frames - frames_written, delay_frames); | 607 audio_clock_->WroteSilence(requested_frames - frames_written, delay_frames); |
| 607 | 608 |
| 608 if (frames_written == 0) { | 609 if (frames_written == 0) { |
| 609 if (received_end_of_stream_ && !rendered_end_of_stream_ && | 610 if (received_end_of_stream_ && !rendered_end_of_stream_ && |
| 610 audio_clock_->CurrentMediaTimestamp(base::TimeDelta()) == | 611 audio_clock_->CurrentMediaTimestamp(base::TimeDelta()) == |
| 611 audio_clock_->last_endpoint_timestamp()) { | 612 audio_clock_->last_endpoint_timestamp()) { |
| 612 rendered_end_of_stream_ = true; | 613 rendered_end_of_stream_ = true; |
| 613 ended_cb_.Run(); | 614 ended_cb_.Run(); |
| 614 } else if (!received_end_of_stream_ && state_ == kPlaying) { | 615 } else if (!received_end_of_stream_ && state_ == kPlaying) { |
| (...skipping 95 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 710 << buffering_state; | 711 << buffering_state; |
| 711 DCHECK_NE(buffering_state_, buffering_state); | 712 DCHECK_NE(buffering_state_, buffering_state); |
| 712 lock_.AssertAcquired(); | 713 lock_.AssertAcquired(); |
| 713 buffering_state_ = buffering_state; | 714 buffering_state_ = buffering_state; |
| 714 | 715 |
| 715 task_runner_->PostTask(FROM_HERE, | 716 task_runner_->PostTask(FROM_HERE, |
| 716 base::Bind(buffering_state_cb_, buffering_state_)); | 717 base::Bind(buffering_state_cb_, buffering_state_)); |
| 717 } | 718 } |
| 718 | 719 |
| 719 } // namespace media | 720 } // namespace media |
| OLD | NEW |