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 |