| 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 |
| 11 #include "base/bind.h" | 11 #include "base/bind.h" |
| 12 #include "base/callback.h" | 12 #include "base/callback.h" |
| 13 #include "base/callback_helpers.h" | 13 #include "base/callback_helpers.h" |
| 14 #include "base/logging.h" | 14 #include "base/logging.h" |
| 15 #include "base/message_loop/message_loop_proxy.h" | |
| 16 #include "base/metrics/histogram.h" | 15 #include "base/metrics/histogram.h" |
| 16 #include "base/single_thread_task_runner.h" |
| 17 #include "media/base/audio_buffer.h" | 17 #include "media/base/audio_buffer.h" |
| 18 #include "media/base/audio_splicer.h" | 18 #include "media/base/audio_splicer.h" |
| 19 #include "media/base/bind_to_loop.h" | 19 #include "media/base/bind_to_loop.h" |
| 20 #include "media/base/demuxer_stream.h" | 20 #include "media/base/demuxer_stream.h" |
| 21 #include "media/filters/audio_decoder_selector.h" | 21 #include "media/filters/audio_decoder_selector.h" |
| 22 #include "media/filters/decrypting_demuxer_stream.h" | 22 #include "media/filters/decrypting_demuxer_stream.h" |
| 23 | 23 |
| 24 namespace media { | 24 namespace media { |
| 25 | 25 |
| 26 namespace { | 26 namespace { |
| 27 | 27 |
| 28 enum AudioRendererEvent { | 28 enum AudioRendererEvent { |
| 29 INITIALIZED, | 29 INITIALIZED, |
| 30 RENDER_ERROR, | 30 RENDER_ERROR, |
| 31 MAX_EVENTS | 31 MAX_EVENTS |
| 32 }; | 32 }; |
| 33 | 33 |
| 34 void HistogramRendererEvent(AudioRendererEvent event) { | 34 void HistogramRendererEvent(AudioRendererEvent event) { |
| 35 UMA_HISTOGRAM_ENUMERATION("Media.AudioRendererEvents", event, MAX_EVENTS); | 35 UMA_HISTOGRAM_ENUMERATION("Media.AudioRendererEvents", event, MAX_EVENTS); |
| 36 } | 36 } |
| 37 | 37 |
| 38 } // namespace | 38 } // namespace |
| 39 | 39 |
| 40 AudioRendererImpl::AudioRendererImpl( | 40 AudioRendererImpl::AudioRendererImpl( |
| 41 const scoped_refptr<base::MessageLoopProxy>& message_loop, | 41 const scoped_refptr<base::SingleThreadTaskRunner>& task_runner, |
| 42 media::AudioRendererSink* sink, | 42 media::AudioRendererSink* sink, |
| 43 ScopedVector<AudioDecoder> decoders, | 43 ScopedVector<AudioDecoder> decoders, |
| 44 const SetDecryptorReadyCB& set_decryptor_ready_cb) | 44 const SetDecryptorReadyCB& set_decryptor_ready_cb) |
| 45 : message_loop_(message_loop), | 45 : task_runner_(task_runner), |
| 46 weak_factory_(this), | 46 weak_factory_(this), |
| 47 sink_(sink), | 47 sink_(sink), |
| 48 decoder_selector_(new AudioDecoderSelector( | 48 decoder_selector_(new AudioDecoderSelector( |
| 49 message_loop, decoders.Pass(), set_decryptor_ready_cb)), | 49 task_runner, decoders.Pass(), set_decryptor_ready_cb)), |
| 50 now_cb_(base::Bind(&base::TimeTicks::Now)), | 50 now_cb_(base::Bind(&base::TimeTicks::Now)), |
| 51 state_(kUninitialized), | 51 state_(kUninitialized), |
| 52 sink_playing_(false), | 52 sink_playing_(false), |
| 53 pending_read_(false), | 53 pending_read_(false), |
| 54 received_end_of_stream_(false), | 54 received_end_of_stream_(false), |
| 55 rendered_end_of_stream_(false), | 55 rendered_end_of_stream_(false), |
| 56 audio_time_buffered_(kNoTimestamp()), | 56 audio_time_buffered_(kNoTimestamp()), |
| 57 current_time_(kNoTimestamp()), | 57 current_time_(kNoTimestamp()), |
| 58 underflow_disabled_(false), | 58 underflow_disabled_(false), |
| 59 preroll_aborted_(false) { | 59 preroll_aborted_(false) { |
| 60 } | 60 } |
| 61 | 61 |
| 62 AudioRendererImpl::~AudioRendererImpl() { | 62 AudioRendererImpl::~AudioRendererImpl() { |
| 63 // Stop() should have been called and |algorithm_| should have been destroyed. | 63 // Stop() should have been called and |algorithm_| should have been destroyed. |
| 64 DCHECK(state_ == kUninitialized || state_ == kStopped); | 64 DCHECK(state_ == kUninitialized || state_ == kStopped); |
| 65 DCHECK(!algorithm_.get()); | 65 DCHECK(!algorithm_.get()); |
| 66 } | 66 } |
| 67 | 67 |
| 68 void AudioRendererImpl::Play(const base::Closure& callback) { | 68 void AudioRendererImpl::Play(const base::Closure& callback) { |
| 69 DCHECK(message_loop_->BelongsToCurrentThread()); | 69 DCHECK(task_runner_->BelongsToCurrentThread()); |
| 70 | 70 |
| 71 base::AutoLock auto_lock(lock_); | 71 base::AutoLock auto_lock(lock_); |
| 72 DCHECK_EQ(state_, kPaused); | 72 DCHECK_EQ(state_, kPaused); |
| 73 ChangeState_Locked(kPlaying); | 73 ChangeState_Locked(kPlaying); |
| 74 callback.Run(); | 74 callback.Run(); |
| 75 earliest_end_time_ = now_cb_.Run(); | 75 earliest_end_time_ = now_cb_.Run(); |
| 76 | 76 |
| 77 if (algorithm_->playback_rate() != 0) | 77 if (algorithm_->playback_rate() != 0) |
| 78 DoPlay_Locked(); | 78 DoPlay_Locked(); |
| 79 else | 79 else |
| 80 DCHECK(!sink_playing_); | 80 DCHECK(!sink_playing_); |
| 81 } | 81 } |
| 82 | 82 |
| 83 void AudioRendererImpl::DoPlay_Locked() { | 83 void AudioRendererImpl::DoPlay_Locked() { |
| 84 DCHECK(message_loop_->BelongsToCurrentThread()); | 84 DCHECK(task_runner_->BelongsToCurrentThread()); |
| 85 lock_.AssertAcquired(); | 85 lock_.AssertAcquired(); |
| 86 earliest_end_time_ = now_cb_.Run(); | 86 earliest_end_time_ = now_cb_.Run(); |
| 87 | 87 |
| 88 if ((state_ == kPlaying || state_ == kRebuffering || state_ == kUnderflow) && | 88 if ((state_ == kPlaying || state_ == kRebuffering || state_ == kUnderflow) && |
| 89 !sink_playing_) { | 89 !sink_playing_) { |
| 90 { | 90 { |
| 91 base::AutoUnlock auto_unlock(lock_); | 91 base::AutoUnlock auto_unlock(lock_); |
| 92 sink_->Play(); | 92 sink_->Play(); |
| 93 } | 93 } |
| 94 | 94 |
| 95 sink_playing_ = true; | 95 sink_playing_ = true; |
| 96 } | 96 } |
| 97 } | 97 } |
| 98 | 98 |
| 99 void AudioRendererImpl::Pause(const base::Closure& callback) { | 99 void AudioRendererImpl::Pause(const base::Closure& callback) { |
| 100 DCHECK(message_loop_->BelongsToCurrentThread()); | 100 DCHECK(task_runner_->BelongsToCurrentThread()); |
| 101 | 101 |
| 102 base::AutoLock auto_lock(lock_); | 102 base::AutoLock auto_lock(lock_); |
| 103 DCHECK(state_ == kPlaying || state_ == kUnderflow || | 103 DCHECK(state_ == kPlaying || state_ == kUnderflow || |
| 104 state_ == kRebuffering) << "state_ == " << state_; | 104 state_ == kRebuffering) << "state_ == " << state_; |
| 105 ChangeState_Locked(kPaused); | 105 ChangeState_Locked(kPaused); |
| 106 | 106 |
| 107 DoPause_Locked(); | 107 DoPause_Locked(); |
| 108 | 108 |
| 109 callback.Run(); | 109 callback.Run(); |
| 110 } | 110 } |
| 111 | 111 |
| 112 void AudioRendererImpl::DoPause_Locked() { | 112 void AudioRendererImpl::DoPause_Locked() { |
| 113 DCHECK(message_loop_->BelongsToCurrentThread()); | 113 DCHECK(task_runner_->BelongsToCurrentThread()); |
| 114 lock_.AssertAcquired(); | 114 lock_.AssertAcquired(); |
| 115 | 115 |
| 116 if (sink_playing_) { | 116 if (sink_playing_) { |
| 117 { | 117 { |
| 118 base::AutoUnlock auto_unlock(lock_); | 118 base::AutoUnlock auto_unlock(lock_); |
| 119 sink_->Pause(); | 119 sink_->Pause(); |
| 120 } | 120 } |
| 121 sink_playing_ = false; | 121 sink_playing_ = false; |
| 122 } | 122 } |
| 123 } | 123 } |
| 124 | 124 |
| 125 void AudioRendererImpl::Flush(const base::Closure& callback) { | 125 void AudioRendererImpl::Flush(const base::Closure& callback) { |
| 126 DCHECK(message_loop_->BelongsToCurrentThread()); | 126 DCHECK(task_runner_->BelongsToCurrentThread()); |
| 127 | 127 |
| 128 base::AutoLock auto_lock(lock_); | 128 base::AutoLock auto_lock(lock_); |
| 129 DCHECK_EQ(state_, kPaused); | 129 DCHECK_EQ(state_, kPaused); |
| 130 DCHECK(flush_cb_.is_null()); | 130 DCHECK(flush_cb_.is_null()); |
| 131 | 131 |
| 132 flush_cb_ = callback; | 132 flush_cb_ = callback; |
| 133 | 133 |
| 134 if (pending_read_) { | 134 if (pending_read_) { |
| 135 ChangeState_Locked(kFlushing); | 135 ChangeState_Locked(kFlushing); |
| 136 return; | 136 return; |
| 137 } | 137 } |
| 138 | 138 |
| 139 DoFlush_Locked(); | 139 DoFlush_Locked(); |
| 140 } | 140 } |
| 141 | 141 |
| 142 void AudioRendererImpl::DoFlush_Locked() { | 142 void AudioRendererImpl::DoFlush_Locked() { |
| 143 DCHECK(message_loop_->BelongsToCurrentThread()); | 143 DCHECK(task_runner_->BelongsToCurrentThread()); |
| 144 lock_.AssertAcquired(); | 144 lock_.AssertAcquired(); |
| 145 | 145 |
| 146 DCHECK(!pending_read_); | 146 DCHECK(!pending_read_); |
| 147 DCHECK_EQ(state_, kPaused); | 147 DCHECK_EQ(state_, kPaused); |
| 148 | 148 |
| 149 if (decrypting_demuxer_stream_) { | 149 if (decrypting_demuxer_stream_) { |
| 150 decrypting_demuxer_stream_->Reset(BindToCurrentLoop( | 150 decrypting_demuxer_stream_->Reset(BindToCurrentLoop( |
| 151 base::Bind(&AudioRendererImpl::ResetDecoder, weak_this_))); | 151 base::Bind(&AudioRendererImpl::ResetDecoder, weak_this_))); |
| 152 return; | 152 return; |
| 153 } | 153 } |
| 154 | 154 |
| 155 ResetDecoder(); | 155 ResetDecoder(); |
| 156 } | 156 } |
| 157 | 157 |
| 158 void AudioRendererImpl::ResetDecoder() { | 158 void AudioRendererImpl::ResetDecoder() { |
| 159 DCHECK(message_loop_->BelongsToCurrentThread()); | 159 DCHECK(task_runner_->BelongsToCurrentThread()); |
| 160 decoder_->Reset(BindToCurrentLoop( | 160 decoder_->Reset(BindToCurrentLoop( |
| 161 base::Bind(&AudioRendererImpl::ResetDecoderDone, weak_this_))); | 161 base::Bind(&AudioRendererImpl::ResetDecoderDone, weak_this_))); |
| 162 } | 162 } |
| 163 | 163 |
| 164 void AudioRendererImpl::ResetDecoderDone() { | 164 void AudioRendererImpl::ResetDecoderDone() { |
| 165 base::AutoLock auto_lock(lock_); | 165 base::AutoLock auto_lock(lock_); |
| 166 if (state_ == kStopped) | 166 if (state_ == kStopped) |
| 167 return; | 167 return; |
| 168 | 168 |
| 169 DCHECK_EQ(state_, kPaused); | 169 DCHECK_EQ(state_, kPaused); |
| 170 DCHECK(!flush_cb_.is_null()); | 170 DCHECK(!flush_cb_.is_null()); |
| 171 | 171 |
| 172 audio_time_buffered_ = kNoTimestamp(); | 172 audio_time_buffered_ = kNoTimestamp(); |
| 173 current_time_ = kNoTimestamp(); | 173 current_time_ = kNoTimestamp(); |
| 174 received_end_of_stream_ = false; | 174 received_end_of_stream_ = false; |
| 175 rendered_end_of_stream_ = false; | 175 rendered_end_of_stream_ = false; |
| 176 preroll_aborted_ = false; | 176 preroll_aborted_ = false; |
| 177 | 177 |
| 178 earliest_end_time_ = now_cb_.Run(); | 178 earliest_end_time_ = now_cb_.Run(); |
| 179 splicer_->Reset(); | 179 splicer_->Reset(); |
| 180 algorithm_->FlushBuffers(); | 180 algorithm_->FlushBuffers(); |
| 181 | 181 |
| 182 base::ResetAndReturn(&flush_cb_).Run(); | 182 base::ResetAndReturn(&flush_cb_).Run(); |
| 183 } | 183 } |
| 184 | 184 |
| 185 void AudioRendererImpl::Stop(const base::Closure& callback) { | 185 void AudioRendererImpl::Stop(const base::Closure& callback) { |
| 186 DCHECK(message_loop_->BelongsToCurrentThread()); | 186 DCHECK(task_runner_->BelongsToCurrentThread()); |
| 187 DCHECK(!callback.is_null()); | 187 DCHECK(!callback.is_null()); |
| 188 | 188 |
| 189 // TODO(scherkus): Consider invalidating |weak_factory_| and replacing | 189 // TODO(scherkus): Consider invalidating |weak_factory_| and replacing |
| 190 // task-running guards that check |state_| with DCHECK(). | 190 // task-running guards that check |state_| with DCHECK(). |
| 191 | 191 |
| 192 if (sink_) { | 192 if (sink_) { |
| 193 sink_->Stop(); | 193 sink_->Stop(); |
| 194 sink_ = NULL; | 194 sink_ = NULL; |
| 195 } | 195 } |
| 196 | 196 |
| 197 { | 197 { |
| 198 base::AutoLock auto_lock(lock_); | 198 base::AutoLock auto_lock(lock_); |
| 199 ChangeState_Locked(kStopped); | 199 ChangeState_Locked(kStopped); |
| 200 algorithm_.reset(NULL); | 200 algorithm_.reset(NULL); |
| 201 init_cb_.Reset(); | 201 init_cb_.Reset(); |
| 202 underflow_cb_.Reset(); | 202 underflow_cb_.Reset(); |
| 203 time_cb_.Reset(); | 203 time_cb_.Reset(); |
| 204 flush_cb_.Reset(); | 204 flush_cb_.Reset(); |
| 205 } | 205 } |
| 206 | 206 |
| 207 callback.Run(); | 207 callback.Run(); |
| 208 } | 208 } |
| 209 | 209 |
| 210 void AudioRendererImpl::Preroll(base::TimeDelta time, | 210 void AudioRendererImpl::Preroll(base::TimeDelta time, |
| 211 const PipelineStatusCB& cb) { | 211 const PipelineStatusCB& cb) { |
| 212 DCHECK(message_loop_->BelongsToCurrentThread()); | 212 DCHECK(task_runner_->BelongsToCurrentThread()); |
| 213 | 213 |
| 214 base::AutoLock auto_lock(lock_); | 214 base::AutoLock auto_lock(lock_); |
| 215 DCHECK(!sink_playing_); | 215 DCHECK(!sink_playing_); |
| 216 DCHECK_EQ(state_, kPaused); | 216 DCHECK_EQ(state_, kPaused); |
| 217 DCHECK(!pending_read_) << "Pending read must complete before seeking"; | 217 DCHECK(!pending_read_) << "Pending read must complete before seeking"; |
| 218 DCHECK(preroll_cb_.is_null()); | 218 DCHECK(preroll_cb_.is_null()); |
| 219 | 219 |
| 220 ChangeState_Locked(kPrerolling); | 220 ChangeState_Locked(kPrerolling); |
| 221 preroll_cb_ = cb; | 221 preroll_cb_ = cb; |
| 222 preroll_timestamp_ = time; | 222 preroll_timestamp_ = time; |
| 223 | 223 |
| 224 AttemptRead_Locked(); | 224 AttemptRead_Locked(); |
| 225 } | 225 } |
| 226 | 226 |
| 227 void AudioRendererImpl::Initialize(DemuxerStream* stream, | 227 void AudioRendererImpl::Initialize(DemuxerStream* stream, |
| 228 const PipelineStatusCB& init_cb, | 228 const PipelineStatusCB& init_cb, |
| 229 const StatisticsCB& statistics_cb, | 229 const StatisticsCB& statistics_cb, |
| 230 const base::Closure& underflow_cb, | 230 const base::Closure& underflow_cb, |
| 231 const TimeCB& time_cb, | 231 const TimeCB& time_cb, |
| 232 const base::Closure& ended_cb, | 232 const base::Closure& ended_cb, |
| 233 const base::Closure& disabled_cb, | 233 const base::Closure& disabled_cb, |
| 234 const PipelineStatusCB& error_cb) { | 234 const PipelineStatusCB& error_cb) { |
| 235 DCHECK(message_loop_->BelongsToCurrentThread()); | 235 DCHECK(task_runner_->BelongsToCurrentThread()); |
| 236 DCHECK(stream); | 236 DCHECK(stream); |
| 237 DCHECK_EQ(stream->type(), DemuxerStream::AUDIO); | 237 DCHECK_EQ(stream->type(), DemuxerStream::AUDIO); |
| 238 DCHECK(!init_cb.is_null()); | 238 DCHECK(!init_cb.is_null()); |
| 239 DCHECK(!statistics_cb.is_null()); | 239 DCHECK(!statistics_cb.is_null()); |
| 240 DCHECK(!underflow_cb.is_null()); | 240 DCHECK(!underflow_cb.is_null()); |
| 241 DCHECK(!time_cb.is_null()); | 241 DCHECK(!time_cb.is_null()); |
| 242 DCHECK(!ended_cb.is_null()); | 242 DCHECK(!ended_cb.is_null()); |
| 243 DCHECK(!disabled_cb.is_null()); | 243 DCHECK(!disabled_cb.is_null()); |
| 244 DCHECK(!error_cb.is_null()); | 244 DCHECK(!error_cb.is_null()); |
| 245 DCHECK_EQ(kUninitialized, state_); | 245 DCHECK_EQ(kUninitialized, state_); |
| (...skipping 10 matching lines...) Expand all Loading... |
| 256 | 256 |
| 257 decoder_selector_->SelectAudioDecoder( | 257 decoder_selector_->SelectAudioDecoder( |
| 258 stream, | 258 stream, |
| 259 statistics_cb, | 259 statistics_cb, |
| 260 base::Bind(&AudioRendererImpl::OnDecoderSelected, weak_this_)); | 260 base::Bind(&AudioRendererImpl::OnDecoderSelected, weak_this_)); |
| 261 } | 261 } |
| 262 | 262 |
| 263 void AudioRendererImpl::OnDecoderSelected( | 263 void AudioRendererImpl::OnDecoderSelected( |
| 264 scoped_ptr<AudioDecoder> decoder, | 264 scoped_ptr<AudioDecoder> decoder, |
| 265 scoped_ptr<DecryptingDemuxerStream> decrypting_demuxer_stream) { | 265 scoped_ptr<DecryptingDemuxerStream> decrypting_demuxer_stream) { |
| 266 DCHECK(message_loop_->BelongsToCurrentThread()); | 266 DCHECK(task_runner_->BelongsToCurrentThread()); |
| 267 | 267 |
| 268 base::AutoLock auto_lock(lock_); | 268 base::AutoLock auto_lock(lock_); |
| 269 scoped_ptr<AudioDecoderSelector> deleter(decoder_selector_.Pass()); | 269 scoped_ptr<AudioDecoderSelector> deleter(decoder_selector_.Pass()); |
| 270 | 270 |
| 271 if (state_ == kStopped) { | 271 if (state_ == kStopped) { |
| 272 DCHECK(!sink_); | 272 DCHECK(!sink_); |
| 273 return; | 273 return; |
| 274 } | 274 } |
| 275 | 275 |
| 276 if (!decoder) { | 276 if (!decoder) { |
| (...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 313 // Some sinks play on start... | 313 // Some sinks play on start... |
| 314 sink_->Pause(); | 314 sink_->Pause(); |
| 315 } | 315 } |
| 316 | 316 |
| 317 DCHECK(!sink_playing_); | 317 DCHECK(!sink_playing_); |
| 318 | 318 |
| 319 base::ResetAndReturn(&init_cb_).Run(PIPELINE_OK); | 319 base::ResetAndReturn(&init_cb_).Run(PIPELINE_OK); |
| 320 } | 320 } |
| 321 | 321 |
| 322 void AudioRendererImpl::ResumeAfterUnderflow() { | 322 void AudioRendererImpl::ResumeAfterUnderflow() { |
| 323 DCHECK(message_loop_->BelongsToCurrentThread()); | 323 DCHECK(task_runner_->BelongsToCurrentThread()); |
| 324 base::AutoLock auto_lock(lock_); | 324 base::AutoLock auto_lock(lock_); |
| 325 if (state_ == kUnderflow) { | 325 if (state_ == kUnderflow) { |
| 326 // The "!preroll_aborted_" is a hack. If preroll is aborted, then we | 326 // The "!preroll_aborted_" is a hack. If preroll is aborted, then we |
| 327 // shouldn't even reach the kUnderflow state to begin with. But for now | 327 // shouldn't even reach the kUnderflow state to begin with. But for now |
| 328 // we're just making sure that the audio buffer capacity (i.e. the | 328 // we're just making sure that the audio buffer capacity (i.e. the |
| 329 // number of bytes that need to be buffered for preroll to complete) | 329 // number of bytes that need to be buffered for preroll to complete) |
| 330 // does not increase due to an aborted preroll. | 330 // does not increase due to an aborted preroll. |
| 331 // TODO(vrk): Fix this bug correctly! (crbug.com/151352) | 331 // TODO(vrk): Fix this bug correctly! (crbug.com/151352) |
| 332 if (!preroll_aborted_) | 332 if (!preroll_aborted_) |
| 333 algorithm_->IncreaseQueueCapacity(); | 333 algorithm_->IncreaseQueueCapacity(); |
| 334 | 334 |
| 335 ChangeState_Locked(kRebuffering); | 335 ChangeState_Locked(kRebuffering); |
| 336 } | 336 } |
| 337 } | 337 } |
| 338 | 338 |
| 339 void AudioRendererImpl::SetVolume(float volume) { | 339 void AudioRendererImpl::SetVolume(float volume) { |
| 340 DCHECK(message_loop_->BelongsToCurrentThread()); | 340 DCHECK(task_runner_->BelongsToCurrentThread()); |
| 341 DCHECK(sink_); | 341 DCHECK(sink_); |
| 342 sink_->SetVolume(volume); | 342 sink_->SetVolume(volume); |
| 343 } | 343 } |
| 344 | 344 |
| 345 void AudioRendererImpl::DecodedAudioReady( | 345 void AudioRendererImpl::DecodedAudioReady( |
| 346 AudioDecoder::Status status, | 346 AudioDecoder::Status status, |
| 347 const scoped_refptr<AudioBuffer>& buffer) { | 347 const scoped_refptr<AudioBuffer>& buffer) { |
| 348 DVLOG(1) << __FUNCTION__ << "(" << status << ")"; | 348 DVLOG(1) << __FUNCTION__ << "(" << status << ")"; |
| 349 DCHECK(message_loop_->BelongsToCurrentThread()); | 349 DCHECK(task_runner_->BelongsToCurrentThread()); |
| 350 | 350 |
| 351 base::AutoLock auto_lock(lock_); | 351 base::AutoLock auto_lock(lock_); |
| 352 DCHECK(state_ != kUninitialized); | 352 DCHECK(state_ != kUninitialized); |
| 353 | 353 |
| 354 CHECK(pending_read_); | 354 CHECK(pending_read_); |
| 355 pending_read_ = false; | 355 pending_read_ = false; |
| 356 | 356 |
| 357 if (status == AudioDecoder::kAborted) { | 357 if (status == AudioDecoder::kAborted) { |
| 358 HandleAbortedReadOrDecodeError(false); | 358 HandleAbortedReadOrDecodeError(false); |
| 359 return; | 359 return; |
| (...skipping 96 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 456 } | 456 } |
| 457 return false; | 457 return false; |
| 458 } | 458 } |
| 459 | 459 |
| 460 void AudioRendererImpl::AttemptRead() { | 460 void AudioRendererImpl::AttemptRead() { |
| 461 base::AutoLock auto_lock(lock_); | 461 base::AutoLock auto_lock(lock_); |
| 462 AttemptRead_Locked(); | 462 AttemptRead_Locked(); |
| 463 } | 463 } |
| 464 | 464 |
| 465 void AudioRendererImpl::AttemptRead_Locked() { | 465 void AudioRendererImpl::AttemptRead_Locked() { |
| 466 DCHECK(message_loop_->BelongsToCurrentThread()); | 466 DCHECK(task_runner_->BelongsToCurrentThread()); |
| 467 lock_.AssertAcquired(); | 467 lock_.AssertAcquired(); |
| 468 | 468 |
| 469 if (!CanRead_Locked()) | 469 if (!CanRead_Locked()) |
| 470 return; | 470 return; |
| 471 | 471 |
| 472 pending_read_ = true; | 472 pending_read_ = true; |
| 473 decoder_->Read(base::Bind(&AudioRendererImpl::DecodedAudioReady, weak_this_)); | 473 decoder_->Read(base::Bind(&AudioRendererImpl::DecodedAudioReady, weak_this_)); |
| 474 } | 474 } |
| 475 | 475 |
| 476 bool AudioRendererImpl::CanRead_Locked() { | 476 bool AudioRendererImpl::CanRead_Locked() { |
| (...skipping 12 matching lines...) Expand all Loading... |
| 489 case kRebuffering: | 489 case kRebuffering: |
| 490 break; | 490 break; |
| 491 } | 491 } |
| 492 | 492 |
| 493 return !pending_read_ && !received_end_of_stream_ && | 493 return !pending_read_ && !received_end_of_stream_ && |
| 494 !algorithm_->IsQueueFull(); | 494 !algorithm_->IsQueueFull(); |
| 495 } | 495 } |
| 496 | 496 |
| 497 void AudioRendererImpl::SetPlaybackRate(float playback_rate) { | 497 void AudioRendererImpl::SetPlaybackRate(float playback_rate) { |
| 498 DVLOG(1) << __FUNCTION__ << "(" << playback_rate << ")"; | 498 DVLOG(1) << __FUNCTION__ << "(" << playback_rate << ")"; |
| 499 DCHECK(message_loop_->BelongsToCurrentThread()); | 499 DCHECK(task_runner_->BelongsToCurrentThread()); |
| 500 DCHECK_GE(playback_rate, 0); | 500 DCHECK_GE(playback_rate, 0); |
| 501 DCHECK(sink_); | 501 DCHECK(sink_); |
| 502 | 502 |
| 503 base::AutoLock auto_lock(lock_); | 503 base::AutoLock auto_lock(lock_); |
| 504 | 504 |
| 505 // We have two cases here: | 505 // We have two cases here: |
| 506 // Play: current_playback_rate == 0 && playback_rate != 0 | 506 // Play: current_playback_rate == 0 && playback_rate != 0 |
| 507 // Pause: current_playback_rate != 0 && playback_rate == 0 | 507 // Pause: current_playback_rate != 0 && playback_rate == 0 |
| 508 float current_playback_rate = algorithm_->playback_rate(); | 508 float current_playback_rate = algorithm_->playback_rate(); |
| 509 if (current_playback_rate == 0 && playback_rate != 0) | 509 if (current_playback_rate == 0 && playback_rate != 0) |
| (...skipping 64 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 574 ChangeState_Locked(kUnderflow); | 574 ChangeState_Locked(kUnderflow); |
| 575 underflow_cb = underflow_cb_; | 575 underflow_cb = underflow_cb_; |
| 576 } else { | 576 } else { |
| 577 // We can't write any data this cycle. For example, we may have | 577 // We can't write any data this cycle. For example, we may have |
| 578 // sent all available data to the audio device while not reaching | 578 // sent all available data to the audio device while not reaching |
| 579 // |earliest_end_time_|. | 579 // |earliest_end_time_|. |
| 580 } | 580 } |
| 581 } | 581 } |
| 582 | 582 |
| 583 if (CanRead_Locked()) { | 583 if (CanRead_Locked()) { |
| 584 message_loop_->PostTask(FROM_HERE, base::Bind( | 584 task_runner_->PostTask(FROM_HERE, base::Bind( |
| 585 &AudioRendererImpl::AttemptRead, weak_this_)); | 585 &AudioRendererImpl::AttemptRead, weak_this_)); |
| 586 } | 586 } |
| 587 | 587 |
| 588 // The |audio_time_buffered_| is the ending timestamp of the last frame | 588 // The |audio_time_buffered_| is the ending timestamp of the last frame |
| 589 // buffered at the audio device. |playback_delay| is the amount of time | 589 // buffered at the audio device. |playback_delay| is the amount of time |
| 590 // buffered at the audio device. The current time can be computed by their | 590 // buffered at the audio device. The current time can be computed by their |
| 591 // difference. | 591 // difference. |
| 592 if (audio_time_buffered_ != kNoTimestamp()) { | 592 if (audio_time_buffered_ != kNoTimestamp()) { |
| 593 // Adjust the delay according to playback rate. | 593 // Adjust the delay according to playback rate. |
| 594 base::TimeDelta adjusted_playback_delay = | 594 base::TimeDelta adjusted_playback_delay = |
| (...skipping 105 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 700 } | 700 } |
| 701 } | 701 } |
| 702 | 702 |
| 703 void AudioRendererImpl::ChangeState_Locked(State new_state) { | 703 void AudioRendererImpl::ChangeState_Locked(State new_state) { |
| 704 DVLOG(1) << __FUNCTION__ << " : " << state_ << " -> " << new_state; | 704 DVLOG(1) << __FUNCTION__ << " : " << state_ << " -> " << new_state; |
| 705 lock_.AssertAcquired(); | 705 lock_.AssertAcquired(); |
| 706 state_ = new_state; | 706 state_ = new_state; |
| 707 } | 707 } |
| 708 | 708 |
| 709 } // namespace media | 709 } // namespace media |
| OLD | NEW |