Chromium Code Reviews| Index: media/renderers/renderer_impl.cc |
| diff --git a/media/renderers/renderer_impl.cc b/media/renderers/renderer_impl.cc |
| index 59a00bfaf97046b13eccd31f36153a84e53e4d85..0e066ba9710685b34f7d4c2bf1ec80a0f90960f1 100644 |
| --- a/media/renderers/renderer_impl.cc |
| +++ b/media/renderers/renderer_impl.cc |
| @@ -19,6 +19,7 @@ |
| #include "media/base/bind_to_current_loop.h" |
| #include "media/base/demuxer_stream_provider.h" |
| #include "media/base/media_switches.h" |
| +#include "media/base/renderer_client.h" |
| #include "media/base/time_source.h" |
| #include "media/base/video_decoder_config.h" |
| #include "media/base/video_renderer.h" |
| @@ -29,6 +30,28 @@ namespace media { |
| // See |video_underflow_threshold_|. |
| static const int kDefaultVideoUnderflowThresholdMs = 3000; |
| +class RendererImpl::AudioVideoRendererClient : public RendererClient { |
| + public: |
| + AudioVideoRendererClient(RendererImpl* renderer) : renderer_(renderer) {} |
| + |
| + void OnError(PipelineStatus error) override { |
| + renderer_->OnError(this, error); |
| + } |
| + void OnEnded() override { renderer_->OnRendererEnded(this); } |
| + void OnStatisticsUpdate(const PipelineStatistics& stats) override { |
| + renderer_->OnStatisticsUpdate(this, stats); |
| + } |
| + void OnBufferingStateChange(BufferingState state) override { |
| + renderer_->OnBufferingStateChange(this, state); |
| + } |
| + void OnWaitingForDecryptionKey() override { |
| + renderer_->OnWaitingForDecryptionKey(this); |
| + } |
| + |
| + private: |
| + RendererImpl* renderer_; |
| +}; |
| + |
| RendererImpl::RendererImpl( |
| const scoped_refptr<base::SingleThreadTaskRunner>& task_runner, |
| std::unique_ptr<AudioRenderer> audio_renderer, |
| @@ -81,32 +104,20 @@ RendererImpl::~RendererImpl() { |
| } |
| } |
| -void RendererImpl::Initialize( |
| - DemuxerStreamProvider* demuxer_stream_provider, |
| - const PipelineStatusCB& init_cb, |
| - const StatisticsCB& statistics_cb, |
| - const BufferingStateCB& buffering_state_cb, |
| - const base::Closure& ended_cb, |
| - const PipelineStatusCB& error_cb, |
| - const base::Closure& waiting_for_decryption_key_cb) { |
| +void RendererImpl::Initialize(RendererClient* client, |
| + DemuxerStreamProvider* demuxer_stream_provider, |
| + const PipelineStatusCB& init_cb) { |
| DVLOG(1) << __FUNCTION__; |
| DCHECK(task_runner_->BelongsToCurrentThread()); |
| DCHECK_EQ(state_, STATE_UNINITIALIZED); |
| DCHECK(!init_cb.is_null()); |
| - DCHECK(!statistics_cb.is_null()); |
| - DCHECK(!buffering_state_cb.is_null()); |
| - DCHECK(!ended_cb.is_null()); |
| - DCHECK(!error_cb.is_null()); |
| + DCHECK(client); |
| DCHECK(demuxer_stream_provider->GetStream(DemuxerStream::AUDIO) || |
| demuxer_stream_provider->GetStream(DemuxerStream::VIDEO)); |
| + client_ = client; |
| demuxer_stream_provider_ = demuxer_stream_provider; |
| - statistics_cb_ = statistics_cb; |
| - buffering_state_cb_ = buffering_state_cb; |
| - ended_cb_ = ended_cb; |
| - error_cb_ = error_cb; |
| init_cb_ = init_cb; |
| - waiting_for_decryption_key_cb_ = waiting_for_decryption_key_cb; |
| if (HasEncryptedStream() && !cdm_context_) { |
| state_ = STATE_INIT_PENDING_CDM; |
| @@ -305,16 +316,13 @@ void RendererImpl::InitializeAudioRenderer() { |
| return; |
| } |
| + audio_renderer_client_.reset(new AudioVideoRendererClient(this)); |
| // Note: After the initialization of a renderer, error events from it may |
| // happen at any time and all future calls must guard against STATE_ERROR. |
| audio_renderer_->Initialize( |
| - demuxer_stream_provider_->GetStream(DemuxerStream::AUDIO), done_cb, |
| - cdm_context_, base::Bind(&RendererImpl::OnUpdateStatistics, weak_this_), |
| - base::Bind(&RendererImpl::OnBufferingStateChanged, weak_this_, |
| - &audio_buffering_state_), |
| - base::Bind(&RendererImpl::OnAudioRendererEnded, weak_this_), |
| - base::Bind(&RendererImpl::OnError, weak_this_), |
| - waiting_for_decryption_key_cb_); |
| + audio_renderer_client_.get(), |
| + demuxer_stream_provider_->GetStream(DemuxerStream::AUDIO), cdm_context_, |
| + done_cb); |
| } |
| void RendererImpl::OnAudioRendererInitializeDone(PipelineStatus status) { |
| @@ -353,15 +361,12 @@ void RendererImpl::InitializeVideoRenderer() { |
| return; |
| } |
| + video_renderer_client_.reset(new AudioVideoRendererClient(this)); |
| video_renderer_->Initialize( |
| - demuxer_stream_provider_->GetStream(DemuxerStream::VIDEO), done_cb, |
| - cdm_context_, base::Bind(&RendererImpl::OnUpdateStatistics, weak_this_), |
| - base::Bind(&RendererImpl::OnBufferingStateChanged, weak_this_, |
| - &video_buffering_state_), |
| - base::Bind(&RendererImpl::OnVideoRendererEnded, weak_this_), |
| - base::Bind(&RendererImpl::OnError, weak_this_), |
| + video_renderer_client_.get(), |
| + demuxer_stream_provider_->GetStream(DemuxerStream::VIDEO), cdm_context_, |
| base::Bind(&RendererImpl::GetWallClockTimes, base::Unretained(this)), |
| - waiting_for_decryption_key_cb_); |
| + done_cb); |
| } |
| void RendererImpl::OnVideoRendererInitializeDone(PipelineStatus status) { |
| @@ -467,14 +472,18 @@ void RendererImpl::OnVideoRendererFlushDone() { |
| base::ResetAndReturn(&flush_cb_).Run(); |
| } |
| -void RendererImpl::OnUpdateStatistics(const PipelineStatistics& stats) { |
| +void RendererImpl::OnStatisticsUpdate(AudioVideoRendererClient* client, |
|
xhwang
2016/05/09 18:13:23
Why do you need |client| here?
|
| + const PipelineStatistics& stats) { |
| DCHECK(task_runner_->BelongsToCurrentThread()); |
| - statistics_cb_.Run(stats); |
| + client_->OnStatisticsUpdate(stats); |
| } |
| -void RendererImpl::OnBufferingStateChanged(BufferingState* buffering_state, |
| - BufferingState new_buffering_state) { |
| - const bool is_audio = buffering_state == &audio_buffering_state_; |
| +void RendererImpl::OnBufferingStateChange(AudioVideoRendererClient* client, |
| + BufferingState new_buffering_state) { |
| + const bool is_audio = client == audio_renderer_client_.get(); |
|
xhwang
2016/05/09 18:13:23
The old code here was a bit hacky (I blame legacy
alokp
2016/05/09 21:31:44
SGTM. What do you think about using DemuxerStream:
alokp
2016/05/11 18:21:50
I have addressed all comments except this one. Xia
|
| + BufferingState* buffering_state = |
| + is_audio ? &audio_buffering_state_ : &video_buffering_state_; |
| + |
| DVLOG(1) << __FUNCTION__ << "(" << *buffering_state << ", " |
| << new_buffering_state << ") " << (is_audio ? "audio" : "video"); |
| DCHECK(task_runner_->BelongsToCurrentThread()); |
| @@ -489,9 +498,9 @@ void RendererImpl::OnBufferingStateChanged(BufferingState* buffering_state, |
| audio_buffering_state_ == BUFFERING_HAVE_ENOUGH && |
| new_buffering_state == BUFFERING_HAVE_NOTHING && |
| deferred_underflow_cb_.IsCancelled()) { |
| - deferred_underflow_cb_.Reset(base::Bind( |
| - &RendererImpl::OnBufferingStateChanged, weak_factory_.GetWeakPtr(), |
| - buffering_state, new_buffering_state)); |
| + deferred_underflow_cb_.Reset( |
| + base::Bind(&RendererImpl::OnBufferingStateChange, |
| + weak_factory_.GetWeakPtr(), client, new_buffering_state)); |
| task_runner_->PostDelayedTask(FROM_HERE, |
| deferred_underflow_cb_.callback(), |
| video_underflow_threshold_); |
| @@ -528,7 +537,7 @@ void RendererImpl::OnBufferingStateChanged(BufferingState* buffering_state, |
| // Renderer prerolled. |
| if (was_waiting_for_enough_data && !WaitingForEnoughData()) { |
| StartPlayback(); |
| - buffering_state_cb_.Run(BUFFERING_HAVE_ENOUGH); |
| + client_->OnBufferingStateChange(BUFFERING_HAVE_ENOUGH); |
| return; |
| } |
| } |
| @@ -588,28 +597,21 @@ void RendererImpl::StartPlayback() { |
| video_renderer_->OnTimeStateChanged(true); |
| } |
| -void RendererImpl::OnAudioRendererEnded() { |
| - DVLOG(1) << __FUNCTION__; |
| - DCHECK(task_runner_->BelongsToCurrentThread()); |
| - |
| - if (state_ != STATE_PLAYING) |
| - return; |
| - |
| - DCHECK(!audio_ended_); |
| - audio_ended_ = true; |
| - |
| - RunEndedCallbackIfNeeded(); |
| -} |
| - |
| -void RendererImpl::OnVideoRendererEnded() { |
| +void RendererImpl::OnRendererEnded(AudioVideoRendererClient* client) { |
| DVLOG(1) << __FUNCTION__; |
| DCHECK(task_runner_->BelongsToCurrentThread()); |
| if (state_ != STATE_PLAYING) |
| return; |
| - DCHECK(!video_ended_); |
| - video_ended_ = true; |
| + if (client == audio_renderer_client_.get()) { |
| + DCHECK(!audio_ended_); |
| + audio_ended_ = true; |
| + } else { |
| + DCHECK_EQ(client, video_renderer_client_.get()); |
| + DCHECK(!video_ended_); |
| + video_ended_ = true; |
| + } |
|
xhwang
2016/05/09 18:13:23
ditto about not relying on pointer comparison
|
| RunEndedCallbackIfNeeded(); |
| } |
| @@ -637,10 +639,11 @@ void RendererImpl::RunEndedCallbackIfNeeded() { |
| if (time_ticking_) |
| PausePlayback(); |
| - ended_cb_.Run(); |
| + client_->OnEnded(); |
| } |
| -void RendererImpl::OnError(PipelineStatus error) { |
| +void RendererImpl::OnError(AudioVideoRendererClient* client, |
|
xhwang
2016/05/09 18:13:23
|client| not needed?
|
| + PipelineStatus error) { |
| DVLOG(1) << __FUNCTION__ << "(" << error << ")"; |
| DCHECK(task_runner_->BelongsToCurrentThread()); |
| DCHECK_NE(PIPELINE_OK, error) << "PIPELINE_OK isn't an error!"; |
| @@ -660,10 +663,15 @@ void RendererImpl::OnError(PipelineStatus error) { |
| } |
| // After OnError() returns, the pipeline may destroy |this|. |
| - base::ResetAndReturn(&error_cb_).Run(error); |
| + client_->OnError(error); |
| if (!flush_cb_.is_null()) |
| base::ResetAndReturn(&flush_cb_).Run(); |
| } |
| +void RendererImpl::OnWaitingForDecryptionKey(AudioVideoRendererClient* client) { |
|
xhwang
2016/05/09 18:13:23
|client| not needed?
|
| + DCHECK(task_runner_->BelongsToCurrentThread()); |
| + client_->OnWaitingForDecryptionKey(); |
| +} |
| + |
| } // namespace media |