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 43 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
54 set_decryptor_ready_cb)), | 54 set_decryptor_ready_cb)), |
55 hardware_config_(hardware_config), | 55 hardware_config_(hardware_config), |
56 playback_rate_(0), | 56 playback_rate_(0), |
57 state_(kUninitialized), | 57 state_(kUninitialized), |
58 buffering_state_(BUFFERING_HAVE_NOTHING), | 58 buffering_state_(BUFFERING_HAVE_NOTHING), |
59 rendering_(false), | 59 rendering_(false), |
60 sink_playing_(false), | 60 sink_playing_(false), |
61 pending_read_(false), | 61 pending_read_(false), |
62 received_end_of_stream_(false), | 62 received_end_of_stream_(false), |
63 rendered_end_of_stream_(false), | 63 rendered_end_of_stream_(false), |
64 last_timestamp_update_(kNoTimestamp()), | |
65 weak_factory_(this) { | 64 weak_factory_(this) { |
66 audio_buffer_stream_->set_splice_observer(base::Bind( | 65 audio_buffer_stream_->set_splice_observer(base::Bind( |
67 &AudioRendererImpl::OnNewSpliceBuffer, weak_factory_.GetWeakPtr())); | 66 &AudioRendererImpl::OnNewSpliceBuffer, weak_factory_.GetWeakPtr())); |
68 audio_buffer_stream_->set_config_change_observer(base::Bind( | 67 audio_buffer_stream_->set_config_change_observer(base::Bind( |
69 &AudioRendererImpl::OnConfigChange, weak_factory_.GetWeakPtr())); | 68 &AudioRendererImpl::OnConfigChange, weak_factory_.GetWeakPtr())); |
70 } | 69 } |
71 | 70 |
72 AudioRendererImpl::~AudioRendererImpl() { | 71 AudioRendererImpl::~AudioRendererImpl() { |
73 DVLOG(1) << __FUNCTION__; | 72 DVLOG(1) << __FUNCTION__; |
74 DCHECK(task_runner_->BelongsToCurrentThread()); | 73 DCHECK(task_runner_->BelongsToCurrentThread()); |
(...skipping 67 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
142 void AudioRendererImpl::SetMediaTime(base::TimeDelta time) { | 141 void AudioRendererImpl::SetMediaTime(base::TimeDelta time) { |
143 DVLOG(1) << __FUNCTION__ << "(" << time.InMicroseconds() << ")"; | 142 DVLOG(1) << __FUNCTION__ << "(" << time.InMicroseconds() << ")"; |
144 DCHECK(task_runner_->BelongsToCurrentThread()); | 143 DCHECK(task_runner_->BelongsToCurrentThread()); |
145 | 144 |
146 base::AutoLock auto_lock(lock_); | 145 base::AutoLock auto_lock(lock_); |
147 DCHECK(!rendering_); | 146 DCHECK(!rendering_); |
148 DCHECK_EQ(state_, kFlushed); | 147 DCHECK_EQ(state_, kFlushed); |
149 | 148 |
150 start_timestamp_ = time; | 149 start_timestamp_ = time; |
151 ended_timestamp_ = kInfiniteDuration(); | 150 ended_timestamp_ = kInfiniteDuration(); |
151 last_render_ticks_ = base::TimeTicks(); | |
152 audio_clock_.reset(new AudioClock(time, audio_parameters_.sample_rate())); | 152 audio_clock_.reset(new AudioClock(time, audio_parameters_.sample_rate())); |
153 } | 153 } |
154 | 154 |
155 base::TimeDelta AudioRendererImpl::CurrentMediaTime() { | 155 base::TimeDelta AudioRendererImpl::CurrentMediaTime() { |
156 DVLOG(2) << __FUNCTION__; | 156 DVLOG(2) << __FUNCTION__; |
157 DCHECK(task_runner_->BelongsToCurrentThread()); | |
158 | 157 |
159 // TODO(scherkus): Finish implementing when ready to switch Pipeline to using | 158 base::AutoLock auto_lock(lock_); |
160 // TimeSource http://crbug.com/370634 | 159 return audio_clock_->front_timestamp(); |
xhwang
2014/09/08 22:56:06
Add a comment that since this is updated pretty fr
scherkus (not reviewing)
2014/09/09 18:17:18
Done.
| |
161 NOTIMPLEMENTED(); | 160 } |
162 | 161 |
163 return base::TimeDelta(); | 162 base::TimeDelta AudioRendererImpl::ApproximateCurrentMediaTime() { |
163 DVLOG(2) << __FUNCTION__; | |
164 | |
165 base::AutoLock auto_lock(lock_); | |
166 if (last_render_ticks_.is_null()) | |
167 return audio_clock_->front_timestamp(); | |
168 | |
169 return audio_clock_->TimestampSinceWriting(base::TimeTicks::Now() - | |
170 last_render_ticks_); | |
164 } | 171 } |
165 | 172 |
166 TimeSource* AudioRendererImpl::GetTimeSource() { | 173 TimeSource* AudioRendererImpl::GetTimeSource() { |
167 return this; | 174 return this; |
168 } | 175 } |
169 | 176 |
170 void AudioRendererImpl::Flush(const base::Closure& callback) { | 177 void AudioRendererImpl::Flush(const base::Closure& callback) { |
171 DVLOG(1) << __FUNCTION__; | 178 DVLOG(1) << __FUNCTION__; |
172 DCHECK(task_runner_->BelongsToCurrentThread()); | 179 DCHECK(task_runner_->BelongsToCurrentThread()); |
173 | 180 |
(...skipping 23 matching lines...) Expand all Loading... | |
197 } | 204 } |
198 | 205 |
199 void AudioRendererImpl::ResetDecoderDone() { | 206 void AudioRendererImpl::ResetDecoderDone() { |
200 DCHECK(task_runner_->BelongsToCurrentThread()); | 207 DCHECK(task_runner_->BelongsToCurrentThread()); |
201 { | 208 { |
202 base::AutoLock auto_lock(lock_); | 209 base::AutoLock auto_lock(lock_); |
203 | 210 |
204 DCHECK_EQ(state_, kFlushed); | 211 DCHECK_EQ(state_, kFlushed); |
205 DCHECK(!flush_cb_.is_null()); | 212 DCHECK(!flush_cb_.is_null()); |
206 | 213 |
207 audio_clock_.reset(); | |
208 received_end_of_stream_ = false; | 214 received_end_of_stream_ = false; |
209 rendered_end_of_stream_ = false; | 215 rendered_end_of_stream_ = false; |
210 last_timestamp_update_ = kNoTimestamp(); | |
211 | 216 |
212 // Flush() may have been called while underflowed/not fully buffered. | 217 // Flush() may have been called while underflowed/not fully buffered. |
213 if (buffering_state_ != BUFFERING_HAVE_NOTHING) | 218 if (buffering_state_ != BUFFERING_HAVE_NOTHING) |
214 SetBufferingState_Locked(BUFFERING_HAVE_NOTHING); | 219 SetBufferingState_Locked(BUFFERING_HAVE_NOTHING); |
215 | 220 |
216 splicer_->Reset(); | 221 splicer_->Reset(); |
217 if (buffer_converter_) | 222 if (buffer_converter_) |
218 buffer_converter_->Reset(); | 223 buffer_converter_->Reset(); |
219 algorithm_->FlushBuffers(); | 224 algorithm_->FlushBuffers(); |
220 } | 225 } |
(...skipping 13 matching lines...) Expand all Loading... | |
234 DCHECK_EQ(buffering_state_, BUFFERING_HAVE_NOTHING); | 239 DCHECK_EQ(buffering_state_, BUFFERING_HAVE_NOTHING); |
235 DCHECK(!pending_read_) << "Pending read must complete before seeking"; | 240 DCHECK(!pending_read_) << "Pending read must complete before seeking"; |
236 | 241 |
237 ChangeState_Locked(kPlaying); | 242 ChangeState_Locked(kPlaying); |
238 AttemptRead_Locked(); | 243 AttemptRead_Locked(); |
239 } | 244 } |
240 | 245 |
241 void AudioRendererImpl::Initialize(DemuxerStream* stream, | 246 void AudioRendererImpl::Initialize(DemuxerStream* stream, |
242 const PipelineStatusCB& init_cb, | 247 const PipelineStatusCB& init_cb, |
243 const StatisticsCB& statistics_cb, | 248 const StatisticsCB& statistics_cb, |
244 const TimeCB& time_cb, | |
245 const BufferingStateCB& buffering_state_cb, | 249 const BufferingStateCB& buffering_state_cb, |
246 const base::Closure& ended_cb, | 250 const base::Closure& ended_cb, |
247 const PipelineStatusCB& error_cb) { | 251 const PipelineStatusCB& error_cb) { |
248 DCHECK(task_runner_->BelongsToCurrentThread()); | 252 DCHECK(task_runner_->BelongsToCurrentThread()); |
249 DCHECK(stream); | 253 DCHECK(stream); |
250 DCHECK_EQ(stream->type(), DemuxerStream::AUDIO); | 254 DCHECK_EQ(stream->type(), DemuxerStream::AUDIO); |
251 DCHECK(!init_cb.is_null()); | 255 DCHECK(!init_cb.is_null()); |
252 DCHECK(!statistics_cb.is_null()); | 256 DCHECK(!statistics_cb.is_null()); |
253 DCHECK(!time_cb.is_null()); | |
254 DCHECK(!buffering_state_cb.is_null()); | 257 DCHECK(!buffering_state_cb.is_null()); |
255 DCHECK(!ended_cb.is_null()); | 258 DCHECK(!ended_cb.is_null()); |
256 DCHECK(!error_cb.is_null()); | 259 DCHECK(!error_cb.is_null()); |
257 DCHECK_EQ(kUninitialized, state_); | 260 DCHECK_EQ(kUninitialized, state_); |
258 DCHECK(sink_.get()); | 261 DCHECK(sink_.get()); |
259 | 262 |
260 state_ = kInitializing; | 263 state_ = kInitializing; |
261 | 264 |
262 // Always post |init_cb_| because |this| could be destroyed if initialization | 265 // Always post |init_cb_| because |this| could be destroyed if initialization |
263 // failed. | 266 // failed. |
264 init_cb_ = BindToCurrentLoop(init_cb); | 267 init_cb_ = BindToCurrentLoop(init_cb); |
265 | 268 |
266 time_cb_ = time_cb; | |
267 buffering_state_cb_ = buffering_state_cb; | 269 buffering_state_cb_ = buffering_state_cb; |
268 ended_cb_ = ended_cb; | 270 ended_cb_ = ended_cb; |
269 error_cb_ = error_cb; | 271 error_cb_ = error_cb; |
270 | 272 |
271 expecting_config_changes_ = stream->SupportsConfigChanges(); | 273 expecting_config_changes_ = stream->SupportsConfigChanges(); |
272 if (!expecting_config_changes_) { | 274 if (!expecting_config_changes_) { |
273 // The actual buffer size is controlled via the size of the AudioBus | 275 // The actual buffer size is controlled via the size of the AudioBus |
274 // provided to Render(), so just choose something reasonable here for looks. | 276 // provided to Render(), so just choose something reasonable here for looks. |
275 int buffer_size = stream->audio_decoder_config().samples_per_second() / 100; | 277 int buffer_size = stream->audio_decoder_config().samples_per_second() / 100; |
276 audio_parameters_.Reset( | 278 audio_parameters_.Reset( |
(...skipping 266 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
543 int AudioRendererImpl::Render(AudioBus* audio_bus, | 545 int AudioRendererImpl::Render(AudioBus* audio_bus, |
544 int audio_delay_milliseconds) { | 546 int audio_delay_milliseconds) { |
545 const int requested_frames = audio_bus->frames(); | 547 const int requested_frames = audio_bus->frames(); |
546 base::TimeDelta playback_delay = base::TimeDelta::FromMilliseconds( | 548 base::TimeDelta playback_delay = base::TimeDelta::FromMilliseconds( |
547 audio_delay_milliseconds); | 549 audio_delay_milliseconds); |
548 const int delay_frames = static_cast<int>(playback_delay.InSecondsF() * | 550 const int delay_frames = static_cast<int>(playback_delay.InSecondsF() * |
549 audio_parameters_.sample_rate()); | 551 audio_parameters_.sample_rate()); |
550 int frames_written = 0; | 552 int frames_written = 0; |
551 { | 553 { |
552 base::AutoLock auto_lock(lock_); | 554 base::AutoLock auto_lock(lock_); |
555 last_render_ticks_ = base::TimeTicks::Now(); | |
553 | 556 |
554 // Ensure Stop() hasn't destroyed our |algorithm_| on the pipeline thread. | 557 // Ensure Stop() hasn't destroyed our |algorithm_| on the pipeline thread. |
555 if (!algorithm_) { | 558 if (!algorithm_) { |
556 audio_clock_->WroteAudio( | 559 audio_clock_->WroteAudio( |
557 0, requested_frames, delay_frames, playback_rate_); | 560 0, requested_frames, delay_frames, playback_rate_); |
558 return 0; | 561 return 0; |
559 } | 562 } |
560 | 563 |
561 if (playback_rate_ == 0) { | 564 if (playback_rate_ == 0) { |
562 audio_clock_->WroteAudio( | 565 audio_clock_->WroteAudio( |
(...skipping 50 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
613 requested_frames, | 616 requested_frames, |
614 delay_frames, | 617 delay_frames, |
615 playback_rate_); | 618 playback_rate_); |
616 | 619 |
617 if (CanRead_Locked()) { | 620 if (CanRead_Locked()) { |
618 task_runner_->PostTask(FROM_HERE, | 621 task_runner_->PostTask(FROM_HERE, |
619 base::Bind(&AudioRendererImpl::AttemptRead, | 622 base::Bind(&AudioRendererImpl::AttemptRead, |
620 weak_factory_.GetWeakPtr())); | 623 weak_factory_.GetWeakPtr())); |
621 } | 624 } |
622 | 625 |
623 if (last_timestamp_update_ != audio_clock_->front_timestamp()) { | 626 if (audio_clock_->front_timestamp() >= ended_timestamp_ && |
624 // Since |max_time| uses linear interpolation, only provide an upper bound | 627 !rendered_end_of_stream_) { |
625 // that is for audio data at the same playback rate. Failing to do so can | 628 rendered_end_of_stream_ = true; |
626 // make time jump backwards when the linear interpolated time advances | 629 task_runner_->PostTask(FROM_HERE, ended_cb_); |
627 // past buffered regions of audio at different rates. | |
628 last_timestamp_update_ = audio_clock_->front_timestamp(); | |
629 base::TimeDelta max_time = | |
630 last_timestamp_update_ + | |
631 audio_clock_->contiguous_audio_data_buffered_at_same_rate(); | |
632 task_runner_->PostTask( | |
633 FROM_HERE, base::Bind(time_cb_, last_timestamp_update_, max_time)); | |
634 | |
635 if (last_timestamp_update_ >= ended_timestamp_ && | |
636 !rendered_end_of_stream_) { | |
637 rendered_end_of_stream_ = true; | |
638 task_runner_->PostTask(FROM_HERE, ended_cb_); | |
639 } | |
640 } | 630 } |
641 } | 631 } |
642 | 632 |
643 DCHECK_LE(frames_written, requested_frames); | 633 DCHECK_LE(frames_written, requested_frames); |
644 return frames_written; | 634 return frames_written; |
645 } | 635 } |
646 | 636 |
647 void AudioRendererImpl::OnRenderError() { | 637 void AudioRendererImpl::OnRenderError() { |
648 // UMA data tells us this happens ~0.01% of the time. Trigger an error instead | 638 // UMA data tells us this happens ~0.01% of the time. Trigger an error instead |
649 // of trying to gracefully fall back to a fake sink. It's very likely | 639 // of trying to gracefully fall back to a fake sink. It's very likely |
(...skipping 62 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
712 << buffering_state; | 702 << buffering_state; |
713 DCHECK_NE(buffering_state_, buffering_state); | 703 DCHECK_NE(buffering_state_, buffering_state); |
714 lock_.AssertAcquired(); | 704 lock_.AssertAcquired(); |
715 buffering_state_ = buffering_state; | 705 buffering_state_ = buffering_state; |
716 | 706 |
717 task_runner_->PostTask(FROM_HERE, | 707 task_runner_->PostTask(FROM_HERE, |
718 base::Bind(buffering_state_cb_, buffering_state_)); | 708 base::Bind(buffering_state_cb_, buffering_state_)); |
719 } | 709 } |
720 | 710 |
721 } // namespace media | 711 } // namespace media |
OLD | NEW |