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