#include "base/cancelable_callback.h"
#include "base/compiler_specific.h"
-#include "base/memory/memory_pressure_listener.h"
+#include "base/memory/raw_ptr.h"
#include "base/memory/ref_counted.h"
#include "base/memory/scoped_refptr.h"
#include "base/memory/weak_ptr.h"
+#include "base/task/sequenced_task_runner.h"
#include "base/threading/thread.h"
#include "base/time/default_tick_clock.h"
#include "base/time/time.h"
#include "base/timer/timer.h"
#include "build/build_config.h"
#include "media/base/cdm_config.h"
+#include "media/base/data_source.h"
+#include "media/base/demuxer.h"
+#include "media/base/eme_constants.h"
#include "media/base/encryption_scheme.h"
#include "media/base/media_observer.h"
#include "media/base/media_tracks.h"
#include "media/base/renderer_factory_selector.h"
#include "media/base/routing_token_callback.h"
#include "media/base/simple_watch_timer.h"
-#include "media/base/text_track.h"
+#include "media/filters/demuxer_manager.h"
#include "media/mojo/mojom/media_metrics_provider.mojom.h"
#include "media/mojo/mojom/playback_events_recorder.mojom.h"
#include "media/renderers/paint_canvas_video_renderer.h"
#include "third_party/blink/public/platform/web_media_player.h"
#include "third_party/blink/public/platform/web_surface_layer_bridge.h"
#include "third_party/blink/public/web/modules/media/webmediaplayer_util.h"
+#include "third_party/blink/renderer/platform/allow_discouraged_type.h"
#include "third_party/blink/renderer/platform/media/learning_experiment_helper.h"
#include "third_party/blink/renderer/platform/media/multi_buffer_data_source.h"
#include "third_party/blink/renderer/platform/media/smoothness_helper.h"
namespace media {
class CdmContextRef;
class ChunkDemuxer;
-class DataSource;
class Demuxer;
class MediaLog;
class MemoryDumpProviderProxy;
public WebMediaPlayerDelegate::Observer,
public media::Pipeline::Client,
public media::MediaObserverClient,
+ public media::DemuxerManager::Client,
public WebSurfaceLayerBridgeObserver,
public SmoothnessHelper::Client {
public:
media::MediaPlayerLoggingID player_id,
WebMediaPlayerBuilder::DeferLoadCB defer_load_cb,
scoped_refptr<media::SwitchableAudioRendererSink> audio_renderer_sink,
- scoped_refptr<base::SingleThreadTaskRunner> media_task_runner,
+ scoped_refptr<base::SequencedTaskRunner> media_task_runner,
scoped_refptr<base::TaskRunner> worker_task_runner,
scoped_refptr<base::SingleThreadTaskRunner> compositor_task_runner,
scoped_refptr<base::SingleThreadTaskRunner>
mojo::PendingRemote<media::mojom::MediaMetricsProvider> metrics_provider,
CreateSurfaceLayerBridgeCB create_bridge_callback,
scoped_refptr<viz::RasterContextProvider> raster_context_provider,
+#if defined(TIZEN_VIDEO_HOLE)
+ bool is_video_hole,
+#endif
bool use_surface_layer,
bool is_background_suspend_enabled,
bool is_background_video_play_enabled,
void SetPreload(WebMediaPlayer::Preload preload) override;
WebTimeRanges Buffered() const override;
WebTimeRanges Seekable() const override;
+#if defined(TIZEN_MULTIMEDIA)
+ void Suspend() override;
+ void Resume() override;
+
+ bool SuspendedByPlayer() override { return was_suspended_by_player_; }
+#endif
void OnFrozen() override;
const gfx::Rect& rect,
cc::PaintFlags& flags) override;
scoped_refptr<media::VideoFrame> GetCurrentFrameThenUpdate() override;
- absl::optional<int> CurrentFrameId() const override;
+ absl::optional<media::VideoFrame::ID> CurrentFrameId() const override;
media::PaintCanvasVideoRenderer* GetPaintCanvasVideoRenderer() override;
// True if the loaded media has a playable video/audio track.
bool Seeking() const override;
double Duration() const override;
virtual double timelineOffset() const;
- double CurrentTime() const override;
bool IsEnded() const override;
+ // Shared between the WebMediaPlayer and DemuxerManager::Client interfaces.
+ double CurrentTime() const override;
+
bool PausedWhenHidden() const override;
// Internal states of loading and network.
void SuspendForFrameClosed() override;
bool HasAvailableVideoFrame() const override;
+ bool HasReadableVideoFrame() const override;
scoped_refptr<WebAudioSourceProviderImpl> GetAudioSourceProvider() override;
void OnFrameHidden() override;
void OnFrameShown() override;
void OnIdleTimeout() override;
+
void RequestRemotePlaybackDisabled(bool disabled) override;
+ void RequestMediaRemoting() override;
#if BUILDFLAG(IS_ANDROID)
// TODO(https://crbug.com/839651): Rename Flinging[Started/Stopped] to
friend class WebMediaPlayerImplTest;
friend class WebMediaPlayerImplBackgroundBehaviorTest;
+ // Helper function that can be used for generating different UMA records:
+ // |key| is the UMA prefix, such as "Media.TimeToPlayReady", for example.
+ // |UmaFunction| is some UMA function, like base::UmaHistogramMediumTimes
+ // which the record actually gets logged with
+ // |T...| are the arguments passed. Usually this is only one piece of data,
+ // such as a base::TimeDelta, in the case of UmaHistogramMediumTimes,
+ // but could also be a series of fields that customize bucket sizes
+ // or the like.
+ //
+ // Finally, the |Flags| template argument is used to determine which suffixes
+ // are logged - An integer enum is provided |SplitHistogramTypes| which is
+ // a bitmask, and can be used to require logging:
+ // PlaybackType: {".SRC", ".MSE", ".HLS" (in the future)} based on demuxer
+ // type
+ // Encrypted: {".EME"} based on the value of |is_encrypted_|
+ // All: {".All"} all the time.
+ // |Flags| is provided as a template argument instead of a function argument
+ // in order to guard different components in "if constexpr" conditionals,
+ // so we won't even compile in strings such as "Media.TimeToPlayReady.All"
+ // if it's not specified.
+ template <uint32_t Flags, typename... T>
+ void WriteSplitHistogram(void (*UmaFunction)(const std::string&, T...),
+ const std::string& key,
+ const T&... value);
+
void EnableOverlay();
void DisableOverlay();
void OnBeforePipelineResume();
void OnPipelineResumed();
void OnPipelineSeeked(bool time_updated);
- void OnDemuxerOpened();
// media::Pipeline::Client overrides.
void OnError(media::PipelineStatus status) override;
media::BufferingState state,
media::BufferingStateChangeReason reason) override;
void OnDurationChange() override;
- void OnAddTextTrack(const media::TextTrackConfig& config,
- media::AddTextTrackDoneCB done_cb) override;
+#if BUILDFLAG(IS_TIZEN_TV)
+ void SetParentalRatingResult(bool is_pass) override;
+#endif
void OnWaiting(media::WaitingReason reason) override;
void OnAudioConfigChange(const media::AudioDecoderConfig& config) override;
void OnVideoConfigChange(const media::VideoDecoderConfig& config) override;
void OnVideoAverageKeyframeDistanceUpdate() override;
void OnAudioPipelineInfoChange(const media::AudioPipelineInfo& info) override;
void OnVideoPipelineInfoChange(const media::VideoPipelineInfo& info) override;
+#if defined(TIZEN_MULTIMEDIA)
+ void OnSeekableTimeChange(base::TimeDelta min_time,
+ base::TimeDelta max_time,
+ bool is_live) override;
+ void OnLivePlaybackComplete() override;
+
+ // Called if a player in the browser process is suspended.
+ void OnRequestSuspend(bool resource_conflicted) override;
+
+ void FullscreenModeToggled();
+#endif
+
+ // media::DemuxerManager::Client overrides.
+ void OnChunkDemuxerOpened(media::ChunkDemuxer* demuxer) override;
+ void OnProgress() override;
+ void OnEncryptedMediaInitData(media::EmeInitDataType init_data_type,
+ const std::vector<uint8_t>& init_data) override;
+ void MakeDemuxerThreadDumper(media::Demuxer* demuxer) override;
+ bool CouldPlayIfEnoughData() override;
+ bool IsMediaPlayerRendererClient() override;
+ void StopForDemuxerReset() override;
+ void RestartForHls() override;
+ bool IsSecurityOriginCryptographic() const override;
+ void UpdateLoadedUrl(const GURL& url) override;
+ void DemuxerRequestsSeek(base::TimeDelta seek_time) override;
+
+#if BUILDFLAG(ENABLE_FFMPEG)
+ void AddAudioTrack(const std::string& id,
+ const std::string& label,
+ const std::string& language,
+ bool is_first_track) override;
+ void AddVideoTrack(const std::string& id,
+ const std::string& label,
+ const std::string& language,
+ bool is_first_track) override;
+#endif // BUILDFLAG(ENABLE_FFMPEG)
+
+#if BUILDFLAG(ENABLE_HLS_DEMUXER)
+ void GetUrlData(const GURL& gurl,
+ base::OnceCallback<void(scoped_refptr<UrlData>)> cb);
+ base::SequenceBound<media::HlsDataSourceProvider> GetHlsDataSourceProvider()
+ override;
+#endif // BUILDFLAG(ENABLE_HLS_DEMUXER)
// Simplified watch time reporting.
void OnSimpleWatchTimerTick();
CorsMode cors_mode,
bool is_cache_disabled);
- // Called after asynchronous initialization of a data source completed.
+ // Called after synchronous initialization of a data source completes.
void DataSourceInitialized(bool success);
+ // Called after asynchronous initialization of a multibuffer data source
+ // completes.
+ void MultiBufferDataSourceInitialized(bool success);
+
+ // Called after synchronous or asynchronous MemoryDataSource initialization.
+ void MemoryDataSourceInitialized(bool success, size_t data_size);
+
// Called if the |MultiBufferDataSource| is redirected.
void OnDataSourceRedirected();
// Can return a nullptr.
scoped_refptr<media::VideoFrame> GetCurrentFrameFromCompositor() const;
- // Called when the demuxer encounters encrypted streams.
- void OnEncryptedMediaInitData(media::EmeInitDataType init_data_type,
- const std::vector<uint8_t>& init_data);
-
- // Called when the FFmpegDemuxer encounters new media tracks. This is only
- // invoked when using FFmpegDemuxer, since MSE/ChunkDemuxer handle media
- // tracks separately in WebSourceBufferImpl.
- void OnFFmpegMediaTracksUpdated(std::unique_ptr<media::MediaTracks> tracks);
-
// Sets CdmContext from |cdm| on the pipeline and calls OnCdmAttached()
// when done.
void SetCdmInternal(WebContentDecryptionModule* cdm);
void SetMemoryReportingState(bool is_memory_reporting_enabled);
void SetSuspendState(bool is_suspended);
- void SetDemuxer(std::unique_ptr<media::Demuxer> demuxer);
-
// Called at low frequency to tell external observers how much memory we're
// using for video playback. Called by |memory_usage_reporting_timer_|.
// Memory usage reporting is done in two steps, because |demuxer_| must be
const base::trace_event::MemoryDumpArgs& args,
base::trace_event::ProcessMemoryDump* pmd);
- void OnMemoryPressure(
- base::MemoryPressureListener::MemoryPressureLevel memory_pressure_level);
-
// Called during OnHidden() when we want a suspended player to enter the
// paused state after some idle timeout.
void ScheduleIdlePauseTimer();
// Returns true if the player is hidden.
bool IsHidden() const;
- // Returns true if the player's source is streaming.
+ // Returns true if the player is in streaming mode, meaning that the source
+ // or the demuxer doesn't support timeline or seeking.
bool IsStreaming() const;
// Return whether |pipeline_metadata_| is compatible with an overlay. This
// pipeline's state.
bool ShouldDisableVideoWhenHidden() const;
- // Whether the video is suitable for background playback optimizations (either
- // pausing it or disabling the video track). Uses metadata so has meaning only
- // after the pipeline has started, otherwise returns false.
- // The logical OR between the two methods above that is also used as their
- // common implementation.
- bool IsBackgroundOptimizationCandidate() const;
-
// If enabling or disabling background video optimization has been delayed,
// because of the pipeline not running, seeking or resuming, this method
// needs to be called to update the optimization state.
// handling a src= or MSE based playback.
void RecordUnderflowDuration(base::TimeDelta duration);
- // Called by the data source (for src=) or demuxer (for mse) when loading
- // progresses.
- // Can be called quite often.
- void OnProgress();
-
// Returns true when we estimate that we can play the rest of the media
// without buffering.
bool CanPlayThrough();
base::TimeDelta GetCurrentTimeInternal() const;
// Called by the compositor the very first time a frame is received.
- void OnFirstFrame(base::TimeTicks frame_time);
-
- // Records timing metrics for three UMA metrics: #key.SRC, #key.MSE, and
- // #key.EME. The SRC and MSE ones are mutually exclusive based on the presence
- // of |chunk_demuxer_|, while the EME one is only recorded if |is_encrypted_|.
- void RecordTimingUMA(const std::string& key, base::TimeDelta elapsed);
+ void OnFirstFrame(base::TimeTicks frame_time, bool is_frame_readable);
// Records the encryption scheme used by the stream |stream_name|. This is
// only recorded when metadata is available.
// RequestAnimationFrame() is called.
void OnNewFramePresentedCallback();
- // Notifies |mb_data_source_| of playback and rate changes which may increase
+ // Notifies |demuxer_manager_| of playback and rate changes which may increase
// the amount of data the DataSource buffers. Does nothing prior to reaching
// kReadyStateHaveEnoughData for the first time.
void MaybeUpdateBufferSizesForPlayback();
// Returns true if the video frame from this player are being captured.
bool IsVideoBeingCaptured() const;
+#if defined(TIZEN_VIDEO_HOLE)
+ bool ShouldUseVideoHole() const;
+ void CreateVideoHoleFrame();
+ void OnDrawableContentRectChanged(gfx::Rect rect, bool is_video);
+ bool UpdateBoundaryRectangle();
+ void StartLayerBoundUpdateTimer();
+ void StopLayerBoundUpdateTimer();
+ void OnLayerBoundUpdateTimerFired();
+#endif
+
// Report UMAs when this object instance is destroyed.
void ReportSessionUMAs() const;
- WebLocalFrame* const frame_;
+ absl::optional<media::DemuxerType> GetDemuxerType() const;
+
+ // Useful to bind for a cb to be called when a demuxer is created.
+ media::PipelineStatus OnDemuxerCreated(media::Demuxer* demuxer,
+ media::Pipeline::StartType start_type,
+ bool is_streaming,
+ bool is_static);
+
+ // Notifies the `client_` and the `delegate_` about metadata change.
+ void DidMediaMetadataChange();
+
+ const raw_ptr<WebLocalFrame, ExperimentalRenderer> frame_;
WebMediaPlayer::NetworkState network_state_ =
WebMediaPlayer::kNetworkStateEmpty;
WebMediaPlayer::ReadyState highest_ready_state_ =
WebMediaPlayer::kReadyStateHaveNothing;
- // Preload state for when |data_source_| is created after setPreload().
- MultiBufferDataSource::Preload preload_ = MultiBufferDataSource::METADATA;
+ // Preload state for when a DataSource is created after setPreload().
+ media::DataSource::Preload preload_ = media::DataSource::METADATA;
// Poster state (for UMA reporting).
bool has_poster_ = false;
// Task runner for posting tasks on Chrome's main thread. Also used
// for DCHECKs so methods calls won't execute in the wrong thread.
const scoped_refptr<base::SingleThreadTaskRunner> main_task_runner_;
- const scoped_refptr<base::SingleThreadTaskRunner> media_task_runner_;
+ const scoped_refptr<base::SequencedTaskRunner> media_task_runner_;
const scoped_refptr<base::TaskRunner> worker_task_runner_;
// This is the ID that is used within the internals of the media element
bool overlay_enabled_ = false;
+ // Cors and Caching flags set during `Load` and used while creating demuxers.
+ CorsMode cors_mode_ = kCorsModeUnspecified;
+ bool is_cache_disabled_ = false;
+
// Whether the current decoder requires a restart on overlay transitions.
bool decoder_requires_restart_for_overlay_ = false;
- WebMediaPlayerClient* const client_;
- WebMediaPlayerEncryptedMediaClient* const encrypted_client_;
+ const raw_ptr<WebMediaPlayerClient, ExperimentalRenderer> client_;
+ const raw_ptr<WebMediaPlayerEncryptedMediaClient, ExperimentalRenderer>
+ encrypted_client_;
// WebMediaPlayer notifies the |delegate_| of playback state changes using
// |delegate_id_|; an id provided after registering with the delegate. The
// before the frame is destroyed). RenderFrameImpl owns |delegate_| and is
// guaranteed to outlive |this|; thus it is safe to store |delegate_| as a raw
// pointer.
- WebMediaPlayerDelegate* delegate_;
+ raw_ptr<WebMediaPlayerDelegate, ExperimentalRenderer> delegate_;
int delegate_id_ = 0;
// The playback state last reported to |delegate_|, to avoid setting duplicate
// Routes audio playback to either AudioRendererSink or WebAudio.
scoped_refptr<WebAudioSourceProviderImpl> audio_source_provider_;
- // These two are mutually exclusive:
- // |data_source_| is used for regular resource loads.
- // |chunk_demuxer_| is used for Media Source resource loads.
- //
- // |demuxer_| will contain the appropriate demuxer based on which resource
- // load strategy we're using.
- MultiBufferDataSource* mb_data_source_ = nullptr;
- std::unique_ptr<media::DataSource> data_source_;
- std::unique_ptr<media::Demuxer> demuxer_;
- media::ChunkDemuxer* chunk_demuxer_ = nullptr;
-
- std::unique_ptr<base::MemoryPressureListener> memory_pressure_listener_;
+ // Manages the lifetime of the DataSource, and soon the Demuxer.
+ std::unique_ptr<media::DemuxerManager> demuxer_manager_;
- const base::TickClock* tick_clock_ = nullptr;
+ raw_ptr<const base::TickClock, ExperimentalRenderer> tick_clock_ = nullptr;
std::unique_ptr<BufferedDataSourceHostImpl> buffered_data_source_host_;
- UrlIndex* const url_index_;
+ const raw_ptr<UrlIndex, ExperimentalRenderer> url_index_;
scoped_refptr<viz::RasterContextProvider> raster_context_provider_;
// Video rendering members.
// unimportant.
bool suppress_destruction_errors_ = false;
- // TODO(dalecurtis): The following comment is inaccurate as this value is also
- // used for, for example, data URLs.
- // Used for HLS playback and in certain fallback paths (e.g. on older devices
- // that can't support the unified media pipeline).
- GURL loaded_url_;
-
// NOTE: |using_media_player_renderer_| is set based on the usage of a
// MediaResource::Type::URL in StartPipeline(). This works because
// MediaPlayerRendererClientFactory is the only factory that uses
// Stores the current position state of the media.
media_session::MediaPosition media_position_state_;
- // Set whenever the demuxer encounters an HLS file.
- // This flag is distinct from |using_media_player_renderer_|, because on older
- // devices we might use MediaPlayerRenderer for non HLS playback.
- bool demuxer_found_hls_ = false;
-
// Called sometime after the media is suspended in a playing state in
// OnFrameHidden(), causing the state to change to paused.
base::OneShotTimer background_pause_timer_;
// playback optimizations (MSE).
base::TimeDelta max_keyframe_distance_to_disable_background_video_mse_;
- // When MSE memory pressure based garbage collection is enabled, the
- // |enable_instant_source_buffer_gc| controls whether the GC is done
- // immediately on memory pressure notification or during the next SourceBuffer
- // append (slower, but MSE spec compliant).
- bool enable_instant_source_buffer_gc_ = false;
-
// Whether disabled the video track as an optimization.
bool video_track_disabled_ = false;
// to false as soon as |has_first_frame_| is set to true.
bool needs_first_frame_ = false;
+ // Whether the rendered frame is readable, e.g. can be converted to image.
+ bool is_frame_readable_ = false;
+
// True if StartPipeline() completed a lazy load startup.
bool did_lazy_load_ = false;
// Whether background video optimization is supported on current platform.
bool is_background_video_track_optimization_supported_ = true;
+ const bool should_pause_background_muted_audio_;
+
bool was_suspended_for_frame_closed_ = false;
+#if defined(TIZEN_MULTIMEDIA)
+ bool was_suspended_by_player_ = false;
+
+ // used for live streams.
+ bool is_live_stream_ = false;
+ base::TimeDelta min_seekable_time_;
+ base::TimeDelta max_seekable_time_;
+#endif
+
+ // Request pipeline to suspend. It should not block other signals after
+ // suspended.
+ bool pending_oneshot_suspend_ = false;
+
base::CancelableOnceClosure have_enough_after_lazy_load_cb_;
- media::RendererType renderer_type_ = media::RendererType::kDefault;
+ media::RendererType renderer_type_ = media::RendererType::kRendererImpl;
media::SimpleWatchTimer simple_watch_timer_;
LearningExperimentHelper will_play_helper_;
- // Stores the optional override Demuxer until it is used in DoLoad().
- std::unique_ptr<media::Demuxer> demuxer_override_;
+#if defined(TIZEN_VIDEO_HOLE)
+ bool is_video_hole_;
+ gfx::RectF last_computed_rect_;
+ base::RepeatingTimer layer_bound_update_timer_;
+#endif
std::unique_ptr<PowerStatusHelper> power_status_helper_;