| 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 |