Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(33)

Side by Side Diff: media/filters/audio_renderer_impl.cc

Issue 11183048: Miscellaneous AudioRendererImpl cleanup salvaged from http://codereview.chromium.org/10918022/. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Created 8 years, 2 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « media/filters/audio_renderer_impl.h ('k') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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
11 #include "base/bind.h" 11 #include "base/bind.h"
12 #include "base/callback.h" 12 #include "base/callback.h"
13 #include "base/callback_helpers.h" 13 #include "base/callback_helpers.h"
14 #include "base/logging.h" 14 #include "base/logging.h"
15 #include "media/audio/audio_util.h" 15 #include "media/audio/audio_util.h"
16 #include "media/base/demuxer_stream.h" 16 #include "media/base/demuxer_stream.h"
17 17
18 namespace media { 18 namespace media {
19 19
20 AudioRendererImpl::AudioRendererImpl(media::AudioRendererSink* sink) 20 AudioRendererImpl::AudioRendererImpl(media::AudioRendererSink* sink)
21 : state_(kUninitialized), 21 : state_(kUninitialized),
22 pending_read_(false), 22 pending_read_(false),
23 received_end_of_stream_(false), 23 received_end_of_stream_(false),
24 rendered_end_of_stream_(false), 24 rendered_end_of_stream_(false),
25 audio_time_buffered_(kNoTimestamp()), 25 audio_time_buffered_(kNoTimestamp()),
26 current_time_(kNoTimestamp()), 26 current_time_(kNoTimestamp()),
27 bytes_per_frame_(0), 27 bytes_per_frame_(0),
28 bytes_per_second_(0),
29 stopped_(false), 28 stopped_(false),
30 sink_(sink), 29 sink_(sink),
31 is_initialized_(false),
32 underflow_disabled_(false), 30 underflow_disabled_(false),
33 preroll_aborted_(false) { 31 preroll_aborted_(false) {
34 } 32 }
35 33
36 void AudioRendererImpl::Play(const base::Closure& callback) { 34 void AudioRendererImpl::Play(const base::Closure& callback) {
37 { 35 {
38 base::AutoLock auto_lock(lock_); 36 base::AutoLock auto_lock(lock_);
39 DCHECK_EQ(kPaused, state_); 37 DCHECK_EQ(kPaused, state_);
40 state_ = kPlaying; 38 state_ = kPlaying;
41 callback.Run(); 39 callback.Run();
42 } 40 }
43 41
44 if (stopped_) 42 if (stopped_)
45 return; 43 return;
46 44
47 if (GetPlaybackRate() != 0.0f) { 45 if (GetPlaybackRate() != 0.0f) {
48 DoPlay(); 46 DoPlay();
49 } else { 47 } else {
50 DoPause(); 48 DoPause();
51 } 49 }
52 } 50 }
53 51
54 void AudioRendererImpl::DoPlay() { 52 void AudioRendererImpl::DoPlay() {
55 earliest_end_time_ = base::Time::Now(); 53 earliest_end_time_ = base::Time::Now();
56 DCHECK(sink_.get());
57 sink_->Play(); 54 sink_->Play();
58 } 55 }
59 56
60 void AudioRendererImpl::Pause(const base::Closure& callback) { 57 void AudioRendererImpl::Pause(const base::Closure& callback) {
61 { 58 {
62 base::AutoLock auto_lock(lock_); 59 base::AutoLock auto_lock(lock_);
63 DCHECK(state_ == kPlaying || state_ == kUnderflow || 60 DCHECK(state_ == kPlaying || state_ == kUnderflow ||
64 state_ == kRebuffering); 61 state_ == kRebuffering);
65 pause_cb_ = callback; 62 pause_cb_ = callback;
66 state_ = kPaused; 63 state_ = kPaused;
67 64
68 // Pause only when we've completed our pending read. 65 // Pause only when we've completed our pending read.
69 if (!pending_read_) 66 if (!pending_read_)
70 base::ResetAndReturn(&pause_cb_).Run(); 67 base::ResetAndReturn(&pause_cb_).Run();
71 } 68 }
72 69
73 if (stopped_) 70 if (stopped_)
74 return; 71 return;
75 72
76 DoPause(); 73 DoPause();
77 } 74 }
78 75
79 void AudioRendererImpl::DoPause() { 76 void AudioRendererImpl::DoPause() {
80 DCHECK(sink_.get());
81 sink_->Pause(false); 77 sink_->Pause(false);
82 } 78 }
83 79
84 void AudioRendererImpl::Flush(const base::Closure& callback) { 80 void AudioRendererImpl::Flush(const base::Closure& callback) {
85 decoder_->Reset(callback); 81 decoder_->Reset(callback);
86 } 82 }
87 83
88 void AudioRendererImpl::Stop(const base::Closure& callback) { 84 void AudioRendererImpl::Stop(const base::Closure& callback) {
89 DCHECK(!callback.is_null()); 85 DCHECK(!callback.is_null());
90 86
91 if (!stopped_) { 87 if (!stopped_) {
92 DCHECK(sink_.get());
93 sink_->Stop(); 88 sink_->Stop();
94
95 stopped_ = true; 89 stopped_ = true;
96 } 90 }
97 { 91 {
98 base::AutoLock auto_lock(lock_); 92 base::AutoLock auto_lock(lock_);
99 state_ = kStopped; 93 state_ = kStopped;
100 algorithm_.reset(NULL); 94 algorithm_.reset(NULL);
101 init_cb_.Reset(); 95 init_cb_.Reset();
102 underflow_cb_.Reset(); 96 underflow_cb_.Reset();
103 time_cb_.Reset(); 97 time_cb_.Reset();
104 } 98 }
(...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after
142 const base::Closure& underflow_cb, 136 const base::Closure& underflow_cb,
143 const TimeCB& time_cb, 137 const TimeCB& time_cb,
144 const base::Closure& ended_cb, 138 const base::Closure& ended_cb,
145 const base::Closure& disabled_cb, 139 const base::Closure& disabled_cb,
146 const PipelineStatusCB& error_cb) { 140 const PipelineStatusCB& error_cb) {
147 base::AutoLock auto_lock(lock_); 141 base::AutoLock auto_lock(lock_);
148 DCHECK(stream); 142 DCHECK(stream);
149 DCHECK(!decoders.empty()); 143 DCHECK(!decoders.empty());
150 DCHECK_EQ(stream->type(), DemuxerStream::AUDIO); 144 DCHECK_EQ(stream->type(), DemuxerStream::AUDIO);
151 DCHECK(!init_cb.is_null()); 145 DCHECK(!init_cb.is_null());
146 DCHECK(!statistics_cb.is_null());
152 DCHECK(!underflow_cb.is_null()); 147 DCHECK(!underflow_cb.is_null());
153 DCHECK(!time_cb.is_null()); 148 DCHECK(!time_cb.is_null());
154 DCHECK(!ended_cb.is_null()); 149 DCHECK(!ended_cb.is_null());
155 DCHECK(!disabled_cb.is_null()); 150 DCHECK(!disabled_cb.is_null());
156 DCHECK(!error_cb.is_null()); 151 DCHECK(!error_cb.is_null());
157 DCHECK_EQ(kUninitialized, state_); 152 DCHECK_EQ(kUninitialized, state_);
158 153
159 init_cb_ = init_cb; 154 init_cb_ = init_cb;
160 statistics_cb_ = statistics_cb; 155 statistics_cb_ = statistics_cb;
161 underflow_cb_ = underflow_cb; 156 underflow_cb_ = underflow_cb;
(...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after
201 if (!decoders->empty() && status == DECODER_ERROR_NOT_SUPPORTED) { 196 if (!decoders->empty() && status == DECODER_ERROR_NOT_SUPPORTED) {
202 InitializeNextDecoder(demuxer_stream, decoders.Pass()); 197 InitializeNextDecoder(demuxer_stream, decoders.Pass());
203 return; 198 return;
204 } 199 }
205 200
206 if (status != PIPELINE_OK) { 201 if (status != PIPELINE_OK) {
207 base::ResetAndReturn(&init_cb_).Run(status); 202 base::ResetAndReturn(&init_cb_).Run(status);
208 return; 203 return;
209 } 204 }
210 205
211 // Create a callback so our algorithm can request more reads. 206 // We're all good! Continue initializing the rest of the audio renderer based
212 base::Closure cb = base::Bind(&AudioRendererImpl::ScheduleRead_Locked, this); 207 // on the decoder format.
213 208
214 // Construct the algorithm.
215 algorithm_.reset(new AudioRendererAlgorithm());
216
217 // Initialize our algorithm with media properties, initial playback rate,
218 // and a callback to request more reads from the data source.
219 ChannelLayout channel_layout = decoder_->channel_layout(); 209 ChannelLayout channel_layout = decoder_->channel_layout();
220 int channels = ChannelLayoutToChannelCount(channel_layout); 210 int channels = ChannelLayoutToChannelCount(channel_layout);
221 int bits_per_channel = decoder_->bits_per_channel(); 211 int bits_per_channel = decoder_->bits_per_channel();
222 int sample_rate = decoder_->samples_per_second(); 212 int sample_rate = decoder_->samples_per_second();
223 // TODO(vrk): Add method to AudioDecoder to compute bytes per frame. 213 // TODO(vrk): Add method to AudioDecoder to compute bytes per frame.
224 bytes_per_frame_ = channels * bits_per_channel / 8; 214 bytes_per_frame_ = channels * bits_per_channel / 8;
225 215
226 bool config_ok = algorithm_->ValidateConfig(channels, sample_rate, 216 algorithm_.reset(new AudioRendererAlgorithm());
227 bits_per_channel); 217 if (!algorithm_->ValidateConfig(channels, sample_rate, bits_per_channel)) {
228 if (!config_ok || is_initialized_) {
229 base::ResetAndReturn(&init_cb_).Run(PIPELINE_ERROR_INITIALIZATION_FAILED); 218 base::ResetAndReturn(&init_cb_).Run(PIPELINE_ERROR_INITIALIZATION_FAILED);
230 return; 219 return;
231 } 220 }
232 221
233 if (config_ok) 222 algorithm_->Initialize(
234 algorithm_->Initialize(channels, sample_rate, bits_per_channel, 0.0f, cb); 223 channels, sample_rate, bits_per_channel, 0.0f,
224 base::Bind(&AudioRendererImpl::ScheduleRead_Locked, this));
235 225
236 // We use the AUDIO_PCM_LINEAR flag because AUDIO_PCM_LOW_LATENCY 226 // We use the AUDIO_PCM_LINEAR flag because AUDIO_PCM_LOW_LATENCY
237 // does not currently support all the sample-rates that we require. 227 // does not currently support all the sample-rates that we require.
238 // Please see: http://code.google.com/p/chromium/issues/detail?id=103627 228 // Please see: http://code.google.com/p/chromium/issues/detail?id=103627
239 // for more details. 229 // for more details.
240 audio_parameters_ = AudioParameters( 230 audio_parameters_ = AudioParameters(
241 AudioParameters::AUDIO_PCM_LINEAR, channel_layout, sample_rate, 231 AudioParameters::AUDIO_PCM_LINEAR, channel_layout, sample_rate,
242 bits_per_channel, GetHighLatencyOutputBufferSize(sample_rate)); 232 bits_per_channel, GetHighLatencyOutputBufferSize(sample_rate));
243 233
244 bytes_per_second_ = audio_parameters_.GetBytesPerSecond(); 234 sink_->Initialize(audio_parameters_, this);
235 sink_->Start();
245 236
246 DCHECK(sink_.get());
247 DCHECK(!is_initialized_);
248
249 sink_->Initialize(audio_parameters_, this);
250
251 sink_->Start();
252 is_initialized_ = true;
253
254 // Finally, execute the start callback.
255 state_ = kPaused; 237 state_ = kPaused;
256 base::ResetAndReturn(&init_cb_).Run(PIPELINE_OK); 238 base::ResetAndReturn(&init_cb_).Run(PIPELINE_OK);
257 } 239 }
258 240
259 void AudioRendererImpl::ResumeAfterUnderflow(bool buffer_more_audio) { 241 void AudioRendererImpl::ResumeAfterUnderflow(bool buffer_more_audio) {
260 base::AutoLock auto_lock(lock_); 242 base::AutoLock auto_lock(lock_);
261 if (state_ == kUnderflow) { 243 if (state_ == kUnderflow) {
262 // The "&& preroll_aborted_" is a hack. If preroll is aborted, then we 244 // The "&& preroll_aborted_" is a hack. If preroll is aborted, then we
263 // shouldn't even reach the kUnderflow state to begin with. But for now 245 // shouldn't even reach the kUnderflow state to begin with. But for now
264 // we're just making sure that the audio buffer capacity (i.e. the 246 // we're just making sure that the audio buffer capacity (i.e. the
(...skipping 273 matching lines...) Expand 10 before | Expand all | Expand 10 after
538 static_cast<int64>(ceil(predicted_play_time.InMicroseconds() * 520 static_cast<int64>(ceil(predicted_play_time.InMicroseconds() *
539 playback_rate))); 521 playback_rate)));
540 } 522 }
541 earliest_end_time_ = 523 earliest_end_time_ =
542 std::max(earliest_end_time_, 524 std::max(earliest_end_time_,
543 time_now + request_delay + predicted_play_time); 525 time_now + request_delay + predicted_play_time);
544 } 526 }
545 } 527 }
546 528
547 base::TimeDelta AudioRendererImpl::ConvertToDuration(int bytes) { 529 base::TimeDelta AudioRendererImpl::ConvertToDuration(int bytes) {
548 if (bytes_per_second_) { 530 int bytes_per_second = audio_parameters_.GetBytesPerSecond();
549 return base::TimeDelta::FromMicroseconds( 531 CHECK(bytes_per_second);
550 base::Time::kMicrosecondsPerSecond * bytes / bytes_per_second_); 532 return base::TimeDelta::FromMicroseconds(
551 } 533 base::Time::kMicrosecondsPerSecond * bytes / bytes_per_second);
552 return base::TimeDelta();
553 } 534 }
554 535
555 void AudioRendererImpl::OnRenderError() { 536 void AudioRendererImpl::OnRenderError() {
556 disabled_cb_.Run(); 537 disabled_cb_.Run();
557 } 538 }
558 539
559 void AudioRendererImpl::DisableUnderflowForTesting() { 540 void AudioRendererImpl::DisableUnderflowForTesting() {
560 DCHECK(!is_initialized_);
561 underflow_disabled_ = true; 541 underflow_disabled_ = true;
562 } 542 }
563 543
564 void AudioRendererImpl::HandleAbortedReadOrDecodeError(bool is_decode_error) { 544 void AudioRendererImpl::HandleAbortedReadOrDecodeError(bool is_decode_error) {
565 PipelineStatus status = is_decode_error ? PIPELINE_ERROR_DECODE : PIPELINE_OK; 545 PipelineStatus status = is_decode_error ? PIPELINE_ERROR_DECODE : PIPELINE_OK;
566 switch (state_) { 546 switch (state_) {
567 case kUninitialized: 547 case kUninitialized:
568 NOTREACHED(); 548 NOTREACHED();
569 return; 549 return;
570 case kPaused: 550 case kPaused:
(...skipping 11 matching lines...) Expand all
582 case kUnderflow: 562 case kUnderflow:
583 case kRebuffering: 563 case kRebuffering:
584 case kStopped: 564 case kStopped:
585 if (status != PIPELINE_OK) 565 if (status != PIPELINE_OK)
586 error_cb_.Run(status); 566 error_cb_.Run(status);
587 return; 567 return;
588 } 568 }
589 } 569 }
590 570
591 } // namespace media 571 } // namespace media
OLDNEW
« no previous file with comments | « media/filters/audio_renderer_impl.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698