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) {} |
brettw
2013/06/24 21:18:29
I liked the old way better.
| |
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( |
brettw
2013/06/24 21:18:29
Old way was better
| |
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) { |
brettw
2013/06/24 21:18:29
Old way was better.
| |
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 24 matching lines...) Expand all Loading... | |
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()) |
352 return; | 344 return; |
353 | 345 |
354 AttemptRead_Locked(); | 346 AttemptRead_Locked(); |
355 } | 347 } |
356 | 348 |
357 bool AudioRendererImpl::HandleSplicerBuffer( | 349 bool AudioRendererImpl::HandleSplicerBuffer( |
358 const scoped_refptr<DataBuffer>& buffer) { | 350 const scoped_refptr<DataBuffer>& buffer) { |
359 if (buffer->IsEndOfStream()) { | 351 if (buffer->end_of_stream()) { |
360 received_end_of_stream_ = true; | 352 received_end_of_stream_ = true; |
361 | 353 |
362 // Transition to kPlaying if we are currently handling an underflow since | 354 // Transition to kPlaying if we are currently handling an underflow since |
363 // no more data will be arriving. | 355 // no more data will be arriving. |
364 if (state_ == kUnderflow || state_ == kRebuffering) | 356 if (state_ == kUnderflow || state_ == kRebuffering) |
365 state_ = kPlaying; | 357 state_ = kPlaying; |
366 } | 358 } |
367 | 359 |
368 switch (state_) { | 360 switch (state_) { |
369 case kUninitialized: | 361 case kUninitialized: |
370 NOTREACHED(); | 362 NOTREACHED(); |
371 return false; | 363 return false; |
372 case kPaused: | 364 case kPaused: |
373 if (!buffer->IsEndOfStream()) | 365 if (!buffer->end_of_stream()) algorithm_->EnqueueBuffer(buffer); |
374 algorithm_->EnqueueBuffer(buffer); | |
375 DCHECK(!pending_read_); | 366 DCHECK(!pending_read_); |
376 base::ResetAndReturn(&pause_cb_).Run(); | 367 base::ResetAndReturn(&pause_cb_).Run(); |
377 return false; | 368 return false; |
378 case kPrerolling: | 369 case kPrerolling: |
379 if (IsBeforePrerollTime(buffer)) | 370 if (IsBeforePrerollTime(buffer)) |
380 return true; | 371 return true; |
381 | 372 |
382 if (!buffer->IsEndOfStream()) { | 373 if (!buffer->end_of_stream()) { |
383 algorithm_->EnqueueBuffer(buffer); | 374 algorithm_->EnqueueBuffer(buffer); |
384 if (!algorithm_->IsQueueFull()) | 375 if (!algorithm_->IsQueueFull()) |
385 return false; | 376 return false; |
386 } | 377 } |
387 state_ = kPaused; | 378 state_ = kPaused; |
388 base::ResetAndReturn(&preroll_cb_).Run(PIPELINE_OK); | 379 base::ResetAndReturn(&preroll_cb_).Run(PIPELINE_OK); |
389 return false; | 380 return false; |
390 case kPlaying: | 381 case kPlaying: |
391 case kUnderflow: | 382 case kUnderflow: |
392 case kRebuffering: | 383 case kRebuffering: |
393 if (!buffer->IsEndOfStream()) | 384 if (!buffer->end_of_stream()) |
394 algorithm_->EnqueueBuffer(buffer); | 385 algorithm_->EnqueueBuffer(buffer); |
395 return false; | 386 return false; |
396 case kStopped: | 387 case kStopped: |
397 return false; | 388 return false; |
398 } | 389 } |
399 return false; | 390 return false; |
400 } | 391 } |
401 | 392 |
402 void AudioRendererImpl::AttemptRead() { | 393 void AudioRendererImpl::AttemptRead() { |
403 base::AutoLock auto_lock(lock_); | 394 base::AutoLock auto_lock(lock_); |
(...skipping 21 matching lines...) Expand all Loading... | |
425 return false; | 416 return false; |
426 | 417 |
427 case kPrerolling: | 418 case kPrerolling: |
428 case kPlaying: | 419 case kPlaying: |
429 case kUnderflow: | 420 case kUnderflow: |
430 case kRebuffering: | 421 case kRebuffering: |
431 break; | 422 break; |
432 } | 423 } |
433 | 424 |
434 return !pending_read_ && !received_end_of_stream_ && | 425 return !pending_read_ && !received_end_of_stream_ && |
435 !algorithm_->IsQueueFull(); | 426 !algorithm_->IsQueueFull(); |
436 } | 427 } |
437 | 428 |
438 void AudioRendererImpl::SetPlaybackRate(float playback_rate) { | 429 void AudioRendererImpl::SetPlaybackRate(float playback_rate) { |
439 DCHECK(message_loop_->BelongsToCurrentThread()); | 430 DCHECK(message_loop_->BelongsToCurrentThread()); |
440 DCHECK_GE(playback_rate, 0); | 431 DCHECK_GE(playback_rate, 0); |
441 DCHECK(sink_.get()); | 432 DCHECK(sink_.get()); |
442 | 433 |
443 // We have two cases here: | 434 // We have two cases here: |
444 // Play: current_playback_rate == 0 && playback_rate != 0 | 435 // Play: current_playback_rate == 0 && playback_rate != 0 |
445 // Pause: current_playback_rate != 0 && playback_rate == 0 | 436 // Pause: current_playback_rate != 0 && playback_rate == 0 |
446 float current_playback_rate = algorithm_->playback_rate(); | 437 float current_playback_rate = algorithm_->playback_rate(); |
447 if (current_playback_rate == 0 && playback_rate != 0) | 438 if (current_playback_rate == 0 && playback_rate != 0) |
448 DoPlay(); | 439 DoPlay(); |
449 else if (current_playback_rate != 0 && playback_rate == 0) | 440 else if (current_playback_rate != 0 && playback_rate == 0) |
450 DoPause(); | 441 DoPause(); |
451 | 442 |
452 base::AutoLock auto_lock(lock_); | 443 base::AutoLock auto_lock(lock_); |
453 algorithm_->SetPlaybackRate(playback_rate); | 444 algorithm_->SetPlaybackRate(playback_rate); |
454 } | 445 } |
455 | 446 |
456 bool AudioRendererImpl::IsBeforePrerollTime( | 447 bool AudioRendererImpl::IsBeforePrerollTime( |
457 const scoped_refptr<DataBuffer>& buffer) { | 448 const scoped_refptr<DataBuffer>& buffer) { |
458 return (state_ == kPrerolling) && buffer.get() && !buffer->IsEndOfStream() && | 449 return (state_ == kPrerolling) && buffer.get() && |
459 (buffer->GetTimestamp() + buffer->GetDuration()) < preroll_timestamp_; | 450 !buffer->end_of_stream() && |
451 (buffer->timestamp() + buffer->duration()) < | |
452 preroll_timestamp_; | |
460 } | 453 } |
461 | 454 |
462 int AudioRendererImpl::Render(AudioBus* audio_bus, | 455 int AudioRendererImpl::Render(AudioBus* audio_bus, |
463 int audio_delay_milliseconds) { | 456 int audio_delay_milliseconds) { |
464 if (actual_frames_per_buffer_ != audio_bus->frames()) { | 457 if (actual_frames_per_buffer_ != audio_bus->frames()) { |
465 audio_buffer_.reset( | 458 audio_buffer_.reset( |
466 new uint8[audio_bus->frames() * audio_parameters_.GetBytesPerFrame()]); | 459 new uint8[audio_bus->frames() * audio_parameters_.GetBytesPerFrame()]); |
467 actual_frames_per_buffer_ = audio_bus->frames(); | 460 actual_frames_per_buffer_ = audio_bus->frames(); |
468 } | 461 } |
469 | 462 |
470 int frames_filled = FillBuffer( | 463 int frames_filled = FillBuffer(audio_buffer_.get(), audio_bus->frames(), |
471 audio_buffer_.get(), audio_bus->frames(), audio_delay_milliseconds); | 464 audio_delay_milliseconds); |
472 DCHECK_LE(frames_filled, actual_frames_per_buffer_); | 465 DCHECK_LE(frames_filled, actual_frames_per_buffer_); |
473 | 466 |
474 // Deinterleave audio data into the output bus. | 467 // Deinterleave audio data into the output bus. |
475 audio_bus->FromInterleaved( | 468 audio_bus->FromInterleaved(audio_buffer_.get(), frames_filled, |
476 audio_buffer_.get(), frames_filled, | 469 audio_parameters_.bits_per_sample() / 8); |
477 audio_parameters_.bits_per_sample() / 8); | |
478 | 470 |
479 return frames_filled; | 471 return frames_filled; |
480 } | 472 } |
481 | 473 |
482 uint32 AudioRendererImpl::FillBuffer(uint8* dest, | 474 uint32 AudioRendererImpl::FillBuffer(uint8* dest, uint32 requested_frames, |
483 uint32 requested_frames, | |
484 int audio_delay_milliseconds) { | 475 int audio_delay_milliseconds) { |
485 base::TimeDelta current_time = kNoTimestamp(); | 476 base::TimeDelta current_time = kNoTimestamp(); |
486 base::TimeDelta max_time = kNoTimestamp(); | 477 base::TimeDelta max_time = kNoTimestamp(); |
487 base::TimeDelta playback_delay = base::TimeDelta::FromMilliseconds( | 478 base::TimeDelta playback_delay = |
488 audio_delay_milliseconds); | 479 base::TimeDelta::FromMilliseconds(audio_delay_milliseconds); |
489 | 480 |
490 size_t frames_written = 0; | 481 size_t frames_written = 0; |
491 base::Closure underflow_cb; | 482 base::Closure underflow_cb; |
492 { | 483 { |
493 base::AutoLock auto_lock(lock_); | 484 base::AutoLock auto_lock(lock_); |
494 | 485 |
495 // Ensure Stop() hasn't destroyed our |algorithm_| on the pipeline thread. | 486 // Ensure Stop() hasn't destroyed our |algorithm_| on the pipeline thread. |
496 if (!algorithm_) | 487 if (!algorithm_) |
497 return 0; | 488 return 0; |
498 | 489 |
(...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
535 state_ = kUnderflow; | 526 state_ = kUnderflow; |
536 underflow_cb = underflow_cb_; | 527 underflow_cb = underflow_cb_; |
537 } else { | 528 } else { |
538 // We can't write any data this cycle. For example, we may have | 529 // 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 | 530 // sent all available data to the audio device while not reaching |
540 // |earliest_end_time_|. | 531 // |earliest_end_time_|. |
541 } | 532 } |
542 } | 533 } |
543 | 534 |
544 if (CanRead_Locked()) { | 535 if (CanRead_Locked()) { |
545 message_loop_->PostTask(FROM_HERE, base::Bind( | 536 message_loop_->PostTask( |
546 &AudioRendererImpl::AttemptRead, weak_this_)); | 537 FROM_HERE, base::Bind(&AudioRendererImpl::AttemptRead, weak_this_)); |
547 } | 538 } |
548 | 539 |
549 // The |audio_time_buffered_| is the ending timestamp of the last frame | 540 // 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 | 541 // 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 | 542 // buffered at the audio device. The current time can be computed by their |
552 // difference. | 543 // difference. |
553 if (audio_time_buffered_ != kNoTimestamp()) { | 544 if (audio_time_buffered_ != kNoTimestamp()) { |
554 // Adjust the delay according to playback rate. | 545 // Adjust the delay according to playback rate. |
555 base::TimeDelta adjusted_playback_delay = | 546 base::TimeDelta adjusted_playback_delay = |
556 base::TimeDelta::FromMicroseconds(ceil( | 547 base::TimeDelta::FromMicroseconds( |
557 playback_delay.InMicroseconds() * playback_rate)); | 548 ceil(playback_delay.InMicroseconds() * playback_rate)); |
558 | 549 |
559 base::TimeDelta previous_time = current_time_; | 550 base::TimeDelta previous_time = current_time_; |
560 current_time_ = audio_time_buffered_ - adjusted_playback_delay; | 551 current_time_ = audio_time_buffered_ - adjusted_playback_delay; |
561 | 552 |
562 // Time can change in one of two ways: | 553 // Time can change in one of two ways: |
563 // 1) The time of the audio data at the audio device changed, or | 554 // 1) The time of the audio data at the audio device changed, or |
564 // 2) The playback delay value has changed | 555 // 2) The playback delay value has changed |
565 // | 556 // |
566 // We only want to set |current_time| (and thus execute |time_cb_|) if | 557 // 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. | 558 // time has progressed and we haven't signaled end of stream yet. |
568 // | 559 // |
569 // Why? The current latency of the system results in getting the last call | 560 // 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' | 561 // to FillBuffer() later than we'd like, which delays firing the 'ended' |
571 // event, which delays the looping/trigging performance of short sound | 562 // event, which delays the looping/trigging performance of short sound |
572 // effects. | 563 // effects. |
573 // | 564 // |
574 // TODO(scherkus): revisit this and switch back to relying on playback | 565 // TODO(scherkus): revisit this and switch back to relying on playback |
575 // delay after we've revamped our audio IPC subsystem. | 566 // delay after we've revamped our audio IPC subsystem. |
576 if (current_time_ > previous_time && !rendered_end_of_stream_) { | 567 if (current_time_ > previous_time && !rendered_end_of_stream_) { |
577 current_time = current_time_; | 568 current_time = current_time_; |
578 } | 569 } |
579 } | 570 } |
580 | 571 |
581 // The call to FillBuffer() on |algorithm_| has increased the amount of | 572 // The call to FillBuffer() on |algorithm_| has increased the amount of |
582 // buffered audio data. Update the new amount of time buffered. | 573 // buffered audio data. Update the new amount of time buffered. |
583 max_time = algorithm_->GetTime(); | 574 max_time = algorithm_->GetTime(); |
584 audio_time_buffered_ = max_time; | 575 audio_time_buffered_ = max_time; |
585 | 576 |
586 UpdateEarliestEndTime_Locked( | 577 UpdateEarliestEndTime_Locked(frames_written, playback_delay, now_cb_.Run()); |
587 frames_written, playback_delay, now_cb_.Run()); | |
588 } | 578 } |
589 | 579 |
590 if (current_time != kNoTimestamp() && max_time != kNoTimestamp()) { | 580 if (current_time != kNoTimestamp() && max_time != kNoTimestamp()) { |
591 time_cb_.Run(current_time, max_time); | 581 time_cb_.Run(current_time, max_time); |
592 } | 582 } |
593 | 583 |
594 if (!underflow_cb.is_null()) | 584 if (!underflow_cb.is_null()) |
595 underflow_cb.Run(); | 585 underflow_cb.Run(); |
596 | 586 |
597 return frames_written; | 587 return frames_written; |
(...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
642 case kUnderflow: | 632 case kUnderflow: |
643 case kRebuffering: | 633 case kRebuffering: |
644 case kStopped: | 634 case kStopped: |
645 if (status != PIPELINE_OK) | 635 if (status != PIPELINE_OK) |
646 error_cb_.Run(status); | 636 error_cb_.Run(status); |
647 return; | 637 return; |
648 } | 638 } |
649 } | 639 } |
650 | 640 |
651 } // namespace media | 641 } // namespace media |
OLD | NEW |