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