| 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; |
| 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->is_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; |
| 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->is_end_of_stream()) algorithm_->EnqueueBuffer(buffer); |
| 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; |
| 380 return true; | |
| 381 | 369 |
| 382 if (!buffer->IsEndOfStream()) { | 370 if (!buffer->is_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->is_end_of_stream()) algorithm_->EnqueueBuffer(buffer); |
| 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; |
| 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->is_end_of_stream() && |
| 445 (buffer->get_timestamp() + buffer->get_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; |
| 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; |
| 501 return 0; | |
| 502 | 485 |
| 503 if (state_ == kRebuffering && algorithm_->IsQueueFull()) | 486 if (state_ == kRebuffering && algorithm_->IsQueueFull()) state_ = kPlaying; |
| 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; |
| 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(); |
| 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; |
| 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); |
| 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); |
| 646 error_cb_.Run(status); | |
| 647 return; | 623 return; |
| 648 } | 624 } |
| 649 } | 625 } |
| 650 | 626 |
| 651 } // namespace media | 627 } // namespace media |
| OLD | NEW |