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/renderers/audio_renderer_impl.h" | 5 #include "media/renderers/audio_renderer_impl.h" |
6 | 6 |
7 #include <math.h> | 7 #include <math.h> |
8 #include <stddef.h> | 8 #include <stddef.h> |
9 #include <algorithm> | 9 #include <algorithm> |
10 #include <utility> | 10 #include <utility> |
11 | 11 |
12 #include "base/bind.h" | 12 #include "base/bind.h" |
13 #include "base/callback.h" | 13 #include "base/callback.h" |
14 #include "base/callback_helpers.h" | 14 #include "base/callback_helpers.h" |
15 #include "base/command_line.h" | 15 #include "base/command_line.h" |
16 #include "base/logging.h" | 16 #include "base/logging.h" |
17 #include "base/single_thread_task_runner.h" | 17 #include "base/single_thread_task_runner.h" |
18 #include "base/time/default_tick_clock.h" | 18 #include "base/time/default_tick_clock.h" |
19 #include "build/build_config.h" | 19 #include "build/build_config.h" |
20 #include "media/base/audio_buffer.h" | 20 #include "media/base/audio_buffer.h" |
21 #include "media/base/audio_buffer_converter.h" | 21 #include "media/base/audio_buffer_converter.h" |
22 #include "media/base/audio_hardware_config.h" | 22 #include "media/base/audio_hardware_config.h" |
23 #include "media/base/audio_splicer.h" | 23 #include "media/base/audio_splicer.h" |
24 #include "media/base/bind_to_current_loop.h" | 24 #include "media/base/bind_to_current_loop.h" |
25 #include "media/base/demuxer_stream.h" | 25 #include "media/base/demuxer_stream.h" |
26 #include "media/base/media_log.h" | 26 #include "media/base/media_log.h" |
27 #include "media/base/media_switches.h" | 27 #include "media/base/media_switches.h" |
| 28 #include "media/base/renderer_client.h" |
28 #include "media/base/timestamp_constants.h" | 29 #include "media/base/timestamp_constants.h" |
29 #include "media/filters/audio_clock.h" | 30 #include "media/filters/audio_clock.h" |
30 #include "media/filters/decrypting_demuxer_stream.h" | 31 #include "media/filters/decrypting_demuxer_stream.h" |
31 | 32 |
32 namespace media { | 33 namespace media { |
33 | 34 |
34 AudioRendererImpl::AudioRendererImpl( | 35 AudioRendererImpl::AudioRendererImpl( |
35 const scoped_refptr<base::SingleThreadTaskRunner>& task_runner, | 36 const scoped_refptr<base::SingleThreadTaskRunner>& task_runner, |
36 media::AudioRendererSink* sink, | 37 media::AudioRendererSink* sink, |
37 ScopedVector<AudioDecoder> decoders, | 38 ScopedVector<AudioDecoder> decoders, |
38 const AudioHardwareConfig& hardware_config, | 39 const AudioHardwareConfig& hardware_config, |
39 const scoped_refptr<MediaLog>& media_log) | 40 const scoped_refptr<MediaLog>& media_log) |
40 : task_runner_(task_runner), | 41 : task_runner_(task_runner), |
41 expecting_config_changes_(false), | 42 expecting_config_changes_(false), |
42 sink_(sink), | 43 sink_(sink), |
43 audio_buffer_stream_( | 44 audio_buffer_stream_( |
44 new AudioBufferStream(task_runner, std::move(decoders), media_log)), | 45 new AudioBufferStream(task_runner, std::move(decoders), media_log)), |
45 hardware_config_(hardware_config), | 46 hardware_config_(hardware_config), |
46 media_log_(media_log), | 47 media_log_(media_log), |
| 48 client_(nullptr), |
47 tick_clock_(new base::DefaultTickClock()), | 49 tick_clock_(new base::DefaultTickClock()), |
48 last_audio_memory_usage_(0), | 50 last_audio_memory_usage_(0), |
49 last_decoded_sample_rate_(0), | 51 last_decoded_sample_rate_(0), |
50 playback_rate_(0.0), | 52 playback_rate_(0.0), |
51 state_(kUninitialized), | 53 state_(kUninitialized), |
52 buffering_state_(BUFFERING_HAVE_NOTHING), | 54 buffering_state_(BUFFERING_HAVE_NOTHING), |
53 rendering_(false), | 55 rendering_(false), |
54 sink_playing_(false), | 56 sink_playing_(false), |
55 pending_read_(false), | 57 pending_read_(false), |
56 received_end_of_stream_(false), | 58 received_end_of_stream_(false), |
(...skipping 246 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
303 base::AutoLock auto_lock(lock_); | 305 base::AutoLock auto_lock(lock_); |
304 DCHECK(!sink_playing_); | 306 DCHECK(!sink_playing_); |
305 DCHECK_EQ(state_, kFlushed); | 307 DCHECK_EQ(state_, kFlushed); |
306 DCHECK_EQ(buffering_state_, BUFFERING_HAVE_NOTHING); | 308 DCHECK_EQ(buffering_state_, BUFFERING_HAVE_NOTHING); |
307 DCHECK(!pending_read_) << "Pending read must complete before seeking"; | 309 DCHECK(!pending_read_) << "Pending read must complete before seeking"; |
308 | 310 |
309 ChangeState_Locked(kPlaying); | 311 ChangeState_Locked(kPlaying); |
310 AttemptRead_Locked(); | 312 AttemptRead_Locked(); |
311 } | 313 } |
312 | 314 |
313 void AudioRendererImpl::Initialize( | 315 void AudioRendererImpl::Initialize(RendererClient* client, |
314 DemuxerStream* stream, | 316 DemuxerStream* stream, |
315 const PipelineStatusCB& init_cb, | 317 CdmContext* cdm_context, |
316 CdmContext* cdm_context, | 318 const PipelineStatusCB& init_cb) { |
317 const StatisticsCB& statistics_cb, | |
318 const BufferingStateCB& buffering_state_cb, | |
319 const base::Closure& ended_cb, | |
320 const PipelineStatusCB& error_cb, | |
321 const base::Closure& waiting_for_decryption_key_cb) { | |
322 DVLOG(1) << __FUNCTION__; | 319 DVLOG(1) << __FUNCTION__; |
323 DCHECK(task_runner_->BelongsToCurrentThread()); | 320 DCHECK(task_runner_->BelongsToCurrentThread()); |
| 321 DCHECK(client); |
324 DCHECK(stream); | 322 DCHECK(stream); |
325 DCHECK_EQ(stream->type(), DemuxerStream::AUDIO); | 323 DCHECK_EQ(stream->type(), DemuxerStream::AUDIO); |
326 DCHECK(!init_cb.is_null()); | 324 DCHECK(!init_cb.is_null()); |
327 DCHECK(!statistics_cb.is_null()); | |
328 DCHECK(!buffering_state_cb.is_null()); | |
329 DCHECK(!ended_cb.is_null()); | |
330 DCHECK(!error_cb.is_null()); | |
331 DCHECK_EQ(kUninitialized, state_); | 325 DCHECK_EQ(kUninitialized, state_); |
332 DCHECK(sink_.get()); | 326 DCHECK(sink_.get()); |
333 | 327 |
334 state_ = kInitializing; | 328 state_ = kInitializing; |
| 329 client_ = client; |
335 | 330 |
336 // Always post |init_cb_| because |this| could be destroyed if initialization | 331 // Always post |init_cb_| because |this| could be destroyed if initialization |
337 // failed. | 332 // failed. |
338 init_cb_ = BindToCurrentLoop(init_cb); | 333 init_cb_ = BindToCurrentLoop(init_cb); |
339 | 334 |
340 buffering_state_cb_ = buffering_state_cb; | |
341 ended_cb_ = ended_cb; | |
342 error_cb_ = error_cb; | |
343 statistics_cb_ = statistics_cb; | |
344 | |
345 const AudioParameters& hw_params = hardware_config_.GetOutputConfig(); | 335 const AudioParameters& hw_params = hardware_config_.GetOutputConfig(); |
346 expecting_config_changes_ = stream->SupportsConfigChanges(); | 336 expecting_config_changes_ = stream->SupportsConfigChanges(); |
347 if (!expecting_config_changes_ || !hw_params.IsValid() || | 337 if (!expecting_config_changes_ || !hw_params.IsValid() || |
348 hw_params.format() == AudioParameters::AUDIO_FAKE) { | 338 hw_params.format() == AudioParameters::AUDIO_FAKE) { |
349 // The actual buffer size is controlled via the size of the AudioBus | 339 // The actual buffer size is controlled via the size of the AudioBus |
350 // provided to Render(), so just choose something reasonable here for looks. | 340 // provided to Render(), so just choose something reasonable here for looks. |
351 int buffer_size = stream->audio_decoder_config().samples_per_second() / 100; | 341 int buffer_size = stream->audio_decoder_config().samples_per_second() / 100; |
352 audio_parameters_.Reset( | 342 audio_parameters_.Reset( |
353 AudioParameters::AUDIO_PCM_LOW_LATENCY, | 343 AudioParameters::AUDIO_PCM_LOW_LATENCY, |
354 stream->audio_decoder_config().channel_layout(), | 344 stream->audio_decoder_config().channel_layout(), |
(...skipping 68 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
423 AudioHardwareConfig::GetHighLatencyBufferSize( | 413 AudioHardwareConfig::GetHighLatencyBufferSize( |
424 sample_rate, preferred_buffer_size)); | 414 sample_rate, preferred_buffer_size)); |
425 } | 415 } |
426 | 416 |
427 audio_clock_.reset( | 417 audio_clock_.reset( |
428 new AudioClock(base::TimeDelta(), audio_parameters_.sample_rate())); | 418 new AudioClock(base::TimeDelta(), audio_parameters_.sample_rate())); |
429 | 419 |
430 audio_buffer_stream_->Initialize( | 420 audio_buffer_stream_->Initialize( |
431 stream, base::Bind(&AudioRendererImpl::OnAudioBufferStreamInitialized, | 421 stream, base::Bind(&AudioRendererImpl::OnAudioBufferStreamInitialized, |
432 weak_factory_.GetWeakPtr()), | 422 weak_factory_.GetWeakPtr()), |
433 cdm_context, statistics_cb, waiting_for_decryption_key_cb); | 423 cdm_context, base::Bind(&AudioRendererImpl::OnStatisticsUpdate, |
| 424 weak_factory_.GetWeakPtr()), |
| 425 base::Bind(&AudioRendererImpl::OnWaitingForDecryptionKey, |
| 426 weak_factory_.GetWeakPtr())); |
434 } | 427 } |
435 | 428 |
436 void AudioRendererImpl::OnAudioBufferStreamInitialized(bool success) { | 429 void AudioRendererImpl::OnAudioBufferStreamInitialized(bool success) { |
437 DVLOG(1) << __FUNCTION__ << ": " << success; | 430 DVLOG(1) << __FUNCTION__ << ": " << success; |
438 DCHECK(task_runner_->BelongsToCurrentThread()); | 431 DCHECK(task_runner_->BelongsToCurrentThread()); |
439 | 432 |
440 base::AutoLock auto_lock(lock_); | 433 base::AutoLock auto_lock(lock_); |
441 | 434 |
442 if (!success) { | 435 if (!success) { |
443 state_ = kUninitialized; | 436 state_ = kUninitialized; |
(...skipping 26 matching lines...) Expand all Loading... |
470 sink_->Start(); | 463 sink_->Start(); |
471 | 464 |
472 // Some sinks play on start... | 465 // Some sinks play on start... |
473 sink_->Pause(); | 466 sink_->Pause(); |
474 } | 467 } |
475 | 468 |
476 DCHECK(!sink_playing_); | 469 DCHECK(!sink_playing_); |
477 base::ResetAndReturn(&init_cb_).Run(PIPELINE_OK); | 470 base::ResetAndReturn(&init_cb_).Run(PIPELINE_OK); |
478 } | 471 } |
479 | 472 |
| 473 void AudioRendererImpl::OnPlaybackError(PipelineStatus error) { |
| 474 DCHECK(task_runner_->BelongsToCurrentThread()); |
| 475 client_->OnError(error); |
| 476 } |
| 477 |
| 478 void AudioRendererImpl::OnPlaybackEnded() { |
| 479 DCHECK(task_runner_->BelongsToCurrentThread()); |
| 480 client_->OnEnded(); |
| 481 } |
| 482 |
| 483 void AudioRendererImpl::OnStatisticsUpdate(const PipelineStatistics& stats) { |
| 484 DCHECK(task_runner_->BelongsToCurrentThread()); |
| 485 client_->OnStatisticsUpdate(stats); |
| 486 } |
| 487 |
| 488 void AudioRendererImpl::OnBufferingStateChange(BufferingState state) { |
| 489 DCHECK(task_runner_->BelongsToCurrentThread()); |
| 490 client_->OnBufferingStateChange(state); |
| 491 } |
| 492 |
| 493 void AudioRendererImpl::OnWaitingForDecryptionKey() { |
| 494 DCHECK(task_runner_->BelongsToCurrentThread()); |
| 495 client_->OnWaitingForDecryptionKey(); |
| 496 } |
| 497 |
480 void AudioRendererImpl::SetVolume(float volume) { | 498 void AudioRendererImpl::SetVolume(float volume) { |
481 DCHECK(task_runner_->BelongsToCurrentThread()); | 499 DCHECK(task_runner_->BelongsToCurrentThread()); |
482 DCHECK(sink_.get()); | 500 DCHECK(sink_.get()); |
483 sink_->SetVolume(volume); | 501 sink_->SetVolume(volume); |
484 } | 502 } |
485 | 503 |
486 void AudioRendererImpl::DecodedAudioReady( | 504 void AudioRendererImpl::DecodedAudioReady( |
487 AudioBufferStream::Status status, | 505 AudioBufferStream::Status status, |
488 const scoped_refptr<AudioBuffer>& buffer) { | 506 const scoped_refptr<AudioBuffer>& buffer) { |
489 DVLOG(2) << __FUNCTION__ << "(" << status << ")"; | 507 DVLOG(2) << __FUNCTION__ << "(" << status << ")"; |
(...skipping 114 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
604 | 622 |
605 // Store the timestamp of the first packet so we know when to start actual | 623 // Store the timestamp of the first packet so we know when to start actual |
606 // audio playback. | 624 // audio playback. |
607 if (first_packet_timestamp_ == kNoTimestamp()) | 625 if (first_packet_timestamp_ == kNoTimestamp()) |
608 first_packet_timestamp_ = buffer->timestamp(); | 626 first_packet_timestamp_ = buffer->timestamp(); |
609 | 627 |
610 const size_t memory_usage = algorithm_->GetMemoryUsage(); | 628 const size_t memory_usage = algorithm_->GetMemoryUsage(); |
611 PipelineStatistics stats; | 629 PipelineStatistics stats; |
612 stats.audio_memory_usage = memory_usage - last_audio_memory_usage_; | 630 stats.audio_memory_usage = memory_usage - last_audio_memory_usage_; |
613 last_audio_memory_usage_ = memory_usage; | 631 last_audio_memory_usage_ = memory_usage; |
614 task_runner_->PostTask(FROM_HERE, base::Bind(statistics_cb_, stats)); | 632 task_runner_->PostTask(FROM_HERE, |
| 633 base::Bind(&AudioRendererImpl::OnStatisticsUpdate, |
| 634 weak_factory_.GetWeakPtr(), stats)); |
615 | 635 |
616 switch (state_) { | 636 switch (state_) { |
617 case kUninitialized: | 637 case kUninitialized: |
618 case kInitializing: | 638 case kInitializing: |
619 case kFlushing: | 639 case kFlushing: |
620 NOTREACHED(); | 640 NOTREACHED(); |
621 return false; | 641 return false; |
622 | 642 |
623 case kFlushed: | 643 case kFlushed: |
624 DCHECK(!pending_read_); | 644 DCHECK(!pending_read_); |
(...skipping 191 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
816 | 836 |
817 if (CanRead_Locked()) { | 837 if (CanRead_Locked()) { |
818 task_runner_->PostTask(FROM_HERE, | 838 task_runner_->PostTask(FROM_HERE, |
819 base::Bind(&AudioRendererImpl::AttemptRead, | 839 base::Bind(&AudioRendererImpl::AttemptRead, |
820 weak_factory_.GetWeakPtr())); | 840 weak_factory_.GetWeakPtr())); |
821 } | 841 } |
822 | 842 |
823 if (audio_clock_->front_timestamp() >= ended_timestamp_ && | 843 if (audio_clock_->front_timestamp() >= ended_timestamp_ && |
824 !rendered_end_of_stream_) { | 844 !rendered_end_of_stream_) { |
825 rendered_end_of_stream_ = true; | 845 rendered_end_of_stream_ = true; |
826 task_runner_->PostTask(FROM_HERE, ended_cb_); | 846 task_runner_->PostTask(FROM_HERE, |
| 847 base::Bind(&AudioRendererImpl::OnPlaybackEnded, |
| 848 weak_factory_.GetWeakPtr())); |
827 } | 849 } |
828 } | 850 } |
829 | 851 |
830 DCHECK_LE(frames_written, frames_requested); | 852 DCHECK_LE(frames_written, frames_requested); |
831 return frames_written; | 853 return frames_written; |
832 } | 854 } |
833 | 855 |
834 void AudioRendererImpl::OnRenderError() { | 856 void AudioRendererImpl::OnRenderError() { |
835 MEDIA_LOG(ERROR, media_log_) << "audio render error"; | 857 MEDIA_LOG(ERROR, media_log_) << "audio render error"; |
836 | 858 |
837 // Post to |task_runner_| as this is called on the audio callback thread. | 859 // Post to |task_runner_| as this is called on the audio callback thread. |
838 task_runner_->PostTask(FROM_HERE, | 860 task_runner_->PostTask( |
839 base::Bind(error_cb_, AUDIO_RENDERER_ERROR)); | 861 FROM_HERE, base::Bind(&AudioRendererImpl::OnPlaybackError, |
| 862 weak_factory_.GetWeakPtr(), AUDIO_RENDERER_ERROR)); |
840 } | 863 } |
841 | 864 |
842 void AudioRendererImpl::HandleAbortedReadOrDecodeError(PipelineStatus status) { | 865 void AudioRendererImpl::HandleAbortedReadOrDecodeError(PipelineStatus status) { |
843 DCHECK(task_runner_->BelongsToCurrentThread()); | 866 DCHECK(task_runner_->BelongsToCurrentThread()); |
844 lock_.AssertAcquired(); | 867 lock_.AssertAcquired(); |
845 | 868 |
846 switch (state_) { | 869 switch (state_) { |
847 case kUninitialized: | 870 case kUninitialized: |
848 case kInitializing: | 871 case kInitializing: |
849 NOTREACHED(); | 872 NOTREACHED(); |
850 return; | 873 return; |
851 case kFlushing: | 874 case kFlushing: |
852 ChangeState_Locked(kFlushed); | 875 ChangeState_Locked(kFlushed); |
853 if (status == PIPELINE_OK) { | 876 if (status == PIPELINE_OK) { |
854 DoFlush_Locked(); | 877 DoFlush_Locked(); |
855 return; | 878 return; |
856 } | 879 } |
857 | 880 |
858 MEDIA_LOG(ERROR, media_log_) << "audio error during flushing, status: " | 881 MEDIA_LOG(ERROR, media_log_) << "audio error during flushing, status: " |
859 << MediaLog::PipelineStatusToString(status); | 882 << MediaLog::PipelineStatusToString(status); |
860 error_cb_.Run(status); | 883 client_->OnError(status); |
861 base::ResetAndReturn(&flush_cb_).Run(); | 884 base::ResetAndReturn(&flush_cb_).Run(); |
862 return; | 885 return; |
863 | 886 |
864 case kFlushed: | 887 case kFlushed: |
865 case kPlaying: | 888 case kPlaying: |
866 if (status != PIPELINE_OK) { | 889 if (status != PIPELINE_OK) { |
867 MEDIA_LOG(ERROR, media_log_) | 890 MEDIA_LOG(ERROR, media_log_) |
868 << "audio error during playing, status: " | 891 << "audio error during playing, status: " |
869 << MediaLog::PipelineStatusToString(status); | 892 << MediaLog::PipelineStatusToString(status); |
870 error_cb_.Run(status); | 893 client_->OnError(status); |
871 } | 894 } |
872 return; | 895 return; |
873 } | 896 } |
874 } | 897 } |
875 | 898 |
876 void AudioRendererImpl::ChangeState_Locked(State new_state) { | 899 void AudioRendererImpl::ChangeState_Locked(State new_state) { |
877 DVLOG(1) << __FUNCTION__ << " : " << state_ << " -> " << new_state; | 900 DVLOG(1) << __FUNCTION__ << " : " << state_ << " -> " << new_state; |
878 lock_.AssertAcquired(); | 901 lock_.AssertAcquired(); |
879 state_ = new_state; | 902 state_ = new_state; |
880 } | 903 } |
(...skipping 15 matching lines...) Expand all Loading... |
896 } | 919 } |
897 | 920 |
898 void AudioRendererImpl::SetBufferingState_Locked( | 921 void AudioRendererImpl::SetBufferingState_Locked( |
899 BufferingState buffering_state) { | 922 BufferingState buffering_state) { |
900 DVLOG(1) << __FUNCTION__ << " : " << buffering_state_ << " -> " | 923 DVLOG(1) << __FUNCTION__ << " : " << buffering_state_ << " -> " |
901 << buffering_state; | 924 << buffering_state; |
902 DCHECK_NE(buffering_state_, buffering_state); | 925 DCHECK_NE(buffering_state_, buffering_state); |
903 lock_.AssertAcquired(); | 926 lock_.AssertAcquired(); |
904 buffering_state_ = buffering_state; | 927 buffering_state_ = buffering_state; |
905 | 928 |
906 task_runner_->PostTask(FROM_HERE, | 929 task_runner_->PostTask( |
907 base::Bind(buffering_state_cb_, buffering_state_)); | 930 FROM_HERE, base::Bind(&AudioRendererImpl::OnBufferingStateChange, |
| 931 weak_factory_.GetWeakPtr(), buffering_state_)); |
908 } | 932 } |
909 | 933 |
910 } // namespace media | 934 } // namespace media |
OLD | NEW |