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