| 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 |
| 11 #include "base/bind.h" | 11 #include "base/bind.h" |
| 12 #include "base/callback.h" | 12 #include "base/callback.h" |
| 13 #include "base/callback_helpers.h" | 13 #include "base/callback_helpers.h" |
| 14 #include "base/logging.h" | 14 #include "base/logging.h" |
| 15 #include "base/metrics/histogram.h" | 15 #include "base/metrics/histogram.h" |
| 16 #include "base/single_thread_task_runner.h" | 16 #include "base/single_thread_task_runner.h" |
| 17 #include "base/time/default_tick_clock.h" |
| 17 #include "media/base/audio_buffer.h" | 18 #include "media/base/audio_buffer.h" |
| 18 #include "media/base/audio_buffer_converter.h" | 19 #include "media/base/audio_buffer_converter.h" |
| 19 #include "media/base/audio_hardware_config.h" | 20 #include "media/base/audio_hardware_config.h" |
| 20 #include "media/base/audio_splicer.h" | 21 #include "media/base/audio_splicer.h" |
| 21 #include "media/base/bind_to_current_loop.h" | 22 #include "media/base/bind_to_current_loop.h" |
| 22 #include "media/base/demuxer_stream.h" | 23 #include "media/base/demuxer_stream.h" |
| 23 #include "media/filters/audio_clock.h" | 24 #include "media/filters/audio_clock.h" |
| 24 #include "media/filters/decrypting_demuxer_stream.h" | 25 #include "media/filters/decrypting_demuxer_stream.h" |
| 25 | 26 |
| 26 namespace media { | 27 namespace media { |
| (...skipping 18 matching lines...) Expand all Loading... |
| 45 media::AudioRendererSink* sink, | 46 media::AudioRendererSink* sink, |
| 46 ScopedVector<AudioDecoder> decoders, | 47 ScopedVector<AudioDecoder> decoders, |
| 47 const SetDecryptorReadyCB& set_decryptor_ready_cb, | 48 const SetDecryptorReadyCB& set_decryptor_ready_cb, |
| 48 AudioHardwareConfig* hardware_config) | 49 AudioHardwareConfig* hardware_config) |
| 49 : task_runner_(task_runner), | 50 : task_runner_(task_runner), |
| 50 sink_(sink), | 51 sink_(sink), |
| 51 audio_buffer_stream_(new AudioBufferStream(task_runner, | 52 audio_buffer_stream_(new AudioBufferStream(task_runner, |
| 52 decoders.Pass(), | 53 decoders.Pass(), |
| 53 set_decryptor_ready_cb)), | 54 set_decryptor_ready_cb)), |
| 54 hardware_config_(hardware_config), | 55 hardware_config_(hardware_config), |
| 56 tick_clock_(new base::DefaultTickClock()), |
| 55 state_(kUninitialized), | 57 state_(kUninitialized), |
| 56 buffering_state_(BUFFERING_HAVE_NOTHING), | 58 buffering_state_(BUFFERING_HAVE_NOTHING), |
| 57 rendering_(false), | 59 rendering_(false), |
| 58 sink_playing_(false), | 60 sink_playing_(false), |
| 59 pending_read_(false), | 61 pending_read_(false), |
| 60 received_end_of_stream_(false), | 62 received_end_of_stream_(false), |
| 61 rendered_end_of_stream_(false), | 63 rendered_end_of_stream_(false), |
| 62 weak_factory_(this) { | 64 weak_factory_(this) { |
| 63 audio_buffer_stream_->set_splice_observer(base::Bind( | 65 audio_buffer_stream_->set_splice_observer(base::Bind( |
| 64 &AudioRendererImpl::OnNewSpliceBuffer, weak_factory_.GetWeakPtr())); | 66 &AudioRendererImpl::OnNewSpliceBuffer, weak_factory_.GetWeakPtr())); |
| 65 audio_buffer_stream_->set_config_change_observer(base::Bind( | 67 audio_buffer_stream_->set_config_change_observer(base::Bind( |
| 66 &AudioRendererImpl::OnConfigChange, weak_factory_.GetWeakPtr())); | 68 &AudioRendererImpl::OnConfigChange, weak_factory_.GetWeakPtr())); |
| 67 } | 69 } |
| 68 | 70 |
| 69 AudioRendererImpl::~AudioRendererImpl() { | 71 AudioRendererImpl::~AudioRendererImpl() { |
| 70 // Stop() should have been called and |algorithm_| should have been destroyed. | 72 // Stop() should have been called and |algorithm_| should have been destroyed. |
| 71 DCHECK(state_ == kUninitialized || state_ == kStopped); | 73 DCHECK(state_ == kUninitialized || state_ == kStopped); |
| 72 DCHECK(!algorithm_.get()); | 74 DCHECK(!algorithm_.get()); |
| 73 } | 75 } |
| 74 | 76 |
| 75 void AudioRendererImpl::StartRendering() { | 77 void AudioRendererImpl::StartTicking() { |
| 76 DVLOG(1) << __FUNCTION__; | 78 DVLOG(1) << __FUNCTION__; |
| 77 DCHECK(task_runner_->BelongsToCurrentThread()); | 79 DCHECK(task_runner_->BelongsToCurrentThread()); |
| 78 DCHECK(!rendering_); | 80 DCHECK(!rendering_); |
| 79 rendering_ = true; | 81 rendering_ = true; |
| 80 | 82 |
| 81 base::AutoLock auto_lock(lock_); | 83 base::AutoLock auto_lock(lock_); |
| 82 // Wait for an eventual call to SetPlaybackRate() to start rendering. | 84 // Wait for an eventual call to SetPlaybackRate() to start rendering. |
| 83 if (algorithm_->playback_rate() == 0) { | 85 if (algorithm_->playback_rate() == 0) { |
| 84 DCHECK(!sink_playing_); | 86 DCHECK(!sink_playing_); |
| 85 return; | 87 return; |
| 86 } | 88 } |
| 87 | 89 |
| 88 StartRendering_Locked(); | 90 StartRendering_Locked(); |
| 89 } | 91 } |
| 90 | 92 |
| 91 void AudioRendererImpl::StartRendering_Locked() { | 93 void AudioRendererImpl::StartRendering_Locked() { |
| 92 DVLOG(1) << __FUNCTION__; | 94 DVLOG(1) << __FUNCTION__; |
| 93 DCHECK(task_runner_->BelongsToCurrentThread()); | 95 DCHECK(task_runner_->BelongsToCurrentThread()); |
| 94 DCHECK_EQ(state_, kPlaying); | 96 DCHECK_EQ(state_, kPlaying); |
| 95 DCHECK(!sink_playing_); | 97 DCHECK(!sink_playing_); |
| 96 DCHECK_NE(algorithm_->playback_rate(), 0); | 98 DCHECK_NE(algorithm_->playback_rate(), 0); |
| 97 lock_.AssertAcquired(); | 99 lock_.AssertAcquired(); |
| 98 | 100 |
| 99 sink_playing_ = true; | 101 sink_playing_ = true; |
| 100 | 102 |
| 101 base::AutoUnlock auto_unlock(lock_); | 103 base::AutoUnlock auto_unlock(lock_); |
| 102 sink_->Play(); | 104 sink_->Play(); |
| 103 } | 105 } |
| 104 | 106 |
| 105 void AudioRendererImpl::StopRendering() { | 107 void AudioRendererImpl::StopTicking() { |
| 106 DVLOG(1) << __FUNCTION__; | 108 DVLOG(1) << __FUNCTION__; |
| 107 DCHECK(task_runner_->BelongsToCurrentThread()); | 109 DCHECK(task_runner_->BelongsToCurrentThread()); |
| 108 DCHECK(rendering_); | 110 DCHECK(rendering_); |
| 109 rendering_ = false; | 111 rendering_ = false; |
| 110 | 112 |
| 111 base::AutoLock auto_lock(lock_); | 113 base::AutoLock auto_lock(lock_); |
| 112 // Rendering should have already been stopped with a zero playback rate. | 114 // Rendering should have already been stopped with a zero playback rate. |
| 113 if (algorithm_->playback_rate() == 0) { | 115 if (algorithm_->playback_rate() == 0) { |
| 114 DCHECK(!sink_playing_); | 116 DCHECK(!sink_playing_); |
| 115 return; | 117 return; |
| 116 } | 118 } |
| 117 | 119 |
| 118 StopRendering_Locked(); | 120 StopRendering_Locked(); |
| 119 } | 121 } |
| 120 | 122 |
| 121 void AudioRendererImpl::StopRendering_Locked() { | 123 void AudioRendererImpl::StopRendering_Locked() { |
| 122 DCHECK(task_runner_->BelongsToCurrentThread()); | 124 DCHECK(task_runner_->BelongsToCurrentThread()); |
| 123 DCHECK_EQ(state_, kPlaying); | 125 DCHECK_EQ(state_, kPlaying); |
| 124 DCHECK(sink_playing_); | 126 DCHECK(sink_playing_); |
| 125 lock_.AssertAcquired(); | 127 lock_.AssertAcquired(); |
| 126 | 128 |
| 127 sink_playing_ = false; | 129 sink_playing_ = false; |
| 128 | 130 |
| 129 base::AutoUnlock auto_unlock(lock_); | 131 base::AutoUnlock auto_unlock(lock_); |
| 130 sink_->Pause(); | 132 sink_->Pause(); |
| 131 } | 133 } |
| 132 | 134 |
| 133 void AudioRendererImpl::SetMediaTime(base::TimeDelta time) { | |
| 134 DVLOG(1) << __FUNCTION__ << "(" << time.InMicroseconds() << ")"; | |
| 135 DCHECK(task_runner_->BelongsToCurrentThread()); | |
| 136 | |
| 137 base::AutoLock auto_lock(lock_); | |
| 138 DCHECK(!rendering_); | |
| 139 DCHECK_EQ(state_, kFlushed); | |
| 140 | |
| 141 start_timestamp_ = time; | |
| 142 } | |
| 143 | |
| 144 void AudioRendererImpl::Flush(const base::Closure& callback) { | 135 void AudioRendererImpl::Flush(const base::Closure& callback) { |
| 145 DVLOG(1) << __FUNCTION__; | 136 DVLOG(1) << __FUNCTION__; |
| 146 DCHECK(task_runner_->BelongsToCurrentThread()); | 137 DCHECK(task_runner_->BelongsToCurrentThread()); |
| 147 | 138 |
| 148 base::AutoLock auto_lock(lock_); | 139 base::AutoLock auto_lock(lock_); |
| 149 DCHECK_EQ(state_, kPlaying); | 140 DCHECK_EQ(state_, kPlaying); |
| 150 DCHECK(flush_cb_.is_null()); | 141 DCHECK(flush_cb_.is_null()); |
| 151 | 142 |
| 152 flush_cb_ = callback; | 143 flush_cb_ = callback; |
| 153 ChangeState_Locked(kFlushing); | 144 ChangeState_Locked(kFlushing); |
| (...skipping 83 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 237 base::AutoLock auto_lock(lock_); | 228 base::AutoLock auto_lock(lock_); |
| 238 DCHECK(!sink_playing_); | 229 DCHECK(!sink_playing_); |
| 239 DCHECK_EQ(state_, kFlushed); | 230 DCHECK_EQ(state_, kFlushed); |
| 240 DCHECK_EQ(buffering_state_, BUFFERING_HAVE_NOTHING); | 231 DCHECK_EQ(buffering_state_, BUFFERING_HAVE_NOTHING); |
| 241 DCHECK(!pending_read_) << "Pending read must complete before seeking"; | 232 DCHECK(!pending_read_) << "Pending read must complete before seeking"; |
| 242 | 233 |
| 243 ChangeState_Locked(kPlaying); | 234 ChangeState_Locked(kPlaying); |
| 244 AttemptRead_Locked(); | 235 AttemptRead_Locked(); |
| 245 } | 236 } |
| 246 | 237 |
| 238 void AudioRendererImpl::SetMediaTime(base::TimeDelta timestamp) { |
| 239 DVLOG(1) << __FUNCTION__ << "(" << timestamp.InMicroseconds() << ")"; |
| 240 DCHECK(task_runner_->BelongsToCurrentThread()); |
| 241 |
| 242 base::AutoLock auto_lock(lock_); |
| 243 DCHECK(!rendering_); |
| 244 DCHECK_EQ(state_, kFlushed); |
| 245 start_timestamp_ = timestamp; |
| 246 } |
| 247 |
| 248 base::TimeDelta AudioRendererImpl::CurrentMediaTime() { |
| 249 DVLOG(1) << __FUNCTION__; |
| 250 DCHECK(task_runner_->BelongsToCurrentThread()); |
| 251 |
| 252 base::AutoLock auto_lock(lock_); |
| 253 base::TimeDelta timestamp = audio_clock_->CurrentMediaTimestamp( |
| 254 tick_clock_->NowTicks() - last_render_ticks_); |
| 255 if (timestamp == kNoTimestamp()) |
| 256 return start_timestamp_; |
| 257 return timestamp; |
| 258 } |
| 259 |
| 247 void AudioRendererImpl::Initialize(DemuxerStream* stream, | 260 void AudioRendererImpl::Initialize(DemuxerStream* stream, |
| 248 const PipelineStatusCB& init_cb, | 261 const PipelineStatusCB& init_cb, |
| 249 const StatisticsCB& statistics_cb, | 262 const StatisticsCB& statistics_cb, |
| 250 const TimeCB& time_cb, | 263 const TimeCB& time_cb, |
| 251 const BufferingStateCB& buffering_state_cb, | 264 const BufferingStateCB& buffering_state_cb, |
| 252 const base::Closure& ended_cb, | 265 const base::Closure& ended_cb, |
| 253 const PipelineStatusCB& error_cb) { | 266 const PipelineStatusCB& error_cb) { |
| 254 DCHECK(task_runner_->BelongsToCurrentThread()); | 267 DCHECK(task_runner_->BelongsToCurrentThread()); |
| 255 DCHECK(stream); | 268 DCHECK(stream); |
| 256 DCHECK_EQ(stream->type(), DemuxerStream::AUDIO); | 269 DCHECK_EQ(stream->type(), DemuxerStream::AUDIO); |
| (...skipping 105 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 362 | 375 |
| 363 base::ResetAndReturn(&init_cb_).Run(PIPELINE_OK); | 376 base::ResetAndReturn(&init_cb_).Run(PIPELINE_OK); |
| 364 } | 377 } |
| 365 | 378 |
| 366 void AudioRendererImpl::SetVolume(float volume) { | 379 void AudioRendererImpl::SetVolume(float volume) { |
| 367 DCHECK(task_runner_->BelongsToCurrentThread()); | 380 DCHECK(task_runner_->BelongsToCurrentThread()); |
| 368 DCHECK(sink_); | 381 DCHECK(sink_); |
| 369 sink_->SetVolume(volume); | 382 sink_->SetVolume(volume); |
| 370 } | 383 } |
| 371 | 384 |
| 385 void AudioRendererImpl::SetTickClockForTesting( |
| 386 scoped_ptr<base::TickClock> tick_clock) { |
| 387 tick_clock_.swap(tick_clock); |
| 388 } |
| 389 |
| 372 void AudioRendererImpl::DecodedAudioReady( | 390 void AudioRendererImpl::DecodedAudioReady( |
| 373 AudioBufferStream::Status status, | 391 AudioBufferStream::Status status, |
| 374 const scoped_refptr<AudioBuffer>& buffer) { | 392 const scoped_refptr<AudioBuffer>& buffer) { |
| 375 DVLOG(2) << __FUNCTION__ << "(" << status << ")"; | 393 DVLOG(2) << __FUNCTION__ << "(" << status << ")"; |
| 376 DCHECK(task_runner_->BelongsToCurrentThread()); | 394 DCHECK(task_runner_->BelongsToCurrentThread()); |
| 377 | 395 |
| 378 base::AutoLock auto_lock(lock_); | 396 base::AutoLock auto_lock(lock_); |
| 379 DCHECK(state_ != kUninitialized); | 397 DCHECK(state_ != kUninitialized); |
| 380 | 398 |
| 381 CHECK(pending_read_); | 399 CHECK(pending_read_); |
| (...skipping 176 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 558 int audio_delay_milliseconds) { | 576 int audio_delay_milliseconds) { |
| 559 const int requested_frames = audio_bus->frames(); | 577 const int requested_frames = audio_bus->frames(); |
| 560 base::TimeDelta playback_delay = base::TimeDelta::FromMilliseconds( | 578 base::TimeDelta playback_delay = base::TimeDelta::FromMilliseconds( |
| 561 audio_delay_milliseconds); | 579 audio_delay_milliseconds); |
| 562 const int delay_frames = static_cast<int>(playback_delay.InSecondsF() * | 580 const int delay_frames = static_cast<int>(playback_delay.InSecondsF() * |
| 563 audio_parameters_.sample_rate()); | 581 audio_parameters_.sample_rate()); |
| 564 int frames_written = 0; | 582 int frames_written = 0; |
| 565 base::Closure time_cb; | 583 base::Closure time_cb; |
| 566 { | 584 { |
| 567 base::AutoLock auto_lock(lock_); | 585 base::AutoLock auto_lock(lock_); |
| 586 last_render_ticks_ = tick_clock_->NowTicks(); |
| 568 | 587 |
| 569 // Ensure Stop() hasn't destroyed our |algorithm_| on the pipeline thread. | 588 // Ensure Stop() hasn't destroyed our |algorithm_| on the pipeline thread. |
| 570 if (!algorithm_) { | 589 if (!algorithm_) { |
| 571 audio_clock_->WroteSilence(requested_frames, delay_frames); | 590 audio_clock_->WroteSilence(requested_frames, delay_frames); |
| 572 return 0; | 591 return 0; |
| 573 } | 592 } |
| 574 | 593 |
| 575 float playback_rate = algorithm_->playback_rate(); | 594 float playback_rate = algorithm_->playback_rate(); |
| 576 if (playback_rate == 0) { | 595 if (playback_rate == 0) { |
| 577 audio_clock_->WroteSilence(requested_frames, delay_frames); | 596 audio_clock_->WroteSilence(requested_frames, delay_frames); |
| (...skipping 132 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 710 << buffering_state; | 729 << buffering_state; |
| 711 DCHECK_NE(buffering_state_, buffering_state); | 730 DCHECK_NE(buffering_state_, buffering_state); |
| 712 lock_.AssertAcquired(); | 731 lock_.AssertAcquired(); |
| 713 buffering_state_ = buffering_state; | 732 buffering_state_ = buffering_state; |
| 714 | 733 |
| 715 task_runner_->PostTask(FROM_HERE, | 734 task_runner_->PostTask(FROM_HERE, |
| 716 base::Bind(buffering_state_cb_, buffering_state_)); | 735 base::Bind(buffering_state_cb_, buffering_state_)); |
| 717 } | 736 } |
| 718 | 737 |
| 719 } // namespace media | 738 } // namespace media |
| OLD | NEW |