avdemux: Combine upstream and local tags

Otherwise whatever caps appear last are going to override the others instead of
extending them.

Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/7366>
This commit is contained in:
Sebastian Dröge 2024-08-15 12:01:53 +03:00 committed by GStreamer Marge Bot
parent b86bf6d9c0
commit b501022ab8

View file

@ -69,6 +69,8 @@ struct _GstFFMpegDemux
AVFormatContext *context;
/* set while avformat_open_input() is called */
gboolean opening;
/* global tags */
GstTagList *tags, *upstream_global_tags, *upstream_stream_tags;
GstFFStream *streams[MAX_STREAMS];
@ -345,6 +347,7 @@ gst_ffmpegdemux_close (GstFFMpegDemux * demux)
}
demux->videopads = 0;
demux->audiopads = 0;
gst_clear_tag_list (&demux->tags);
/* close demuxer context from ffmpeg */
if (demux->seekable)
@ -1223,7 +1226,7 @@ gst_ffmpegdemux_open (GstFFMpegDemux * demux)
GstFFMpegDemuxClass *oclass =
(GstFFMpegDemuxClass *) G_OBJECT_GET_CLASS (demux);
gint res, n_streams, i;
GstTagList *tags;
GstTagList *tags = NULL;
GstEvent *event;
GList *cached_events;
GstQuery *query;
@ -1331,10 +1334,31 @@ gst_ffmpegdemux_open (GstFFMpegDemux * demux)
}
/* grab the global tags */
tags = gst_ffmpeg_metadata_to_tag_list (demux->context->metadata);
if (tags) {
demux->tags = gst_ffmpeg_metadata_to_tag_list (demux->context->metadata);
if (demux->tags) {
GstTagList *upstream_tags;
gst_tag_list_set_scope (demux->tags, GST_TAG_SCOPE_GLOBAL);
GST_INFO_OBJECT (demux, "global tags: %" GST_PTR_FORMAT, demux->tags);
GST_INFO_OBJECT (demux, "local tags: %" GST_PTR_FORMAT, demux->tags);
upstream_tags =
gst_tag_list_merge (demux->upstream_stream_tags,
demux->upstream_global_tags, GST_TAG_MERGE_REPLACE);
if (upstream_tags) {
tags =
gst_tag_list_merge (upstream_tags, demux->tags,
GST_TAG_MERGE_REPLACE);
if (gst_tag_list_get_scope (tags) != GST_TAG_SCOPE_GLOBAL) {
tags = gst_tag_list_make_writable (tags);
gst_tag_list_set_scope (tags, GST_TAG_SCOPE_GLOBAL);
}
gst_clear_tag_list (&upstream_tags);
} else {
tags = gst_tag_list_ref (demux->tags);
}
GST_INFO_OBJECT (demux, "combined tags: %" GST_PTR_FORMAT, tags);
}
/* now handle the stream tags */
@ -1726,6 +1750,34 @@ gst_ffmpegdemux_sink_event (GstPad * sinkpad, GstObject * parent,
GST_LOG_OBJECT (demux, "dropping %s event", GST_EVENT_TYPE_NAME (event));
gst_event_unref (event);
goto done;
case GST_EVENT_TAG:{
GstTagList *tags, *upstream_tags;
guint32 seqnum;
gst_event_parse_tag (event, &tags);
if (gst_tag_list_get_scope (tags) == GST_TAG_SCOPE_GLOBAL)
gst_tag_list_replace (&demux->upstream_global_tags, tags);
else
gst_tag_list_replace (&demux->upstream_stream_tags, tags);
seqnum = gst_event_get_seqnum (event);
gst_event_unref (event);
upstream_tags =
gst_tag_list_merge (demux->upstream_stream_tags,
demux->upstream_global_tags, GST_TAG_MERGE_REPLACE);
tags =
gst_tag_list_merge (upstream_tags, demux->tags,
GST_TAG_MERGE_REPLACE);
if (gst_tag_list_get_scope (tags) != GST_TAG_SCOPE_GLOBAL) {
tags = gst_tag_list_make_writable (tags);
gst_tag_list_set_scope (tags, GST_TAG_SCOPE_GLOBAL);
}
gst_clear_tag_list (&upstream_tags);
event = gst_event_new_tag (tags);
gst_event_set_seqnum (event, seqnum);
/* fall through */
}
default:
/* for a serialized event, wait until an earlier data is gone,
* though this is no guarantee as to when task is done with it.
@ -1975,6 +2027,8 @@ gst_ffmpegdemux_change_state (GstElement * element, GstStateChange transition)
demux->cached_events = NULL;
demux->have_group_id = FALSE;
demux->group_id = G_MAXUINT;
gst_clear_tag_list (&demux->upstream_global_tags);
gst_clear_tag_list (&demux->upstream_stream_tags);
break;
default:
break;