--- a/media/base/decoder_buffer.cc +++ b/media/base/decoder_buffer.cc @@ -306,9 +306,7 @@ memory_usage += size(); - // Side data may be added after construction (e.g, timed metadata attached by - // FFmpegDemuxer), so only fields that do not change are counted here. Callers - // that cache this value rely on it. + // Side data and decrypt config would not change after construction. if (side_data()) { memory_usage += sizeof(decltype(side_data_->spatial_layers)::value_type) * side_data_->spatial_layers.capacity(); --- a/media/base/decoder_buffer_queue.cc +++ b/media/base/decoder_buffer_queue.cc @@ -45,11 +45,6 @@ in_order_queue_.emplace_back(std::move(buffer)); } -DecoderBuffer& DecoderBufferQueue::Front() { - DCHECK(!queue_.empty()); - return *queue_.front(); -} - scoped_refptr DecoderBufferQueue::Pop() { scoped_refptr buffer = std::move(queue_.front()); queue_.pop_front(); --- a/media/base/decoder_buffer_queue.h +++ b/media/base/decoder_buffer_queue.h @@ -38,12 +38,6 @@ // It is invalid to push an end-of-stream |buffer|. void Push(scoped_refptr buffer); - // Returns the buffer at the front of the queue, which may be modified in - // place by the caller. - // - // It is invalid to call Front() on an empty queue. - DecoderBuffer& Front(); - // Pops a DecoderBuffer from the front of the queue. // // It is invalid to call Pop() on an empty queue. --- a/media/base/media_switches.cc +++ b/media/base/media_switches.cc @@ -598,10 +598,6 @@ BASE_FEATURE(kFeatureManagementLiveTranslateCrOS, base::FEATURE_DISABLED_BY_DEFAULT); -// Controls whether FFmpegDemuxer attaches the HDR metadata carried by ITU-T -// T.35 timed metadata tracks to the video tracks that reference them. -BASE_FEATURE(kFFmpegDemuxerIT35MetadataTrack, base::FEATURE_ENABLED_BY_DEFAULT); - // Forces software video encoders to be used for low resolutions. // Enabled-by-default, except for Android where SW encoder for H26x and AV1 are // (sometimes) not available. --- a/media/base/media_switches.h +++ b/media/base/media_switches.h @@ -196,7 +196,6 @@ MEDIA_EXPORT BASE_DECLARE_FEATURE(kFailUrlProvisionFetcherForTesting); MEDIA_EXPORT BASE_DECLARE_FEATURE(kFallbackAfterDecodeError); MEDIA_EXPORT BASE_DECLARE_FEATURE(kFeatureManagementLiveTranslateCrOS); -MEDIA_EXPORT BASE_DECLARE_FEATURE(kFFmpegDemuxerIT35MetadataTrack); MEDIA_EXPORT BASE_DECLARE_FEATURE(kForceSoftwareForRtcLowResolutions); MEDIA_EXPORT BASE_DECLARE_FEATURE(kGetDisplayMediaConfersActivation); MEDIA_EXPORT BASE_DECLARE_FEATURE(kGlobalMediaControlsAutoDismiss); --- a/media/ffmpeg/ffmpeg_common.h +++ b/media/ffmpeg/ffmpeg_common.h @@ -100,30 +100,6 @@ base::checked_cast(codec_context->nb_streams))); } -inline base::span AVFormatContextStreamGroupsToSpan( - const AVFormatContext* format_context) { - // SAFETY: - // https://ffmpeg.org/doxygen/trunk/structAVFormatContext.html#ac2a7709bc15daf6165f68a5a88648aaa - // ffmpeg documentation: `nb_stream_groups` is the number of elements in - // `AVFormatContext.stream_groups`. - return UNSAFE_BUFFERS( - base::span(format_context->stream_groups, - base::checked_cast(format_context->nb_stream_groups))); -} - -// Returns the streams that make up `stream_group`, which are a subset of the -// streams of the `AVFormatContext` that the group belongs to. -inline base::span AVStreamGroupToSpan( - const AVStreamGroup* stream_group) { - // SAFETY: - // https://ffmpeg.org/doxygen/trunk/structAVStreamGroup.html#a75c06164e99a41e514dcb5c222b2bdaa - // ffmpeg documentation: `nb_streams` is the number of elements in - // `AVStreamGroup.streams`. - return UNSAFE_BUFFERS( - base::span(stream_group->streams, - base::checked_cast(stream_group->nb_streams))); -} - inline base::span AVCodecContextExtraDataToSpan( const AVCodecContext* codec_context) { // SAFETY: --- a/media/filters/ffmpeg_demuxer.cc +++ b/media/filters/ffmpeg_demuxer.cc @@ -596,13 +596,6 @@ SatisfyPendingRead(); } -void FFmpegDemuxerStream::OnMetadataAvailable() { - DCHECK(task_runner_->RunsTasksInCurrentSequence()); - - // Buffers that were waiting on metadata might now be ready to be emitted. - SatisfyPendingRead(); -} - void FFmpegDemuxerStream::SetEndOfStream() { DCHECK(task_runner_->RunsTasksInCurrentSequence()); end_of_stream_ = true; @@ -801,12 +794,14 @@ void FFmpegDemuxerStream::SatisfyPendingRead() { DCHECK(task_runner_->RunsTasksInCurrentSequence()); if (read_cb_) { - DemuxerStream::DecoderBufferVector output_buffers; - while (output_buffers.size() < requested_buffer_count_ && - PrepareFrontBufferForRead()) { - output_buffers.emplace_back(buffer_queue_.Pop()); - } - if (!output_buffers.empty()) { + if (!buffer_queue_.IsEmpty()) { + DemuxerStream::DecoderBufferVector output_buffers; + + for (size_t i = 0; + i < std::min(requested_buffer_count_, buffer_queue_.queue_size()); + ++i) { + output_buffers.emplace_back(buffer_queue_.Pop()); + } DVLOG(3) << __func__ << " Status:kOk, return output_buffers.size = " << output_buffers.size(); std::move(read_cb_).Run(DemuxerStream::kOk, std::move(output_buffers)); @@ -821,30 +816,6 @@ } } -bool FFmpegDemuxerStream::PrepareFrontBufferForRead() { - if (buffer_queue_.IsEmpty()) { - return false; - } - // This may re-attach the same metadata multiple times (which is okay). - if (demuxer_->TryAttachMetadata(buffer_queue_.Front(), stream_->index)) { - return true; - } - // Metadata that applies to this buffer has not been demuxed yet. Keep the - // buffer queued until it has been, unless there is no capacity to buffer - // more, or the stream has ended and there will be no more metadata. - if (!end_of_stream_ && HasAvailableCapacity()) { - return false; - } - // The buffer is emitted with incomplete metadata, and so may be rendered - // incorrectly. - LIMITED_MEDIA_LOG(WARNING, media_log_, num_missing_metadata_warnings_, 5) - << "Timed metadata for the buffer at " - << buffer_queue_.Front().timestamp() << " " - << (end_of_stream_ ? "was never demuxed" : "has not been demuxed yet") - << "; emitting the buffer without it."; - return true; -} - bool FFmpegDemuxerStream::HasAvailableCapacity() { // Try to have two second's worth of encoded data per stream. const base::TimeDelta kCapacity = base::Seconds(2); @@ -1109,15 +1080,12 @@ DCHECK(demux_stream); const AVStream* seeking_stream = demux_stream->av_stream(); DCHECK(seeking_stream); - const int64_t seek_timestamp = - ConvertToTimeBase(demux_stream->stream_time_base(), seek_time); - // The MP4 demuxer seeks each stream individually, so metadata samples needed - // after the seek will be demuxed again. blocking_task_runner_->PostTaskAndReplyWithResult( FROM_HERE, - base::BindOnce(&AVSeekFrame, glue_->format_context(), - seeking_stream->index, seek_timestamp), + base::BindOnce( + &AVSeekFrame, glue_->format_context(), seeking_stream->index, + ConvertToTimeBase(demux_stream->stream_time_base(), seek_time)), std::move(seek_cb)); } @@ -1263,45 +1231,6 @@ weak_factory_.GetWeakPtr())); } -// static -FFmpegDemuxer::MetadataTrackMap FFmpegDemuxer::BuildMetadataTracks( - const AVFormatContext* format_context) { - MetadataTrackMap result; - if (!base::FeatureList::IsEnabled(kFFmpegDemuxerIT35MetadataTrack)) { - return result; - } - - for (const AVStreamGroup* stream_group : - AVFormatContextStreamGroupsToSpan(format_context)) { - if (stream_group->type != AV_STREAM_GROUP_PARAMS_TREF) { - continue; - } - auto streams = AVStreamGroupToSpan(stream_group); - const AVStream* metadata_stream = - streams[stream_group->params.tref->metadata_index]; - // Map only IT35 metadata tracks. - if (metadata_stream->codecpar->codec_id != AV_CODEC_ID_ITUT_T35) { - continue; - } - // Only AGTM metadata tracks are supported. - if (!MatchesAgtmT35( - AVCodecParametersExtraDataToSpan(metadata_stream->codecpar))) { - continue; - } - MetadataTrackEntry& entry = result[metadata_stream->index]; - entry.track = std::make_unique( - MetadataTrack::IT35PrefixType::kSmpteSt2094App5); - for (const AVStream* stream : streams) { - if (stream == metadata_stream || - stream->codecpar->codec_type != AVMEDIA_TYPE_VIDEO) { - continue; - } - entry.render_stream_indices.insert(stream->index); - } - } - return result; -} - void FFmpegDemuxer::OnFindStreamInfoDone(int result) { DCHECK(task_runner_->RunsTasksInCurrentSequence()); if (stopped_ || !data_source_) { @@ -1359,9 +1288,6 @@ << ": no tracks are enabled, track enabled flag will be ignored"; } - // Create MetadataTrackEntrys for each metadata track that we support. - metadata_tracks_ = BuildMetadataTracks(format_context); - // Create an FFmpegDemuxerStreams for each enabled audio/video stream. base::TimeDelta max_duration; int supported_audio_track_count = 0; @@ -1416,11 +1342,6 @@ } else if (codec_type == AVMEDIA_TYPE_SUBTITLE) { stream->discard = AVDISCARD_ALL; continue; - } else if (codec_id == AV_CODEC_ID_ITUT_T35) { - if (!metadata_tracks_.contains(stream->index)) { - stream->discard = AVDISCARD_ALL; - } - continue; } else { stream->discard = AVDISCARD_ALL; continue; @@ -1745,12 +1666,6 @@ stream->FlushBuffers(false); } - // Needed metadata will be demuxed again (see SeekInternal()). Track-change - // seeks (which keep other streams' buffers) don't reset. - for (auto& it : metadata_tracks_) { - it.second.track->Reset(); - } - // Resume reading until capacity. ReadFrameIfNeeded(); @@ -1838,59 +1753,6 @@ weak_factory_.GetWeakPtr(), std::move(packet))); } -bool FFmpegDemuxer::TryAttachMetadata(DecoderBuffer& buffer, - int render_stream_index) { - DCHECK(task_runner_->RunsTasksInCurrentSequence()); - - bool all_attached = true; - for (const auto& [metadata_stream_index, entry] : metadata_tracks_) { - if (entry.render_stream_indices.contains(render_stream_index)) { - // This may re-attach the same metadata multiple times (which is okay). - all_attached &= entry.track->TryAttachMetadata(buffer); - } - } - return all_attached; -} - -bool FFmpegDemuxer::CacheMetadataPacket(const AVPacket& packet) { - DCHECK(task_runner_->RunsTasksInCurrentSequence()); - - const auto metadata_tracks_it = metadata_tracks_.find(packet.stream_index); - if (metadata_tracks_it == metadata_tracks_.end()) { - return false; - } - - // Create a DecoderBuffer for the packet. - const AVStream* packet_stream = - AVFormatContextToSpan(glue_->format_context())[packet.stream_index]; - auto buffer = DecoderBuffer::CopyFrom(AVPacketData(packet)); - buffer->set_timestamp( - ConvertStreamTimestamp(packet_stream->time_base, packet.pts)); - buffer->set_duration( - ConvertStreamTimestamp(packet_stream->time_base, packet.duration)); - - // Cache the metadata buffer. - metadata_tracks_it->second.track->InsertMetadataBuffer(*buffer); - return true; -} - -void FFmpegDemuxer::NotifyMetadataAvailable(int metadata_stream_index) { - DCHECK(task_runner_->RunsTasksInCurrentSequence()); - - const auto metadata_tracks_it = metadata_tracks_.find(metadata_stream_index); - CHECK(metadata_tracks_it != metadata_tracks_.end()); - - // Notify referenced streams that the metadata is ready, so they can submit - // any now-read buffers. Only enabled streams can have a pending read. - for (int render_stream_index : - metadata_tracks_it->second.render_stream_indices) { - auto& render_stream = streams_[render_stream_index]; - if (render_stream && render_stream->IsEnabled()) { - render_stream->OnMetadataAvailable(); - } - } -} - void FFmpegDemuxer::OnReadFrameDone(ScopedAVPacket packet, int result) { DCHECK(task_runner_->RunsTasksInCurrentSequence()); DCHECK(pending_read_); @@ -1955,8 +1817,6 @@ host_->SetDuration(duration_); } } - } else if (CacheMetadataPacket(*packet)) { - NotifyMetadataAvailable(packet->stream_index); } } --- a/media/filters/ffmpeg_demuxer.h +++ b/media/filters/ffmpeg_demuxer.h @@ -31,7 +31,6 @@ #include #include "base/containers/flat_map.h" -#include "base/containers/flat_set.h" #include "base/functional/callback.h" #include "base/memory/raw_ptr.h" #include "base/memory/weak_ptr.h" @@ -41,7 +40,6 @@ #include "media/base/decoder_buffer_queue.h" #include "media/base/demuxer.h" #include "media/base/media_log.h" -#include "media/base/metadata_track.h" #include "media/base/pipeline_status.h" #include "media/base/timestamp_constants.h" #include "media/base/video_decoder_config.h" @@ -82,10 +80,6 @@ // SetEndOfStream() has been called. void EnqueuePacket(ScopedAVPacket packet); - // Called when new metadata has been added to one of the timed metadata - // tracks feeding this stream. Emits any buffers that were waiting for it. - void OnMetadataAvailable(); - // Enters the end of stream state. After delivering remaining queued buffers // only end of stream buffers will be delivered. void SetEndOfStream(); @@ -153,11 +147,6 @@ // NotifyCapacityAvailable() if capacity is still available. void SatisfyPendingRead(); - // Returns true if the buffer at the front of `buffer_queue_` may be emitted. - // (either has all timed metadata attached, or the stream is out of space or - // has ended). - bool PrepareFrontBufferForRead(); - // Resets any currently active bitstream converter. void ResetBitstreamConverter(); @@ -195,7 +184,6 @@ bool fixup_chained_ogg_ = false; int num_discarded_packet_warnings_ = 0; - int num_missing_metadata_warnings_ = 0; int64_t last_packet_pos_; int64_t last_packet_dts_; // Requested buffer count. The actual returned buffer count could be less @@ -244,11 +232,6 @@ void NotifyCapacityAvailable(); void NotifyBufferingChanged(); - // Attaches to `buffer` the metadata that applies to it from every timed - // metadata track that references it. Returns false if any of that metadata - // has not been demuxed yet. - bool TryAttachMetadata(DecoderBuffer& buffer, int render_stream_index); - // Allow FFmpegDemxuerStream to notify us about an error. void NotifyDemuxerError(PipelineStatus error); @@ -275,19 +258,6 @@ // To allow tests access to privates. friend class FFmpegDemuxerTest; - // A timed metadata track, and the indices of the render streams that its - // metadata is to be attached to. - struct MetadataTrackEntry { - std::unique_ptr track; - base::flat_set render_stream_indices; - }; - using MetadataTrackMap = base::flat_map; - - // Returns the timed metadata tracks declared by `format_context`. Returns an - // empty map if timed metadata tracks are not enabled. - static MetadataTrackMap BuildMetadataTracks( - const AVFormatContext* format_context); - // FFmpeg callbacks during initialization. void OnOpenContextDone(bool result); void OnFindStreamInfoDone(int result); @@ -334,15 +304,6 @@ void SeekInternal(base::TimeDelta time, base::OnceCallback seek_cb); - - // If `packet` is for a timed metadata track, cache it in `metadata_tracks_` - // and return true. Otherwise return false. - bool CacheMetadataPacket(const AVPacket& packet); - - // Tells the streams that reference the timed metadata track carried by the - // AVStream at `metadata_stream_index` that it has new metadata. - void NotifyMetadataAvailable(int metadata_stream_index); - void OnTrackChangeSeekComplete(base::OnceClosure seek_completed_cb, FFmpegDemuxerStream* needs_flush, int result); @@ -376,13 +337,6 @@ // results of pre-seek av_read_frame() operations. PipelineStatusCallback pending_seek_cb_; - // The timed metadata tracks and the render streams that reference them. - // - // The metadata that these accumulate is only discarded when seeking, so they - // grow for the duration of linear playback, and are invisible to - // IsMaxMemoryUsageReached(), however adjacent samples are deduped. - MetadataTrackMap metadata_tracks_; - // |streams_| mirrors the AVStream array in AVFormatContext. It contains // FFmpegDemuxerStreams encapsluating AVStream objects at the same index. //