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

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: nits 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
« no previous file with comments | « media/filters/audio_renderer_impl.h ('k') | media/filters/audio_renderer_impl_unittest.cc » ('j') | 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>
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();
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) {
199 DCHECK(stopped_);
200 return;
201 }
202
203 if (!decoders->empty() && status == DECODER_ERROR_NOT_SUPPORTED) {
204 InitializeNextDecoder(demuxer_stream, decoders.Pass());
205 return;
206 }
207
208 if (status != PIPELINE_OK) {
209 base::ResetAndReturn(&init_cb_).Run(status);
210 return;
211 }
212
155 // Create a callback so our algorithm can request more reads. 213 // Create a callback so our algorithm can request more reads.
156 base::Closure cb = base::Bind(&AudioRendererImpl::ScheduleRead_Locked, this); 214 base::Closure cb = base::Bind(&AudioRendererImpl::ScheduleRead_Locked, this);
157 215
158 // Construct the algorithm. 216 // Construct the algorithm.
159 algorithm_.reset(new AudioRendererAlgorithm()); 217 algorithm_.reset(new AudioRendererAlgorithm());
160 218
161 // Initialize our algorithm with media properties, initial playback rate, 219 // Initialize our algorithm with media properties, initial playback rate,
162 // and a callback to request more reads from the data source. 220 // and a callback to request more reads from the data source.
163 ChannelLayout channel_layout = decoder_->channel_layout(); 221 ChannelLayout channel_layout = decoder_->channel_layout();
164 int channels = ChannelLayoutToChannelCount(channel_layout); 222 int channels = ChannelLayoutToChannelCount(channel_layout);
165 int bits_per_channel = decoder_->bits_per_channel(); 223 int bits_per_channel = decoder_->bits_per_channel();
166 int sample_rate = decoder_->samples_per_second(); 224 int sample_rate = decoder_->samples_per_second();
167 // TODO(vrk): Add method to AudioDecoder to compute bytes per frame. 225 // TODO(vrk): Add method to AudioDecoder to compute bytes per frame.
168 bytes_per_frame_ = channels * bits_per_channel / 8; 226 bytes_per_frame_ = channels * bits_per_channel / 8;
169 227
170 bool config_ok = algorithm_->ValidateConfig(channels, sample_rate, 228 bool config_ok = algorithm_->ValidateConfig(channels, sample_rate,
171 bits_per_channel); 229 bits_per_channel);
172 if (!config_ok || is_initialized_) { 230 if (!config_ok || is_initialized_) {
173 init_cb.Run(PIPELINE_ERROR_INITIALIZATION_FAILED); 231 base::ResetAndReturn(&init_cb_).Run(PIPELINE_ERROR_INITIALIZATION_FAILED);
174 return; 232 return;
175 } 233 }
176 234
177 if (config_ok) 235 if (config_ok)
178 algorithm_->Initialize(channels, sample_rate, bits_per_channel, 0.0f, cb); 236 algorithm_->Initialize(channels, sample_rate, bits_per_channel, 0.0f, cb);
179 237
180 // We use the AUDIO_PCM_LINEAR flag because AUDIO_PCM_LOW_LATENCY 238 // We use the AUDIO_PCM_LINEAR flag because AUDIO_PCM_LOW_LATENCY
181 // does not currently support all the sample-rates that we require. 239 // does not currently support all the sample-rates that we require.
182 // Please see: http://code.google.com/p/chromium/issues/detail?id=103627 240 // Please see: http://code.google.com/p/chromium/issues/detail?id=103627
183 // for more details. 241 // for more details.
184 audio_parameters_ = AudioParameters( 242 audio_parameters_ = AudioParameters(
185 AudioParameters::AUDIO_PCM_LINEAR, channel_layout, sample_rate, 243 AudioParameters::AUDIO_PCM_LINEAR, channel_layout, sample_rate,
186 bits_per_channel, GetHighLatencyOutputBufferSize(sample_rate)); 244 bits_per_channel, GetHighLatencyOutputBufferSize(sample_rate));
187 245
188 bytes_per_second_ = audio_parameters_.GetBytesPerSecond(); 246 bytes_per_second_ = audio_parameters_.GetBytesPerSecond();
189 247
190 DCHECK(sink_.get()); 248 DCHECK(sink_.get());
191 DCHECK(!is_initialized_); 249 DCHECK(!is_initialized_);
192 250
193 sink_->Initialize(audio_parameters_, this); 251 sink_->Initialize(audio_parameters_, this);
194 252
195 sink_->Start(); 253 sink_->Start();
196 is_initialized_ = true; 254 is_initialized_ = true;
197 255
198 // Finally, execute the start callback. 256 // Finally, execute the start callback.
199 state_ = kPaused; 257 state_ = kPaused;
200 init_cb.Run(PIPELINE_OK); 258 base::ResetAndReturn(&init_cb_).Run(PIPELINE_OK);
201 } 259 }
202 260
203 void AudioRendererImpl::ResumeAfterUnderflow(bool buffer_more_audio) { 261 void AudioRendererImpl::ResumeAfterUnderflow(bool buffer_more_audio) {
204 base::AutoLock auto_lock(lock_); 262 base::AutoLock auto_lock(lock_);
205 if (state_ == kUnderflow) { 263 if (state_ == kUnderflow) {
206 // The "&& preroll_aborted_" is a hack. If preroll is aborted, then we 264 // 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 265 // 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 266 // 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) 267 // number of bytes that need to be buffered for preroll to complete)
210 // does not increase due to an aborted preroll. 268 // does not increase due to an aborted preroll.
(...skipping 315 matching lines...) Expand 10 before | Expand all | Expand 10 after
526 case kUnderflow: 584 case kUnderflow:
527 case kRebuffering: 585 case kRebuffering:
528 case kStopped: 586 case kStopped:
529 if (status != PIPELINE_OK) 587 if (status != PIPELINE_OK)
530 error_cb_.Run(status); 588 error_cb_.Run(status);
531 return; 589 return;
532 } 590 }
533 } 591 }
534 592
535 } // namespace media 593 } // namespace media
OLDNEW
« no previous file with comments | « media/filters/audio_renderer_impl.h ('k') | media/filters/audio_renderer_impl_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698