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

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: resolve acolwell's comments 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 <algorithm>
10
9 #include "base/bind.h" 11 #include "base/bind.h"
10 #include "base/callback.h" 12 #include "base/callback.h"
11 #include "base/callback_helpers.h" 13 #include "base/callback_helpers.h"
12 #include "base/logging.h" 14 #include "base/logging.h"
13 #include "media/audio/audio_util.h" 15 #include "media/audio/audio_util.h"
16 #include "media/base/demuxer_stream.h"
14 17
15 namespace media { 18 namespace media {
16 19
17 AudioRendererImpl::AudioRendererImpl(media::AudioRendererSink* sink) 20 AudioRendererImpl::AudioRendererImpl(media::AudioRendererSink* sink)
18 : state_(kUninitialized), 21 : state_(kUninitialized),
19 pending_read_(false), 22 pending_read_(false),
20 received_end_of_stream_(false), 23 received_end_of_stream_(false),
21 rendered_end_of_stream_(false), 24 rendered_end_of_stream_(false),
22 audio_time_buffered_(kNoTimestamp()), 25 audio_time_buffered_(kNoTimestamp()),
23 current_time_(kNoTimestamp()), 26 current_time_(kNoTimestamp()),
(...skipping 52 matching lines...) Expand 10 before | Expand all | Expand 10 after
76 void AudioRendererImpl::DoPause() { 79 void AudioRendererImpl::DoPause() {
77 DCHECK(sink_.get()); 80 DCHECK(sink_.get());
78 sink_->Pause(false); 81 sink_->Pause(false);
79 } 82 }
80 83
81 void AudioRendererImpl::Flush(const base::Closure& callback) { 84 void AudioRendererImpl::Flush(const base::Closure& callback) {
82 decoder_->Reset(callback); 85 decoder_->Reset(callback);
83 } 86 }
84 87
85 void AudioRendererImpl::Stop(const base::Closure& callback) { 88 void AudioRendererImpl::Stop(const base::Closure& callback) {
89 DCHECK(!callback.is_null());
90
86 if (!stopped_) { 91 if (!stopped_) {
87 DCHECK(sink_.get()); 92 DCHECK(sink_.get());
88 sink_->Stop(); 93 sink_->Stop();
89 94
90 stopped_ = true; 95 stopped_ = true;
91 } 96 }
92 { 97 {
93 base::AutoLock auto_lock(lock_); 98 base::AutoLock auto_lock(lock_);
94 state_ = kStopped; 99 state_ = kStopped;
95 algorithm_.reset(NULL); 100 algorithm_.reset(NULL);
101 init_cb_.Reset();
102 underflow_cb_.Reset();
96 time_cb_.Reset(); 103 time_cb_.Reset();
97 underflow_cb_.Reset();
98 } 104 }
99 if (!callback.is_null()) { 105
100 callback.Run(); 106 callback.Run();
xhwang 2012/10/15 22:52:23 I found AudioDecoder doesn't have a Stop() method.
acolwell GONE FROM CHROMIUM 2012/10/16 16:23:38 I was a little surprised to see that the decode in
101 }
102 } 107 }
103 108
104 void AudioRendererImpl::Preroll(base::TimeDelta time, 109 void AudioRendererImpl::Preroll(base::TimeDelta time,
105 const PipelineStatusCB& cb) { 110 const PipelineStatusCB& cb) {
106 base::AutoLock auto_lock(lock_); 111 base::AutoLock auto_lock(lock_);
107 DCHECK_EQ(kPaused, state_); 112 DCHECK_EQ(kPaused, state_);
108 DCHECK(!pending_read_) << "Pending read must complete before seeking"; 113 DCHECK(!pending_read_) << "Pending read must complete before seeking";
109 DCHECK(pause_cb_.is_null()); 114 DCHECK(pause_cb_.is_null());
110 DCHECK(preroll_cb_.is_null()); 115 DCHECK(preroll_cb_.is_null());
111 state_ = kPrerolling; 116 state_ = kPrerolling;
(...skipping 11 matching lines...) Expand all
123 algorithm_->FlushBuffers(); 128 algorithm_->FlushBuffers();
124 129
125 if (stopped_) 130 if (stopped_)
126 return; 131 return;
127 132
128 // Pause and flush the stream when we preroll to a new location. 133 // Pause and flush the stream when we preroll to a new location.
129 earliest_end_time_ = base::Time::Now(); 134 earliest_end_time_ = base::Time::Now();
130 sink_->Pause(true); 135 sink_->Pause(true);
131 } 136 }
132 137
133 void AudioRendererImpl::Initialize(const scoped_refptr<AudioDecoder>& decoder, 138 void AudioRendererImpl::Initialize(const scoped_refptr<DemuxerStream>& stream,
139 const AudioDecoderList& decoders,
134 const PipelineStatusCB& init_cb, 140 const PipelineStatusCB& init_cb,
141 const StatisticsCB& statistics_cb,
135 const base::Closure& underflow_cb, 142 const base::Closure& underflow_cb,
136 const TimeCB& time_cb, 143 const TimeCB& time_cb,
137 const base::Closure& ended_cb, 144 const base::Closure& ended_cb,
138 const base::Closure& disabled_cb, 145 const base::Closure& disabled_cb,
139 const PipelineStatusCB& error_cb) { 146 const PipelineStatusCB& error_cb) {
140 DCHECK(decoder); 147 base::AutoLock auto_lock(lock_);
148 DCHECK(stream);
149 DCHECK(!decoders.empty());
150 DCHECK_EQ(stream->type(), DemuxerStream::AUDIO);
141 DCHECK(!init_cb.is_null()); 151 DCHECK(!init_cb.is_null());
142 DCHECK(!underflow_cb.is_null()); 152 DCHECK(!underflow_cb.is_null());
143 DCHECK(!time_cb.is_null()); 153 DCHECK(!time_cb.is_null());
144 DCHECK(!ended_cb.is_null()); 154 DCHECK(!ended_cb.is_null());
145 DCHECK(!disabled_cb.is_null()); 155 DCHECK(!disabled_cb.is_null());
146 DCHECK(!error_cb.is_null()); 156 DCHECK(!error_cb.is_null());
147 DCHECK_EQ(kUninitialized, state_); 157 DCHECK_EQ(kUninitialized, state_);
148 decoder_ = decoder; 158
159 init_cb_ = init_cb;
160 statistics_cb_ = statistics_cb;
149 underflow_cb_ = underflow_cb; 161 underflow_cb_ = underflow_cb;
150 time_cb_ = time_cb; 162 time_cb_ = time_cb;
151 ended_cb_ = ended_cb; 163 ended_cb_ = ended_cb;
152 disabled_cb_ = disabled_cb; 164 disabled_cb_ = disabled_cb;
153 error_cb_ = error_cb; 165 error_cb_ = error_cb;
154 166
167 scoped_ptr<AudioDecoderList> decoder_list(new AudioDecoderList(decoders));
168 InitializeNextDecoder(stream, decoder_list.Pass());
169 }
170
171 void AudioRendererImpl::InitializeNextDecoder(
172 const scoped_refptr<DemuxerStream>& demuxer_stream,
173 scoped_ptr<AudioDecoderList> decoders) {
174 lock_.AssertAcquired();
175 DCHECK(!decoders->empty());
176
177 scoped_refptr<AudioDecoder> decoder = decoders->front();
178 decoders->pop_front();
179
180 DCHECK(decoder);
181 decoder_ = decoder;
182
183 base::AutoUnlock auto_unlock(lock_);
184 decoder->Initialize(
185 demuxer_stream,
186 base::Bind(&AudioRendererImpl::OnDecoderInitDone, this,
187 demuxer_stream,
188 base::Passed(&decoders)),
189 statistics_cb_);
190 }
191
192 void AudioRendererImpl::OnDecoderInitDone(
193 const scoped_refptr<DemuxerStream>& demuxer_stream,
194 scoped_ptr<AudioDecoderList> decoders,
195 PipelineStatus status) {
196 base::AutoLock auto_lock(lock_);
197
198 if (state_ == kStopped)
scherkus (not reviewing) 2012/10/18 00:30:28 also check stopped_?
xhwang 2012/10/18 01:35:02 Done.
199 return;
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 base::ResetAndReturn(&init_cb_).Run(PIPELINE_ERROR_INITIALIZATION_FAILED);
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 base::ResetAndReturn(&init_cb_).Run(PIPELINE_OK);
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