| 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 |
| 11 #include "base/bind.h" | 11 #include "base/bind.h" |
| 12 #include "base/callback.h" | 12 #include "base/callback.h" |
| 13 #include "base/callback_helpers.h" | 13 #include "base/callback_helpers.h" |
| 14 #include "base/logging.h" | 14 #include "base/logging.h" |
| 15 #include "base/metrics/histogram.h" | 15 #include "base/metrics/histogram.h" |
| 16 #include "base/single_thread_task_runner.h" | 16 #include "base/single_thread_task_runner.h" |
| 17 #include "media/base/audio_buffer.h" | 17 #include "media/base/audio_buffer.h" |
| 18 #include "media/base/audio_buffer_converter.h" |
| 19 #include "media/base/audio_hardware_config.h" |
| 18 #include "media/base/audio_splicer.h" | 20 #include "media/base/audio_splicer.h" |
| 19 #include "media/base/bind_to_current_loop.h" | 21 #include "media/base/bind_to_current_loop.h" |
| 20 #include "media/base/demuxer_stream.h" | 22 #include "media/base/demuxer_stream.h" |
| 21 #include "media/filters/decrypting_demuxer_stream.h" | 23 #include "media/filters/decrypting_demuxer_stream.h" |
| 22 | 24 |
| 23 namespace media { | 25 namespace media { |
| 24 | 26 |
| 25 namespace { | 27 namespace { |
| 26 | 28 |
| 27 enum AudioRendererEvent { | 29 enum AudioRendererEvent { |
| 28 INITIALIZED, | 30 INITIALIZED, |
| 29 RENDER_ERROR, | 31 RENDER_ERROR, |
| 30 RENDER_EVENT_MAX = RENDER_ERROR, | 32 RENDER_EVENT_MAX = RENDER_ERROR, |
| 31 }; | 33 }; |
| 32 | 34 |
| 33 void HistogramRendererEvent(AudioRendererEvent event) { | 35 void HistogramRendererEvent(AudioRendererEvent event) { |
| 34 UMA_HISTOGRAM_ENUMERATION( | 36 UMA_HISTOGRAM_ENUMERATION( |
| 35 "Media.AudioRendererEvents", event, RENDER_EVENT_MAX + 1); | 37 "Media.AudioRendererEvents", event, RENDER_EVENT_MAX + 1); |
| 36 } | 38 } |
| 37 | 39 |
| 38 } // namespace | 40 } // namespace |
| 39 | 41 |
| 40 AudioRendererImpl::AudioRendererImpl( | 42 AudioRendererImpl::AudioRendererImpl( |
| 41 const scoped_refptr<base::SingleThreadTaskRunner>& task_runner, | 43 const scoped_refptr<base::SingleThreadTaskRunner>& task_runner, |
| 42 media::AudioRendererSink* sink, | 44 media::AudioRendererSink* sink, |
| 43 ScopedVector<AudioDecoder> decoders, | 45 ScopedVector<AudioDecoder> decoders, |
| 44 const SetDecryptorReadyCB& set_decryptor_ready_cb) | 46 const SetDecryptorReadyCB& set_decryptor_ready_cb, |
| 47 const AudioHardwareConfig& hardware_config) |
| 45 : task_runner_(task_runner), | 48 : task_runner_(task_runner), |
| 46 sink_(sink), | 49 sink_(sink), |
| 47 audio_buffer_stream_(task_runner, | 50 audio_buffer_stream_(task_runner, |
| 48 decoders.Pass(), | 51 decoders.Pass(), |
| 49 set_decryptor_ready_cb), | 52 set_decryptor_ready_cb), |
| 53 hardware_config_(hardware_config), |
| 50 now_cb_(base::Bind(&base::TimeTicks::Now)), | 54 now_cb_(base::Bind(&base::TimeTicks::Now)), |
| 51 state_(kUninitialized), | 55 state_(kUninitialized), |
| 52 sink_playing_(false), | 56 sink_playing_(false), |
| 53 pending_read_(false), | 57 pending_read_(false), |
| 54 received_end_of_stream_(false), | 58 received_end_of_stream_(false), |
| 55 rendered_end_of_stream_(false), | 59 rendered_end_of_stream_(false), |
| 56 audio_time_buffered_(kNoTimestamp()), | 60 audio_time_buffered_(kNoTimestamp()), |
| 57 current_time_(kNoTimestamp()), | 61 current_time_(kNoTimestamp()), |
| 58 underflow_disabled_(false), | 62 underflow_disabled_(false), |
| 59 preroll_aborted_(false), | 63 preroll_aborted_(false), |
| (...skipping 101 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 161 DCHECK(!flush_cb_.is_null()); | 165 DCHECK(!flush_cb_.is_null()); |
| 162 | 166 |
| 163 audio_time_buffered_ = kNoTimestamp(); | 167 audio_time_buffered_ = kNoTimestamp(); |
| 164 current_time_ = kNoTimestamp(); | 168 current_time_ = kNoTimestamp(); |
| 165 received_end_of_stream_ = false; | 169 received_end_of_stream_ = false; |
| 166 rendered_end_of_stream_ = false; | 170 rendered_end_of_stream_ = false; |
| 167 preroll_aborted_ = false; | 171 preroll_aborted_ = false; |
| 168 | 172 |
| 169 earliest_end_time_ = now_cb_.Run(); | 173 earliest_end_time_ = now_cb_.Run(); |
| 170 splicer_->Reset(); | 174 splicer_->Reset(); |
| 175 if (buffer_converter_) |
| 176 buffer_converter_->Reset(); |
| 171 algorithm_->FlushBuffers(); | 177 algorithm_->FlushBuffers(); |
| 172 } | 178 } |
| 173 base::ResetAndReturn(&flush_cb_).Run(); | 179 base::ResetAndReturn(&flush_cb_).Run(); |
| 174 } | 180 } |
| 175 | 181 |
| 176 void AudioRendererImpl::Stop(const base::Closure& callback) { | 182 void AudioRendererImpl::Stop(const base::Closure& callback) { |
| 177 DCHECK(task_runner_->BelongsToCurrentThread()); | 183 DCHECK(task_runner_->BelongsToCurrentThread()); |
| 178 DCHECK(!callback.is_null()); | 184 DCHECK(!callback.is_null()); |
| 179 | 185 |
| 180 // TODO(scherkus): Consider invalidating |weak_factory_| and replacing | 186 // TODO(scherkus): Consider invalidating |weak_factory_| and replacing |
| (...skipping 62 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 243 | 249 |
| 244 state_ = kInitializing; | 250 state_ = kInitializing; |
| 245 | 251 |
| 246 init_cb_ = init_cb; | 252 init_cb_ = init_cb; |
| 247 underflow_cb_ = underflow_cb; | 253 underflow_cb_ = underflow_cb; |
| 248 time_cb_ = time_cb; | 254 time_cb_ = time_cb; |
| 249 ended_cb_ = ended_cb; | 255 ended_cb_ = ended_cb; |
| 250 disabled_cb_ = disabled_cb; | 256 disabled_cb_ = disabled_cb; |
| 251 error_cb_ = error_cb; | 257 error_cb_ = error_cb; |
| 252 | 258 |
| 259 expecting_config_changes_ = stream->SupportsConfigChanges(); |
| 260 if (!expecting_config_changes_) { |
| 261 // The actual buffer size is controlled via the size of the AudioBus |
| 262 // provided to Render(), so just choose something reasonable here for looks. |
| 263 int buffer_size = stream->audio_decoder_config().samples_per_second() / 100; |
| 264 audio_parameters_.Reset( |
| 265 AudioParameters::AUDIO_PCM_LOW_LATENCY, |
| 266 stream->audio_decoder_config().channel_layout(), |
| 267 ChannelLayoutToChannelCount( |
| 268 stream->audio_decoder_config().channel_layout()), |
| 269 0, |
| 270 stream->audio_decoder_config().samples_per_second(), |
| 271 stream->audio_decoder_config().bits_per_channel(), |
| 272 buffer_size); |
| 273 buffer_converter_.reset(); |
| 274 } else { |
| 275 // TODO(rileya): Support hardware config changes |
| 276 audio_parameters_ = hardware_config_.GetOutputConfig(); |
| 277 } |
| 278 |
| 253 audio_buffer_stream_.Initialize( | 279 audio_buffer_stream_.Initialize( |
| 254 stream, | 280 stream, |
| 255 statistics_cb, | 281 statistics_cb, |
| 256 base::Bind(&AudioRendererImpl::OnAudioBufferStreamInitialized, | 282 base::Bind(&AudioRendererImpl::OnAudioBufferStreamInitialized, |
| 257 weak_factory_.GetWeakPtr())); | 283 weak_factory_.GetWeakPtr())); |
| 258 } | 284 } |
| 259 | 285 |
| 260 void AudioRendererImpl::OnAudioBufferStreamInitialized(bool success) { | 286 void AudioRendererImpl::OnAudioBufferStreamInitialized(bool success) { |
| 261 DCHECK(task_runner_->BelongsToCurrentThread()); | 287 DCHECK(task_runner_->BelongsToCurrentThread()); |
| 262 | 288 |
| 263 base::AutoLock auto_lock(lock_); | 289 base::AutoLock auto_lock(lock_); |
| 264 | 290 |
| 265 if (state_ == kStopped) { | 291 if (state_ == kStopped) { |
| 266 base::ResetAndReturn(&init_cb_).Run(PIPELINE_ERROR_ABORT); | 292 base::ResetAndReturn(&init_cb_).Run(PIPELINE_ERROR_ABORT); |
| 267 return; | 293 return; |
| 268 } | 294 } |
| 269 | 295 |
| 270 if (!success) { | 296 if (!success) { |
| 271 state_ = kUninitialized; | 297 state_ = kUninitialized; |
| 272 base::ResetAndReturn(&init_cb_).Run(DECODER_ERROR_NOT_SUPPORTED); | 298 base::ResetAndReturn(&init_cb_).Run(DECODER_ERROR_NOT_SUPPORTED); |
| 273 return; | 299 return; |
| 274 } | 300 } |
| 275 | 301 |
| 276 int sample_rate = audio_buffer_stream_.decoder()->samples_per_second(); | |
| 277 | |
| 278 // The actual buffer size is controlled via the size of the AudioBus | |
| 279 // provided to Render(), so just choose something reasonable here for looks. | |
| 280 int buffer_size = audio_buffer_stream_.decoder()->samples_per_second() / 100; | |
| 281 | |
| 282 // TODO(rileya): Remove the channel_layout/bits_per_channel/samples_per_second | |
| 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); | |
| 290 if (!audio_parameters_.IsValid()) { | 302 if (!audio_parameters_.IsValid()) { |
| 291 ChangeState_Locked(kUninitialized); | 303 ChangeState_Locked(kUninitialized); |
| 292 base::ResetAndReturn(&init_cb_).Run(PIPELINE_ERROR_INITIALIZATION_FAILED); | 304 base::ResetAndReturn(&init_cb_).Run(PIPELINE_ERROR_INITIALIZATION_FAILED); |
| 293 return; | 305 return; |
| 294 } | 306 } |
| 295 | 307 |
| 296 splicer_.reset(new AudioSplicer(sample_rate)); | 308 if (expecting_config_changes_) |
| 309 buffer_converter_.reset(new AudioBufferConverter(audio_parameters_)); |
| 310 splicer_.reset(new AudioSplicer(audio_parameters_.sample_rate())); |
| 297 | 311 |
| 298 // We're all good! Continue initializing the rest of the audio renderer | 312 // We're all good! Continue initializing the rest of the audio renderer |
| 299 // based on the decoder format. | 313 // based on the decoder format. |
| 300 algorithm_.reset(new AudioRendererAlgorithm()); | 314 algorithm_.reset(new AudioRendererAlgorithm()); |
| 301 algorithm_->Initialize(0, audio_parameters_); | 315 algorithm_->Initialize(0, audio_parameters_); |
| 302 | 316 |
| 303 ChangeState_Locked(kPaused); | 317 ChangeState_Locked(kPaused); |
| 304 | 318 |
| 305 HistogramRendererEvent(INITIALIZED); | 319 HistogramRendererEvent(INITIALIZED); |
| 306 | 320 |
| (...skipping 59 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 366 | 380 |
| 367 DCHECK_EQ(status, AudioBufferStream::OK); | 381 DCHECK_EQ(status, AudioBufferStream::OK); |
| 368 DCHECK(buffer.get()); | 382 DCHECK(buffer.get()); |
| 369 | 383 |
| 370 if (state_ == kFlushing) { | 384 if (state_ == kFlushing) { |
| 371 ChangeState_Locked(kPaused); | 385 ChangeState_Locked(kPaused); |
| 372 DoFlush_Locked(); | 386 DoFlush_Locked(); |
| 373 return; | 387 return; |
| 374 } | 388 } |
| 375 | 389 |
| 376 if (!splicer_->AddInput(buffer)) { | 390 if (expecting_config_changes_) { |
| 377 HandleAbortedReadOrDecodeError(true); | 391 DCHECK(buffer_converter_); |
| 378 return; | 392 buffer_converter_->AddInput(buffer); |
| 393 while (buffer_converter_->HasNextBuffer()) { |
| 394 if (!splicer_->AddInput(buffer_converter_->GetNextBuffer())) { |
| 395 HandleAbortedReadOrDecodeError(true); |
| 396 return; |
| 397 } |
| 398 } |
| 399 } else { |
| 400 if (!splicer_->AddInput(buffer)) { |
| 401 HandleAbortedReadOrDecodeError(true); |
| 402 return; |
| 403 } |
| 379 } | 404 } |
| 380 | 405 |
| 381 if (!splicer_->HasNextBuffer()) { | 406 if (!splicer_->HasNextBuffer()) { |
| 382 AttemptRead_Locked(); | 407 AttemptRead_Locked(); |
| 383 return; | 408 return; |
| 384 } | 409 } |
| 385 | 410 |
| 386 bool need_another_buffer = false; | 411 bool need_another_buffer = false; |
| 387 while (splicer_->HasNextBuffer()) | 412 while (splicer_->HasNextBuffer()) |
| 388 need_another_buffer = HandleSplicerBuffer(splicer_->GetNextBuffer()); | 413 need_another_buffer = HandleSplicerBuffer(splicer_->GetNextBuffer()); |
| (...skipping 316 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 705 } | 730 } |
| 706 } | 731 } |
| 707 | 732 |
| 708 void AudioRendererImpl::ChangeState_Locked(State new_state) { | 733 void AudioRendererImpl::ChangeState_Locked(State new_state) { |
| 709 DVLOG(1) << __FUNCTION__ << " : " << state_ << " -> " << new_state; | 734 DVLOG(1) << __FUNCTION__ << " : " << state_ << " -> " << new_state; |
| 710 lock_.AssertAcquired(); | 735 lock_.AssertAcquired(); |
| 711 state_ = new_state; | 736 state_ = new_state; |
| 712 } | 737 } |
| 713 | 738 |
| 714 } // namespace media | 739 } // namespace media |
| OLD | NEW |