#include "media/filters/chunk_demuxer.h"
#include <algorithm>
#include <limits>
#include <memory>
#include <utility>
#include "base/functional/bind.h"
#include "base/functional/callback_helpers.h"
#include "base/memory/raw_ptr.h"
#include "base/not_fatal_until.h"
#include "base/strings/string_number_conversions.h"
#include "base/task/bind_post_task.h"
#include "base/trace_event/trace_event.h"
#include "media/base/audio_decoder_config.h"
#include "media/base/demuxer.h"
#include "media/base/media_tracks.h"
#include "media/base/mime_util.h"
#include "media/base/stream_parser.h"
#include "media/base/stream_parser_buffer.h"
#include "media/base/timestamp_constants.h"
#include "media/base/video_codecs.h"
#include "media/base/video_decoder_config.h"
#include "media/filters/frame_processor.h"
#include "media/filters/source_buffer_stream.h"
#include "media/filters/stream_parser_factory.h"
namespace {
std::unique_ptr<media::StreamParser> CreateParserForTypeAndCodecs(
const std::string& content_type,
const std::string& codecs,
media::MediaLog* media_log) { … }
std::string ExpectedCodecs(const std::string& content_type,
const std::string& codecs) { … }
}
namespace media {
ChunkDemuxerStream::ChunkDemuxerStream(Type type, MediaTrack::Id media_track_id)
: … { … }
void ChunkDemuxerStream::StartReturningData() { … }
void ChunkDemuxerStream::AbortReads() { … }
void ChunkDemuxerStream::CompletePendingReadIfPossible() { … }
void ChunkDemuxerStream::Shutdown() { … }
bool ChunkDemuxerStream::IsSeekWaitingForData() const { … }
void ChunkDemuxerStream::Seek(base::TimeDelta time) { … }
bool ChunkDemuxerStream::Append(const StreamParser::BufferQueue& buffers) { … }
void ChunkDemuxerStream::Remove(base::TimeDelta start,
base::TimeDelta end,
base::TimeDelta duration) { … }
bool ChunkDemuxerStream::EvictCodedFrames(base::TimeDelta media_time,
size_t newDataSize) { … }
void ChunkDemuxerStream::OnMemoryPressure(
base::TimeDelta media_time,
base::MemoryPressureListener::MemoryPressureLevel memory_pressure_level,
bool force_instant_gc) { … }
void ChunkDemuxerStream::OnSetDuration(base::TimeDelta duration) { … }
Ranges<base::TimeDelta> ChunkDemuxerStream::GetBufferedRanges(
base::TimeDelta duration) const { … }
base::TimeDelta ChunkDemuxerStream::GetLowestPresentationTimestamp() const { … }
base::TimeDelta ChunkDemuxerStream::GetHighestPresentationTimestamp() const { … }
base::TimeDelta ChunkDemuxerStream::GetBufferedDuration() const { … }
size_t ChunkDemuxerStream::GetMemoryUsage() const { … }
void ChunkDemuxerStream::OnStartOfCodedFrameGroup(DecodeTimestamp start_dts,
base::TimeDelta start_pts) { … }
bool ChunkDemuxerStream::UpdateAudioConfig(const AudioDecoderConfig& config,
bool allow_codec_change,
MediaLog* media_log) { … }
bool ChunkDemuxerStream::UpdateVideoConfig(const VideoDecoderConfig& config,
bool allow_codec_change,
MediaLog* media_log) { … }
void ChunkDemuxerStream::MarkEndOfStream() { … }
void ChunkDemuxerStream::UnmarkEndOfStream() { … }
void ChunkDemuxerStream::Read(uint32_t count, ReadCB read_cb) { … }
DemuxerStream::Type ChunkDemuxerStream::type() const { … }
StreamLiveness ChunkDemuxerStream::liveness() const { … }
AudioDecoderConfig ChunkDemuxerStream::audio_decoder_config() { … }
VideoDecoderConfig ChunkDemuxerStream::video_decoder_config() { … }
bool ChunkDemuxerStream::SupportsConfigChanges() { … }
bool ChunkDemuxerStream::IsEnabled() const { … }
void ChunkDemuxerStream::SetEnabled(bool enabled, base::TimeDelta timestamp) { … }
void ChunkDemuxerStream::SetStreamMemoryLimit(size_t memory_limit) { … }
void ChunkDemuxerStream::SetLiveness(StreamLiveness liveness) { … }
void ChunkDemuxerStream::ChangeState_Locked(State state) { … }
ChunkDemuxerStream::~ChunkDemuxerStream() = default;
void ChunkDemuxerStream::CompletePendingReadIfPossible_Locked() { … }
std::pair<SourceBufferStreamStatus, DemuxerStream::DecoderBufferVector>
ChunkDemuxerStream::GetPendingBuffers_Locked() { … }
ChunkDemuxer::ChunkDemuxer(
base::OnceClosure open_cb,
base::RepeatingClosure progress_cb,
EncryptedMediaInitDataCB encrypted_media_init_data_cb,
MediaLog* media_log)
: … { … }
std::string ChunkDemuxer::GetDisplayName() const { … }
DemuxerType ChunkDemuxer::GetDemuxerType() const { … }
void ChunkDemuxer::Initialize(DemuxerHost* host,
PipelineStatusCallback init_cb) { … }
void ChunkDemuxer::Stop() { … }
void ChunkDemuxer::Seek(base::TimeDelta time, PipelineStatusCallback cb) { … }
bool ChunkDemuxer::IsSeekable() const { … }
base::Time ChunkDemuxer::GetTimelineOffset() const { … }
std::vector<DemuxerStream*> ChunkDemuxer::GetAllStreams() { … }
base::TimeDelta ChunkDemuxer::GetStartTime() const { … }
int64_t ChunkDemuxer::GetMemoryUsage() const { … }
std::optional<container_names::MediaContainerName>
ChunkDemuxer::GetContainerForMetrics() const { … }
void ChunkDemuxer::AbortPendingReads() { … }
void ChunkDemuxer::StartWaitingForSeek(base::TimeDelta seek_time) { … }
void ChunkDemuxer::CancelPendingSeek(base::TimeDelta seek_time) { … }
ChunkDemuxer::Status ChunkDemuxer::AddId(
const std::string& id,
std::unique_ptr<AudioDecoderConfig> audio_config) { … }
ChunkDemuxer::Status ChunkDemuxer::AddId(
const std::string& id,
std::unique_ptr<VideoDecoderConfig> video_config) { … }
ChunkDemuxer::Status ChunkDemuxer::AddId(const std::string& id,
const std::string& content_type,
const std::string& codecs) { … }
#if BUILDFLAG(ENABLE_HLS_DEMUXER)
ChunkDemuxer::Status ChunkDemuxer::AddAutoDetectedCodecsId(
const std::string& id,
RelaxedParserSupportedType mime_type) {
DVLOG(1) << __func__ << " id=" << id
<< " content_type=" << static_cast<int>(mime_type);
base::AutoLock auto_lock(lock_);
if ((state_ != WAITING_FOR_INIT && state_ != INITIALIZING) ||
IsValidId_Locked(id)) {
return kReachedIdLimit;
}
CHECK(init_cb_);
std::unique_ptr<media::StreamParser> stream_parser =
StreamParserFactory::CreateRelaxedParser(mime_type);
if (!stream_parser) {
DVLOG(1) << __func__ << " failed: unsupported mime type for relaxed parser";
return kNotSupported;
}
return AddIdInternal(id, std::move(stream_parser), std::nullopt);
}
#endif
ChunkDemuxer::Status ChunkDemuxer::AddIdInternal(
const std::string& id,
std::unique_ptr<media::StreamParser> stream_parser,
std::optional<std::string_view> expected_codecs) { … }
void ChunkDemuxer::SetTracksWatcher(const std::string& id,
MediaTracksUpdatedCB tracks_updated_cb) { … }
void ChunkDemuxer::SetParseWarningCallback(
const std::string& id,
SourceBufferParseWarningCB parse_warning_cb) { … }
void ChunkDemuxer::RemoveId(const std::string& id) { … }
Ranges<base::TimeDelta> ChunkDemuxer::GetBufferedRanges(
const std::string& id) const { … }
base::TimeDelta ChunkDemuxer::GetLowestPresentationTimestamp(
const std::string& id) const { … }
base::TimeDelta ChunkDemuxer::GetHighestPresentationTimestamp(
const std::string& id) const { … }
void ChunkDemuxer::FindAndEnableProperTracks(
const std::vector<MediaTrack::Id>& track_ids,
base::TimeDelta curr_time,
DemuxerStream::Type track_type,
TrackChangeCB change_completed_cb) { … }
void ChunkDemuxer::OnEnabledAudioTracksChanged(
const std::vector<MediaTrack::Id>& track_ids,
base::TimeDelta curr_time,
TrackChangeCB change_completed_cb) { … }
void ChunkDemuxer::OnSelectedVideoTrackChanged(
const std::vector<MediaTrack::Id>& track_ids,
base::TimeDelta curr_time,
TrackChangeCB change_completed_cb) { … }
void ChunkDemuxer::DisableCanChangeType() { … }
void ChunkDemuxer::OnMemoryPressure(
base::TimeDelta currentMediaTime,
base::MemoryPressureListener::MemoryPressureLevel memory_pressure_level,
bool force_instant_gc) { … }
bool ChunkDemuxer::EvictCodedFrames(const std::string& id,
base::TimeDelta currentMediaTime,
size_t newDataSize) { … }
bool ChunkDemuxer::AppendToParseBuffer(const std::string& id,
base::span<const uint8_t> data) { … }
StreamParser::ParseStatus ChunkDemuxer::RunSegmentParserLoop(
const std::string& id,
base::TimeDelta append_window_start,
base::TimeDelta append_window_end,
base::TimeDelta* timestamp_offset) { … }
bool ChunkDemuxer::AppendChunks(
const std::string& id,
std::unique_ptr<StreamParser::BufferQueue> buffer_queue,
base::TimeDelta append_window_start,
base::TimeDelta append_window_end,
base::TimeDelta* timestamp_offset) { … }
void ChunkDemuxer::ResetParserState(const std::string& id,
base::TimeDelta append_window_start,
base::TimeDelta append_window_end,
base::TimeDelta* timestamp_offset) { … }
void ChunkDemuxer::Remove(const std::string& id,
base::TimeDelta start,
base::TimeDelta end) { … }
bool ChunkDemuxer::CanChangeType(const std::string& id,
const std::string& content_type,
const std::string& codecs) { … }
void ChunkDemuxer::ChangeType(const std::string& id,
const std::string& content_type,
const std::string& codecs) { … }
double ChunkDemuxer::GetDuration() { … }
double ChunkDemuxer::GetDuration_Locked() { … }
void ChunkDemuxer::SetDuration(double duration) { … }
bool ChunkDemuxer::IsParsingMediaSegment(const std::string& id) { … }
bool ChunkDemuxer::GetGenerateTimestampsFlag(const std::string& id) { … }
void ChunkDemuxer::SetSequenceMode(const std::string& id,
bool sequence_mode) { … }
void ChunkDemuxer::SetGroupStartTimestampIfInSequenceMode(
const std::string& id,
base::TimeDelta timestamp_offset) { … }
void ChunkDemuxer::MarkEndOfStream(PipelineStatus status) { … }
void ChunkDemuxer::UnmarkEndOfStream() { … }
void ChunkDemuxer::Shutdown() { … }
void ChunkDemuxer::SetMemoryLimitsForTest(DemuxerStream::Type type,
size_t memory_limit) { … }
void ChunkDemuxer::ChangeState_Locked(State new_state) { … }
ChunkDemuxer::~ChunkDemuxer() { … }
void ChunkDemuxer::ReportError_Locked(PipelineStatus error) { … }
bool ChunkDemuxer::IsSeekWaitingForData_Locked() const { … }
void ChunkDemuxer::OnSourceInitDone(
const std::string& source_id,
const StreamParser::InitParameters& params) { … }
MediaTrack::Id ChunkDemuxer::GenerateMediaTrackId() { … }
ChunkDemuxerStream* ChunkDemuxer::CreateDemuxerStream(
const std::string& source_id,
DemuxerStream::Type type) { … }
bool ChunkDemuxer::IsValidId_Locked(const std::string& source_id) const { … }
void ChunkDemuxer::UpdateDuration(base::TimeDelta new_duration) { … }
void ChunkDemuxer::IncreaseDurationIfNecessary(base::TimeDelta new_duration) { … }
void ChunkDemuxer::DecreaseDurationIfNecessary() { … }
Ranges<base::TimeDelta> ChunkDemuxer::GetBufferedRanges() const { … }
Ranges<base::TimeDelta> ChunkDemuxer::GetBufferedRanges_Locked() const { … }
void ChunkDemuxer::StartReturningData() { … }
void ChunkDemuxer::AbortPendingReads_Locked() { … }
void ChunkDemuxer::SeekAllSources(base::TimeDelta seek_time) { … }
void ChunkDemuxer::CompletePendingReadsIfPossible() { … }
void ChunkDemuxer::ShutdownAllStreams() { … }
void ChunkDemuxer::RunInitCB_Locked(PipelineStatus status) { … }
void ChunkDemuxer::RunSeekCB_Locked(PipelineStatus status) { … }
}