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 |