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 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), |
60 weak_factory_(this) { | 64 weak_factory_(this) { |
61 audio_buffer_stream_.set_splice_observer(base::Bind( | 65 audio_buffer_stream_.set_splice_observer(base::Bind( |
62 &AudioRendererImpl::OnNewSpliceBuffer, weak_factory_.GetWeakPtr())); | 66 &AudioRendererImpl::OnNewSpliceBuffer, weak_factory_.GetWeakPtr())); |
67 audio_buffer_stream_.set_config_change_observer(base::Bind( | |
68 &AudioRendererImpl::OnConfigChange, weak_factory_.GetWeakPtr())); | |
63 } | 69 } |
64 | 70 |
65 AudioRendererImpl::~AudioRendererImpl() { | 71 AudioRendererImpl::~AudioRendererImpl() { |
66 // Stop() should have been called and |algorithm_| should have been destroyed. | 72 // Stop() should have been called and |algorithm_| should have been destroyed. |
67 DCHECK(state_ == kUninitialized || state_ == kStopped); | 73 DCHECK(state_ == kUninitialized || state_ == kStopped); |
68 DCHECK(!algorithm_.get()); | 74 DCHECK(!algorithm_.get()); |
69 } | 75 } |
70 | 76 |
71 void AudioRendererImpl::Play(const base::Closure& callback) { | 77 void AudioRendererImpl::Play(const base::Closure& callback) { |
72 DCHECK(task_runner_->BelongsToCurrentThread()); | 78 DCHECK(task_runner_->BelongsToCurrentThread()); |
(...skipping 91 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
164 DCHECK(!flush_cb_.is_null()); | 170 DCHECK(!flush_cb_.is_null()); |
165 | 171 |
166 audio_time_buffered_ = kNoTimestamp(); | 172 audio_time_buffered_ = kNoTimestamp(); |
167 current_time_ = kNoTimestamp(); | 173 current_time_ = kNoTimestamp(); |
168 received_end_of_stream_ = false; | 174 received_end_of_stream_ = false; |
169 rendered_end_of_stream_ = false; | 175 rendered_end_of_stream_ = false; |
170 preroll_aborted_ = false; | 176 preroll_aborted_ = false; |
171 | 177 |
172 earliest_end_time_ = now_cb_.Run(); | 178 earliest_end_time_ = now_cb_.Run(); |
173 splicer_->Reset(); | 179 splicer_->Reset(); |
180 if (buffer_converter_) | |
181 buffer_converter_->Reset(); | |
174 algorithm_->FlushBuffers(); | 182 algorithm_->FlushBuffers(); |
175 } | 183 } |
176 base::ResetAndReturn(&flush_cb_).Run(); | 184 base::ResetAndReturn(&flush_cb_).Run(); |
177 } | 185 } |
178 | 186 |
179 void AudioRendererImpl::Stop(const base::Closure& callback) { | 187 void AudioRendererImpl::Stop(const base::Closure& callback) { |
180 DCHECK(task_runner_->BelongsToCurrentThread()); | 188 DCHECK(task_runner_->BelongsToCurrentThread()); |
181 DCHECK(!callback.is_null()); | 189 DCHECK(!callback.is_null()); |
182 | 190 |
183 // TODO(scherkus): Consider invalidating |weak_factory_| and replacing | 191 // TODO(scherkus): Consider invalidating |weak_factory_| and replacing |
(...skipping 62 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
246 | 254 |
247 state_ = kInitializing; | 255 state_ = kInitializing; |
248 | 256 |
249 init_cb_ = init_cb; | 257 init_cb_ = init_cb; |
250 underflow_cb_ = underflow_cb; | 258 underflow_cb_ = underflow_cb; |
251 time_cb_ = time_cb; | 259 time_cb_ = time_cb; |
252 ended_cb_ = ended_cb; | 260 ended_cb_ = ended_cb; |
253 disabled_cb_ = disabled_cb; | 261 disabled_cb_ = disabled_cb; |
254 error_cb_ = error_cb; | 262 error_cb_ = error_cb; |
255 | 263 |
264 expecting_config_changes_ = stream->SupportsConfigChanges(); | |
265 if (!expecting_config_changes_) { | |
266 // The actual buffer size is controlled via the size of the AudioBus | |
267 // provided to Render(), so just choose something reasonable here for looks. | |
268 int buffer_size = stream->audio_decoder_config().samples_per_second() / 100; | |
269 audio_parameters_.Reset( | |
270 AudioParameters::AUDIO_PCM_LOW_LATENCY, | |
271 stream->audio_decoder_config().channel_layout(), | |
272 ChannelLayoutToChannelCount( | |
273 stream->audio_decoder_config().channel_layout()), | |
274 0, | |
275 stream->audio_decoder_config().samples_per_second(), | |
276 stream->audio_decoder_config().bits_per_channel(), | |
277 buffer_size); | |
278 buffer_converter_.reset(); | |
279 } else { | |
280 // TODO(rileya): Support hardware config changes | |
281 audio_parameters_ = hardware_config_->GetOutputConfig(); | |
282 } | |
283 | |
256 audio_buffer_stream_.Initialize( | 284 audio_buffer_stream_.Initialize( |
257 stream, | 285 stream, |
258 statistics_cb, | 286 statistics_cb, |
259 base::Bind(&AudioRendererImpl::OnAudioBufferStreamInitialized, | 287 base::Bind(&AudioRendererImpl::OnAudioBufferStreamInitialized, |
260 weak_factory_.GetWeakPtr())); | 288 weak_factory_.GetWeakPtr())); |
261 } | 289 } |
262 | 290 |
263 void AudioRendererImpl::OnAudioBufferStreamInitialized(bool success) { | 291 void AudioRendererImpl::OnAudioBufferStreamInitialized(bool success) { |
264 DCHECK(task_runner_->BelongsToCurrentThread()); | 292 DCHECK(task_runner_->BelongsToCurrentThread()); |
265 | 293 |
266 base::AutoLock auto_lock(lock_); | 294 base::AutoLock auto_lock(lock_); |
267 | 295 |
268 if (state_ == kStopped) { | 296 if (state_ == kStopped) { |
269 base::ResetAndReturn(&init_cb_).Run(PIPELINE_ERROR_ABORT); | 297 base::ResetAndReturn(&init_cb_).Run(PIPELINE_ERROR_ABORT); |
270 return; | 298 return; |
271 } | 299 } |
272 | 300 |
273 if (!success) { | 301 if (!success) { |
274 state_ = kUninitialized; | 302 state_ = kUninitialized; |
275 base::ResetAndReturn(&init_cb_).Run(DECODER_ERROR_NOT_SUPPORTED); | 303 base::ResetAndReturn(&init_cb_).Run(DECODER_ERROR_NOT_SUPPORTED); |
276 return; | 304 return; |
277 } | 305 } |
278 | 306 |
279 int sample_rate = audio_buffer_stream_.decoder()->samples_per_second(); | |
280 | |
281 // The actual buffer size is controlled via the size of the AudioBus | |
282 // provided to Render(), so just choose something reasonable here for looks. | |
283 int buffer_size = audio_buffer_stream_.decoder()->samples_per_second() / 100; | |
284 | |
285 // TODO(rileya): Remove the channel_layout/bits_per_channel/samples_per_second | |
286 // getters from AudioDecoder, and adjust this accordingly. | |
287 audio_parameters_ = | |
288 AudioParameters(AudioParameters::AUDIO_PCM_LOW_LATENCY, | |
289 audio_buffer_stream_.decoder()->channel_layout(), | |
290 sample_rate, | |
291 audio_buffer_stream_.decoder()->bits_per_channel(), | |
292 buffer_size); | |
293 if (!audio_parameters_.IsValid()) { | 307 if (!audio_parameters_.IsValid()) { |
294 ChangeState_Locked(kUninitialized); | 308 ChangeState_Locked(kUninitialized); |
295 base::ResetAndReturn(&init_cb_).Run(PIPELINE_ERROR_INITIALIZATION_FAILED); | 309 base::ResetAndReturn(&init_cb_).Run(PIPELINE_ERROR_INITIALIZATION_FAILED); |
296 return; | 310 return; |
297 } | 311 } |
298 | 312 |
299 splicer_.reset(new AudioSplicer(sample_rate)); | 313 if (expecting_config_changes_) |
314 buffer_converter_.reset(new AudioBufferConverter(audio_parameters_)); | |
315 splicer_.reset(new AudioSplicer(audio_parameters_.sample_rate())); | |
300 | 316 |
301 // We're all good! Continue initializing the rest of the audio renderer | 317 // We're all good! Continue initializing the rest of the audio renderer |
302 // based on the decoder format. | 318 // based on the decoder format. |
303 algorithm_.reset(new AudioRendererAlgorithm()); | 319 algorithm_.reset(new AudioRendererAlgorithm()); |
304 algorithm_->Initialize(0, audio_parameters_); | 320 algorithm_->Initialize(0, audio_parameters_); |
305 | 321 |
306 ChangeState_Locked(kPaused); | 322 ChangeState_Locked(kPaused); |
307 | 323 |
308 HistogramRendererEvent(INITIALIZED); | 324 HistogramRendererEvent(INITIALIZED); |
309 | 325 |
(...skipping 59 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
369 | 385 |
370 DCHECK_EQ(status, AudioBufferStream::OK); | 386 DCHECK_EQ(status, AudioBufferStream::OK); |
371 DCHECK(buffer.get()); | 387 DCHECK(buffer.get()); |
372 | 388 |
373 if (state_ == kFlushing) { | 389 if (state_ == kFlushing) { |
374 ChangeState_Locked(kPaused); | 390 ChangeState_Locked(kPaused); |
375 DoFlush_Locked(); | 391 DoFlush_Locked(); |
376 return; | 392 return; |
377 } | 393 } |
378 | 394 |
379 if (!splicer_->AddInput(buffer)) { | 395 if (expecting_config_changes_) { |
380 HandleAbortedReadOrDecodeError(true); | 396 DCHECK(buffer_converter_); |
381 return; | 397 buffer_converter_->AddInput(buffer); |
398 while (buffer_converter_->HasNextBuffer()) { | |
399 if (!splicer_->AddInput(buffer_converter_->GetNextBuffer())) { | |
400 HandleAbortedReadOrDecodeError(true); | |
401 return; | |
402 } | |
403 } | |
404 } else { | |
405 if (!splicer_->AddInput(buffer)) { | |
406 HandleAbortedReadOrDecodeError(true); | |
407 return; | |
408 } | |
382 } | 409 } |
383 | 410 |
384 if (!splicer_->HasNextBuffer()) { | 411 if (!splicer_->HasNextBuffer()) { |
385 AttemptRead_Locked(); | 412 AttemptRead_Locked(); |
386 return; | 413 return; |
387 } | 414 } |
388 | 415 |
389 bool need_another_buffer = false; | 416 bool need_another_buffer = false; |
390 while (splicer_->HasNextBuffer()) | 417 while (splicer_->HasNextBuffer()) |
391 need_another_buffer = HandleSplicerBuffer(splicer_->GetNextBuffer()); | 418 need_another_buffer = HandleSplicerBuffer(splicer_->GetNextBuffer()); |
(...skipping 320 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
712 DVLOG(1) << __FUNCTION__ << " : " << state_ << " -> " << new_state; | 739 DVLOG(1) << __FUNCTION__ << " : " << state_ << " -> " << new_state; |
713 lock_.AssertAcquired(); | 740 lock_.AssertAcquired(); |
714 state_ = new_state; | 741 state_ = new_state; |
715 } | 742 } |
716 | 743 |
717 void AudioRendererImpl::OnNewSpliceBuffer(base::TimeDelta splice_timestamp) { | 744 void AudioRendererImpl::OnNewSpliceBuffer(base::TimeDelta splice_timestamp) { |
718 DCHECK(task_runner_->BelongsToCurrentThread()); | 745 DCHECK(task_runner_->BelongsToCurrentThread()); |
719 splicer_->SetSpliceTimestamp(splice_timestamp); | 746 splicer_->SetSpliceTimestamp(splice_timestamp); |
720 } | 747 } |
721 | 748 |
749 void AudioRendererImpl::OnConfigChange() { | |
750 DCHECK(task_runner_->BelongsToCurrentThread()); | |
751 buffer_converter_->ResetTimestampState(); | |
DaleCurtis
2014/03/27 20:59:55
Need to check expecting_config_changes here.
| |
752 } | |
753 | |
722 } // namespace media | 754 } // namespace media |
OLD | NEW |