| 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 "base/bind.h" | 9 #include "base/bind.h" |
| 10 #include "base/callback.h" | 10 #include "base/callback.h" |
| 11 #include "base/callback_helpers.h" | 11 #include "base/callback_helpers.h" |
| 12 #include "base/logging.h" | 12 #include "base/logging.h" |
| 13 #include "media/base/filter_host.h" | 13 #include "media/base/filter_host.h" |
| 14 #include "media/audio/audio_util.h" | 14 #include "media/audio/audio_util.h" |
| 15 | 15 |
| 16 namespace media { | 16 namespace media { |
| 17 | 17 |
| 18 AudioRendererImpl::AudioRendererImpl(media::AudioRendererSink* sink) | 18 AudioRendererImpl::AudioRendererImpl(media::AudioRendererSink* sink) |
| 19 : host_(NULL), | 19 : state_(kUninitialized), |
| 20 state_(kUninitialized), | |
| 21 pending_read_(false), | 20 pending_read_(false), |
| 22 received_end_of_stream_(false), | 21 received_end_of_stream_(false), |
| 23 rendered_end_of_stream_(false), | 22 rendered_end_of_stream_(false), |
| 24 audio_time_buffered_(kNoTimestamp()), | 23 audio_time_buffered_(kNoTimestamp()), |
| 25 current_time_(kNoTimestamp()), | 24 current_time_(kNoTimestamp()), |
| 26 bytes_per_frame_(0), | 25 bytes_per_frame_(0), |
| 27 bytes_per_second_(0), | 26 bytes_per_second_(0), |
| 28 stopped_(false), | 27 stopped_(false), |
| 29 sink_(sink), | 28 sink_(sink), |
| 30 is_initialized_(false), | 29 is_initialized_(false), |
| 31 underflow_disabled_(false), | 30 underflow_disabled_(false), |
| 32 read_cb_(base::Bind(&AudioRendererImpl::DecodedAudioReady, | 31 read_cb_(base::Bind(&AudioRendererImpl::DecodedAudioReady, |
| 33 base::Unretained(this))) { | 32 base::Unretained(this))) { |
| 34 } | 33 } |
| 35 | 34 |
| 36 void AudioRendererImpl::SetHost(FilterHost* host) { | |
| 37 DCHECK(host); | |
| 38 DCHECK(!host_); | |
| 39 host_ = host; | |
| 40 } | |
| 41 | |
| 42 void AudioRendererImpl::Play(const base::Closure& callback) { | 35 void AudioRendererImpl::Play(const base::Closure& callback) { |
| 43 { | 36 { |
| 44 base::AutoLock auto_lock(lock_); | 37 base::AutoLock auto_lock(lock_); |
| 45 DCHECK_EQ(kPaused, state_); | 38 DCHECK_EQ(kPaused, state_); |
| 46 state_ = kPlaying; | 39 state_ = kPlaying; |
| 47 callback.Run(); | 40 callback.Run(); |
| 48 } | 41 } |
| 49 | 42 |
| 50 if (stopped_) | 43 if (stopped_) |
| 51 return; | 44 return; |
| (...skipping 86 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 138 void AudioRendererImpl::DoSeek() { | 131 void AudioRendererImpl::DoSeek() { |
| 139 earliest_end_time_ = base::Time::Now(); | 132 earliest_end_time_ = base::Time::Now(); |
| 140 | 133 |
| 141 // Pause and flush the stream when we seek to a new location. | 134 // Pause and flush the stream when we seek to a new location. |
| 142 sink_->Pause(true); | 135 sink_->Pause(true); |
| 143 } | 136 } |
| 144 | 137 |
| 145 void AudioRendererImpl::Initialize(const scoped_refptr<AudioDecoder>& decoder, | 138 void AudioRendererImpl::Initialize(const scoped_refptr<AudioDecoder>& decoder, |
| 146 const PipelineStatusCB& init_cb, | 139 const PipelineStatusCB& init_cb, |
| 147 const base::Closure& underflow_cb, | 140 const base::Closure& underflow_cb, |
| 148 const TimeCB& time_cb) { | 141 const TimeCB& time_cb, |
| 142 const base::Closure& ended_cb, |
| 143 const base::Closure& disabled_cb, |
| 144 const PipelineStatusCB& error_cb) { |
| 149 DCHECK(decoder); | 145 DCHECK(decoder); |
| 150 DCHECK(!init_cb.is_null()); | 146 DCHECK(!init_cb.is_null()); |
| 151 DCHECK(!underflow_cb.is_null()); | 147 DCHECK(!underflow_cb.is_null()); |
| 152 DCHECK(!time_cb.is_null()); | 148 DCHECK(!time_cb.is_null()); |
| 149 DCHECK(!ended_cb.is_null()); |
| 150 DCHECK(!disabled_cb.is_null()); |
| 151 DCHECK(!error_cb.is_null()); |
| 153 DCHECK_EQ(kUninitialized, state_); | 152 DCHECK_EQ(kUninitialized, state_); |
| 154 decoder_ = decoder; | 153 decoder_ = decoder; |
| 155 underflow_cb_ = underflow_cb; | 154 underflow_cb_ = underflow_cb; |
| 156 time_cb_ = time_cb; | 155 time_cb_ = time_cb; |
| 156 ended_cb_ = ended_cb; |
| 157 disabled_cb_ = disabled_cb; |
| 158 error_cb_ = error_cb; |
| 157 | 159 |
| 158 // Create a callback so our algorithm can request more reads. | 160 // Create a callback so our algorithm can request more reads. |
| 159 base::Closure cb = base::Bind(&AudioRendererImpl::ScheduleRead_Locked, this); | 161 base::Closure cb = base::Bind(&AudioRendererImpl::ScheduleRead_Locked, this); |
| 160 | 162 |
| 161 // Construct the algorithm. | 163 // Construct the algorithm. |
| 162 algorithm_.reset(new AudioRendererAlgorithm()); | 164 algorithm_.reset(new AudioRendererAlgorithm()); |
| 163 | 165 |
| 164 // Initialize our algorithm with media properties, initial playback rate, | 166 // Initialize our algorithm with media properties, initial playback rate, |
| 165 // and a callback to request more reads from the data source. | 167 // and a callback to request more reads from the data source. |
| 166 ChannelLayout channel_layout = decoder_->channel_layout(); | 168 ChannelLayout channel_layout = decoder_->channel_layout(); |
| (...skipping 262 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 429 // | 431 // |
| 430 // We use the following conditions to determine underflow: | 432 // We use the following conditions to determine underflow: |
| 431 // 1) Algorithm can not fill the audio callback buffer | 433 // 1) Algorithm can not fill the audio callback buffer |
| 432 // 2) We have NOT received an end of stream buffer | 434 // 2) We have NOT received an end of stream buffer |
| 433 // 3) We are in the kPlaying state | 435 // 3) We are in the kPlaying state |
| 434 // | 436 // |
| 435 // Otherwise fill the buffer with whatever data we can send to the device. | 437 // Otherwise fill the buffer with whatever data we can send to the device. |
| 436 if (!algorithm_->CanFillBuffer() && received_end_of_stream_ && | 438 if (!algorithm_->CanFillBuffer() && received_end_of_stream_ && |
| 437 !rendered_end_of_stream_ && base::Time::Now() >= earliest_end_time_) { | 439 !rendered_end_of_stream_ && base::Time::Now() >= earliest_end_time_) { |
| 438 rendered_end_of_stream_ = true; | 440 rendered_end_of_stream_ = true; |
| 439 host_->NotifyEnded(); | 441 ended_cb_.Run(); |
| 440 } else if (!algorithm_->CanFillBuffer() && !received_end_of_stream_ && | 442 } else if (!algorithm_->CanFillBuffer() && !received_end_of_stream_ && |
| 441 state_ == kPlaying && !underflow_disabled_) { | 443 state_ == kPlaying && !underflow_disabled_) { |
| 442 state_ = kUnderflow; | 444 state_ = kUnderflow; |
| 443 underflow_cb = underflow_cb_; | 445 underflow_cb = underflow_cb_; |
| 444 } else if (algorithm_->CanFillBuffer()) { | 446 } else if (algorithm_->CanFillBuffer()) { |
| 445 frames_written = algorithm_->FillBuffer(dest, requested_frames); | 447 frames_written = algorithm_->FillBuffer(dest, requested_frames); |
| 446 DCHECK_GT(frames_written, 0u); | 448 DCHECK_GT(frames_written, 0u); |
| 447 } else { | 449 } else { |
| 448 // We can't write any data this cycle. For example, we may have | 450 // We can't write any data this cycle. For example, we may have |
| 449 // sent all available data to the audio device while not reaching | 451 // sent all available data to the audio device while not reaching |
| (...skipping 62 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 512 | 514 |
| 513 base::TimeDelta AudioRendererImpl::ConvertToDuration(int bytes) { | 515 base::TimeDelta AudioRendererImpl::ConvertToDuration(int bytes) { |
| 514 if (bytes_per_second_) { | 516 if (bytes_per_second_) { |
| 515 return base::TimeDelta::FromMicroseconds( | 517 return base::TimeDelta::FromMicroseconds( |
| 516 base::Time::kMicrosecondsPerSecond * bytes / bytes_per_second_); | 518 base::Time::kMicrosecondsPerSecond * bytes / bytes_per_second_); |
| 517 } | 519 } |
| 518 return base::TimeDelta(); | 520 return base::TimeDelta(); |
| 519 } | 521 } |
| 520 | 522 |
| 521 void AudioRendererImpl::OnRenderError() { | 523 void AudioRendererImpl::OnRenderError() { |
| 522 host_->DisableAudioRenderer(); | 524 disabled_cb_.Run(); |
| 523 } | 525 } |
| 524 | 526 |
| 525 void AudioRendererImpl::DisableUnderflowForTesting() { | 527 void AudioRendererImpl::DisableUnderflowForTesting() { |
| 526 DCHECK(!is_initialized_); | 528 DCHECK(!is_initialized_); |
| 527 underflow_disabled_ = true; | 529 underflow_disabled_ = true; |
| 528 } | 530 } |
| 529 | 531 |
| 530 void AudioRendererImpl::HandleAbortedReadOrDecodeError(bool is_decode_error) { | 532 void AudioRendererImpl::HandleAbortedReadOrDecodeError(bool is_decode_error) { |
| 531 PipelineStatus status = is_decode_error ? PIPELINE_ERROR_DECODE : PIPELINE_OK; | 533 PipelineStatus status = is_decode_error ? PIPELINE_ERROR_DECODE : PIPELINE_OK; |
| 532 switch (state_) { | 534 switch (state_) { |
| 533 case kUninitialized: | 535 case kUninitialized: |
| 534 NOTREACHED(); | 536 NOTREACHED(); |
| 535 return; | 537 return; |
| 536 case kPaused: | 538 case kPaused: |
| 537 if (status != PIPELINE_OK) | 539 if (status != PIPELINE_OK) |
| 538 host_->SetError(status); | 540 error_cb_.Run(status); |
| 539 base::ResetAndReturn(&pause_cb_).Run(); | 541 base::ResetAndReturn(&pause_cb_).Run(); |
| 540 return; | 542 return; |
| 541 case kSeeking: | 543 case kSeeking: |
| 542 state_ = kPaused; | 544 state_ = kPaused; |
| 543 base::ResetAndReturn(&seek_cb_).Run(status); | 545 base::ResetAndReturn(&seek_cb_).Run(status); |
| 544 return; | 546 return; |
| 545 case kPlaying: | 547 case kPlaying: |
| 546 case kUnderflow: | 548 case kUnderflow: |
| 547 case kRebuffering: | 549 case kRebuffering: |
| 548 case kStopped: | 550 case kStopped: |
| 549 if (status != PIPELINE_OK) | 551 if (status != PIPELINE_OK) |
| 550 host_->SetError(status); | 552 error_cb_.Run(status); |
| 551 return; | 553 return; |
| 552 } | 554 } |
| 553 } | 555 } |
| 554 | 556 |
| 555 } // namespace media | 557 } // namespace media |
| OLD | NEW |