Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(20)

Side by Side Diff: media/filters/audio_renderer_impl.cc

Issue 534073002: Switch to using media::TimeSource inside media::RendererImpl. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: fix bad rebase Created 6 years, 3 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « media/filters/audio_renderer_impl.h ('k') | media/filters/audio_renderer_impl_unittest.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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
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
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
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
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
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
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
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
OLDNEW
« no previous file with comments | « media/filters/audio_renderer_impl.h ('k') | media/filters/audio_renderer_impl_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698