blob: 8cce4fc2b41f1807323319761ae1fd851929982c [file] [log] [blame]
// Copyright 2022 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef MEDIA_FILTERS_DEMUXER_MANAGER_H_
#define MEDIA_FILTERS_DEMUXER_MANAGER_H_
#include <vector>
#include "base/functional/callback.h"
#include "base/memory/memory_pressure_listener.h"
#include "base/memory/raw_ptr.h"
#include "base/memory/weak_ptr.h"
#include "base/task/sequenced_task_runner.h"
#include "media/base/data_source.h"
#include "media/base/demuxer.h"
#include "media/base/eme_constants.h"
#include "media/base/media_export.h"
#include "media/base/media_log.h"
#include "media/base/pipeline.h"
#include "media/base/pipeline_status.h"
#include "media/filters/chunk_demuxer.h"
#include "third_party/abseil-cpp/absl/types/optional.h"
#include "url/gurl.h"
#include "url/origin.h"
#if BUILDFLAG(ENABLE_HLS_DEMUXER)
#include "base/threading/sequence_bound.h"
#include "media/filters/hls_data_source_provider.h"
#endif // BUILDFLAG(ENABLE_HLS_DEMUXER)
namespace media {
enum class HlsFallbackImplementation {
kNone,
kMediaPlayer,
kBuiltinHlsPlayer,
};
// This class manages both an implementation of media::Demuxer and of
// media::DataSource. DataSource, in particular may be null, since both MSE
// playback and Android's MediaPlayerRenderer do not make use of it. In the
// case that DataSource is present, these objects should have a similar
// lifetime, and both must be destroyed on the media thread, so owning them
// together makes sense. Additionally, the demuxer or data source can change
// during the lifetime of the player that owns them, so encapsulating that
// change logic separately lets the media player impl (WMPI) be a bit simpler,
// and dedicate a higher percentage of its complexity to managing playback
// state.
class MEDIA_EXPORT DemuxerManager {
public:
class Client {
public:
virtual void OnEncryptedMediaInitData(
EmeInitDataType init_data_type,
const std::vector<uint8_t>& init_data) = 0;
virtual void OnChunkDemuxerOpened(ChunkDemuxer* demuxer) = 0;
// Called by the data source (for src=) or demuxer (for mse) when loading
// progresses.
// Can be called quite often.
virtual void OnProgress() = 0;
// Used to determine if the client is additionally a client for Android's
// MediaPlayerRenderer, which can inform us if we need to create a
// MediaUrlDemuxer.
virtual bool IsMediaPlayerRendererClient() = 0;
virtual void OnError(media::PipelineStatus status) = 0;
// Used for controlling the client when a demuxer swap happens.
virtual void StopForDemuxerReset() = 0;
virtual void RestartForHls() = 0;
virtual bool IsSecurityOriginCryptographic() const = 0;
#if BUILDFLAG(ENABLE_FFMPEG)
virtual void AddAudioTrack(const std::string& id,
const std::string& label,
const std::string& language,
bool is_first_track) = 0;
virtual void AddVideoTrack(const std::string& id,
const std::string& label,
const std::string& language,
bool is_first_track) = 0;
#endif // BUILDFLAG(ENABLE_FFMPEG)
#if BUILDFLAG(ENABLE_HLS_DEMUXER)
virtual base::SequenceBound<HlsDataSourceProvider>
GetHlsDataSourceProvider() = 0;
#endif // BUILDFLAG(ENABLE_HLS_DEMUXER)
// Returns true if playback would be able to start if data is present.
virtual bool CouldPlayIfEnoughData() = 0;
// Given a demuxer, the client should construct an implementation of
// base::trace_event::MemoryDumpProvider for debugging purposes.
virtual void MakeDemuxerThreadDumper(media::Demuxer* demuxer) = 0;
virtual double CurrentTime() const = 0;
// Allows us to set a loaded url on the client, which might happen when we
// handle a redirect as part of a restart for switching to HLS.
virtual void UpdateLoadedUrl(const GURL& url) = 0;
};
// Demuxer, StartType, IsStreaming, IsStatic
using DemuxerCreatedCB =
base::OnceCallback<PipelineStatus(Demuxer* demuxer,
Pipeline::StartType start_type,
bool /*is_streaming*/,
bool /*is_static*/)>;
DemuxerManager(Client* client,
scoped_refptr<base::SequencedTaskRunner> media_task_runner,
MediaLog* log,
net::SiteForCookies site_for_cookies,
url::Origin top_frame_origin,
bool has_storage_access,
bool enable_instant_source_buffer_gc,
std::unique_ptr<Demuxer> demuxer_override);
~DemuxerManager();
void InvalidateWeakPtrs();
void OnPipelineError(PipelineStatus error);
void SetLoadedUrl(GURL url);
#if BUILDFLAG(ENABLE_HLS_DEMUXER) || BUILDFLAG(IS_ANDROID)
void PopulateHlsHistograms(bool cryptographic_url);
PipelineStatus SelectHlsFallbackMechanism(bool cryptographic_url);
#endif // BUILDFLAG(ENABLE_HLS_DEMUXER) || BUILDFLAG(IS_ANDROID)
void DisallowFallback();
// Methods that help manage demuxers
absl::optional<double> GetDemuxerDuration();
absl::optional<DemuxerType> GetDemuxerType();
absl::optional<container_names::MediaContainerName> GetContainerForMetrics();
void RespondToDemuxerMemoryUsageReport(base::OnceCallback<void(int64_t)> cb);
void DisableDemuxerCanChangeType();
// Returns a forwarded error/success from |on_demuxer_created|, or an error
// if a demuxer couldn't be created.
PipelineStatus CreateDemuxer(bool load_media_source,
DataSource::Preload preload,
bool has_poster,
DemuxerCreatedCB on_demuxer_created);
#if BUILDFLAG(IS_ANDROID)
void SetAllowMediaPlayerRendererCredentials(bool allow);
#endif // BUILDFLAG(IS_ANDROID)
// Methods that help manage or access |data_source_|
const DataSource* GetDataSourceForTesting() const;
void SetDataSource(std::unique_ptr<DataSource> data_source);
void OnBufferingHaveEnough(bool enough);
void SetPreload(DataSource::Preload preload);
void StopAndResetClient(Client* client);
int64_t GetDataSourceMemoryUsage();
void OnDataSourcePlaybackRateChange(double rate, bool paused);
bool WouldTaintOrigin() const;
bool HasDataSource() const;
bool HasDemuxer() const;
bool HasDemuxerOverride() const;
absl::optional<GURL> GetDataSourceUrlAfterRedirects() const;
bool DataSourceFullyBuffered() const;
bool IsStreaming() const;
bool PassedDataSourceTimingAllowOriginCheck() const;
private:
// Demuxer creation and helper methods
std::unique_ptr<media::Demuxer> CreateChunkDemuxer();
#if BUILDFLAG(ENABLE_FFMPEG)
std::unique_ptr<media::Demuxer> CreateFFmpegDemuxer();
#endif // BUILDFLAG(ENABLE_FFMPEG)
#if BUILDFLAG(ENABLE_HLS_DEMUXER)
std::unique_ptr<Demuxer> CreateHlsDemuxer();
#endif
#if BUILDFLAG(IS_ANDROID)
std::unique_ptr<media::Demuxer> CreateMediaUrlDemuxer(bool hls_content);
#endif // BUILDFLAG(IS_ANDROID)
void SetDemuxer(std::unique_ptr<Demuxer> demuxer);
// Memory pressure listener specifically for when using ChunkDemuxer.
void OnMemoryPressure(
base::MemoryPressureListener::MemoryPressureLevel level);
// Trampoline methods for binding with |weak_this_| that call into |client_|.;
void OnEncryptedMediaInitData(EmeInitDataType init_data_type,
const std::vector<uint8_t>& init_data);
void OnChunkDemuxerOpened();
void OnProgress();
void RestartClientForHLS();
void FreeResourcesAfterMediaThreadWait(base::OnceClosure cb);
#if BUILDFLAG(ENABLE_FFMPEG)
void OnFFmpegMediaTracksUpdated(std::unique_ptr<MediaTracks> tracks);
#endif // BUILDFLAG(ENABLE_FFMPEG)
// This is usually just the WebMediaPlayerImpl.
raw_ptr<Client, DanglingUntriaged> client_;
// The demuxers need access the the media task runner and media log.
const scoped_refptr<base::SequencedTaskRunner> media_task_runner_;
std::unique_ptr<MediaLog> media_log_;
// Android's MediaUrlDemuxer needs access to these.
net::SiteForCookies site_for_cookies_;
url::Origin top_frame_origin_;
#if BUILDFLAG(IS_ANDROID)
bool has_storage_access_;
#endif // BUILDFLAG(IS_ANDROID)
// 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;
// Used for MediaUrlDemuxer when playing HLS content, as well as
// FFmpegDemuxer in most cases. Also used for creating MemoryDataSource
// objects.
GURL loaded_url_;
// The data source for creating a demuxer. This should be null when using
// ChunkDemuxer.
std::unique_ptr<DataSource> data_source_;
// Holds whichever demuxer implementation is being used.
std::unique_ptr<Demuxer> demuxer_;
// Holds an optional demuxer that can be passed in at time of creation,
// which becomes the default demuxer to use.
std::unique_ptr<Demuxer> demuxer_override_;
// RAII member for notifying demuxers of memory pressure.
std::unique_ptr<base::MemoryPressureListener> memory_pressure_listener_;
#if BUILDFLAG(IS_ANDROID)
// Used to determine whether to allow credentials or not for
// MediaPlayerRenderer.
bool allow_media_player_renderer_credentials_ = false;
#endif // BUILDFLAG(IS_ANDROID)
HlsFallbackImplementation hls_fallback_ = HlsFallbackImplementation::kNone;
// Are we allowed to switch demuxer mid-stream when fallback error codes
// are encountered
bool fallback_allowed_ = true;
// Weak pointer implementation.
base::WeakPtrFactory<DemuxerManager> weak_factory_{this};
};
} // namespace media
#endif // MEDIA_FILTERS_DEMUXER_MANAGER_H_