| Index: media/renderers/renderer_impl.cc
|
| diff --git a/media/renderers/renderer_impl.cc b/media/renderers/renderer_impl.cc
|
| index 59a00bfaf97046b13eccd31f36153a84e53e4d85..9649ac15debabed1c3565c1f28f0ea1e90dd9098 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,30 @@ namespace media {
|
| // See |video_underflow_threshold_|.
|
| static const int kDefaultVideoUnderflowThresholdMs = 3000;
|
|
|
| +class RendererImpl::RendererClientInternal : public RendererClient {
|
| + public:
|
| + RendererClientInternal(DemuxerStream::Type type, RendererImpl* renderer)
|
| + : type_(type), renderer_(renderer) {
|
| + DCHECK((type_ == DemuxerStream::AUDIO) || (type_ == DemuxerStream::VIDEO));
|
| + }
|
| +
|
| + void OnError(PipelineStatus error) override { renderer_->OnError(error); }
|
| + void OnEnded() override { renderer_->OnRendererEnded(type_); }
|
| + void OnStatisticsUpdate(const PipelineStatistics& stats) override {
|
| + renderer_->OnStatisticsUpdate(stats);
|
| + }
|
| + void OnBufferingStateChange(BufferingState state) override {
|
| + renderer_->OnBufferingStateChange(type_, state);
|
| + }
|
| + void OnWaitingForDecryptionKey() override {
|
| + renderer_->OnWaitingForDecryptionKey();
|
| + }
|
| +
|
| + private:
|
| + DemuxerStream::Type type_;
|
| + RendererImpl* renderer_;
|
| +};
|
| +
|
| RendererImpl::RendererImpl(
|
| const scoped_refptr<base::SingleThreadTaskRunner>& task_runner,
|
| std::unique_ptr<AudioRenderer> audio_renderer,
|
| @@ -81,32 +106,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(DemuxerStreamProvider* demuxer_stream_provider,
|
| + RendererClient* client,
|
| + 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 +318,13 @@ void RendererImpl::InitializeAudioRenderer() {
|
| return;
|
| }
|
|
|
| + audio_renderer_client_.reset(
|
| + new RendererClientInternal(DemuxerStream::AUDIO, 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_);
|
| + demuxer_stream_provider_->GetStream(DemuxerStream::AUDIO), cdm_context_,
|
| + audio_renderer_client_.get(), done_cb);
|
| }
|
|
|
| void RendererImpl::OnAudioRendererInitializeDone(PipelineStatus status) {
|
| @@ -353,15 +363,13 @@ void RendererImpl::InitializeVideoRenderer() {
|
| return;
|
| }
|
|
|
| + video_renderer_client_.reset(
|
| + new RendererClientInternal(DemuxerStream::VIDEO, 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_),
|
| + demuxer_stream_provider_->GetStream(DemuxerStream::VIDEO), cdm_context_,
|
| + video_renderer_client_.get(),
|
| base::Bind(&RendererImpl::GetWallClockTimes, base::Unretained(this)),
|
| - waiting_for_decryption_key_cb_);
|
| + done_cb);
|
| }
|
|
|
| void RendererImpl::OnVideoRendererInitializeDone(PipelineStatus status) {
|
| @@ -467,16 +475,21 @@ void RendererImpl::OnVideoRendererFlushDone() {
|
| base::ResetAndReturn(&flush_cb_).Run();
|
| }
|
|
|
| -void RendererImpl::OnUpdateStatistics(const PipelineStatistics& stats) {
|
| +void RendererImpl::OnStatisticsUpdate(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(DemuxerStream::Type type,
|
| + BufferingState new_buffering_state) {
|
| + DCHECK((type == DemuxerStream::AUDIO) || (type == DemuxerStream::VIDEO));
|
| + BufferingState* buffering_state = type == DemuxerStream::AUDIO
|
| + ? &audio_buffering_state_
|
| + : &video_buffering_state_;
|
| +
|
| DVLOG(1) << __FUNCTION__ << "(" << *buffering_state << ", "
|
| - << new_buffering_state << ") " << (is_audio ? "audio" : "video");
|
| + << new_buffering_state << ") "
|
| + << (type == DemuxerStream::AUDIO ? "audio" : "video");
|
| DCHECK(task_runner_->BelongsToCurrentThread());
|
|
|
| bool was_waiting_for_enough_data = WaitingForEnoughData();
|
| @@ -484,14 +497,15 @@ void RendererImpl::OnBufferingStateChanged(BufferingState* buffering_state,
|
| // When audio is present and has enough data, defer video underflow callbacks
|
| // for some time to avoid unnecessary glitches in audio; see
|
| // http://crbug.com/144683#c53.
|
| - if (audio_renderer_ && !is_audio && state_ == STATE_PLAYING) {
|
| + if (audio_renderer_ && type == DemuxerStream::VIDEO &&
|
| + state_ == STATE_PLAYING) {
|
| if (video_buffering_state_ == BUFFERING_HAVE_ENOUGH &&
|
| 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(), type, new_buffering_state));
|
| task_runner_->PostDelayedTask(FROM_HERE,
|
| deferred_underflow_cb_.callback(),
|
| video_underflow_threshold_);
|
| @@ -499,7 +513,8 @@ void RendererImpl::OnBufferingStateChanged(BufferingState* buffering_state,
|
| }
|
|
|
| deferred_underflow_cb_.Cancel();
|
| - } else if (!deferred_underflow_cb_.IsCancelled() && is_audio &&
|
| + } else if (!deferred_underflow_cb_.IsCancelled() &&
|
| + type == DemuxerStream::AUDIO &&
|
| new_buffering_state == BUFFERING_HAVE_NOTHING) {
|
| // If audio underflows while we have a deferred video underflow in progress
|
| // we want to mark video as underflowed immediately and cancel the deferral.
|
| @@ -528,7 +543,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 +603,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(DemuxerStream::Type type) {
|
| DVLOG(1) << __FUNCTION__;
|
| DCHECK(task_runner_->BelongsToCurrentThread());
|
| + DCHECK((type == DemuxerStream::AUDIO) || (type == DemuxerStream::VIDEO));
|
|
|
| if (state_ != STATE_PLAYING)
|
| return;
|
|
|
| - DCHECK(!video_ended_);
|
| - video_ended_ = true;
|
| + if (type == DemuxerStream::AUDIO) {
|
| + DCHECK(!audio_ended_);
|
| + audio_ended_ = true;
|
| + } else {
|
| + DCHECK(!video_ended_);
|
| + video_ended_ = true;
|
| + }
|
|
|
| RunEndedCallbackIfNeeded();
|
| }
|
| @@ -637,7 +645,7 @@ void RendererImpl::RunEndedCallbackIfNeeded() {
|
| if (time_ticking_)
|
| PausePlayback();
|
|
|
| - ended_cb_.Run();
|
| + client_->OnEnded();
|
| }
|
|
|
| void RendererImpl::OnError(PipelineStatus error) {
|
| @@ -660,10 +668,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() {
|
| + DCHECK(task_runner_->BelongsToCurrentThread());
|
| + client_->OnWaitingForDecryptionKey();
|
| +}
|
| +
|
| } // namespace media
|
|
|