diff options
author | alokp <alokp@chromium.org> | 2016-02-18 17:30:00 -0800 |
---|---|---|
committer | Commit bot <commit-bot@chromium.org> | 2016-02-19 01:31:14 +0000 |
commit | 2ac89b3d8c3acc46b44e8f593220f5114047f210 (patch) | |
tree | d63e1a684909edb9fe3300ef0e8db2ecc91f0040 | |
parent | 91c73e42354a73e8c651b9d8e811644799d2e354 (diff) | |
download | chromium_src-2ac89b3d8c3acc46b44e8f593220f5114047f210.zip chromium_src-2ac89b3d8c3acc46b44e8f593220f5114047f210.tar.gz chromium_src-2ac89b3d8c3acc46b44e8f593220f5114047f210.tar.bz2 |
Refactors backend state management in MediaPipelineImpl.
Also moves the workaround for crbug.com/144683 from CmaRenderer
to MediaPipelineImpl so that it can be shared by both CMA and
mojo media pipeline.
BUG=571155
Review URL: https://codereview.chromium.org/1709823002
Cr-Commit-Position: refs/heads/master@{#376334}
-rw-r--r-- | chromecast/media/cma/pipeline/media_pipeline_impl.cc | 71 | ||||
-rw-r--r-- | chromecast/media/cma/pipeline/media_pipeline_impl.h | 18 | ||||
-rw-r--r-- | chromecast/renderer/media/cma_renderer.cc | 11 |
3 files changed, 48 insertions, 52 deletions
diff --git a/chromecast/media/cma/pipeline/media_pipeline_impl.cc b/chromecast/media/cma/pipeline/media_pipeline_impl.cc index 2ad1da0..2ae9c51 100644 --- a/chromecast/media/cma/pipeline/media_pipeline_impl.cc +++ b/chromecast/media/cma/pipeline/media_pipeline_impl.cc @@ -61,12 +61,10 @@ struct MediaPipelineImpl::FlushTask { MediaPipelineImpl::MediaPipelineImpl() : cdm_(nullptr), + backend_state_(BACKEND_STATE_UNINITIALIZED), + playback_rate_(1.0f), audio_decoder_(nullptr), video_decoder_(nullptr), - backend_initialized_(false), - paused_(false), - target_playback_rate_(1.0f), - backend_started_(false), pending_time_update_task_(false), statistics_rolling_counter_(0), weak_factory_(this) { @@ -184,16 +182,14 @@ void MediaPipelineImpl::StartPlayingFrom(base::TimeDelta time) { DCHECK(thread_checker_.CalledOnValidThread()); DCHECK(audio_pipeline_ || video_pipeline_); DCHECK(!pending_flush_task_); - // When starting, we always enter the "playing" state (not paused). - paused_ = false; - // Lazy initialise - if (!backend_initialized_) { - backend_initialized_ = media_pipeline_backend_->Initialize(); - if (!backend_initialized_) { + // Lazy initialize. + if (backend_state_ == BACKEND_STATE_UNINITIALIZED) { + if (!media_pipeline_backend_->Initialize()) { OnError(::media::PIPELINE_ERROR_ABORT); return; } + backend_state_ = BACKEND_STATE_INITIALIZED; } // Start the backend. @@ -201,9 +197,9 @@ void MediaPipelineImpl::StartPlayingFrom(base::TimeDelta time) { OnError(::media::PIPELINE_ERROR_ABORT); return; } + backend_state_ = BACKEND_STATE_PLAYING; // Enable time updates. - backend_started_ = true; statistics_rolling_counter_ = 0; if (!pending_time_update_task_) { pending_time_update_task_ = true; @@ -235,10 +231,11 @@ void MediaPipelineImpl::StartPlayingFrom(base::TimeDelta time) { void MediaPipelineImpl::Flush(const base::Closure& flush_cb) { CMALOG(kLogControl) << __FUNCTION__; DCHECK(thread_checker_.CalledOnValidThread()); + DCHECK((backend_state_ == BACKEND_STATE_PLAYING) || + (backend_state_ == BACKEND_STATE_PAUSED)); DCHECK(audio_pipeline_ || video_pipeline_); DCHECK(!pending_flush_task_); - backend_started_ = false; buffering_controller_->Reset(); // 1. Stop both the audio and video pipeline so that they stop feeding @@ -251,6 +248,7 @@ void MediaPipelineImpl::Flush(const base::Closure& flush_cb) { // 2. Stop the backend, so that the backend won't push their pending buffer, // which may be invalidated later, to hardware. (b/25342604) CHECK(media_pipeline_backend_->Stop()); + backend_state_ = BACKEND_STATE_INITIALIZED; // 3. Flush both the audio and video pipeline. This will flush the frame // provider and invalidate all the unreleased buffers. @@ -277,7 +275,6 @@ void MediaPipelineImpl::Stop() { // audio/video pipelines. This will ensure A/V Flush won't happen in // stopped state. pending_flush_task_.reset(); - backend_started_ = false; // Stop both the audio and video pipeline. if (audio_pipeline_) @@ -290,26 +287,28 @@ void MediaPipelineImpl::Stop() { video_pipeline_ = nullptr; audio_decoder_.reset(); media_pipeline_backend_.reset(); + backend_state_ = BACKEND_STATE_UNINITIALIZED; } void MediaPipelineImpl::SetPlaybackRate(double rate) { CMALOG(kLogControl) << __FUNCTION__ << " rate=" << rate; DCHECK(thread_checker_.CalledOnValidThread()); - target_playback_rate_ = rate; - if (!backend_started_) - return; + DCHECK((backend_state_ == BACKEND_STATE_PLAYING) || + (backend_state_ == BACKEND_STATE_PAUSED)); + + playback_rate_ = rate; if (buffering_controller_ && buffering_controller_->IsBuffering()) return; if (rate != 0.0f) { media_pipeline_backend_->SetPlaybackRate(rate); - if (paused_) { - paused_ = false; + if (backend_state_ == BACKEND_STATE_PAUSED) { media_pipeline_backend_->Resume(); + backend_state_ = BACKEND_STATE_PLAYING; } - } else if (!paused_) { - paused_ = true; + } else if (backend_state_ == BACKEND_STATE_PLAYING) { media_pipeline_backend_->Pause(); + backend_state_ = BACKEND_STATE_PAUSED; } } @@ -359,33 +358,37 @@ void MediaPipelineImpl::OnFlushDone(bool is_audio_stream) { void MediaPipelineImpl::OnBufferingNotification(bool is_buffering) { CMALOG(kLogControl) << __FUNCTION__ << " is_buffering=" << is_buffering; DCHECK(thread_checker_.CalledOnValidThread()); + DCHECK((backend_state_ == BACKEND_STATE_PLAYING) || + (backend_state_ == BACKEND_STATE_PAUSED)); DCHECK(buffering_controller_); + DCHECK_EQ(is_buffering, buffering_controller_->IsBuffering()); if (!client_.buffering_state_cb.is_null()) { - ::media::BufferingState buffering_state = - is_buffering ? ::media::BUFFERING_HAVE_NOTHING - : ::media::BUFFERING_HAVE_ENOUGH; - client_.buffering_state_cb.Run(buffering_state); + if (is_buffering) { + // TODO(alokp): WebMediaPlayerImpl currently only handles HAVE_ENOUGH. + // See WebMediaPlayerImpl::OnPipelineBufferingStateChanged, + // http://crbug.com/144683. + LOG(WARNING) << "Ignoring buffering notification."; + } else { + client_.buffering_state_cb.Run(::media::BUFFERING_HAVE_ENOUGH); + } } - if (!is_buffering) { - DCHECK(!buffering_controller_->IsBuffering()); + if (is_buffering && (backend_state_ == BACKEND_STATE_PLAYING)) { + media_pipeline_backend_->Pause(); + backend_state_ = BACKEND_STATE_PAUSED; + } else if (!is_buffering && (backend_state_ == BACKEND_STATE_PAUSED)) { // Once we finish buffering, we need to honour the desired playback rate // (rather than just resuming). This way, if playback was paused while // buffering, it will remain paused rather than incorrectly resuming. - SetPlaybackRate(target_playback_rate_); - return; - } - // Do not consume data in a rebuffering phase. - if (!paused_) { - paused_ = true; - media_pipeline_backend_->Pause(); + SetPlaybackRate(playback_rate_); } } void MediaPipelineImpl::UpdateMediaTime() { pending_time_update_task_ = false; - if (!backend_started_) + if ((backend_state_ != BACKEND_STATE_PLAYING) && + (backend_state_ != BACKEND_STATE_PAUSED)) return; if (statistics_rolling_counter_ == 0) { diff --git a/chromecast/media/cma/pipeline/media_pipeline_impl.h b/chromecast/media/cma/pipeline/media_pipeline_impl.h index 6f6c8d6..6773643 100644 --- a/chromecast/media/cma/pipeline/media_pipeline_impl.h +++ b/chromecast/media/cma/pipeline/media_pipeline_impl.h @@ -66,6 +66,12 @@ class MediaPipelineImpl { void SetCdm(BrowserCdmCast* cdm); private: + enum BackendState { + BACKEND_STATE_UNINITIALIZED, + BACKEND_STATE_INITIALIZED, + BACKEND_STATE_PLAYING, + BACKEND_STATE_PAUSED + }; struct FlushTask; void OnFlushDone(bool is_audio_stream); @@ -82,22 +88,20 @@ class MediaPipelineImpl { BrowserCdmCast* cdm_; // Interface with the underlying hardware media pipeline. + BackendState backend_state_; + // Playback rate set by the upper layer. + // Cached here because CMA pipeline backend does not support rate == 0, + // which is emulated by pausing the backend. + float playback_rate_; scoped_ptr<MediaPipelineBackend> media_pipeline_backend_; scoped_ptr<AudioDecoderSoftwareWrapper> audio_decoder_; MediaPipelineBackend::VideoDecoder* video_decoder_; - bool backend_initialized_; scoped_ptr<AudioPipelineImpl> audio_pipeline_; scoped_ptr<VideoPipelineImpl> video_pipeline_; scoped_ptr<FlushTask> pending_flush_task_; - // Whether or not the backend is currently paused. - bool paused_; - // Playback rate set by the upper layer. - float target_playback_rate_; - // The media time is retrieved at regular intervals. - bool backend_started_; // Whether or not the backend is playing/paused. bool pending_time_update_task_; base::TimeDelta last_media_time_; diff --git a/chromecast/renderer/media/cma_renderer.cc b/chromecast/renderer/media/cma_renderer.cc index 088ebb8..41ef271 100644 --- a/chromecast/renderer/media/cma_renderer.cc +++ b/chromecast/renderer/media/cma_renderer.cc @@ -431,17 +431,6 @@ void CmaRenderer::OnBufferingNotification( ::media::BufferingState buffering_state) { CMALOG(kLogControl) << __FUNCTION__ << ": state=" << state_ << ", buffering=" << buffering_state; - // TODO(gunsch): WebMediaPlayerImpl currently only handles HAVE_ENOUGH while - // playing. See OnPipelineBufferingStateChanged, http://crbug.com/144683. - if (state_ != kPlaying) { - LOG(WARNING) << "Ignoring buffering notification in state: " << state_; - return; - } - if (buffering_state != ::media::BUFFERING_HAVE_ENOUGH) { - LOG(WARNING) << "Ignoring buffering notification during playing: " - << buffering_state; - return; - } buffering_state_cb_.Run(buffering_state); } |