 Chromium Code Reviews
 Chromium Code Reviews Issue 177333003:
  Add support for midstream audio configuration changes.  (Closed) 
  Base URL: https://chromium.googlesource.com/chromium/src.git@ABS
    
  
    Issue 177333003:
  Add support for midstream audio configuration changes.  (Closed) 
  Base URL: https://chromium.googlesource.com/chromium/src.git@ABS| Index: media/filters/audio_renderer_impl.cc | 
| diff --git a/media/filters/audio_renderer_impl.cc b/media/filters/audio_renderer_impl.cc | 
| index 509ae9536a785b0ed43dae326ebe89793ca26bd1..03c5c734069d66a2d97e8fdd866b000bdb7ae6b8 100644 | 
| --- a/media/filters/audio_renderer_impl.cc | 
| +++ b/media/filters/audio_renderer_impl.cc | 
| @@ -15,6 +15,8 @@ | 
| #include "base/metrics/histogram.h" | 
| #include "base/single_thread_task_runner.h" | 
| #include "media/base/audio_buffer.h" | 
| +#include "media/base/audio_buffer_converter.h" | 
| +#include "media/base/audio_hardware_config.h" | 
| #include "media/base/audio_splicer.h" | 
| #include "media/base/bind_to_current_loop.h" | 
| #include "media/base/demuxer_stream.h" | 
| @@ -41,12 +43,14 @@ AudioRendererImpl::AudioRendererImpl( | 
| const scoped_refptr<base::SingleThreadTaskRunner>& task_runner, | 
| media::AudioRendererSink* sink, | 
| ScopedVector<AudioDecoder> decoders, | 
| - const SetDecryptorReadyCB& set_decryptor_ready_cb) | 
| + const SetDecryptorReadyCB& set_decryptor_ready_cb, | 
| + AudioHardwareConfig* hardware_config) | 
| : task_runner_(task_runner), | 
| sink_(sink), | 
| audio_buffer_stream_(task_runner, | 
| decoders.Pass(), | 
| set_decryptor_ready_cb), | 
| + hardware_config_(hardware_config), | 
| now_cb_(base::Bind(&base::TimeTicks::Now)), | 
| state_(kUninitialized), | 
| sink_playing_(false), | 
| @@ -60,6 +64,8 @@ AudioRendererImpl::AudioRendererImpl( | 
| weak_factory_(this) { | 
| audio_buffer_stream_.set_splice_observer(base::Bind( | 
| &AudioRendererImpl::OnNewSpliceBuffer, weak_factory_.GetWeakPtr())); | 
| + audio_buffer_stream_.set_config_change_observer(base::Bind( | 
| + &AudioRendererImpl::OnConfigChange, weak_factory_.GetWeakPtr())); | 
| } | 
| AudioRendererImpl::~AudioRendererImpl() { | 
| @@ -171,6 +177,8 @@ void AudioRendererImpl::ResetDecoderDone() { | 
| earliest_end_time_ = now_cb_.Run(); | 
| splicer_->Reset(); | 
| + if (buffer_converter_) | 
| + buffer_converter_->Reset(); | 
| algorithm_->FlushBuffers(); | 
| } | 
| base::ResetAndReturn(&flush_cb_).Run(); | 
| @@ -253,6 +261,26 @@ void AudioRendererImpl::Initialize(DemuxerStream* stream, | 
| disabled_cb_ = disabled_cb; | 
| error_cb_ = error_cb; | 
| + expecting_config_changes_ = stream->SupportsConfigChanges(); | 
| + if (!expecting_config_changes_) { | 
| + // The actual buffer size is controlled via the size of the AudioBus | 
| + // provided to Render(), so just choose something reasonable here for looks. | 
| + int buffer_size = stream->audio_decoder_config().samples_per_second() / 100; | 
| + audio_parameters_.Reset( | 
| + AudioParameters::AUDIO_PCM_LOW_LATENCY, | 
| + stream->audio_decoder_config().channel_layout(), | 
| + ChannelLayoutToChannelCount( | 
| + stream->audio_decoder_config().channel_layout()), | 
| + 0, | 
| + stream->audio_decoder_config().samples_per_second(), | 
| + stream->audio_decoder_config().bits_per_channel(), | 
| + buffer_size); | 
| + buffer_converter_.reset(); | 
| + } else { | 
| + // TODO(rileya): Support hardware config changes | 
| + audio_parameters_ = hardware_config_->GetOutputConfig(); | 
| + } | 
| + | 
| audio_buffer_stream_.Initialize( | 
| stream, | 
| statistics_cb, | 
| @@ -276,27 +304,15 @@ void AudioRendererImpl::OnAudioBufferStreamInitialized(bool success) { | 
| return; | 
| } | 
| - int sample_rate = audio_buffer_stream_.decoder()->samples_per_second(); | 
| - | 
| - // The actual buffer size is controlled via the size of the AudioBus | 
| - // provided to Render(), so just choose something reasonable here for looks. | 
| - int buffer_size = audio_buffer_stream_.decoder()->samples_per_second() / 100; | 
| - | 
| - // TODO(rileya): Remove the channel_layout/bits_per_channel/samples_per_second | 
| - // getters from AudioDecoder, and adjust this accordingly. | 
| - audio_parameters_ = | 
| - AudioParameters(AudioParameters::AUDIO_PCM_LOW_LATENCY, | 
| - audio_buffer_stream_.decoder()->channel_layout(), | 
| - sample_rate, | 
| - audio_buffer_stream_.decoder()->bits_per_channel(), | 
| - buffer_size); | 
| if (!audio_parameters_.IsValid()) { | 
| ChangeState_Locked(kUninitialized); | 
| base::ResetAndReturn(&init_cb_).Run(PIPELINE_ERROR_INITIALIZATION_FAILED); | 
| return; | 
| } | 
| - splicer_.reset(new AudioSplicer(sample_rate)); | 
| + if (expecting_config_changes_) | 
| + buffer_converter_.reset(new AudioBufferConverter(audio_parameters_)); | 
| + splicer_.reset(new AudioSplicer(audio_parameters_.sample_rate())); | 
| // We're all good! Continue initializing the rest of the audio renderer | 
| // based on the decoder format. | 
| @@ -376,9 +392,20 @@ void AudioRendererImpl::DecodedAudioReady( | 
| return; | 
| } | 
| - if (!splicer_->AddInput(buffer)) { | 
| - HandleAbortedReadOrDecodeError(true); | 
| - return; | 
| + if (expecting_config_changes_) { | 
| + DCHECK(buffer_converter_); | 
| + buffer_converter_->AddInput(buffer); | 
| + while (buffer_converter_->HasNextBuffer()) { | 
| + if (!splicer_->AddInput(buffer_converter_->GetNextBuffer())) { | 
| + HandleAbortedReadOrDecodeError(true); | 
| + return; | 
| + } | 
| + } | 
| + } else { | 
| + if (!splicer_->AddInput(buffer)) { | 
| + HandleAbortedReadOrDecodeError(true); | 
| + return; | 
| + } | 
| } | 
| if (!splicer_->HasNextBuffer()) { | 
| @@ -719,4 +746,9 @@ void AudioRendererImpl::OnNewSpliceBuffer(base::TimeDelta splice_timestamp) { | 
| splicer_->SetSpliceTimestamp(splice_timestamp); | 
| } | 
| +void AudioRendererImpl::OnConfigChange() { | 
| + DCHECK(task_runner_->BelongsToCurrentThread()); | 
| + buffer_converter_->ResetTimestampState(); | 
| 
DaleCurtis
2014/03/27 20:59:55
Need to check expecting_config_changes here.
 | 
| +} | 
| + | 
| } // namespace media |