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

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 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 buffer_converter_->Reset();
171 algorithm_->FlushBuffers(); 176 algorithm_->FlushBuffers();
172 } 177 }
173 base::ResetAndReturn(&flush_cb_).Run(); 178 base::ResetAndReturn(&flush_cb_).Run();
174 } 179 }
175 180
176 void AudioRendererImpl::Stop(const base::Closure& callback) { 181 void AudioRendererImpl::Stop(const base::Closure& callback) {
177 DCHECK(task_runner_->BelongsToCurrentThread()); 182 DCHECK(task_runner_->BelongsToCurrentThread());
178 DCHECK(!callback.is_null()); 183 DCHECK(!callback.is_null());
179 184
180 // TODO(scherkus): Consider invalidating |weak_factory_| and replacing 185 // TODO(scherkus): Consider invalidating |weak_factory_| and replacing
(...skipping 85 matching lines...) Expand 10 before | Expand all | Expand 10 after
266 base::ResetAndReturn(&init_cb_).Run(PIPELINE_ERROR_ABORT); 271 base::ResetAndReturn(&init_cb_).Run(PIPELINE_ERROR_ABORT);
267 return; 272 return;
268 } 273 }
269 274
270 if (!success) { 275 if (!success) {
271 state_ = kUninitialized; 276 state_ = kUninitialized;
272 base::ResetAndReturn(&init_cb_).Run(DECODER_ERROR_NOT_SUPPORTED); 277 base::ResetAndReturn(&init_cb_).Run(DECODER_ERROR_NOT_SUPPORTED);
273 return; 278 return;
274 } 279 }
275 280
276 int sample_rate = audio_buffer_stream_.decoder()->samples_per_second(); 281 // TODO(rileya): Support hardware config changes
282 audio_parameters_ = hardware_config_.GetOutputConfig();
277 283
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()) { 284 if (!audio_parameters_.IsValid()) {
291 ChangeState_Locked(kUninitialized); 285 ChangeState_Locked(kUninitialized);
292 base::ResetAndReturn(&init_cb_).Run(PIPELINE_ERROR_INITIALIZATION_FAILED); 286 base::ResetAndReturn(&init_cb_).Run(PIPELINE_ERROR_INITIALIZATION_FAILED);
293 return; 287 return;
294 } 288 }
295 289
296 splicer_.reset(new AudioSplicer(sample_rate)); 290 buffer_converter_.reset(new AudioBufferConverter(audio_parameters_));
291 splicer_.reset(new AudioSplicer(audio_parameters_.sample_rate()));
297 292
298 // We're all good! Continue initializing the rest of the audio renderer 293 // We're all good! Continue initializing the rest of the audio renderer
299 // based on the decoder format. 294 // based on the decoder format.
300 algorithm_.reset(new AudioRendererAlgorithm()); 295 algorithm_.reset(new AudioRendererAlgorithm());
301 algorithm_->Initialize(0, audio_parameters_); 296 algorithm_->Initialize(0, audio_parameters_);
302 297
303 ChangeState_Locked(kPaused); 298 ChangeState_Locked(kPaused);
304 299
305 HistogramRendererEvent(INITIALIZED); 300 HistogramRendererEvent(INITIALIZED);
306 301
(...skipping 59 matching lines...) Expand 10 before | Expand all | Expand 10 after
366 361
367 DCHECK_EQ(status, AudioBufferStream::OK); 362 DCHECK_EQ(status, AudioBufferStream::OK);
368 DCHECK(buffer.get()); 363 DCHECK(buffer.get());
369 364
370 if (state_ == kFlushing) { 365 if (state_ == kFlushing) {
371 ChangeState_Locked(kPaused); 366 ChangeState_Locked(kPaused);
372 DoFlush_Locked(); 367 DoFlush_Locked();
373 return; 368 return;
374 } 369 }
375 370
376 if (!splicer_->AddInput(buffer)) { 371 buffer_converter_->AddInput(buffer);
377 HandleAbortedReadOrDecodeError(true);
378 return;
379 }
380 372
381 if (!splicer_->HasNextBuffer()) { 373 if (!buffer_converter_->HasNextBuffer()) {
382 AttemptRead_Locked(); 374 AttemptRead_Locked();
383 return; 375 return;
384 } 376 }
385 377
386 bool need_another_buffer = false; 378 bool need_another_buffer = false;
387 while (splicer_->HasNextBuffer()) 379
388 need_another_buffer = HandleSplicerBuffer(splicer_->GetNextBuffer()); 380 while (buffer_converter_->HasNextBuffer()) {
381 scoped_refptr<AudioBuffer> converted_buffer =
382 buffer_converter_->GetNextBuffer();
383
384 if (!splicer_->AddInput(converted_buffer)) {
385 HandleAbortedReadOrDecodeError(true);
386 return;
387 }
388
389 while (splicer_->HasNextBuffer())
390 need_another_buffer = HandleSplicerBuffer(splicer_->GetNextBuffer());
391 }
389 392
390 if (!need_another_buffer && !CanRead_Locked()) 393 if (!need_another_buffer && !CanRead_Locked())
391 return; 394 return;
392 395
393 AttemptRead_Locked(); 396 AttemptRead_Locked();
394 } 397 }
395 398
396 bool AudioRendererImpl::HandleSplicerBuffer( 399 bool AudioRendererImpl::HandleSplicerBuffer(
397 const scoped_refptr<AudioBuffer>& buffer) { 400 const scoped_refptr<AudioBuffer>& buffer) {
398 if (buffer->end_of_stream()) { 401 if (buffer->end_of_stream()) {
(...skipping 306 matching lines...) Expand 10 before | Expand all | Expand 10 after
705 } 708 }
706 } 709 }
707 710
708 void AudioRendererImpl::ChangeState_Locked(State new_state) { 711 void AudioRendererImpl::ChangeState_Locked(State new_state) {
709 DVLOG(1) << __FUNCTION__ << " : " << state_ << " -> " << new_state; 712 DVLOG(1) << __FUNCTION__ << " : " << state_ << " -> " << new_state;
710 lock_.AssertAcquired(); 713 lock_.AssertAcquired();
711 state_ = new_state; 714 state_ = new_state;
712 } 715 }
713 716
714 } // namespace media 717 } // namespace media
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698