Chromium Code Reviews| 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 |