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

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

Issue 2472183004: [TO 54] AudioRendererImpl: Don't advance time when rendering stops. (Closed)
Patch Set: Created 4 years, 1 month 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/renderers/audio_renderer_impl.h ('k') | media/renderers/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/renderers/audio_renderer_impl.h" 5 #include "media/renderers/audio_renderer_impl.h"
6 6
7 #include <math.h> 7 #include <math.h>
8 #include <stddef.h> 8 #include <stddef.h>
9 #include <algorithm> 9 #include <algorithm>
10 #include <utility> 10 #include <utility>
(...skipping 84 matching lines...) Expand 10 before | Expand all | Expand 10 after
95 // After this call, the |sink_| will not call back into |this| anymore. 95 // After this call, the |sink_| will not call back into |this| anymore.
96 sink_->Stop(); 96 sink_->Stop();
97 97
98 if (!init_cb_.is_null()) 98 if (!init_cb_.is_null())
99 base::ResetAndReturn(&init_cb_).Run(PIPELINE_ERROR_ABORT); 99 base::ResetAndReturn(&init_cb_).Run(PIPELINE_ERROR_ABORT);
100 } 100 }
101 101
102 void AudioRendererImpl::StartTicking() { 102 void AudioRendererImpl::StartTicking() {
103 DVLOG(1) << __func__; 103 DVLOG(1) << __func__;
104 DCHECK(task_runner_->BelongsToCurrentThread()); 104 DCHECK(task_runner_->BelongsToCurrentThread());
105
106 base::AutoLock auto_lock(lock_);
107
105 DCHECK(!rendering_); 108 DCHECK(!rendering_);
106 rendering_ = true; 109 rendering_ = true;
107 110
108 base::AutoLock auto_lock(lock_);
109 // Wait for an eventual call to SetPlaybackRate() to start rendering. 111 // Wait for an eventual call to SetPlaybackRate() to start rendering.
110 if (playback_rate_ == 0) { 112 if (playback_rate_ == 0) {
111 DCHECK(!sink_playing_); 113 DCHECK(!sink_playing_);
112 return; 114 return;
113 } 115 }
114 116
115 StartRendering_Locked(); 117 StartRendering_Locked();
116 } 118 }
117 119
118 void AudioRendererImpl::StartRendering_Locked() { 120 void AudioRendererImpl::StartRendering_Locked() {
119 DVLOG(1) << __func__; 121 DVLOG(1) << __func__;
120 DCHECK(task_runner_->BelongsToCurrentThread()); 122 DCHECK(task_runner_->BelongsToCurrentThread());
121 DCHECK_EQ(state_, kPlaying); 123 DCHECK_EQ(state_, kPlaying);
122 DCHECK(!sink_playing_); 124 DCHECK(!sink_playing_);
123 DCHECK_NE(playback_rate_, 0.0); 125 DCHECK_NE(playback_rate_, 0.0);
124 lock_.AssertAcquired(); 126 lock_.AssertAcquired();
125 127
126 sink_playing_ = true; 128 sink_playing_ = true;
127 129
128 base::AutoUnlock auto_unlock(lock_); 130 base::AutoUnlock auto_unlock(lock_);
129 sink_->Play(); 131 sink_->Play();
130 } 132 }
131 133
132 void AudioRendererImpl::StopTicking() { 134 void AudioRendererImpl::StopTicking() {
133 DVLOG(1) << __func__; 135 DVLOG(1) << __func__;
134 DCHECK(task_runner_->BelongsToCurrentThread()); 136 DCHECK(task_runner_->BelongsToCurrentThread());
137
138 base::AutoLock auto_lock(lock_);
139
135 DCHECK(rendering_); 140 DCHECK(rendering_);
136 rendering_ = false; 141 rendering_ = false;
137 142
138 base::AutoLock auto_lock(lock_);
139 // Rendering should have already been stopped with a zero playback rate. 143 // Rendering should have already been stopped with a zero playback rate.
140 if (playback_rate_ == 0) { 144 if (playback_rate_ == 0) {
141 DCHECK(!sink_playing_); 145 DCHECK(!sink_playing_);
142 return; 146 return;
143 } 147 }
144 148
145 StopRendering_Locked(); 149 StopRendering_Locked();
146 } 150 }
147 151
148 void AudioRendererImpl::StopRendering_Locked() { 152 void AudioRendererImpl::StopRendering_Locked() {
(...skipping 16 matching lines...) Expand all
165 base::AutoLock auto_lock(lock_); 169 base::AutoLock auto_lock(lock_);
166 DCHECK(!rendering_); 170 DCHECK(!rendering_);
167 DCHECK_EQ(state_, kFlushed); 171 DCHECK_EQ(state_, kFlushed);
168 172
169 start_timestamp_ = time; 173 start_timestamp_ = time;
170 ended_timestamp_ = kInfiniteDuration; 174 ended_timestamp_ = kInfiniteDuration;
171 last_render_time_ = stop_rendering_time_ = base::TimeTicks(); 175 last_render_time_ = stop_rendering_time_ = base::TimeTicks();
172 first_packet_timestamp_ = kNoTimestamp; 176 first_packet_timestamp_ = kNoTimestamp;
173 last_media_timestamp_ = base::TimeDelta(); 177 last_media_timestamp_ = base::TimeDelta();
174 audio_clock_.reset(new AudioClock(time, audio_parameters_.sample_rate())); 178 audio_clock_.reset(new AudioClock(time, audio_parameters_.sample_rate()));
179 last_reported_media_time_ = kNoTimestamp;
175 } 180 }
176 181
177 base::TimeDelta AudioRendererImpl::CurrentMediaTime() { 182 base::TimeDelta AudioRendererImpl::CurrentMediaTime() {
178 base::AutoLock auto_lock(lock_); 183 base::AutoLock auto_lock(lock_);
179 184
185 // Re-use last reported time if rendering has stopped to avoid confusing blink
186 // layer (avoid currentTime advancing after signaling buffer underflow).
187 // TODO(chcunningham): Do this in blink instead. Patching it here for now
188 // because HTMLMediaElement's currentTime is a mess.
189 if (!rendering_ && last_reported_media_time_ != kNoTimestamp) {
190 // If rendering stops, be sure to at least report the front time of the most
191 // recently rendered audio buffer.
192 if (last_reported_media_time_ < audio_clock_->front_timestamp())
193 last_reported_media_time_ = audio_clock_->front_timestamp();
194
195 DVLOG(3) << __func__ << " Returning cached time while rendering stopped:"
196 << last_reported_media_time_.InMicroseconds();
197 return last_reported_media_time_;
198 }
199
180 // Return the current time based on the known extents of the rendered audio 200 // Return the current time based on the known extents of the rendered audio
181 // data plus an estimate based on the last time those values were calculated. 201 // data plus an estimate based on the last time those values were calculated.
182 base::TimeDelta current_media_time = audio_clock_->front_timestamp(); 202 base::TimeDelta current_media_time = audio_clock_->front_timestamp();
183 if (!last_render_time_.is_null()) { 203 if (!last_render_time_.is_null()) {
184 current_media_time += 204 current_media_time +=
185 (tick_clock_->NowTicks() - last_render_time_) * playback_rate_; 205 (tick_clock_->NowTicks() - last_render_time_) * playback_rate_;
186 if (current_media_time > audio_clock_->back_timestamp()) 206 if (current_media_time > audio_clock_->back_timestamp())
187 current_media_time = audio_clock_->back_timestamp(); 207 current_media_time = audio_clock_->back_timestamp();
188 } 208 }
189 209
190 // Clamp current media time to the last reported value, this prevents higher 210 // Clamp current media time to the last reported value, this prevents higher
191 // level clients from seeing time go backwards based on inaccurate or spurious 211 // level clients from seeing time go backwards based on inaccurate or spurious
192 // delay values reported to the AudioClock. 212 // delay values reported to the AudioClock.
193 // 213 //
194 // It is expected that such events are transient and will be recovered as 214 // It is expected that such events are transient and will be recovered as
195 // rendering continues over time. 215 // rendering continues over time.
196 if (current_media_time < last_media_timestamp_) { 216 if (current_media_time < last_media_timestamp_) {
197 DVLOG(2) << __func__ << ": " << last_media_timestamp_ 217 DVLOG(2) << __func__ << ": " << last_media_timestamp_
198 << " (clamped), actual: " << current_media_time; 218 << " (clamped), actual: " << current_media_time;
199 return last_media_timestamp_; 219 return last_media_timestamp_;
200 } 220 }
201 221
202 DVLOG(2) << __func__ << ": " << current_media_time; 222 DVLOG(2) << __func__ << ": " << current_media_time;
203 last_media_timestamp_ = current_media_time; 223 last_media_timestamp_ = current_media_time;
224 last_reported_media_time_ = current_media_time;
204 return current_media_time; 225 return current_media_time;
205 } 226 }
206 227
207 bool AudioRendererImpl::GetWallClockTimes( 228 bool AudioRendererImpl::GetWallClockTimes(
208 const std::vector<base::TimeDelta>& media_timestamps, 229 const std::vector<base::TimeDelta>& media_timestamps,
209 std::vector<base::TimeTicks>* wall_clock_times) { 230 std::vector<base::TimeTicks>* wall_clock_times) {
210 base::AutoLock auto_lock(lock_); 231 base::AutoLock auto_lock(lock_);
211 DCHECK(wall_clock_times->empty()); 232 DCHECK(wall_clock_times->empty());
212 233
213 // When playback is paused (rate is zero), assume a rate of 1.0. 234 // When playback is paused (rate is zero), assume a rate of 1.0.
(...skipping 224 matching lines...) Expand 10 before | Expand all | Expand 10 after
438 : stream->audio_decoder_config().channel_layout(); 459 : stream->audio_decoder_config().channel_layout();
439 460
440 audio_parameters_.Reset(hw_params.format(), renderer_channel_layout, 461 audio_parameters_.Reset(hw_params.format(), renderer_channel_layout,
441 sample_rate, hw_params.bits_per_sample(), 462 sample_rate, hw_params.bits_per_sample(),
442 media::AudioLatency::GetHighLatencyBufferSize( 463 media::AudioLatency::GetHighLatencyBufferSize(
443 sample_rate, preferred_buffer_size)); 464 sample_rate, preferred_buffer_size));
444 } 465 }
445 466
446 audio_clock_.reset( 467 audio_clock_.reset(
447 new AudioClock(base::TimeDelta(), audio_parameters_.sample_rate())); 468 new AudioClock(base::TimeDelta(), audio_parameters_.sample_rate()));
469 last_reported_media_time_ = kNoTimestamp;
448 470
449 audio_buffer_stream_->Initialize( 471 audio_buffer_stream_->Initialize(
450 stream, base::Bind(&AudioRendererImpl::OnAudioBufferStreamInitialized, 472 stream, base::Bind(&AudioRendererImpl::OnAudioBufferStreamInitialized,
451 weak_factory_.GetWeakPtr()), 473 weak_factory_.GetWeakPtr()),
452 cdm_context, base::Bind(&AudioRendererImpl::OnStatisticsUpdate, 474 cdm_context, base::Bind(&AudioRendererImpl::OnStatisticsUpdate,
453 weak_factory_.GetWeakPtr()), 475 weak_factory_.GetWeakPtr()),
454 base::Bind(&AudioRendererImpl::OnWaitingForDecryptionKey, 476 base::Bind(&AudioRendererImpl::OnWaitingForDecryptionKey,
455 weak_factory_.GetWeakPtr())); 477 weak_factory_.GetWeakPtr()));
456 } 478 }
457 479
(...skipping 510 matching lines...) Expand 10 before | Expand all | Expand 10 after
968 DCHECK_NE(buffering_state_, buffering_state); 990 DCHECK_NE(buffering_state_, buffering_state);
969 lock_.AssertAcquired(); 991 lock_.AssertAcquired();
970 buffering_state_ = buffering_state; 992 buffering_state_ = buffering_state;
971 993
972 task_runner_->PostTask( 994 task_runner_->PostTask(
973 FROM_HERE, base::Bind(&AudioRendererImpl::OnBufferingStateChange, 995 FROM_HERE, base::Bind(&AudioRendererImpl::OnBufferingStateChange,
974 weak_factory_.GetWeakPtr(), buffering_state_)); 996 weak_factory_.GetWeakPtr(), buffering_state_));
975 } 997 }
976 998
977 } // namespace media 999 } // namespace media
OLDNEW
« no previous file with comments | « media/renderers/audio_renderer_impl.h ('k') | media/renderers/audio_renderer_impl_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698