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

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

Issue 141243003: Add AudioBufferStream. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@decoderstream_rebased
Patch Set: add TODOs Created 6 years, 10 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> 9 #include <algorithm>
10 10
(...skipping 26 matching lines...) Expand all
37 } // namespace 37 } // namespace
38 38
39 AudioRendererImpl::AudioRendererImpl( 39 AudioRendererImpl::AudioRendererImpl(
40 const scoped_refptr<base::SingleThreadTaskRunner>& task_runner, 40 const scoped_refptr<base::SingleThreadTaskRunner>& task_runner,
41 media::AudioRendererSink* sink, 41 media::AudioRendererSink* sink,
42 ScopedVector<AudioDecoder> decoders, 42 ScopedVector<AudioDecoder> decoders,
43 const SetDecryptorReadyCB& set_decryptor_ready_cb) 43 const SetDecryptorReadyCB& set_decryptor_ready_cb)
44 : task_runner_(task_runner), 44 : task_runner_(task_runner),
45 weak_factory_(this), 45 weak_factory_(this),
46 sink_(sink), 46 sink_(sink),
47 decoder_selector_(new AudioDecoderSelector( 47 audio_buffer_stream_(task_runner,
48 task_runner, decoders.Pass(), set_decryptor_ready_cb)), 48 decoders.Pass(),
49 set_decryptor_ready_cb),
49 now_cb_(base::Bind(&base::TimeTicks::Now)), 50 now_cb_(base::Bind(&base::TimeTicks::Now)),
50 state_(kUninitialized), 51 state_(kUninitialized),
51 sink_playing_(false), 52 sink_playing_(false),
52 pending_read_(false), 53 pending_read_(false),
53 received_end_of_stream_(false), 54 received_end_of_stream_(false),
54 rendered_end_of_stream_(false), 55 rendered_end_of_stream_(false),
55 audio_time_buffered_(kNoTimestamp()), 56 audio_time_buffered_(kNoTimestamp()),
56 current_time_(kNoTimestamp()), 57 current_time_(kNoTimestamp()),
57 underflow_disabled_(false), 58 underflow_disabled_(false),
58 preroll_aborted_(false) { 59 preroll_aborted_(false) {}
59 }
60 60
61 AudioRendererImpl::~AudioRendererImpl() { 61 AudioRendererImpl::~AudioRendererImpl() {
62 base::AutoLock auto_lock(lock_);
DaleCurtis 2014/02/21 21:48:48 What's this for? To ensure outstanding calls have
rileya (GONE FROM CHROMIUM) 2014/02/21 23:04:02 Yeah, I added this because of VRI doing it, I wasn
xhwang 2014/02/21 23:57:56 Yeah, this shouldn't be necessary unless someone i
rileya (GONE FROM CHROMIUM) 2014/02/24 21:04:11 Alright, removed it. The one in VRI should probabl
62 // Stop() should have been called and |algorithm_| should have been destroyed. 63 // Stop() should have been called and |algorithm_| should have been destroyed.
63 DCHECK(state_ == kUninitialized || state_ == kStopped); 64 DCHECK(state_ == kUninitialized || state_ == kStopped);
64 DCHECK(!algorithm_.get()); 65 DCHECK(!algorithm_.get());
65 } 66 }
66 67
67 void AudioRendererImpl::Play(const base::Closure& callback) { 68 void AudioRendererImpl::Play(const base::Closure& callback) {
68 DCHECK(task_runner_->BelongsToCurrentThread()); 69 DCHECK(task_runner_->BelongsToCurrentThread());
69 70
70 base::AutoLock auto_lock(lock_); 71 base::AutoLock auto_lock(lock_);
71 DCHECK_EQ(state_, kPaused); 72 DCHECK_EQ(state_, kPaused);
(...skipping 66 matching lines...) Expand 10 before | Expand all | Expand 10 after
138 DoFlush_Locked(); 139 DoFlush_Locked();
139 } 140 }
140 141
141 void AudioRendererImpl::DoFlush_Locked() { 142 void AudioRendererImpl::DoFlush_Locked() {
142 DCHECK(task_runner_->BelongsToCurrentThread()); 143 DCHECK(task_runner_->BelongsToCurrentThread());
143 lock_.AssertAcquired(); 144 lock_.AssertAcquired();
144 145
145 DCHECK(!pending_read_); 146 DCHECK(!pending_read_);
146 DCHECK_EQ(state_, kPaused); 147 DCHECK_EQ(state_, kPaused);
147 148
148 if (decrypting_demuxer_stream_) { 149 audio_buffer_stream_.Reset(
149 decrypting_demuxer_stream_->Reset( 150 base::Bind(&AudioRendererImpl::ResetDecoderDone, weak_this_));
150 base::Bind(&AudioRendererImpl::ResetDecoder, weak_this_));
151 return;
152 }
153
154 ResetDecoder();
155 }
156
157 void AudioRendererImpl::ResetDecoder() {
158 DCHECK(task_runner_->BelongsToCurrentThread());
159 decoder_->Reset(base::Bind(&AudioRendererImpl::ResetDecoderDone, weak_this_));
160 } 151 }
161 152
162 void AudioRendererImpl::ResetDecoderDone() { 153 void AudioRendererImpl::ResetDecoderDone() {
163 DCHECK(task_runner_->BelongsToCurrentThread()); 154 DCHECK(task_runner_->BelongsToCurrentThread());
164 { 155 {
165 base::AutoLock auto_lock(lock_); 156 base::AutoLock auto_lock(lock_);
166 if (state_ == kStopped) 157 if (state_ == kStopped)
167 return; 158 return;
168 159
169 DCHECK_EQ(state_, kPaused); 160 DCHECK_EQ(state_, kPaused);
(...skipping 17 matching lines...) Expand all
187 DCHECK(!callback.is_null()); 178 DCHECK(!callback.is_null());
188 DCHECK(stop_cb_.is_null()); 179 DCHECK(stop_cb_.is_null());
189 180
190 stop_cb_ = callback; 181 stop_cb_ = callback;
191 182
192 // TODO(scherkus): Consider invalidating |weak_factory_| and replacing 183 // TODO(scherkus): Consider invalidating |weak_factory_| and replacing
193 // task-running guards that check |state_| with DCHECK(). 184 // task-running guards that check |state_| with DCHECK().
194 185
195 { 186 {
196 base::AutoLock auto_lock(lock_); 187 base::AutoLock auto_lock(lock_);
197 if (state_ == kInitializing) {
198 decoder_selector_->Abort();
199 return;
200 }
201 188
202 if (state_ == kStopped) { 189 if (state_ == kStopped) {
203 task_runner_->PostTask(FROM_HERE, base::ResetAndReturn(&stop_cb_)); 190 task_runner_->PostTask(FROM_HERE, base::ResetAndReturn(&stop_cb_));
204 return; 191 return;
205 } 192 }
206 193
207 ChangeState_Locked(kStopped); 194 ChangeState_Locked(kStopped);
208 algorithm_.reset(); 195 algorithm_.reset();
209 underflow_cb_.Reset(); 196 underflow_cb_.Reset();
210 time_cb_.Reset(); 197 time_cb_.Reset();
211 flush_cb_.Reset(); 198 flush_cb_.Reset();
212 } 199 }
213 200
214 if (sink_) { 201 if (sink_) {
215 sink_->Stop(); 202 sink_->Stop();
216 sink_ = NULL; 203 sink_ = NULL;
217 } 204 }
218 205
219 if (decoder_) { 206 audio_buffer_stream_.Stop(base::ResetAndReturn(&stop_cb_));
220 decoder_->Stop(base::ResetAndReturn(&stop_cb_));
221 return;
222 }
223
224 task_runner_->PostTask(FROM_HERE, base::ResetAndReturn(&stop_cb_));
225 } 207 }
226 208
227 void AudioRendererImpl::Preroll(base::TimeDelta time, 209 void AudioRendererImpl::Preroll(base::TimeDelta time,
228 const PipelineStatusCB& cb) { 210 const PipelineStatusCB& cb) {
229 DCHECK(task_runner_->BelongsToCurrentThread()); 211 DCHECK(task_runner_->BelongsToCurrentThread());
230 212
231 base::AutoLock auto_lock(lock_); 213 base::AutoLock auto_lock(lock_);
232 DCHECK(!sink_playing_); 214 DCHECK(!sink_playing_);
233 DCHECK_EQ(state_, kPaused); 215 DCHECK_EQ(state_, kPaused);
234 DCHECK(!pending_read_) << "Pending read must complete before seeking"; 216 DCHECK(!pending_read_) << "Pending read must complete before seeking";
(...skipping 24 matching lines...) Expand all
259 DCHECK(!ended_cb.is_null()); 241 DCHECK(!ended_cb.is_null());
260 DCHECK(!disabled_cb.is_null()); 242 DCHECK(!disabled_cb.is_null());
261 DCHECK(!error_cb.is_null()); 243 DCHECK(!error_cb.is_null());
262 DCHECK_EQ(kUninitialized, state_); 244 DCHECK_EQ(kUninitialized, state_);
263 DCHECK(sink_); 245 DCHECK(sink_);
264 246
265 state_ = kInitializing; 247 state_ = kInitializing;
266 248
267 weak_this_ = weak_factory_.GetWeakPtr(); 249 weak_this_ = weak_factory_.GetWeakPtr();
268 init_cb_ = init_cb; 250 init_cb_ = init_cb;
269 statistics_cb_ = statistics_cb;
270 underflow_cb_ = underflow_cb; 251 underflow_cb_ = underflow_cb;
271 time_cb_ = time_cb; 252 time_cb_ = time_cb;
272 ended_cb_ = ended_cb; 253 ended_cb_ = ended_cb;
273 disabled_cb_ = disabled_cb; 254 disabled_cb_ = disabled_cb;
274 error_cb_ = error_cb; 255 error_cb_ = error_cb;
275 256
276 decoder_selector_->SelectDecoder( 257 audio_buffer_stream_.Initialize(
277 stream, 258 stream,
278 statistics_cb, 259 statistics_cb,
279 base::Bind(&AudioRendererImpl::OnDecoderSelected, weak_this_)); 260 base::Bind(&AudioRendererImpl::OnAudioBufferStreamInitialized,
261 weak_this_));
280 } 262 }
281 263
282 void AudioRendererImpl::OnDecoderSelected( 264 void AudioRendererImpl::OnAudioBufferStreamInitialized(bool success) {
283 scoped_ptr<AudioDecoder> decoder,
284 scoped_ptr<DecryptingDemuxerStream> decrypting_demuxer_stream) {
285 DCHECK(task_runner_->BelongsToCurrentThread()); 265 DCHECK(task_runner_->BelongsToCurrentThread());
286 266
287 scoped_ptr<AudioDecoderSelector> deleter(decoder_selector_.Pass());
288 267
289 if (!decoder) { 268 base::AutoLock auto_lock(lock_);
290 { 269
291 base::AutoLock auto_lock(lock_); 270 if (!success) {
292 ChangeState_Locked(kUninitialized); 271 state_ = kUninitialized;
293 } 272 base::ResetAndReturn(&init_cb_).Run(DECODER_ERROR_NOT_SUPPORTED);
294 // Stop() called during initialization.
295 if (!stop_cb_.is_null()) {
296 base::ResetAndReturn(&init_cb_).Run(PIPELINE_ERROR_ABORT);
297 Stop(base::ResetAndReturn(&stop_cb_));
298 } else {
299 base::ResetAndReturn(&init_cb_).Run(DECODER_ERROR_NOT_SUPPORTED);
300 }
301 return; 273 return;
302 } 274 }
303 275
304 base::AutoLock auto_lock(lock_); 276 int sample_rate = audio_buffer_stream_.decoder()->samples_per_second();
305 decoder_ = decoder.Pass();
306 decrypting_demuxer_stream_ = decrypting_demuxer_stream.Pass();
307
308 int sample_rate = decoder_->samples_per_second();
309 277
310 // The actual buffer size is controlled via the size of the AudioBus 278 // The actual buffer size is controlled via the size of the AudioBus
311 // provided to Render(), so just choose something reasonable here for looks. 279 // provided to Render(), so just choose something reasonable here for looks.
312 int buffer_size = decoder_->samples_per_second() / 100; 280 int buffer_size = audio_buffer_stream_.decoder()->samples_per_second() / 100;
313 audio_parameters_ = AudioParameters( 281
314 AudioParameters::AUDIO_PCM_LOW_LATENCY, decoder_->channel_layout(), 282 // TODO(rileya): Remove the channel_layout/bits_per_channel/samples_per_second
315 sample_rate, decoder_->bits_per_channel(), buffer_size); 283 // getters from AudioDecoder, and adjust this accordingly.
rileya (GONE FROM CHROMIUM) 2014/02/19 22:37:51 This will require some plumbing that's beyond the
DaleCurtis 2014/02/21 21:48:48 My plan was for ARI and ARA to be agnostic to conf
284 audio_parameters_ =
285 AudioParameters(AudioParameters::AUDIO_PCM_LOW_LATENCY,
286 audio_buffer_stream_.decoder()->channel_layout(),
287 sample_rate,
288 audio_buffer_stream_.decoder()->bits_per_channel(),
289 buffer_size);
316 if (!audio_parameters_.IsValid()) { 290 if (!audio_parameters_.IsValid()) {
317 ChangeState_Locked(kUninitialized); 291 ChangeState_Locked(kUninitialized);
318 base::ResetAndReturn(&init_cb_).Run(PIPELINE_ERROR_INITIALIZATION_FAILED); 292 base::ResetAndReturn(&init_cb_).Run(PIPELINE_ERROR_INITIALIZATION_FAILED);
319 return; 293 return;
320 } 294 }
321 295
322 splicer_.reset(new AudioSplicer(sample_rate)); 296 splicer_.reset(new AudioSplicer(sample_rate));
323 297
324 // We're all good! Continue initializing the rest of the audio renderer 298 // We're all good! Continue initializing the rest of the audio renderer
325 // based on the decoder format. 299 // based on the decoder format.
(...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after
361 } 335 }
362 } 336 }
363 337
364 void AudioRendererImpl::SetVolume(float volume) { 338 void AudioRendererImpl::SetVolume(float volume) {
365 DCHECK(task_runner_->BelongsToCurrentThread()); 339 DCHECK(task_runner_->BelongsToCurrentThread());
366 DCHECK(sink_); 340 DCHECK(sink_);
367 sink_->SetVolume(volume); 341 sink_->SetVolume(volume);
368 } 342 }
369 343
370 void AudioRendererImpl::DecodedAudioReady( 344 void AudioRendererImpl::DecodedAudioReady(
371 AudioDecoder::Status status, 345 AudioBufferStream::Status status,
372 const scoped_refptr<AudioBuffer>& buffer) { 346 const scoped_refptr<AudioBuffer>& buffer) {
373 DVLOG(1) << __FUNCTION__ << "(" << status << ")"; 347 DVLOG(1) << __FUNCTION__ << "(" << status << ")";
374 DCHECK(task_runner_->BelongsToCurrentThread()); 348 DCHECK(task_runner_->BelongsToCurrentThread());
375 349
376 base::AutoLock auto_lock(lock_); 350 base::AutoLock auto_lock(lock_);
377 DCHECK(state_ != kUninitialized); 351 DCHECK(state_ != kUninitialized);
378 352
379 CHECK(pending_read_); 353 CHECK(pending_read_);
380 pending_read_ = false; 354 pending_read_ = false;
381 355
382 if (status == AudioDecoder::kAborted) { 356 if (status == AudioBufferStream::ABORTED ||
357 status == AudioBufferStream::DEMUXER_READ_ABORTED) {
383 HandleAbortedReadOrDecodeError(false); 358 HandleAbortedReadOrDecodeError(false);
384 return; 359 return;
385 } 360 }
386 361
387 if (status == AudioDecoder::kDecodeError) { 362 if (status == AudioBufferStream::DECODE_ERROR) {
388 HandleAbortedReadOrDecodeError(true); 363 HandleAbortedReadOrDecodeError(true);
389 return; 364 return;
390 } 365 }
391 366
392 DCHECK_EQ(status, AudioDecoder::kOk); 367 DCHECK_EQ(status, AudioBufferStream::OK);
393 DCHECK(buffer.get()); 368 DCHECK(buffer.get());
394 369
395 if (state_ == kFlushing) { 370 if (state_ == kFlushing) {
396 ChangeState_Locked(kPaused); 371 ChangeState_Locked(kPaused);
397 DoFlush_Locked(); 372 DoFlush_Locked();
398 return; 373 return;
399 } 374 }
400 375
401 if (!splicer_->AddInput(buffer)) { 376 if (!splicer_->AddInput(buffer)) {
402 HandleAbortedReadOrDecodeError(true); 377 HandleAbortedReadOrDecodeError(true);
(...skipping 86 matching lines...) Expand 10 before | Expand all | Expand 10 after
489 } 464 }
490 465
491 void AudioRendererImpl::AttemptRead_Locked() { 466 void AudioRendererImpl::AttemptRead_Locked() {
492 DCHECK(task_runner_->BelongsToCurrentThread()); 467 DCHECK(task_runner_->BelongsToCurrentThread());
493 lock_.AssertAcquired(); 468 lock_.AssertAcquired();
494 469
495 if (!CanRead_Locked()) 470 if (!CanRead_Locked())
496 return; 471 return;
497 472
498 pending_read_ = true; 473 pending_read_ = true;
499 decoder_->Read(base::Bind(&AudioRendererImpl::DecodedAudioReady, weak_this_)); 474 audio_buffer_stream_.Read(
475 base::Bind(&AudioRendererImpl::DecodedAudioReady, weak_this_));
500 } 476 }
501 477
502 bool AudioRendererImpl::CanRead_Locked() { 478 bool AudioRendererImpl::CanRead_Locked() {
503 lock_.AssertAcquired(); 479 lock_.AssertAcquired();
504 480
505 switch (state_) { 481 switch (state_) {
506 case kUninitialized: 482 case kUninitialized:
507 case kInitializing: 483 case kInitializing:
508 case kPaused: 484 case kPaused:
509 case kFlushing: 485 case kFlushing:
(...skipping 218 matching lines...) Expand 10 before | Expand all | Expand 10 after
728 } 704 }
729 } 705 }
730 706
731 void AudioRendererImpl::ChangeState_Locked(State new_state) { 707 void AudioRendererImpl::ChangeState_Locked(State new_state) {
732 DVLOG(1) << __FUNCTION__ << " : " << state_ << " -> " << new_state; 708 DVLOG(1) << __FUNCTION__ << " : " << state_ << " -> " << new_state;
733 lock_.AssertAcquired(); 709 lock_.AssertAcquired();
734 state_ = new_state; 710 state_ = new_state;
735 } 711 }
736 712
737 } // namespace media 713 } // namespace media
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698