| 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 27 matching lines...) Expand all Loading... |
| 38 } // namespace | 38 } // namespace |
| 39 | 39 |
| 40 AudioRendererImpl::AudioRendererImpl( | 40 AudioRendererImpl::AudioRendererImpl( |
| 41 const scoped_refptr<base::SingleThreadTaskRunner>& task_runner, | 41 const scoped_refptr<base::SingleThreadTaskRunner>& task_runner, |
| 42 media::AudioRendererSink* sink, | 42 media::AudioRendererSink* sink, |
| 43 ScopedVector<AudioDecoder> decoders, | 43 ScopedVector<AudioDecoder> decoders, |
| 44 const SetDecryptorReadyCB& set_decryptor_ready_cb) | 44 const SetDecryptorReadyCB& set_decryptor_ready_cb) |
| 45 : task_runner_(task_runner), | 45 : task_runner_(task_runner), |
| 46 weak_factory_(this), | 46 weak_factory_(this), |
| 47 sink_(sink), | 47 sink_(sink), |
| 48 decoder_selector_(new AudioDecoderSelector( | 48 audio_buffer_stream_(task_runner, |
| 49 task_runner, decoders.Pass(), set_decryptor_ready_cb)), | 49 decoders.Pass(), |
| 50 set_decryptor_ready_cb), |
| 50 now_cb_(base::Bind(&base::TimeTicks::Now)), | 51 now_cb_(base::Bind(&base::TimeTicks::Now)), |
| 51 state_(kUninitialized), | 52 state_(kUninitialized), |
| 52 sink_playing_(false), | 53 sink_playing_(false), |
| 53 pending_read_(false), | 54 pending_read_(false), |
| 54 received_end_of_stream_(false), | 55 received_end_of_stream_(false), |
| 55 rendered_end_of_stream_(false), | 56 rendered_end_of_stream_(false), |
| 56 audio_time_buffered_(kNoTimestamp()), | 57 audio_time_buffered_(kNoTimestamp()), |
| 57 current_time_(kNoTimestamp()), | 58 current_time_(kNoTimestamp()), |
| 58 underflow_disabled_(false), | 59 underflow_disabled_(false), |
| 59 preroll_aborted_(false) { | 60 preroll_aborted_(false) {} |
| 60 } | |
| 61 | 61 |
| 62 AudioRendererImpl::~AudioRendererImpl() { | 62 AudioRendererImpl::~AudioRendererImpl() { |
| 63 // Stop() should have been called and |algorithm_| should have been destroyed. | 63 // Stop() should have been called and |algorithm_| should have been destroyed. |
| 64 DCHECK(state_ == kUninitialized || state_ == kStopped); | 64 DCHECK(state_ == kUninitialized || state_ == kStopped); |
| 65 DCHECK(!algorithm_.get()); | 65 DCHECK(!algorithm_.get()); |
| 66 } | 66 } |
| 67 | 67 |
| 68 void AudioRendererImpl::Play(const base::Closure& callback) { | 68 void AudioRendererImpl::Play(const base::Closure& callback) { |
| 69 DCHECK(task_runner_->BelongsToCurrentThread()); | 69 DCHECK(task_runner_->BelongsToCurrentThread()); |
| 70 | 70 |
| (...skipping 68 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 139 DoFlush_Locked(); | 139 DoFlush_Locked(); |
| 140 } | 140 } |
| 141 | 141 |
| 142 void AudioRendererImpl::DoFlush_Locked() { | 142 void AudioRendererImpl::DoFlush_Locked() { |
| 143 DCHECK(task_runner_->BelongsToCurrentThread()); | 143 DCHECK(task_runner_->BelongsToCurrentThread()); |
| 144 lock_.AssertAcquired(); | 144 lock_.AssertAcquired(); |
| 145 | 145 |
| 146 DCHECK(!pending_read_); | 146 DCHECK(!pending_read_); |
| 147 DCHECK_EQ(state_, kPaused); | 147 DCHECK_EQ(state_, kPaused); |
| 148 | 148 |
| 149 if (decrypting_demuxer_stream_) { | 149 audio_buffer_stream_.Reset( |
| 150 decrypting_demuxer_stream_->Reset( | 150 base::Bind(&AudioRendererImpl::ResetDecoderDone, weak_this_)); |
| 151 base::Bind(&AudioRendererImpl::ResetDecoder, weak_this_)); | |
| 152 return; | |
| 153 } | |
| 154 | |
| 155 ResetDecoder(); | |
| 156 } | |
| 157 | |
| 158 void AudioRendererImpl::ResetDecoder() { | |
| 159 DCHECK(task_runner_->BelongsToCurrentThread()); | |
| 160 decoder_->Reset(base::Bind(&AudioRendererImpl::ResetDecoderDone, weak_this_)); | |
| 161 } | 151 } |
| 162 | 152 |
| 163 void AudioRendererImpl::ResetDecoderDone() { | 153 void AudioRendererImpl::ResetDecoderDone() { |
| 164 DCHECK(task_runner_->BelongsToCurrentThread()); | 154 DCHECK(task_runner_->BelongsToCurrentThread()); |
| 165 { | 155 { |
| 166 base::AutoLock auto_lock(lock_); | 156 base::AutoLock auto_lock(lock_); |
| 167 if (state_ == kStopped) | 157 if (state_ == kStopped) |
| 168 return; | 158 return; |
| 169 | 159 |
| 170 DCHECK_EQ(state_, kPaused); | 160 DCHECK_EQ(state_, kPaused); |
| 171 DCHECK(!flush_cb_.is_null()); | 161 DCHECK(!flush_cb_.is_null()); |
| 172 | 162 |
| 173 audio_time_buffered_ = kNoTimestamp(); | 163 audio_time_buffered_ = kNoTimestamp(); |
| 174 current_time_ = kNoTimestamp(); | 164 current_time_ = kNoTimestamp(); |
| 175 received_end_of_stream_ = false; | 165 received_end_of_stream_ = false; |
| 176 rendered_end_of_stream_ = false; | 166 rendered_end_of_stream_ = false; |
| 177 preroll_aborted_ = false; | 167 preroll_aborted_ = false; |
| 178 | 168 |
| 179 earliest_end_time_ = now_cb_.Run(); | 169 earliest_end_time_ = now_cb_.Run(); |
| 180 splicer_->Reset(); | 170 splicer_->Reset(); |
| 181 algorithm_->FlushBuffers(); | 171 algorithm_->FlushBuffers(); |
| 182 } | 172 } |
| 183 base::ResetAndReturn(&flush_cb_).Run(); | 173 base::ResetAndReturn(&flush_cb_).Run(); |
| 184 } | 174 } |
| 185 | 175 |
| 186 void AudioRendererImpl::Stop(const base::Closure& callback) { | 176 void AudioRendererImpl::Stop(const base::Closure& callback) { |
| 187 DCHECK(task_runner_->BelongsToCurrentThread()); | 177 DCHECK(task_runner_->BelongsToCurrentThread()); |
| 188 DCHECK(!callback.is_null()); | 178 DCHECK(!callback.is_null()); |
| 189 DCHECK(stop_cb_.is_null()); | |
| 190 | |
| 191 stop_cb_ = callback; | |
| 192 | 179 |
| 193 // TODO(scherkus): Consider invalidating |weak_factory_| and replacing | 180 // TODO(scherkus): Consider invalidating |weak_factory_| and replacing |
| 194 // task-running guards that check |state_| with DCHECK(). | 181 // task-running guards that check |state_| with DCHECK(). |
| 195 | 182 |
| 196 { | 183 { |
| 197 base::AutoLock auto_lock(lock_); | 184 base::AutoLock auto_lock(lock_); |
| 198 if (state_ == kInitializing) { | 185 |
| 199 decoder_selector_->Abort(); | 186 if (state_ == kStopped) { |
| 187 task_runner_->PostTask(FROM_HERE, callback); |
| 200 return; | 188 return; |
| 201 } | 189 } |
| 202 | 190 |
| 203 if (state_ == kStopped) { | |
| 204 task_runner_->PostTask(FROM_HERE, base::ResetAndReturn(&stop_cb_)); | |
| 205 return; | |
| 206 } | |
| 207 | |
| 208 ChangeState_Locked(kStopped); | 191 ChangeState_Locked(kStopped); |
| 209 algorithm_.reset(); | 192 algorithm_.reset(); |
| 210 underflow_cb_.Reset(); | 193 underflow_cb_.Reset(); |
| 211 time_cb_.Reset(); | 194 time_cb_.Reset(); |
| 212 flush_cb_.Reset(); | 195 flush_cb_.Reset(); |
| 213 } | 196 } |
| 214 | 197 |
| 215 if (sink_) { | 198 if (sink_) { |
| 216 sink_->Stop(); | 199 sink_->Stop(); |
| 217 sink_ = NULL; | 200 sink_ = NULL; |
| 218 } | 201 } |
| 219 | 202 |
| 220 if (decrypting_demuxer_stream_) { | 203 audio_buffer_stream_.Stop(callback); |
| 221 decrypting_demuxer_stream_->Stop( | |
| 222 base::Bind(&AudioRendererImpl::StopDecoder, weak_this_)); | |
| 223 return; | |
| 224 } | |
| 225 | |
| 226 StopDecoder(); | |
| 227 } | |
| 228 | |
| 229 void AudioRendererImpl::StopDecoder() { | |
| 230 DCHECK(task_runner_->BelongsToCurrentThread()); | |
| 231 DCHECK(!stop_cb_.is_null()); | |
| 232 | |
| 233 if (decoder_) { | |
| 234 decoder_->Stop(base::ResetAndReturn(&stop_cb_)); | |
| 235 return; | |
| 236 } | |
| 237 | |
| 238 task_runner_->PostTask(FROM_HERE, base::ResetAndReturn(&stop_cb_)); | |
| 239 } | 204 } |
| 240 | 205 |
| 241 void AudioRendererImpl::Preroll(base::TimeDelta time, | 206 void AudioRendererImpl::Preroll(base::TimeDelta time, |
| 242 const PipelineStatusCB& cb) { | 207 const PipelineStatusCB& cb) { |
| 243 DCHECK(task_runner_->BelongsToCurrentThread()); | 208 DCHECK(task_runner_->BelongsToCurrentThread()); |
| 244 | 209 |
| 245 base::AutoLock auto_lock(lock_); | 210 base::AutoLock auto_lock(lock_); |
| 246 DCHECK(!sink_playing_); | 211 DCHECK(!sink_playing_); |
| 247 DCHECK_EQ(state_, kPaused); | 212 DCHECK_EQ(state_, kPaused); |
| 248 DCHECK(!pending_read_) << "Pending read must complete before seeking"; | 213 DCHECK(!pending_read_) << "Pending read must complete before seeking"; |
| (...skipping 24 matching lines...) Expand all Loading... |
| 273 DCHECK(!ended_cb.is_null()); | 238 DCHECK(!ended_cb.is_null()); |
| 274 DCHECK(!disabled_cb.is_null()); | 239 DCHECK(!disabled_cb.is_null()); |
| 275 DCHECK(!error_cb.is_null()); | 240 DCHECK(!error_cb.is_null()); |
| 276 DCHECK_EQ(kUninitialized, state_); | 241 DCHECK_EQ(kUninitialized, state_); |
| 277 DCHECK(sink_); | 242 DCHECK(sink_); |
| 278 | 243 |
| 279 state_ = kInitializing; | 244 state_ = kInitializing; |
| 280 | 245 |
| 281 weak_this_ = weak_factory_.GetWeakPtr(); | 246 weak_this_ = weak_factory_.GetWeakPtr(); |
| 282 init_cb_ = init_cb; | 247 init_cb_ = init_cb; |
| 283 statistics_cb_ = statistics_cb; | |
| 284 underflow_cb_ = underflow_cb; | 248 underflow_cb_ = underflow_cb; |
| 285 time_cb_ = time_cb; | 249 time_cb_ = time_cb; |
| 286 ended_cb_ = ended_cb; | 250 ended_cb_ = ended_cb; |
| 287 disabled_cb_ = disabled_cb; | 251 disabled_cb_ = disabled_cb; |
| 288 error_cb_ = error_cb; | 252 error_cb_ = error_cb; |
| 289 | 253 |
| 290 decoder_selector_->SelectDecoder( | 254 audio_buffer_stream_.Initialize( |
| 291 stream, | 255 stream, |
| 292 statistics_cb, | 256 statistics_cb, |
| 293 base::Bind(&AudioRendererImpl::OnDecoderSelected, weak_this_)); | 257 base::Bind(&AudioRendererImpl::OnAudioBufferStreamInitialized, |
| 258 weak_this_)); |
| 294 } | 259 } |
| 295 | 260 |
| 296 void AudioRendererImpl::OnDecoderSelected( | 261 void AudioRendererImpl::OnAudioBufferStreamInitialized(bool success) { |
| 297 scoped_ptr<AudioDecoder> decoder, | |
| 298 scoped_ptr<DecryptingDemuxerStream> decrypting_demuxer_stream) { | |
| 299 DCHECK(task_runner_->BelongsToCurrentThread()); | 262 DCHECK(task_runner_->BelongsToCurrentThread()); |
| 300 | 263 |
| 301 scoped_ptr<AudioDecoderSelector> deleter(decoder_selector_.Pass()); | 264 base::AutoLock auto_lock(lock_); |
| 302 decoder_ = decoder.Pass(); | |
| 303 | 265 |
| 304 if (!decoder_ || !stop_cb_.is_null()) { | 266 if (state_ == kStopped) { |
| 305 { | 267 base::ResetAndReturn(&init_cb_).Run(PIPELINE_ERROR_ABORT); |
| 306 base::AutoLock auto_lock(lock_); | |
| 307 ChangeState_Locked(kUninitialized); | |
| 308 } | |
| 309 // Stop() called during initialization. | |
| 310 if (!stop_cb_.is_null()) { | |
| 311 base::ResetAndReturn(&init_cb_).Run(PIPELINE_ERROR_ABORT); | |
| 312 Stop(base::ResetAndReturn(&stop_cb_)); | |
| 313 } else { | |
| 314 base::ResetAndReturn(&init_cb_).Run(DECODER_ERROR_NOT_SUPPORTED); | |
| 315 } | |
| 316 return; | 268 return; |
| 317 } | 269 } |
| 318 | 270 |
| 319 base::AutoLock auto_lock(lock_); | 271 if (!success) { |
| 320 decrypting_demuxer_stream_ = decrypting_demuxer_stream.Pass(); | 272 state_ = kUninitialized; |
| 273 base::ResetAndReturn(&init_cb_).Run(DECODER_ERROR_NOT_SUPPORTED); |
| 274 return; |
| 275 } |
| 321 | 276 |
| 322 int sample_rate = decoder_->samples_per_second(); | 277 int sample_rate = audio_buffer_stream_.decoder()->samples_per_second(); |
| 323 | 278 |
| 324 // The actual buffer size is controlled via the size of the AudioBus | 279 // The actual buffer size is controlled via the size of the AudioBus |
| 325 // provided to Render(), so just choose something reasonable here for looks. | 280 // provided to Render(), so just choose something reasonable here for looks. |
| 326 int buffer_size = decoder_->samples_per_second() / 100; | 281 int buffer_size = audio_buffer_stream_.decoder()->samples_per_second() / 100; |
| 327 audio_parameters_ = AudioParameters( | 282 |
| 328 AudioParameters::AUDIO_PCM_LOW_LATENCY, decoder_->channel_layout(), | 283 // TODO(rileya): Remove the channel_layout/bits_per_channel/samples_per_second |
| 329 sample_rate, decoder_->bits_per_channel(), buffer_size); | 284 // getters from AudioDecoder, and adjust this accordingly. |
| 285 audio_parameters_ = |
| 286 AudioParameters(AudioParameters::AUDIO_PCM_LOW_LATENCY, |
| 287 audio_buffer_stream_.decoder()->channel_layout(), |
| 288 sample_rate, |
| 289 audio_buffer_stream_.decoder()->bits_per_channel(), |
| 290 buffer_size); |
| 330 if (!audio_parameters_.IsValid()) { | 291 if (!audio_parameters_.IsValid()) { |
| 331 ChangeState_Locked(kUninitialized); | 292 ChangeState_Locked(kUninitialized); |
| 332 base::ResetAndReturn(&init_cb_).Run(PIPELINE_ERROR_INITIALIZATION_FAILED); | 293 base::ResetAndReturn(&init_cb_).Run(PIPELINE_ERROR_INITIALIZATION_FAILED); |
| 333 return; | 294 return; |
| 334 } | 295 } |
| 335 | 296 |
| 336 splicer_.reset(new AudioSplicer(sample_rate)); | 297 splicer_.reset(new AudioSplicer(sample_rate)); |
| 337 | 298 |
| 338 // We're all good! Continue initializing the rest of the audio renderer | 299 // We're all good! Continue initializing the rest of the audio renderer |
| 339 // based on the decoder format. | 300 // based on the decoder format. |
| (...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 375 } | 336 } |
| 376 } | 337 } |
| 377 | 338 |
| 378 void AudioRendererImpl::SetVolume(float volume) { | 339 void AudioRendererImpl::SetVolume(float volume) { |
| 379 DCHECK(task_runner_->BelongsToCurrentThread()); | 340 DCHECK(task_runner_->BelongsToCurrentThread()); |
| 380 DCHECK(sink_); | 341 DCHECK(sink_); |
| 381 sink_->SetVolume(volume); | 342 sink_->SetVolume(volume); |
| 382 } | 343 } |
| 383 | 344 |
| 384 void AudioRendererImpl::DecodedAudioReady( | 345 void AudioRendererImpl::DecodedAudioReady( |
| 385 AudioDecoder::Status status, | 346 AudioBufferStream::Status status, |
| 386 const scoped_refptr<AudioBuffer>& buffer) { | 347 const scoped_refptr<AudioBuffer>& buffer) { |
| 387 DVLOG(1) << __FUNCTION__ << "(" << status << ")"; | 348 DVLOG(1) << __FUNCTION__ << "(" << status << ")"; |
| 388 DCHECK(task_runner_->BelongsToCurrentThread()); | 349 DCHECK(task_runner_->BelongsToCurrentThread()); |
| 389 | 350 |
| 390 base::AutoLock auto_lock(lock_); | 351 base::AutoLock auto_lock(lock_); |
| 391 DCHECK(state_ != kUninitialized); | 352 DCHECK(state_ != kUninitialized); |
| 392 | 353 |
| 393 CHECK(pending_read_); | 354 CHECK(pending_read_); |
| 394 pending_read_ = false; | 355 pending_read_ = false; |
| 395 | 356 |
| 396 if (status == AudioDecoder::kAborted) { | 357 if (status == AudioBufferStream::ABORTED || |
| 358 status == AudioBufferStream::DEMUXER_READ_ABORTED) { |
| 397 HandleAbortedReadOrDecodeError(false); | 359 HandleAbortedReadOrDecodeError(false); |
| 398 return; | 360 return; |
| 399 } | 361 } |
| 400 | 362 |
| 401 if (status == AudioDecoder::kDecodeError) { | 363 if (status == AudioBufferStream::DECODE_ERROR) { |
| 402 HandleAbortedReadOrDecodeError(true); | 364 HandleAbortedReadOrDecodeError(true); |
| 403 return; | 365 return; |
| 404 } | 366 } |
| 405 | 367 |
| 406 DCHECK_EQ(status, AudioDecoder::kOk); | 368 DCHECK_EQ(status, AudioBufferStream::OK); |
| 407 DCHECK(buffer.get()); | 369 DCHECK(buffer.get()); |
| 408 | 370 |
| 409 if (state_ == kFlushing) { | 371 if (state_ == kFlushing) { |
| 410 ChangeState_Locked(kPaused); | 372 ChangeState_Locked(kPaused); |
| 411 DoFlush_Locked(); | 373 DoFlush_Locked(); |
| 412 return; | 374 return; |
| 413 } | 375 } |
| 414 | 376 |
| 415 if (!splicer_->AddInput(buffer)) { | 377 if (!splicer_->AddInput(buffer)) { |
| 416 HandleAbortedReadOrDecodeError(true); | 378 HandleAbortedReadOrDecodeError(true); |
| (...skipping 86 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 503 } | 465 } |
| 504 | 466 |
| 505 void AudioRendererImpl::AttemptRead_Locked() { | 467 void AudioRendererImpl::AttemptRead_Locked() { |
| 506 DCHECK(task_runner_->BelongsToCurrentThread()); | 468 DCHECK(task_runner_->BelongsToCurrentThread()); |
| 507 lock_.AssertAcquired(); | 469 lock_.AssertAcquired(); |
| 508 | 470 |
| 509 if (!CanRead_Locked()) | 471 if (!CanRead_Locked()) |
| 510 return; | 472 return; |
| 511 | 473 |
| 512 pending_read_ = true; | 474 pending_read_ = true; |
| 513 decoder_->Read(base::Bind(&AudioRendererImpl::DecodedAudioReady, weak_this_)); | 475 audio_buffer_stream_.Read( |
| 476 base::Bind(&AudioRendererImpl::DecodedAudioReady, weak_this_)); |
| 514 } | 477 } |
| 515 | 478 |
| 516 bool AudioRendererImpl::CanRead_Locked() { | 479 bool AudioRendererImpl::CanRead_Locked() { |
| 517 lock_.AssertAcquired(); | 480 lock_.AssertAcquired(); |
| 518 | 481 |
| 519 switch (state_) { | 482 switch (state_) { |
| 520 case kUninitialized: | 483 case kUninitialized: |
| 521 case kInitializing: | 484 case kInitializing: |
| 522 case kPaused: | 485 case kPaused: |
| 523 case kFlushing: | 486 case kFlushing: |
| (...skipping 218 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 742 } | 705 } |
| 743 } | 706 } |
| 744 | 707 |
| 745 void AudioRendererImpl::ChangeState_Locked(State new_state) { | 708 void AudioRendererImpl::ChangeState_Locked(State new_state) { |
| 746 DVLOG(1) << __FUNCTION__ << " : " << state_ << " -> " << new_state; | 709 DVLOG(1) << __FUNCTION__ << " : " << state_ << " -> " << new_state; |
| 747 lock_.AssertAcquired(); | 710 lock_.AssertAcquired(); |
| 748 state_ = new_state; | 711 state_ = new_state; |
| 749 } | 712 } |
| 750 | 713 |
| 751 } // namespace media | 714 } // namespace media |
| OLD | NEW |