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