Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(124)

Side by Side Diff: media/filters/audio_renderer_impl.cc

Issue 177333003: Add support for midstream audio configuration changes. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@ABS
Patch Set: add Reset() tests. Only enable ABC in MSE case. Created 6 years, 9 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
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
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
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
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
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
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698