Chromium Code Reviews| OLD | NEW |
|---|---|
| 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 Loading... | |
| 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 Loading... | |
| 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 Loading... | |
| 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 Loading... | |
| 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 Loading... | |
| 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 Loading... | |
| 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 Loading... | |
| 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 |
| OLD | NEW |