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

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

Issue 11148011: Move audio decoder initialization to AudioRendererImpl. (Closed) Base URL: http://git.chromium.org/chromium/src.git@master
Patch Set: Update player_x11 and player_wtl 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
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 "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/audio/audio_util.h" 13 #include "media/audio/audio_util.h"
14 #include "media/base/demuxer_stream.h"
14 15
15 namespace media { 16 namespace media {
16 17
17 AudioRendererImpl::AudioRendererImpl(media::AudioRendererSink* sink) 18 AudioRendererImpl::AudioRendererImpl(media::AudioRendererSink* sink)
18 : state_(kUninitialized), 19 : state_(kUninitialized),
19 pending_read_(false), 20 pending_read_(false),
20 received_end_of_stream_(false), 21 received_end_of_stream_(false),
21 rendered_end_of_stream_(false), 22 rendered_end_of_stream_(false),
22 audio_time_buffered_(kNoTimestamp()), 23 audio_time_buffered_(kNoTimestamp()),
23 current_time_(kNoTimestamp()), 24 current_time_(kNoTimestamp()),
(...skipping 65 matching lines...) Expand 10 before | Expand all | Expand 10 after
89 90
90 stopped_ = true; 91 stopped_ = true;
91 } 92 }
92 { 93 {
93 base::AutoLock auto_lock(lock_); 94 base::AutoLock auto_lock(lock_);
94 state_ = kStopped; 95 state_ = kStopped;
95 algorithm_.reset(NULL); 96 algorithm_.reset(NULL);
96 time_cb_.Reset(); 97 time_cb_.Reset();
97 underflow_cb_.Reset(); 98 underflow_cb_.Reset();
98 } 99 }
99 if (!callback.is_null()) { 100 if (!callback.is_null()) {
acolwell GONE FROM CHROMIUM 2012/10/15 21:00:07 nit: Is this actually ever called w/o a callback?
xhwang 2012/10/15 22:52:23 Done.
100 callback.Run(); 101 callback.Run();
101 } 102 }
102 } 103 }
103 104
104 void AudioRendererImpl::Preroll(base::TimeDelta time, 105 void AudioRendererImpl::Preroll(base::TimeDelta time,
105 const PipelineStatusCB& cb) { 106 const PipelineStatusCB& cb) {
106 base::AutoLock auto_lock(lock_); 107 base::AutoLock auto_lock(lock_);
107 DCHECK_EQ(kPaused, state_); 108 DCHECK_EQ(kPaused, state_);
108 DCHECK(!pending_read_) << "Pending read must complete before seeking"; 109 DCHECK(!pending_read_) << "Pending read must complete before seeking";
109 DCHECK(pause_cb_.is_null()); 110 DCHECK(pause_cb_.is_null());
(...skipping 13 matching lines...) Expand all
123 algorithm_->FlushBuffers(); 124 algorithm_->FlushBuffers();
124 125
125 if (stopped_) 126 if (stopped_)
126 return; 127 return;
127 128
128 // Pause and flush the stream when we preroll to a new location. 129 // Pause and flush the stream when we preroll to a new location.
129 earliest_end_time_ = base::Time::Now(); 130 earliest_end_time_ = base::Time::Now();
130 sink_->Pause(true); 131 sink_->Pause(true);
131 } 132 }
132 133
133 void AudioRendererImpl::Initialize(const scoped_refptr<AudioDecoder>& decoder, 134 void AudioRendererImpl::Initialize(const scoped_refptr<DemuxerStream>& stream,
135 const AudioDecoderList& decoders,
134 const PipelineStatusCB& init_cb, 136 const PipelineStatusCB& init_cb,
137 const StatisticsCB& statistics_cb,
135 const base::Closure& underflow_cb, 138 const base::Closure& underflow_cb,
136 const TimeCB& time_cb, 139 const TimeCB& time_cb,
137 const base::Closure& ended_cb, 140 const base::Closure& ended_cb,
138 const base::Closure& disabled_cb, 141 const base::Closure& disabled_cb,
139 const PipelineStatusCB& error_cb) { 142 const PipelineStatusCB& error_cb) {
140 DCHECK(decoder); 143 base::AutoLock auto_lock(lock_);
144 DCHECK(stream);
145 DCHECK(!decoders.empty());
146 DCHECK_EQ(stream->type(), DemuxerStream::AUDIO);
141 DCHECK(!init_cb.is_null()); 147 DCHECK(!init_cb.is_null());
142 DCHECK(!underflow_cb.is_null()); 148 DCHECK(!underflow_cb.is_null());
143 DCHECK(!time_cb.is_null()); 149 DCHECK(!time_cb.is_null());
144 DCHECK(!ended_cb.is_null()); 150 DCHECK(!ended_cb.is_null());
145 DCHECK(!disabled_cb.is_null()); 151 DCHECK(!disabled_cb.is_null());
146 DCHECK(!error_cb.is_null()); 152 DCHECK(!error_cb.is_null());
147 DCHECK_EQ(kUninitialized, state_); 153 DCHECK_EQ(kUninitialized, state_);
148 decoder_ = decoder; 154
155 init_cb_ = init_cb;
156 statistics_cb_ = statistics_cb;
149 underflow_cb_ = underflow_cb; 157 underflow_cb_ = underflow_cb;
150 time_cb_ = time_cb; 158 time_cb_ = time_cb;
151 ended_cb_ = ended_cb; 159 ended_cb_ = ended_cb;
152 disabled_cb_ = disabled_cb; 160 disabled_cb_ = disabled_cb;
153 error_cb_ = error_cb; 161 error_cb_ = error_cb;
154 162
163 scoped_ptr<AudioDecoderList> decoder_list(new AudioDecoderList(decoders));
164 InitializeNextDecoder(stream, decoder_list.Pass());
165 }
166
167 void AudioRendererImpl::InitializeNextDecoder(
168 const scoped_refptr<DemuxerStream>& demuxer_stream,
169 scoped_ptr<AudioDecoderList> decoders) {
170 lock_.AssertAcquired();
171 DCHECK(!decoders->empty());
172
173 scoped_refptr<AudioDecoder> decoder = decoders->front();
174 decoders->pop_front();
175
176 DCHECK(decoder);
177 decoder_ = decoder;
178
179 base::AutoUnlock auto_unlock(lock_);
180 decoder->Initialize(
181 demuxer_stream,
182 base::Bind(&AudioRendererImpl::OnDecoderInitDone, this,
183 demuxer_stream,
184 base::Passed(&decoders)),
185 statistics_cb_);
186 }
187
188 void AudioRendererImpl::OnDecoderInitDone(
189 const scoped_refptr<DemuxerStream>& demuxer_stream,
190 scoped_ptr<AudioDecoderList> decoders,
191 PipelineStatus status) {
192 base::AutoLock auto_lock(lock_);
193
194 if (state_ == kStopped) {
195 // TODO(xhwang): Question! Do we need to return init_cb here? Is the
196 // pipeline teardown waiting for this?
xhwang 2012/10/15 17:50:28 In VideoRendererBase we return directly here w/o r
197 base::ResetAndReturn(&init_cb_).Run(PIPELINE_ERROR_ABORT);
acolwell GONE FROM CHROMIUM 2012/10/15 21:00:07 No. You should not call init_cb_ here. init_cb_ sh
xhwang 2012/10/15 22:52:23 Done. Also added init_cb_.Reset() in Stop().
198 return;
199 }
200
201 if (!decoders->empty() && status == DECODER_ERROR_NOT_SUPPORTED) {
202 InitializeNextDecoder(demuxer_stream, decoders.Pass());
203 return;
204 }
205
206 if (status != PIPELINE_OK) {
207 base::ResetAndReturn(&init_cb_).Run(status);
208 return;
209 }
210
155 // Create a callback so our algorithm can request more reads. 211 // Create a callback so our algorithm can request more reads.
156 base::Closure cb = base::Bind(&AudioRendererImpl::ScheduleRead_Locked, this); 212 base::Closure cb = base::Bind(&AudioRendererImpl::ScheduleRead_Locked, this);
157 213
158 // Construct the algorithm. 214 // Construct the algorithm.
159 algorithm_.reset(new AudioRendererAlgorithm()); 215 algorithm_.reset(new AudioRendererAlgorithm());
160 216
161 // Initialize our algorithm with media properties, initial playback rate, 217 // Initialize our algorithm with media properties, initial playback rate,
162 // and a callback to request more reads from the data source. 218 // and a callback to request more reads from the data source.
163 ChannelLayout channel_layout = decoder_->channel_layout(); 219 ChannelLayout channel_layout = decoder_->channel_layout();
164 int channels = ChannelLayoutToChannelCount(channel_layout); 220 int channels = ChannelLayoutToChannelCount(channel_layout);
165 int bits_per_channel = decoder_->bits_per_channel(); 221 int bits_per_channel = decoder_->bits_per_channel();
166 int sample_rate = decoder_->samples_per_second(); 222 int sample_rate = decoder_->samples_per_second();
167 // TODO(vrk): Add method to AudioDecoder to compute bytes per frame. 223 // TODO(vrk): Add method to AudioDecoder to compute bytes per frame.
168 bytes_per_frame_ = channels * bits_per_channel / 8; 224 bytes_per_frame_ = channels * bits_per_channel / 8;
169 225
170 bool config_ok = algorithm_->ValidateConfig(channels, sample_rate, 226 bool config_ok = algorithm_->ValidateConfig(channels, sample_rate,
171 bits_per_channel); 227 bits_per_channel);
172 if (!config_ok || is_initialized_) { 228 if (!config_ok || is_initialized_) {
173 init_cb.Run(PIPELINE_ERROR_INITIALIZATION_FAILED); 229 init_cb_.Run(PIPELINE_ERROR_INITIALIZATION_FAILED);
acolwell GONE FROM CHROMIUM 2012/10/15 21:00:07 nit: Change to base::ResetAndReturn(&init_cb_)
xhwang 2012/10/15 22:52:23 Done.
174 return; 230 return;
175 } 231 }
176 232
177 if (config_ok) 233 if (config_ok)
178 algorithm_->Initialize(channels, sample_rate, bits_per_channel, 0.0f, cb); 234 algorithm_->Initialize(channels, sample_rate, bits_per_channel, 0.0f, cb);
179 235
180 // We use the AUDIO_PCM_LINEAR flag because AUDIO_PCM_LOW_LATENCY 236 // We use the AUDIO_PCM_LINEAR flag because AUDIO_PCM_LOW_LATENCY
181 // does not currently support all the sample-rates that we require. 237 // does not currently support all the sample-rates that we require.
182 // Please see: http://code.google.com/p/chromium/issues/detail?id=103627 238 // Please see: http://code.google.com/p/chromium/issues/detail?id=103627
183 // for more details. 239 // for more details.
184 audio_parameters_ = AudioParameters( 240 audio_parameters_ = AudioParameters(
185 AudioParameters::AUDIO_PCM_LINEAR, channel_layout, sample_rate, 241 AudioParameters::AUDIO_PCM_LINEAR, channel_layout, sample_rate,
186 bits_per_channel, GetHighLatencyOutputBufferSize(sample_rate)); 242 bits_per_channel, GetHighLatencyOutputBufferSize(sample_rate));
187 243
188 bytes_per_second_ = audio_parameters_.GetBytesPerSecond(); 244 bytes_per_second_ = audio_parameters_.GetBytesPerSecond();
189 245
190 DCHECK(sink_.get()); 246 DCHECK(sink_.get());
191 DCHECK(!is_initialized_); 247 DCHECK(!is_initialized_);
192 248
193 sink_->Initialize(audio_parameters_, this); 249 sink_->Initialize(audio_parameters_, this);
194 250
195 sink_->Start(); 251 sink_->Start();
196 is_initialized_ = true; 252 is_initialized_ = true;
197 253
198 // Finally, execute the start callback. 254 // Finally, execute the start callback.
199 state_ = kPaused; 255 state_ = kPaused;
200 init_cb.Run(PIPELINE_OK); 256 init_cb_.Run(PIPELINE_OK);
acolwell GONE FROM CHROMIUM 2012/10/15 21:00:07 ditto
xhwang 2012/10/15 22:52:23 Done.
201 } 257 }
202 258
203 void AudioRendererImpl::ResumeAfterUnderflow(bool buffer_more_audio) { 259 void AudioRendererImpl::ResumeAfterUnderflow(bool buffer_more_audio) {
204 base::AutoLock auto_lock(lock_); 260 base::AutoLock auto_lock(lock_);
205 if (state_ == kUnderflow) { 261 if (state_ == kUnderflow) {
206 // The "&& preroll_aborted_" is a hack. If preroll is aborted, then we 262 // The "&& preroll_aborted_" is a hack. If preroll is aborted, then we
207 // shouldn't even reach the kUnderflow state to begin with. But for now 263 // shouldn't even reach the kUnderflow state to begin with. But for now
208 // we're just making sure that the audio buffer capacity (i.e. the 264 // we're just making sure that the audio buffer capacity (i.e. the
209 // number of bytes that need to be buffered for preroll to complete) 265 // number of bytes that need to be buffered for preroll to complete)
210 // does not increase due to an aborted preroll. 266 // does not increase due to an aborted preroll.
(...skipping 315 matching lines...) Expand 10 before | Expand all | Expand 10 after
526 case kUnderflow: 582 case kUnderflow:
527 case kRebuffering: 583 case kRebuffering:
528 case kStopped: 584 case kStopped:
529 if (status != PIPELINE_OK) 585 if (status != PIPELINE_OK)
530 error_cb_.Run(status); 586 error_cb_.Run(status);
531 return; 587 return;
532 } 588 }
533 } 589 }
534 590
535 } // namespace media 591 } // namespace media
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698