| 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/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 Loading... |
| 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 Loading... |
| 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 Loading... |
| 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 Loading... |
| 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 |
| OLD | NEW |