#ifdef UNSAFE_BUFFERS_BUILD
#pragma allow_unsafe_buffers
#endif
#include "media/filters/ffmpeg_demuxer.h"
#include <algorithm>
#include <memory>
#include <set>
#include <string_view>
#include <utility>
#include "base/base64.h"
#include "base/feature_list.h"
#include "base/functional/bind.h"
#include "base/functional/callback_helpers.h"
#include "base/memory/ptr_util.h"
#include "base/memory/raw_ptr.h"
#include "base/metrics/histogram_functions.h"
#include "base/metrics/histogram_macros.h"
#include "base/numerics/safe_conversions.h"
#include "base/strings/string_number_conversions.h"
#include "base/strings/string_util.h"
#include "base/task/bind_post_task.h"
#include "base/task/sequenced_task_runner.h"
#include "base/task/thread_pool.h"
#include "base/time/time.h"
#include "base/trace_event/trace_event.h"
#include "build/build_config.h"
#include "media/base/decrypt_config.h"
#include "media/base/demuxer.h"
#include "media/base/demuxer_memory_limit.h"
#include "media/base/limits.h"
#include "media/base/media_switches.h"
#include "media/base/media_tracks.h"
#include "media/base/media_types.h"
#include "media/base/sample_rates.h"
#include "media/base/supported_types.h"
#include "media/base/timestamp_constants.h"
#include "media/base/video_codecs.h"
#include "media/base/webvtt_util.h"
#include "media/ffmpeg/ffmpeg_common.h"
#include "media/filters/ffmpeg_aac_bitstream_converter.h"
#include "media/filters/ffmpeg_bitstream_converter.h"
#include "media/filters/ffmpeg_glue.h"
#include "media/filters/ffmpeg_h264_to_annex_b_bitstream_converter.h"
#include "media/formats/mpeg/mpeg1_audio_stream_parser.h"
#include "media/formats/webm/webm_crypto_helpers.h"
#include "media/media_buildflags.h"
#include "third_party/ffmpeg/ffmpeg_features.h"
#include "third_party/ffmpeg/libavcodec/packet.h"
#if BUILDFLAG(ENABLE_PLATFORM_HEVC)
#include "media/filters/ffmpeg_h265_to_annex_b_bitstream_converter.h"
#endif
namespace media {
namespace {
constexpr int64_t kInvalidPTSMarker = …;
void SetAVStreamDiscard(AVStream* stream, AVDiscard discard) { … }
int AVSeekFrame(AVFormatContext* s, int stream_index, int64_t timestamp) { … }
bool IsStreamEnabled(container_names::MediaContainerName container,
AVStream* stream) { … }
}
static base::Time ExtractTimelineOffset(
container_names::MediaContainerName container,
const AVFormatContext* format_context) { … }
static base::TimeDelta FramesToTimeDelta(int frames, double sample_rate) { … }
static base::TimeDelta ExtractStartTime(AVStream* stream) { … }
static void RecordAudioCodecStats(const AudioDecoderConfig& audio_config) { … }
static void RecordVideoCodecStats(container_names::MediaContainerName container,
const VideoDecoderConfig& video_config,
AVColorRange color_range,
MediaLog* media_log) { … }
static const char kCodecNone[] = …;
static const char* GetCodecName(enum AVCodecID id) { … }
static base::Value GetTimeValue(base::TimeDelta value) { … }
template <>
struct MediaLogPropertyTypeSupport<MediaLogProperty::kMaxDuration,
base::TimeDelta> { … };
template <>
struct MediaLogPropertyTypeSupport<MediaLogProperty::kStartTime,
base::TimeDelta> { … };
static int ReadFrameAndDiscardEmpty(AVFormatContext* context,
AVPacket* packet) { … }
std::unique_ptr<FFmpegDemuxerStream> FFmpegDemuxerStream::Create(
FFmpegDemuxer* demuxer,
AVStream* stream,
MediaLog* media_log) { … }
static void UnmarkEndOfStreamAndClearError(AVFormatContext* format_context) { … }
FFmpegDemuxerStream::FFmpegDemuxerStream(
FFmpegDemuxer* demuxer,
AVStream* stream,
std::unique_ptr<AudioDecoderConfig> audio_config,
std::unique_ptr<VideoDecoderConfig> video_config,
MediaLog* media_log)
: … { … }
FFmpegDemuxerStream::~FFmpegDemuxerStream() { … }
void FFmpegDemuxerStream::EnqueuePacket(ScopedAVPacket packet) { … }
void FFmpegDemuxerStream::SetEndOfStream() { … }
void FFmpegDemuxerStream::FlushBuffers(bool preserve_packet_position) { … }
void FFmpegDemuxerStream::Abort() { … }
void FFmpegDemuxerStream::Stop() { … }
DemuxerStream::Type FFmpegDemuxerStream::type() const { … }
StreamLiveness FFmpegDemuxerStream::liveness() const { … }
void FFmpegDemuxerStream::Read(uint32_t count, ReadCB read_cb) { … }
void FFmpegDemuxerStream::EnableBitstreamConverter() { … }
void FFmpegDemuxerStream::ResetBitstreamConverter() { … }
void FFmpegDemuxerStream::InitBitstreamConverter() { … }
bool FFmpegDemuxerStream::SupportsConfigChanges() { … }
AudioDecoderConfig FFmpegDemuxerStream::audio_decoder_config() { … }
VideoDecoderConfig FFmpegDemuxerStream::video_decoder_config() { … }
bool FFmpegDemuxerStream::IsEnabled() const { … }
void FFmpegDemuxerStream::SetEnabled(bool enabled, base::TimeDelta timestamp) { … }
void FFmpegDemuxerStream::SetLiveness(StreamLiveness liveness) { … }
Ranges<base::TimeDelta> FFmpegDemuxerStream::GetBufferedRanges() const { … }
void FFmpegDemuxerStream::SatisfyPendingRead() { … }
bool FFmpegDemuxerStream::HasAvailableCapacity() { … }
size_t FFmpegDemuxerStream::MemoryUsage() const { … }
std::string FFmpegDemuxerStream::GetMetadata(const char* key) const { … }
base::TimeDelta FFmpegDemuxerStream::ConvertStreamTimestamp(
const AVRational& time_base,
int64_t timestamp) { … }
FFmpegDemuxer::FFmpegDemuxer(
const scoped_refptr<base::SequencedTaskRunner>& task_runner,
DataSource* data_source,
const EncryptedMediaInitDataCB& encrypted_media_init_data_cb,
MediaTracksUpdatedCB media_tracks_updated_cb,
MediaLog* media_log,
bool is_local_file)
: … { … }
FFmpegDemuxer::~FFmpegDemuxer() { … }
std::string FFmpegDemuxer::GetDisplayName() const { … }
DemuxerType FFmpegDemuxer::GetDemuxerType() const { … }
void FFmpegDemuxer::Initialize(DemuxerHost* host,
PipelineStatusCallback init_cb) { … }
void FFmpegDemuxer::AbortPendingReads() { … }
void FFmpegDemuxer::Stop() { … }
void FFmpegDemuxer::StartWaitingForSeek(base::TimeDelta seek_time) { … }
void FFmpegDemuxer::CancelPendingSeek(base::TimeDelta seek_time) { … }
void FFmpegDemuxer::Seek(base::TimeDelta time, PipelineStatusCallback cb) { … }
bool FFmpegDemuxer::IsSeekable() const { … }
void FFmpegDemuxer::SeekInternal(base::TimeDelta time,
base::OnceCallback<void(int)> seek_cb) { … }
base::Time FFmpegDemuxer::GetTimelineOffset() const { … }
std::vector<DemuxerStream*> FFmpegDemuxer::GetAllStreams() { … }
FFmpegDemuxerStream* FFmpegDemuxer::GetFirstEnabledFFmpegStream(
DemuxerStream::Type type) const { … }
base::TimeDelta FFmpegDemuxer::GetStartTime() const { … }
int64_t FFmpegDemuxer::GetMemoryUsage() const { … }
std::optional<container_names::MediaContainerName>
FFmpegDemuxer::GetContainerForMetrics() const { … }
void FFmpegDemuxer::OnEncryptedMediaInitData(
EmeInitDataType init_data_type,
const std::string& encryption_key_id) { … }
void FFmpegDemuxer::NotifyCapacityAvailable() { … }
void FFmpegDemuxer::NotifyBufferingChanged() { … }
static int CalculateBitrate(AVFormatContext* format_context,
const base::TimeDelta& duration,
int64_t filesize_in_bytes) { … }
void FFmpegDemuxer::OnOpenContextDone(bool result) { … }
void FFmpegDemuxer::OnFindStreamInfoDone(int result) { … }
void FFmpegDemuxer::LogMetadata(AVFormatContext* avctx,
base::TimeDelta max_duration) { … }
FFmpegDemuxerStream* FFmpegDemuxer::FindStreamWithLowestStartTimestamp(
bool enabled) { … }
FFmpegDemuxerStream* FFmpegDemuxer::FindPreferredStreamForSeeking(
base::TimeDelta seek_time) { … }
void FFmpegDemuxer::OnSeekFrameDone(int result) { … }
void FFmpegDemuxer::FindAndEnableProperTracks(
const std::vector<MediaTrack::Id>& track_ids,
base::TimeDelta curr_time,
DemuxerStream::Type track_type,
TrackChangeCB change_completed_cb) { … }
void FFmpegDemuxer::OnEnabledAudioTracksChanged(
const std::vector<MediaTrack::Id>& track_ids,
base::TimeDelta curr_time,
TrackChangeCB change_completed_cb) { … }
void FFmpegDemuxer::OnVideoSeekedForTrackChange(
DemuxerStream* video_stream,
base::OnceClosure seek_completed_cb,
int result) { … }
void FFmpegDemuxer::SeekOnVideoTrackChange(
base::TimeDelta seek_to_time,
TrackChangeCB seek_completed_cb,
DemuxerStream::Type stream_type,
const std::vector<DemuxerStream*>& streams) { … }
void FFmpegDemuxer::OnSelectedVideoTrackChanged(
const std::vector<MediaTrack::Id>& track_ids,
base::TimeDelta curr_time,
TrackChangeCB change_completed_cb) { … }
void FFmpegDemuxer::ReadFrameIfNeeded() { … }
void FFmpegDemuxer::OnReadFrameDone(ScopedAVPacket packet, int result) { … }
bool FFmpegDemuxer::StreamsHaveAvailableCapacity() { … }
bool FFmpegDemuxer::IsMaxMemoryUsageReached() const { … }
void FFmpegDemuxer::StreamHasEnded() { … }
void FFmpegDemuxer::OnDataSourceError() { … }
void FFmpegDemuxer::NotifyDemuxerError(PipelineStatus status) { … }
void FFmpegDemuxer::SetLiveness(StreamLiveness liveness) { … }
void FFmpegDemuxer::RunInitCB(PipelineStatus status) { … }
void FFmpegDemuxer::RunPendingSeekCB(PipelineStatus status) { … }
}