// Copyright 2014 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. #ifndef MEDIA_RENDERERS_RENDERER_IMPL_H_ #define MEDIA_RENDERERS_RENDERER_IMPL_H_ #include "base/memory/ref_counted.h" #include "base/memory/scoped_ptr.h" #include "base/memory/weak_ptr.h" #include "base/synchronization/lock.h" #include "base/time/clock.h" #include "base/time/default_tick_clock.h" #include "base/time/time.h" #include "media/base/buffering_state.h" #include "media/base/decryptor.h" #include "media/base/media_export.h" #include "media/base/pipeline_status.h" #include "media/base/renderer.h" namespace base { class SingleThreadTaskRunner; } namespace media { class AudioRenderer; class DemuxerStreamProvider; class TimeSource; class VideoRenderer; class WallClockTimeSource; class MEDIA_EXPORT RendererImpl : public Renderer { public: // Renders audio/video streams using |audio_renderer| and |video_renderer| // provided. All methods except for GetMediaTime() run on the |task_runner|. // GetMediaTime() runs on the render main thread because it's part of JS sync // API. RendererImpl(const scoped_refptr& task_runner, scoped_ptr audio_renderer, scoped_ptr video_renderer); ~RendererImpl() final; // Renderer implementation. void Initialize(DemuxerStreamProvider* demuxer_stream_provider, const PipelineStatusCB& init_cb, const StatisticsCB& statistics_cb, const BufferingStateCB& buffering_state_cb, const PaintCB& paint_cb, const base::Closure& ended_cb, const PipelineStatusCB& error_cb, const base::Closure& waiting_for_decryption_key_cb) final; void SetCdm(CdmContext* cdm_context, const CdmAttachedCB& cdm_attached_cb) final; void Flush(const base::Closure& flush_cb) final; void StartPlayingFrom(base::TimeDelta time) final; void SetPlaybackRate(float playback_rate) final; void SetVolume(float volume) final; base::TimeDelta GetMediaTime() final; bool HasAudio() final; bool HasVideo() final; // Helper functions for testing purposes. Must be called before Initialize(). void DisableUnderflowForTesting(); void EnableClocklessVideoPlaybackForTesting(); private: enum State { STATE_UNINITIALIZED, STATE_INITIALIZING, STATE_FLUSHING, STATE_PLAYING, STATE_ERROR }; base::TimeDelta GetMediaTimeForSyncingVideo(); // Requests that this object notifies when a decryptor is ready through the // |decryptor_ready_cb| provided. // If |decryptor_ready_cb| is null, the existing callback will be fired with // nullptr immediately and reset. void SetDecryptorReadyCallback(const DecryptorReadyCB& decryptor_ready_cb); // Helper functions and callbacks for Initialize(). void InitializeAudioRenderer(); void OnAudioRendererInitializeDone(PipelineStatus status); void InitializeVideoRenderer(); void OnVideoRendererInitializeDone(PipelineStatus status); // Helper functions and callbacks for Flush(). void FlushAudioRenderer(); void OnAudioRendererFlushDone(); void FlushVideoRenderer(); void OnVideoRendererFlushDone(); // Callback executed by filters to update statistics. void OnUpdateStatistics(const PipelineStatistics& stats); // Collection of callback methods and helpers for tracking changes in // buffering state and transition from paused/underflow states and playing // states. // // While in the kPlaying state: // - A waiting to non-waiting transition indicates preroll has completed // and StartPlayback() should be called // - A non-waiting to waiting transition indicates underflow has occurred // and PausePlayback() should be called void OnBufferingStateChanged(BufferingState* buffering_state, BufferingState new_buffering_state); bool WaitingForEnoughData() const; void PausePlayback(); void StartPlayback(); // Callbacks executed when a renderer has ended. void OnAudioRendererEnded(); void OnVideoRendererEnded(); bool PlaybackHasEnded() const; void RunEndedCallbackIfNeeded(); // Callback executed when a runtime error happens. void OnError(PipelineStatus error); State state_; // Task runner used to execute pipeline tasks. scoped_refptr task_runner_; DemuxerStreamProvider* demuxer_stream_provider_; // Permanent callbacks to notify various renderer states/stats. StatisticsCB statistics_cb_; base::Closure ended_cb_; PipelineStatusCB error_cb_; BufferingStateCB buffering_state_cb_; PaintCB paint_cb_; base::Closure waiting_for_decryption_key_cb_; // Temporary callback used for Initialize() and Flush(). PipelineStatusCB init_cb_; base::Closure flush_cb_; scoped_ptr audio_renderer_; scoped_ptr video_renderer_; // Renderer-provided time source used to control playback. TimeSource* time_source_; scoped_ptr wall_clock_time_source_; bool time_ticking_; // The time to start playback from after starting/seeking has completed. base::TimeDelta start_time_; BufferingState audio_buffering_state_; BufferingState video_buffering_state_; // Whether we've received the audio/video ended events. bool audio_ended_; bool video_ended_; CdmContext* cdm_context_; // Callback registered by filters (decoder or demuxer) to be informed of a // Decryptor. // Note: We could have multiple filters registering this callback. One // callback is okay because: // 1, We always initialize filters in sequence. // 2, Filter initialization will not finish until this callback is satisfied. DecryptorReadyCB decryptor_ready_cb_; bool underflow_disabled_for_testing_; bool clockless_video_playback_enabled_for_testing_; base::WeakPtr weak_this_; base::WeakPtrFactory weak_factory_; DISALLOW_COPY_AND_ASSIGN(RendererImpl); }; } // namespace media #endif // MEDIA_RENDERERS_RENDERER_IMPL_H_