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 |
(...skipping 22 matching lines...) Expand all Loading... | |
33 }; | 33 }; |
34 | 34 |
35 void HistogramRendererEvent(AudioRendererEvent event) { | 35 void HistogramRendererEvent(AudioRendererEvent event) { |
36 UMA_HISTOGRAM_ENUMERATION("Media.AudioRendererEvents", event, MAX_EVENTS); | 36 UMA_HISTOGRAM_ENUMERATION("Media.AudioRendererEvents", event, MAX_EVENTS); |
37 } | 37 } |
38 | 38 |
39 } // namespace | 39 } // namespace |
40 | 40 |
41 AudioRendererImpl::AudioRendererImpl( | 41 AudioRendererImpl::AudioRendererImpl( |
42 const scoped_refptr<base::MessageLoopProxy>& message_loop, | 42 const scoped_refptr<base::MessageLoopProxy>& message_loop, |
43 media::AudioRendererSink* sink, | 43 media::AudioRendererSink* sink, ScopedVector<AudioDecoder> decoders, |
44 ScopedVector<AudioDecoder> decoders, | |
45 const SetDecryptorReadyCB& set_decryptor_ready_cb, | 44 const SetDecryptorReadyCB& set_decryptor_ready_cb, |
46 bool increase_preroll_on_underflow) | 45 bool increase_preroll_on_underflow) |
47 : message_loop_(message_loop), | 46 : message_loop_(message_loop), |
48 weak_factory_(this), | 47 weak_factory_(this), |
49 sink_(sink), | 48 sink_(sink), |
50 decoder_selector_(new AudioDecoderSelector( | 49 decoder_selector_(new AudioDecoderSelector(message_loop, decoders.Pass(), |
51 message_loop, decoders.Pass(), set_decryptor_ready_cb)), | 50 set_decryptor_ready_cb)), |
52 now_cb_(base::Bind(&base::TimeTicks::Now)), | 51 now_cb_(base::Bind(&base::TimeTicks::Now)), |
53 state_(kUninitialized), | 52 state_(kUninitialized), |
54 sink_playing_(false), | 53 sink_playing_(false), |
55 pending_read_(false), | 54 pending_read_(false), |
56 received_end_of_stream_(false), | 55 received_end_of_stream_(false), |
57 rendered_end_of_stream_(false), | 56 rendered_end_of_stream_(false), |
58 audio_time_buffered_(kNoTimestamp()), | 57 audio_time_buffered_(kNoTimestamp()), |
59 current_time_(kNoTimestamp()), | 58 current_time_(kNoTimestamp()), |
60 underflow_disabled_(false), | 59 underflow_disabled_(false), |
61 increase_preroll_on_underflow_(increase_preroll_on_underflow), | 60 increase_preroll_on_underflow_(increase_preroll_on_underflow), |
62 preroll_aborted_(false), | 61 preroll_aborted_(false), |
63 actual_frames_per_buffer_(0) { | 62 actual_frames_per_buffer_(0) {} |
64 } | |
65 | 63 |
66 AudioRendererImpl::~AudioRendererImpl() { | 64 AudioRendererImpl::~AudioRendererImpl() { |
67 // Stop() should have been called and |algorithm_| should have been destroyed. | 65 // Stop() should have been called and |algorithm_| should have been destroyed. |
68 DCHECK(state_ == kUninitialized || state_ == kStopped); | 66 DCHECK(state_ == kUninitialized || state_ == kStopped); |
69 DCHECK(!algorithm_.get()); | 67 DCHECK(!algorithm_.get()); |
70 } | 68 } |
71 | 69 |
72 void AudioRendererImpl::Play(const base::Closure& callback) { | 70 void AudioRendererImpl::Play(const base::Closure& callback) { |
73 DCHECK(message_loop_->BelongsToCurrentThread()); | 71 DCHECK(message_loop_->BelongsToCurrentThread()); |
74 | 72 |
(...skipping 22 matching lines...) Expand all Loading... | |
97 sink_->Play(); | 95 sink_->Play(); |
98 sink_playing_ = true; | 96 sink_playing_ = true; |
99 } | 97 } |
100 } | 98 } |
101 | 99 |
102 void AudioRendererImpl::Pause(const base::Closure& callback) { | 100 void AudioRendererImpl::Pause(const base::Closure& callback) { |
103 DCHECK(message_loop_->BelongsToCurrentThread()); | 101 DCHECK(message_loop_->BelongsToCurrentThread()); |
104 | 102 |
105 { | 103 { |
106 base::AutoLock auto_lock(lock_); | 104 base::AutoLock auto_lock(lock_); |
107 DCHECK(state_ == kPlaying || state_ == kUnderflow || | 105 DCHECK(state_ == kPlaying || state_ == kUnderflow || state_ == kRebuffering) |
108 state_ == kRebuffering) << "state_ == " << state_; | 106 << "state_ == " << state_; |
109 pause_cb_ = callback; | 107 pause_cb_ = callback; |
110 state_ = kPaused; | 108 state_ = kPaused; |
111 | 109 |
112 // Pause only when we've completed our pending read. | 110 // Pause only when we've completed our pending read. |
113 if (!pending_read_) | 111 if (!pending_read_) base::ResetAndReturn(&pause_cb_).Run(); |
114 base::ResetAndReturn(&pause_cb_).Run(); | |
115 } | 112 } |
116 | 113 |
117 DoPause(); | 114 DoPause(); |
118 } | 115 } |
119 | 116 |
120 void AudioRendererImpl::DoPause() { | 117 void AudioRendererImpl::DoPause() { |
121 DCHECK(message_loop_->BelongsToCurrentThread()); | 118 DCHECK(message_loop_->BelongsToCurrentThread()); |
122 if (sink_playing_) { | 119 if (sink_playing_) { |
123 sink_->Pause(); | 120 sink_->Pause(); |
124 sink_playing_ = false; | 121 sink_playing_ = false; |
125 } | 122 } |
126 } | 123 } |
127 | 124 |
128 void AudioRendererImpl::Flush(const base::Closure& callback) { | 125 void AudioRendererImpl::Flush(const base::Closure& callback) { |
129 DCHECK(message_loop_->BelongsToCurrentThread()); | 126 DCHECK(message_loop_->BelongsToCurrentThread()); |
130 | 127 |
131 if (decrypting_demuxer_stream_) { | 128 if (decrypting_demuxer_stream_) { |
132 decrypting_demuxer_stream_->Reset(base::Bind( | 129 decrypting_demuxer_stream_->Reset( |
133 &AudioRendererImpl::ResetDecoder, weak_this_, callback)); | 130 base::Bind(&AudioRendererImpl::ResetDecoder, weak_this_, callback)); |
134 return; | 131 return; |
135 } | 132 } |
136 | 133 |
137 decoder_->Reset(callback); | 134 decoder_->Reset(callback); |
138 } | 135 } |
139 | 136 |
140 void AudioRendererImpl::ResetDecoder(const base::Closure& callback) { | 137 void AudioRendererImpl::ResetDecoder(const base::Closure& callback) { |
141 DCHECK(message_loop_->BelongsToCurrentThread()); | 138 DCHECK(message_loop_->BelongsToCurrentThread()); |
142 decoder_->Reset(callback); | 139 decoder_->Reset(callback); |
143 } | 140 } |
(...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
188 rendered_end_of_stream_ = false; | 185 rendered_end_of_stream_ = false; |
189 preroll_aborted_ = false; | 186 preroll_aborted_ = false; |
190 | 187 |
191 splicer_->Reset(); | 188 splicer_->Reset(); |
192 algorithm_->FlushBuffers(); | 189 algorithm_->FlushBuffers(); |
193 earliest_end_time_ = now_cb_.Run(); | 190 earliest_end_time_ = now_cb_.Run(); |
194 | 191 |
195 AttemptRead_Locked(); | 192 AttemptRead_Locked(); |
196 } | 193 } |
197 | 194 |
198 void AudioRendererImpl::Initialize(DemuxerStream* stream, | 195 void AudioRendererImpl::Initialize( |
199 const PipelineStatusCB& init_cb, | 196 DemuxerStream* stream, const PipelineStatusCB& init_cb, |
200 const StatisticsCB& statistics_cb, | 197 const StatisticsCB& statistics_cb, const base::Closure& underflow_cb, |
201 const base::Closure& underflow_cb, | 198 const TimeCB& time_cb, const base::Closure& ended_cb, |
202 const TimeCB& time_cb, | 199 const base::Closure& disabled_cb, const PipelineStatusCB& error_cb) { |
203 const base::Closure& ended_cb, | |
204 const base::Closure& disabled_cb, | |
205 const PipelineStatusCB& error_cb) { | |
206 DCHECK(message_loop_->BelongsToCurrentThread()); | 200 DCHECK(message_loop_->BelongsToCurrentThread()); |
207 DCHECK(stream); | 201 DCHECK(stream); |
208 DCHECK_EQ(stream->type(), DemuxerStream::AUDIO); | 202 DCHECK_EQ(stream->type(), DemuxerStream::AUDIO); |
209 DCHECK(!init_cb.is_null()); | 203 DCHECK(!init_cb.is_null()); |
210 DCHECK(!statistics_cb.is_null()); | 204 DCHECK(!statistics_cb.is_null()); |
211 DCHECK(!underflow_cb.is_null()); | 205 DCHECK(!underflow_cb.is_null()); |
212 DCHECK(!time_cb.is_null()); | 206 DCHECK(!time_cb.is_null()); |
213 DCHECK(!ended_cb.is_null()); | 207 DCHECK(!ended_cb.is_null()); |
214 DCHECK(!disabled_cb.is_null()); | 208 DCHECK(!disabled_cb.is_null()); |
215 DCHECK(!error_cb.is_null()); | 209 DCHECK(!error_cb.is_null()); |
216 DCHECK_EQ(kUninitialized, state_); | 210 DCHECK_EQ(kUninitialized, state_); |
217 DCHECK(sink_.get()); | 211 DCHECK(sink_.get()); |
218 | 212 |
219 weak_this_ = weak_factory_.GetWeakPtr(); | 213 weak_this_ = weak_factory_.GetWeakPtr(); |
220 init_cb_ = init_cb; | 214 init_cb_ = init_cb; |
221 statistics_cb_ = statistics_cb; | 215 statistics_cb_ = statistics_cb; |
222 underflow_cb_ = underflow_cb; | 216 underflow_cb_ = underflow_cb; |
223 time_cb_ = time_cb; | 217 time_cb_ = time_cb; |
224 ended_cb_ = ended_cb; | 218 ended_cb_ = ended_cb; |
225 disabled_cb_ = disabled_cb; | 219 disabled_cb_ = disabled_cb; |
226 error_cb_ = error_cb; | 220 error_cb_ = error_cb; |
227 | 221 |
228 decoder_selector_->SelectAudioDecoder( | 222 decoder_selector_->SelectAudioDecoder( |
229 stream, | 223 stream, statistics_cb, |
230 statistics_cb, | |
231 base::Bind(&AudioRendererImpl::OnDecoderSelected, weak_this_)); | 224 base::Bind(&AudioRendererImpl::OnDecoderSelected, weak_this_)); |
232 } | 225 } |
233 | 226 |
234 void AudioRendererImpl::OnDecoderSelected( | 227 void AudioRendererImpl::OnDecoderSelected( |
235 scoped_ptr<AudioDecoder> decoder, | 228 scoped_ptr<AudioDecoder> decoder, |
236 scoped_ptr<DecryptingDemuxerStream> decrypting_demuxer_stream) { | 229 scoped_ptr<DecryptingDemuxerStream> decrypting_demuxer_stream) { |
237 DCHECK(message_loop_->BelongsToCurrentThread()); | 230 DCHECK(message_loop_->BelongsToCurrentThread()); |
238 scoped_ptr<AudioDecoderSelector> deleter(decoder_selector_.Pass()); | 231 scoped_ptr<AudioDecoderSelector> deleter(decoder_selector_.Pass()); |
239 | 232 |
240 if (state_ == kStopped) { | 233 if (state_ == kStopped) { |
(...skipping 62 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
303 } | 296 } |
304 } | 297 } |
305 | 298 |
306 void AudioRendererImpl::SetVolume(float volume) { | 299 void AudioRendererImpl::SetVolume(float volume) { |
307 DCHECK(message_loop_->BelongsToCurrentThread()); | 300 DCHECK(message_loop_->BelongsToCurrentThread()); |
308 DCHECK(sink_.get()); | 301 DCHECK(sink_.get()); |
309 sink_->SetVolume(volume); | 302 sink_->SetVolume(volume); |
310 } | 303 } |
311 | 304 |
312 void AudioRendererImpl::DecodedAudioReady( | 305 void AudioRendererImpl::DecodedAudioReady( |
313 AudioDecoder::Status status, | 306 AudioDecoder::Status status, const scoped_refptr<DataBuffer>& buffer) { |
314 const scoped_refptr<DataBuffer>& buffer) { | |
315 DCHECK(message_loop_->BelongsToCurrentThread()); | 307 DCHECK(message_loop_->BelongsToCurrentThread()); |
316 | 308 |
317 base::AutoLock auto_lock(lock_); | 309 base::AutoLock auto_lock(lock_); |
318 DCHECK(state_ == kPaused || state_ == kPrerolling || state_ == kPlaying || | 310 DCHECK(state_ == kPaused || state_ == kPrerolling || state_ == kPlaying || |
319 state_ == kUnderflow || state_ == kRebuffering || state_ == kStopped); | 311 state_ == kUnderflow || state_ == kRebuffering || state_ == kStopped); |
320 | 312 |
321 CHECK(pending_read_); | 313 CHECK(pending_read_); |
322 pending_read_ = false; | 314 pending_read_ = false; |
323 | 315 |
324 if (status == AudioDecoder::kAborted) { | 316 if (status == AudioDecoder::kAborted) { |
(...skipping 16 matching lines...) Expand all Loading... | |
341 | 333 |
342 if (!splicer_->HasNextBuffer()) { | 334 if (!splicer_->HasNextBuffer()) { |
343 AttemptRead_Locked(); | 335 AttemptRead_Locked(); |
344 return; | 336 return; |
345 } | 337 } |
346 | 338 |
347 bool need_another_buffer = false; | 339 bool need_another_buffer = false; |
348 while (splicer_->HasNextBuffer()) | 340 while (splicer_->HasNextBuffer()) |
349 need_another_buffer = HandleSplicerBuffer(splicer_->GetNextBuffer()); | 341 need_another_buffer = HandleSplicerBuffer(splicer_->GetNextBuffer()); |
350 | 342 |
351 if (!need_another_buffer && !CanRead_Locked()) | 343 if (!need_another_buffer && !CanRead_Locked()) return; |
scherkus (not reviewing)
2013/06/21 19:48:38
revert this change -- we don't do single-line ifs
| |
352 return; | |
353 | 344 |
354 AttemptRead_Locked(); | 345 AttemptRead_Locked(); |
355 } | 346 } |
356 | 347 |
357 bool AudioRendererImpl::HandleSplicerBuffer( | 348 bool AudioRendererImpl::HandleSplicerBuffer( |
358 const scoped_refptr<DataBuffer>& buffer) { | 349 const scoped_refptr<DataBuffer>& buffer) { |
359 if (buffer->IsEndOfStream()) { | 350 if (buffer->end_of_stream()) { |
360 received_end_of_stream_ = true; | 351 received_end_of_stream_ = true; |
361 | 352 |
362 // Transition to kPlaying if we are currently handling an underflow since | 353 // Transition to kPlaying if we are currently handling an underflow since |
363 // no more data will be arriving. | 354 // no more data will be arriving. |
364 if (state_ == kUnderflow || state_ == kRebuffering) | 355 if (state_ == kUnderflow || state_ == kRebuffering) state_ = kPlaying; |
scherkus (not reviewing)
2013/06/21 19:48:38
revert this change -- we don't do single-line ifs
| |
365 state_ = kPlaying; | |
366 } | 356 } |
367 | 357 |
368 switch (state_) { | 358 switch (state_) { |
369 case kUninitialized: | 359 case kUninitialized: |
370 NOTREACHED(); | 360 NOTREACHED(); |
371 return false; | 361 return false; |
372 case kPaused: | 362 case kPaused: |
373 if (!buffer->IsEndOfStream()) | 363 if (!buffer->end_of_stream()) algorithm_->EnqueueBuffer(buffer); |
scherkus (not reviewing)
2013/06/21 19:48:38
revert this change -- we don't do single-line ifs
| |
374 algorithm_->EnqueueBuffer(buffer); | |
375 DCHECK(!pending_read_); | 364 DCHECK(!pending_read_); |
376 base::ResetAndReturn(&pause_cb_).Run(); | 365 base::ResetAndReturn(&pause_cb_).Run(); |
377 return false; | 366 return false; |
378 case kPrerolling: | 367 case kPrerolling: |
379 if (IsBeforePrerollTime(buffer)) | 368 if (IsBeforePrerollTime(buffer)) return true; |
scherkus (not reviewing)
2013/06/21 19:48:38
revert this change -- we don't do single-line ifs
| |
380 return true; | |
381 | 369 |
382 if (!buffer->IsEndOfStream()) { | 370 if (!buffer->end_of_stream()) { |
383 algorithm_->EnqueueBuffer(buffer); | 371 algorithm_->EnqueueBuffer(buffer); |
384 if (!algorithm_->IsQueueFull()) | 372 if (!algorithm_->IsQueueFull()) return false; |
385 return false; | |
386 } | 373 } |
387 state_ = kPaused; | 374 state_ = kPaused; |
388 base::ResetAndReturn(&preroll_cb_).Run(PIPELINE_OK); | 375 base::ResetAndReturn(&preroll_cb_).Run(PIPELINE_OK); |
389 return false; | 376 return false; |
390 case kPlaying: | 377 case kPlaying: |
391 case kUnderflow: | 378 case kUnderflow: |
392 case kRebuffering: | 379 case kRebuffering: |
393 if (!buffer->IsEndOfStream()) | 380 if (!buffer->end_of_stream()) algorithm_->EnqueueBuffer(buffer); |
scherkus (not reviewing)
2013/06/21 19:48:38
revert this change -- we don't do single-line ifs
| |
394 algorithm_->EnqueueBuffer(buffer); | |
395 return false; | 381 return false; |
396 case kStopped: | 382 case kStopped: |
397 return false; | 383 return false; |
398 } | 384 } |
399 return false; | 385 return false; |
400 } | 386 } |
401 | 387 |
402 void AudioRendererImpl::AttemptRead() { | 388 void AudioRendererImpl::AttemptRead() { |
403 base::AutoLock auto_lock(lock_); | 389 base::AutoLock auto_lock(lock_); |
404 AttemptRead_Locked(); | 390 AttemptRead_Locked(); |
405 } | 391 } |
406 | 392 |
407 void AudioRendererImpl::AttemptRead_Locked() { | 393 void AudioRendererImpl::AttemptRead_Locked() { |
408 DCHECK(message_loop_->BelongsToCurrentThread()); | 394 DCHECK(message_loop_->BelongsToCurrentThread()); |
409 lock_.AssertAcquired(); | 395 lock_.AssertAcquired(); |
410 | 396 |
411 if (!CanRead_Locked()) | 397 if (!CanRead_Locked()) return; |
scherkus (not reviewing)
2013/06/21 19:48:38
revert this change -- we don't do single-line ifs
| |
412 return; | |
413 | 398 |
414 pending_read_ = true; | 399 pending_read_ = true; |
415 decoder_->Read(base::Bind(&AudioRendererImpl::DecodedAudioReady, weak_this_)); | 400 decoder_->Read(base::Bind(&AudioRendererImpl::DecodedAudioReady, weak_this_)); |
416 } | 401 } |
417 | 402 |
418 bool AudioRendererImpl::CanRead_Locked() { | 403 bool AudioRendererImpl::CanRead_Locked() { |
419 lock_.AssertAcquired(); | 404 lock_.AssertAcquired(); |
420 | 405 |
421 switch (state_) { | 406 switch (state_) { |
422 case kUninitialized: | 407 case kUninitialized: |
423 case kPaused: | 408 case kPaused: |
424 case kStopped: | 409 case kStopped: |
425 return false; | 410 return false; |
426 | 411 |
427 case kPrerolling: | 412 case kPrerolling: |
428 case kPlaying: | 413 case kPlaying: |
429 case kUnderflow: | 414 case kUnderflow: |
430 case kRebuffering: | 415 case kRebuffering: |
431 break; | 416 break; |
432 } | 417 } |
433 | 418 |
434 return !pending_read_ && !received_end_of_stream_ && | 419 return !pending_read_ && !received_end_of_stream_ && |
435 !algorithm_->IsQueueFull(); | 420 !algorithm_->IsQueueFull(); |
436 } | 421 } |
437 | 422 |
438 void AudioRendererImpl::SetPlaybackRate(float playback_rate) { | 423 void AudioRendererImpl::SetPlaybackRate(float playback_rate) { |
439 DCHECK(message_loop_->BelongsToCurrentThread()); | 424 DCHECK(message_loop_->BelongsToCurrentThread()); |
440 DCHECK_GE(playback_rate, 0); | 425 DCHECK_GE(playback_rate, 0); |
441 DCHECK(sink_.get()); | 426 DCHECK(sink_.get()); |
442 | 427 |
443 // We have two cases here: | 428 // We have two cases here: |
444 // Play: current_playback_rate == 0 && playback_rate != 0 | 429 // Play: current_playback_rate == 0 && playback_rate != 0 |
445 // Pause: current_playback_rate != 0 && playback_rate == 0 | 430 // Pause: current_playback_rate != 0 && playback_rate == 0 |
446 float current_playback_rate = algorithm_->playback_rate(); | 431 float current_playback_rate = algorithm_->playback_rate(); |
447 if (current_playback_rate == 0 && playback_rate != 0) | 432 if (current_playback_rate == 0 && playback_rate != 0) |
448 DoPlay(); | 433 DoPlay(); |
449 else if (current_playback_rate != 0 && playback_rate == 0) | 434 else if (current_playback_rate != 0 && playback_rate == 0) |
450 DoPause(); | 435 DoPause(); |
451 | 436 |
452 base::AutoLock auto_lock(lock_); | 437 base::AutoLock auto_lock(lock_); |
453 algorithm_->SetPlaybackRate(playback_rate); | 438 algorithm_->SetPlaybackRate(playback_rate); |
454 } | 439 } |
455 | 440 |
456 bool AudioRendererImpl::IsBeforePrerollTime( | 441 bool AudioRendererImpl::IsBeforePrerollTime( |
457 const scoped_refptr<DataBuffer>& buffer) { | 442 const scoped_refptr<DataBuffer>& buffer) { |
458 return (state_ == kPrerolling) && buffer.get() && !buffer->IsEndOfStream() && | 443 return (state_ == kPrerolling) && buffer.get() && |
459 (buffer->GetTimestamp() + buffer->GetDuration()) < preroll_timestamp_; | 444 !buffer->end_of_stream() && |
445 (buffer->timestamp() + buffer->duration()) < | |
446 preroll_timestamp_; | |
460 } | 447 } |
461 | 448 |
462 int AudioRendererImpl::Render(AudioBus* audio_bus, | 449 int AudioRendererImpl::Render(AudioBus* audio_bus, |
463 int audio_delay_milliseconds) { | 450 int audio_delay_milliseconds) { |
464 if (actual_frames_per_buffer_ != audio_bus->frames()) { | 451 if (actual_frames_per_buffer_ != audio_bus->frames()) { |
465 audio_buffer_.reset( | 452 audio_buffer_.reset( |
466 new uint8[audio_bus->frames() * audio_parameters_.GetBytesPerFrame()]); | 453 new uint8[audio_bus->frames() * audio_parameters_.GetBytesPerFrame()]); |
467 actual_frames_per_buffer_ = audio_bus->frames(); | 454 actual_frames_per_buffer_ = audio_bus->frames(); |
468 } | 455 } |
469 | 456 |
470 int frames_filled = FillBuffer( | 457 int frames_filled = FillBuffer(audio_buffer_.get(), audio_bus->frames(), |
471 audio_buffer_.get(), audio_bus->frames(), audio_delay_milliseconds); | 458 audio_delay_milliseconds); |
472 DCHECK_LE(frames_filled, actual_frames_per_buffer_); | 459 DCHECK_LE(frames_filled, actual_frames_per_buffer_); |
473 | 460 |
474 // Deinterleave audio data into the output bus. | 461 // Deinterleave audio data into the output bus. |
475 audio_bus->FromInterleaved( | 462 audio_bus->FromInterleaved(audio_buffer_.get(), frames_filled, |
476 audio_buffer_.get(), frames_filled, | 463 audio_parameters_.bits_per_sample() / 8); |
477 audio_parameters_.bits_per_sample() / 8); | |
478 | 464 |
479 return frames_filled; | 465 return frames_filled; |
480 } | 466 } |
481 | 467 |
482 uint32 AudioRendererImpl::FillBuffer(uint8* dest, | 468 uint32 AudioRendererImpl::FillBuffer(uint8* dest, uint32 requested_frames, |
483 uint32 requested_frames, | |
484 int audio_delay_milliseconds) { | 469 int audio_delay_milliseconds) { |
485 base::TimeDelta current_time = kNoTimestamp(); | 470 base::TimeDelta current_time = kNoTimestamp(); |
486 base::TimeDelta max_time = kNoTimestamp(); | 471 base::TimeDelta max_time = kNoTimestamp(); |
487 base::TimeDelta playback_delay = base::TimeDelta::FromMilliseconds( | 472 base::TimeDelta playback_delay = |
488 audio_delay_milliseconds); | 473 base::TimeDelta::FromMilliseconds(audio_delay_milliseconds); |
489 | 474 |
490 size_t frames_written = 0; | 475 size_t frames_written = 0; |
491 base::Closure underflow_cb; | 476 base::Closure underflow_cb; |
492 { | 477 { |
493 base::AutoLock auto_lock(lock_); | 478 base::AutoLock auto_lock(lock_); |
494 | 479 |
495 // Ensure Stop() hasn't destroyed our |algorithm_| on the pipeline thread. | 480 // Ensure Stop() hasn't destroyed our |algorithm_| on the pipeline thread. |
496 if (!algorithm_) | 481 if (!algorithm_) return 0; |
scherkus (not reviewing)
2013/06/21 19:48:38
revert this change -- we don't do single-line ifs
| |
497 return 0; | |
498 | 482 |
499 float playback_rate = algorithm_->playback_rate(); | 483 float playback_rate = algorithm_->playback_rate(); |
500 if (playback_rate == 0) | 484 if (playback_rate == 0) return 0; |
scherkus (not reviewing)
2013/06/21 19:48:38
revert this change -- we don't do single-line ifs
| |
501 return 0; | |
502 | 485 |
503 if (state_ == kRebuffering && algorithm_->IsQueueFull()) | 486 if (state_ == kRebuffering && algorithm_->IsQueueFull()) state_ = kPlaying; |
scherkus (not reviewing)
2013/06/21 19:48:38
revert this change -- we don't do single-line ifs
| |
504 state_ = kPlaying; | |
505 | 487 |
506 // Mute audio by returning 0 when not playing. | 488 // Mute audio by returning 0 when not playing. |
507 if (state_ != kPlaying) | 489 if (state_ != kPlaying) return 0; |
scherkus (not reviewing)
2013/06/21 19:48:38
revert this change -- we don't do single-line ifs
| |
508 return 0; | |
509 | 490 |
510 // We use the following conditions to determine end of playback: | 491 // We use the following conditions to determine end of playback: |
511 // 1) Algorithm can not fill the audio callback buffer | 492 // 1) Algorithm can not fill the audio callback buffer |
512 // 2) We received an end of stream buffer | 493 // 2) We received an end of stream buffer |
513 // 3) We haven't already signalled that we've ended | 494 // 3) We haven't already signalled that we've ended |
514 // 4) Our estimated earliest end time has expired | 495 // 4) Our estimated earliest end time has expired |
515 // | 496 // |
516 // TODO(enal): we should replace (4) with a check that the browser has no | 497 // TODO(enal): we should replace (4) with a check that the browser has no |
517 // more audio data or at least use a delayed callback. | 498 // more audio data or at least use a delayed callback. |
518 // | 499 // |
(...skipping 16 matching lines...) Expand all Loading... | |
535 state_ = kUnderflow; | 516 state_ = kUnderflow; |
536 underflow_cb = underflow_cb_; | 517 underflow_cb = underflow_cb_; |
537 } else { | 518 } else { |
538 // We can't write any data this cycle. For example, we may have | 519 // We can't write any data this cycle. For example, we may have |
539 // sent all available data to the audio device while not reaching | 520 // sent all available data to the audio device while not reaching |
540 // |earliest_end_time_|. | 521 // |earliest_end_time_|. |
541 } | 522 } |
542 } | 523 } |
543 | 524 |
544 if (CanRead_Locked()) { | 525 if (CanRead_Locked()) { |
545 message_loop_->PostTask(FROM_HERE, base::Bind( | 526 message_loop_->PostTask( |
546 &AudioRendererImpl::AttemptRead, weak_this_)); | 527 FROM_HERE, base::Bind(&AudioRendererImpl::AttemptRead, weak_this_)); |
547 } | 528 } |
548 | 529 |
549 // The |audio_time_buffered_| is the ending timestamp of the last frame | 530 // The |audio_time_buffered_| is the ending timestamp of the last frame |
550 // buffered at the audio device. |playback_delay| is the amount of time | 531 // buffered at the audio device. |playback_delay| is the amount of time |
551 // buffered at the audio device. The current time can be computed by their | 532 // buffered at the audio device. The current time can be computed by their |
552 // difference. | 533 // difference. |
553 if (audio_time_buffered_ != kNoTimestamp()) { | 534 if (audio_time_buffered_ != kNoTimestamp()) { |
554 // Adjust the delay according to playback rate. | 535 // Adjust the delay according to playback rate. |
555 base::TimeDelta adjusted_playback_delay = | 536 base::TimeDelta adjusted_playback_delay = |
556 base::TimeDelta::FromMicroseconds(ceil( | 537 base::TimeDelta::FromMicroseconds( |
557 playback_delay.InMicroseconds() * playback_rate)); | 538 ceil(playback_delay.InMicroseconds() * playback_rate)); |
558 | 539 |
559 base::TimeDelta previous_time = current_time_; | 540 base::TimeDelta previous_time = current_time_; |
560 current_time_ = audio_time_buffered_ - adjusted_playback_delay; | 541 current_time_ = audio_time_buffered_ - adjusted_playback_delay; |
561 | 542 |
562 // Time can change in one of two ways: | 543 // Time can change in one of two ways: |
563 // 1) The time of the audio data at the audio device changed, or | 544 // 1) The time of the audio data at the audio device changed, or |
564 // 2) The playback delay value has changed | 545 // 2) The playback delay value has changed |
565 // | 546 // |
566 // We only want to set |current_time| (and thus execute |time_cb_|) if | 547 // We only want to set |current_time| (and thus execute |time_cb_|) if |
567 // time has progressed and we haven't signaled end of stream yet. | 548 // time has progressed and we haven't signaled end of stream yet. |
568 // | 549 // |
569 // Why? The current latency of the system results in getting the last call | 550 // Why? The current latency of the system results in getting the last call |
570 // to FillBuffer() later than we'd like, which delays firing the 'ended' | 551 // to FillBuffer() later than we'd like, which delays firing the 'ended' |
571 // event, which delays the looping/trigging performance of short sound | 552 // event, which delays the looping/trigging performance of short sound |
572 // effects. | 553 // effects. |
573 // | 554 // |
574 // TODO(scherkus): revisit this and switch back to relying on playback | 555 // TODO(scherkus): revisit this and switch back to relying on playback |
575 // delay after we've revamped our audio IPC subsystem. | 556 // delay after we've revamped our audio IPC subsystem. |
576 if (current_time_ > previous_time && !rendered_end_of_stream_) { | 557 if (current_time_ > previous_time && !rendered_end_of_stream_) { |
577 current_time = current_time_; | 558 current_time = current_time_; |
578 } | 559 } |
579 } | 560 } |
580 | 561 |
581 // The call to FillBuffer() on |algorithm_| has increased the amount of | 562 // The call to FillBuffer() on |algorithm_| has increased the amount of |
582 // buffered audio data. Update the new amount of time buffered. | 563 // buffered audio data. Update the new amount of time buffered. |
583 max_time = algorithm_->GetTime(); | 564 max_time = algorithm_->GetTime(); |
584 audio_time_buffered_ = max_time; | 565 audio_time_buffered_ = max_time; |
585 | 566 |
586 UpdateEarliestEndTime_Locked( | 567 UpdateEarliestEndTime_Locked(frames_written, playback_delay, now_cb_.Run()); |
587 frames_written, playback_delay, now_cb_.Run()); | |
588 } | 568 } |
589 | 569 |
590 if (current_time != kNoTimestamp() && max_time != kNoTimestamp()) { | 570 if (current_time != kNoTimestamp() && max_time != kNoTimestamp()) { |
591 time_cb_.Run(current_time, max_time); | 571 time_cb_.Run(current_time, max_time); |
592 } | 572 } |
593 | 573 |
594 if (!underflow_cb.is_null()) | 574 if (!underflow_cb.is_null()) underflow_cb.Run(); |
scherkus (not reviewing)
2013/06/21 19:48:38
revert this change -- we don't do single-line ifs
| |
595 underflow_cb.Run(); | |
596 | 575 |
597 return frames_written; | 576 return frames_written; |
598 } | 577 } |
599 | 578 |
600 void AudioRendererImpl::UpdateEarliestEndTime_Locked( | 579 void AudioRendererImpl::UpdateEarliestEndTime_Locked( |
601 int frames_filled, const base::TimeDelta& playback_delay, | 580 int frames_filled, const base::TimeDelta& playback_delay, |
602 const base::TimeTicks& time_now) { | 581 const base::TimeTicks& time_now) { |
603 if (frames_filled <= 0) | 582 if (frames_filled <= 0) return; |
scherkus (not reviewing)
2013/06/21 19:48:38
revert this change -- we don't do single-line ifs
| |
604 return; | |
605 | 583 |
606 base::TimeDelta predicted_play_time = base::TimeDelta::FromMicroseconds( | 584 base::TimeDelta predicted_play_time = base::TimeDelta::FromMicroseconds( |
607 static_cast<float>(frames_filled) * base::Time::kMicrosecondsPerSecond / | 585 static_cast<float>(frames_filled) * base::Time::kMicrosecondsPerSecond / |
608 audio_parameters_.sample_rate()); | 586 audio_parameters_.sample_rate()); |
609 | 587 |
610 lock_.AssertAcquired(); | 588 lock_.AssertAcquired(); |
611 earliest_end_time_ = std::max( | 589 earliest_end_time_ = std::max( |
612 earliest_end_time_, time_now + playback_delay + predicted_play_time); | 590 earliest_end_time_, time_now + playback_delay + predicted_play_time); |
613 } | 591 } |
614 | 592 |
615 void AudioRendererImpl::OnRenderError() { | 593 void AudioRendererImpl::OnRenderError() { |
616 HistogramRendererEvent(RENDER_ERROR); | 594 HistogramRendererEvent(RENDER_ERROR); |
617 disabled_cb_.Run(); | 595 disabled_cb_.Run(); |
618 } | 596 } |
619 | 597 |
620 void AudioRendererImpl::DisableUnderflowForTesting() { | 598 void AudioRendererImpl::DisableUnderflowForTesting() { |
621 underflow_disabled_ = true; | 599 underflow_disabled_ = true; |
622 } | 600 } |
623 | 601 |
624 void AudioRendererImpl::HandleAbortedReadOrDecodeError(bool is_decode_error) { | 602 void AudioRendererImpl::HandleAbortedReadOrDecodeError(bool is_decode_error) { |
625 PipelineStatus status = is_decode_error ? PIPELINE_ERROR_DECODE : PIPELINE_OK; | 603 PipelineStatus status = is_decode_error ? PIPELINE_ERROR_DECODE : PIPELINE_OK; |
626 switch (state_) { | 604 switch (state_) { |
627 case kUninitialized: | 605 case kUninitialized: |
628 NOTREACHED(); | 606 NOTREACHED(); |
629 return; | 607 return; |
630 case kPaused: | 608 case kPaused: |
631 if (status != PIPELINE_OK) | 609 if (status != PIPELINE_OK) error_cb_.Run(status); |
scherkus (not reviewing)
2013/06/21 19:48:38
revert this change -- we don't do single-line ifs
| |
632 error_cb_.Run(status); | |
633 base::ResetAndReturn(&pause_cb_).Run(); | 610 base::ResetAndReturn(&pause_cb_).Run(); |
634 return; | 611 return; |
635 case kPrerolling: | 612 case kPrerolling: |
636 // This is a signal for abort if it's not an error. | 613 // This is a signal for abort if it's not an error. |
637 preroll_aborted_ = !is_decode_error; | 614 preroll_aborted_ = !is_decode_error; |
638 state_ = kPaused; | 615 state_ = kPaused; |
639 base::ResetAndReturn(&preroll_cb_).Run(status); | 616 base::ResetAndReturn(&preroll_cb_).Run(status); |
640 return; | 617 return; |
641 case kPlaying: | 618 case kPlaying: |
642 case kUnderflow: | 619 case kUnderflow: |
643 case kRebuffering: | 620 case kRebuffering: |
644 case kStopped: | 621 case kStopped: |
645 if (status != PIPELINE_OK) | 622 if (status != PIPELINE_OK) error_cb_.Run(status); |
scherkus (not reviewing)
2013/06/21 19:48:38
revert this change -- we don't do single-line ifs
| |
646 error_cb_.Run(status); | |
647 return; | 623 return; |
648 } | 624 } |
649 } | 625 } |
650 | 626 |
651 } // namespace media | 627 } // namespace media |
OLD | NEW |