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

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: 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 weak_factory_(this), 49 weak_factory_(this),
47 sink_(sink), 50 sink_(sink),
48 audio_buffer_stream_(task_runner, 51 audio_buffer_stream_(task_runner,
49 decoders.Pass(), 52 decoders.Pass(),
50 set_decryptor_ready_cb), 53 set_decryptor_ready_cb),
54 hardware_config_(hardware_config),
51 now_cb_(base::Bind(&base::TimeTicks::Now)), 55 now_cb_(base::Bind(&base::TimeTicks::Now)),
52 state_(kUninitialized), 56 state_(kUninitialized),
53 sink_playing_(false), 57 sink_playing_(false),
54 pending_read_(false), 58 pending_read_(false),
55 received_end_of_stream_(false), 59 received_end_of_stream_(false),
56 rendered_end_of_stream_(false), 60 rendered_end_of_stream_(false),
57 audio_time_buffered_(kNoTimestamp()), 61 audio_time_buffered_(kNoTimestamp()),
58 current_time_(kNoTimestamp()), 62 current_time_(kNoTimestamp()),
59 underflow_disabled_(false), 63 underflow_disabled_(false),
60 preroll_aborted_(false) {} 64 preroll_aborted_(false) {}
(...skipping 100 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 // TODO: add a Reset() or Flush()
176 buffer_converter_.reset(new AudioBufferConverter(audio_parameters_));
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 86 matching lines...) Expand 10 before | Expand all | Expand 10 after
267 base::ResetAndReturn(&init_cb_).Run(PIPELINE_ERROR_ABORT); 273 base::ResetAndReturn(&init_cb_).Run(PIPELINE_ERROR_ABORT);
268 return; 274 return;
269 } 275 }
270 276
271 if (!success) { 277 if (!success) {
272 state_ = kUninitialized; 278 state_ = kUninitialized;
273 base::ResetAndReturn(&init_cb_).Run(DECODER_ERROR_NOT_SUPPORTED); 279 base::ResetAndReturn(&init_cb_).Run(DECODER_ERROR_NOT_SUPPORTED);
274 return; 280 return;
275 } 281 }
276 282
277 int sample_rate = audio_buffer_stream_.decoder()->samples_per_second(); 283 // TODO(rileya): Support hardware config changes
rileya (GONE FROM CHROMIUM) 2014/03/07 01:19:29 What do we currently do when the hardware config c
DaleCurtis 2014/03/07 02:00:10 Nothing currently. It'll get resampled / remixed a
284 audio_parameters_ = hardware_config_.GetOutputConfig();
278 285
279 // The actual buffer size is controlled via the size of the AudioBus
280 // provided to Render(), so just choose something reasonable here for looks.
281 int buffer_size = audio_buffer_stream_.decoder()->samples_per_second() / 100;
282
283 // TODO(rileya): Remove the channel_layout/bits_per_channel/samples_per_second
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);
291 if (!audio_parameters_.IsValid()) { 286 if (!audio_parameters_.IsValid()) {
292 ChangeState_Locked(kUninitialized); 287 ChangeState_Locked(kUninitialized);
293 base::ResetAndReturn(&init_cb_).Run(PIPELINE_ERROR_INITIALIZATION_FAILED); 288 base::ResetAndReturn(&init_cb_).Run(PIPELINE_ERROR_INITIALIZATION_FAILED);
294 return; 289 return;
295 } 290 }
296 291
297 splicer_.reset(new AudioSplicer(sample_rate)); 292 buffer_converter_.reset(new AudioBufferConverter(audio_parameters_));
293 splicer_.reset(new AudioSplicer(audio_parameters_.sample_rate()));
298 294
299 // We're all good! Continue initializing the rest of the audio renderer 295 // We're all good! Continue initializing the rest of the audio renderer
300 // based on the decoder format. 296 // based on the decoder format.
301 algorithm_.reset(new AudioRendererAlgorithm()); 297 algorithm_.reset(new AudioRendererAlgorithm());
302 algorithm_->Initialize(0, audio_parameters_); 298 algorithm_->Initialize(0, audio_parameters_);
303 299
304 ChangeState_Locked(kPaused); 300 ChangeState_Locked(kPaused);
305 301
306 HistogramRendererEvent(INITIALIZED); 302 HistogramRendererEvent(INITIALIZED);
307 303
(...skipping 59 matching lines...) Expand 10 before | Expand all | Expand 10 after
367 363
368 DCHECK_EQ(status, AudioBufferStream::OK); 364 DCHECK_EQ(status, AudioBufferStream::OK);
369 DCHECK(buffer.get()); 365 DCHECK(buffer.get());
370 366
371 if (state_ == kFlushing) { 367 if (state_ == kFlushing) {
372 ChangeState_Locked(kPaused); 368 ChangeState_Locked(kPaused);
373 DoFlush_Locked(); 369 DoFlush_Locked();
374 return; 370 return;
375 } 371 }
376 372
377 if (!splicer_->AddInput(buffer)) { 373 buffer_converter_->AddInput(buffer);
378 HandleAbortedReadOrDecodeError(true); 374 bool need_another_buffer = false;
379 return;
380 }
381 375
382 if (!splicer_->HasNextBuffer()) { 376 if (!buffer_converter_->HasNextBuffer()) {
383 AttemptRead_Locked(); 377 AttemptRead_Locked();
384 return; 378 return;
385 } 379 }
386 380
387 bool need_another_buffer = false; 381 while (buffer_converter_->HasNextBuffer()) {
388 while (splicer_->HasNextBuffer()) 382 scoped_refptr<AudioBuffer> converted_buffer =
389 need_another_buffer = HandleSplicerBuffer(splicer_->GetNextBuffer()); 383 buffer_converter_->GetNextBuffer();
384
385 if (!splicer_->AddInput(converted_buffer)) {
386 HandleAbortedReadOrDecodeError(true);
387 return;
388 }
389
390 while (splicer_->HasNextBuffer())
391 need_another_buffer = HandleSplicerBuffer(splicer_->GetNextBuffer());
392 }
390 393
391 if (!need_another_buffer && !CanRead_Locked()) 394 if (!need_another_buffer && !CanRead_Locked())
392 return; 395 return;
393 396
394 AttemptRead_Locked(); 397 AttemptRead_Locked();
395 } 398 }
396 399
397 bool AudioRendererImpl::HandleSplicerBuffer( 400 bool AudioRendererImpl::HandleSplicerBuffer(
398 const scoped_refptr<AudioBuffer>& buffer) { 401 const scoped_refptr<AudioBuffer>& buffer) {
402
399 if (buffer->end_of_stream()) { 403 if (buffer->end_of_stream()) {
400 received_end_of_stream_ = true; 404 received_end_of_stream_ = true;
401 405
402 // Transition to kPlaying if we are currently handling an underflow since 406 // Transition to kPlaying if we are currently handling an underflow since
403 // no more data will be arriving. 407 // no more data will be arriving.
404 if (state_ == kUnderflow || state_ == kRebuffering) 408 if (state_ == kUnderflow || state_ == kRebuffering)
405 ChangeState_Locked(kPlaying); 409 ChangeState_Locked(kPlaying);
406 } else { 410 } else {
407 if (state_ == kPrerolling) { 411 if (state_ == kPrerolling) {
408 if (IsBeforePrerollTime(buffer)) 412 if (IsBeforePrerollTime(buffer))
(...skipping 296 matching lines...) Expand 10 before | Expand all | Expand 10 after
705 } 709 }
706 } 710 }
707 711
708 void AudioRendererImpl::ChangeState_Locked(State new_state) { 712 void AudioRendererImpl::ChangeState_Locked(State new_state) {
709 DVLOG(1) << __FUNCTION__ << " : " << state_ << " -> " << new_state; 713 DVLOG(1) << __FUNCTION__ << " : " << state_ << " -> " << new_state;
710 lock_.AssertAcquired(); 714 lock_.AssertAcquired();
711 state_ = new_state; 715 state_ = new_state;
712 } 716 }
713 717
714 } // namespace media 718 } // namespace media
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698