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 |