From 47aab6c83203c685d6a5c44fc5849636bb597f08 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sebastian=20Dr=C3=B6ge?= Date: Mon, 6 Jun 2022 12:31:52 +0300 Subject: [PATCH] flvdemux: Make use of the streams API if used in a streams-aware bin This allows adding audio/video streams after 6s. Part-of: --- .../gst-plugins-good/gst/flv/gstflvdemux.c | 121 ++++++++++++++++-- .../gst-plugins-good/gst/flv/gstflvdemux.h | 5 + 2 files changed, 112 insertions(+), 14 deletions(-) diff --git a/subprojects/gst-plugins-good/gst/flv/gstflvdemux.c b/subprojects/gst-plugins-good/gst/flv/gstflvdemux.c index 29db7b97dd..7381ff5c7f 100644 --- a/subprojects/gst-plugins-good/gst/flv/gstflvdemux.c +++ b/subprojects/gst-plugins-good/gst/flv/gstflvdemux.c @@ -909,7 +909,42 @@ gst_flv_demux_audio_negotiate (GstFlvDemux * demux, guint32 codec_tag, gst_event_set_seqnum (event, demux->segment_seqnum); if (have_group_id (demux)) gst_event_set_group_id (event, demux->group_id); - gst_pad_push_event (demux->audio_pad, event); + + if (demux->streams_aware) { + GstStreamCollection *stream_collection; + GstMessage *msg; + + g_assert (!demux->audio_stream); + demux->audio_stream = + gst_stream_new (stream_id, caps, GST_STREAM_TYPE_AUDIO, + GST_STREAM_FLAG_SELECT); + if (demux->audio_tags) + gst_stream_set_tags (demux->audio_stream, demux->audio_tags); + + gst_event_set_stream (event, demux->audio_stream); + gst_pad_push_event (demux->audio_pad, event); + + stream_collection = gst_stream_collection_new (demux->upstream_stream_id); + + gst_stream_collection_add_stream (stream_collection, + gst_object_ref (demux->audio_stream)); + if (demux->video_stream) + gst_stream_collection_add_stream (stream_collection, + gst_object_ref (demux->video_stream)); + + event = gst_event_new_stream_collection (stream_collection); + gst_pad_push_event (demux->audio_pad, event); + + msg = gst_message_new_stream_collection (GST_OBJECT (demux), + stream_collection); + GST_DEBUG_OBJECT (demux, "Posting stream collection"); + gst_element_post_message (GST_ELEMENT (demux), msg); + + gst_clear_object (&stream_collection); + } else { + gst_pad_push_event (demux->audio_pad, event); + } + g_free (stream_id); } if (!old_caps || !gst_caps_is_equal (old_caps, caps)) @@ -1103,7 +1138,8 @@ gst_flv_demux_parse_tag_audio (GstFlvDemux * demux, GstBuffer * buffer) GST_LOG_OBJECT (demux, "parsing an audio tag"); - if (G_UNLIKELY (!demux->audio_pad && demux->no_more_pads)) { + if (G_UNLIKELY (!demux->streams_aware && !demux->audio_pad + && demux->no_more_pads)) { #ifndef GST_DISABLE_DEBUG if (G_UNLIKELY (!demux->no_audio_warned)) { GST_WARNING_OBJECT (demux, @@ -1264,7 +1300,7 @@ gst_flv_demux_parse_tag_audio (GstFlvDemux * demux, GstBuffer * buffer) /* We only emit no more pads when we have audio and video. Indeed we can * not trust the FLV header to tell us if there will be only audio or * only video and we would just break discovery of some files */ - if (demux->audio_pad && demux->video_pad) { + if (demux->audio_pad && demux->video_pad && !demux->streams_aware) { GST_DEBUG_OBJECT (demux, "emitting no more pads"); gst_element_no_more_pads (GST_ELEMENT (demux)); demux->no_more_pads = TRUE; @@ -1360,7 +1396,7 @@ gst_flv_demux_parse_tag_audio (GstFlvDemux * demux, GstBuffer * buffer) demux->audio_first_ts = GST_BUFFER_TIMESTAMP (outbuf); } - if (G_UNLIKELY (!demux->no_more_pads + if (G_UNLIKELY (!demux->streams_aware && !demux->no_more_pads && (GST_CLOCK_DIFF (demux->audio_start, GST_BUFFER_TIMESTAMP (outbuf)) > NO_MORE_PADS_THRESHOLD))) { GST_DEBUG_OBJECT (demux, @@ -1490,11 +1526,46 @@ gst_flv_demux_video_negotiate (GstFlvDemux * demux, guint32 codec_tag) event = gst_event_new_stream_start (stream_id); if (demux->segment_seqnum != GST_SEQNUM_INVALID) gst_event_set_seqnum (event, demux->segment_seqnum); - g_free (stream_id); if (have_group_id (demux)) gst_event_set_group_id (event, demux->group_id); - gst_pad_push_event (demux->video_pad, event); + + if (demux->streams_aware) { + GstStreamCollection *stream_collection; + GstMessage *msg; + + g_assert (!demux->video_stream); + demux->video_stream = + gst_stream_new (stream_id, caps, GST_STREAM_TYPE_VIDEO, + GST_STREAM_FLAG_SELECT); + if (demux->video_tags) + gst_stream_set_tags (demux->video_stream, demux->video_tags); + + gst_event_set_stream (event, demux->video_stream); + gst_pad_push_event (demux->video_pad, event); + + stream_collection = gst_stream_collection_new (demux->upstream_stream_id); + + if (demux->audio_stream) + gst_stream_collection_add_stream (stream_collection, + gst_object_ref (demux->audio_stream)); + gst_stream_collection_add_stream (stream_collection, + gst_object_ref (demux->video_stream)); + + event = gst_event_new_stream_collection (stream_collection); + gst_pad_push_event (demux->video_pad, event); + + msg = gst_message_new_stream_collection (GST_OBJECT (demux), + stream_collection); + GST_DEBUG_OBJECT (demux, "Posting stream collection"); + gst_element_post_message (GST_ELEMENT (demux), msg); + + gst_clear_object (&stream_collection); + } else { + gst_pad_push_event (demux->video_pad, event); + } + + g_free (stream_id); } if (!old_caps || !gst_caps_is_equal (old_caps, caps)) @@ -1548,7 +1619,7 @@ gst_flv_demux_parse_tag_video (GstFlvDemux * demux, GstBuffer * buffer) GST_LOG_OBJECT (demux, "parsing a video tag"); if G_UNLIKELY - (!demux->video_pad && demux->no_more_pads) { + (!demux->streams_aware && !demux->video_pad && demux->no_more_pads) { #ifndef GST_DISABLE_DEBUG if G_UNLIKELY (!demux->no_video_warned) { @@ -1700,7 +1771,7 @@ gst_flv_demux_parse_tag_video (GstFlvDemux * demux, GstBuffer * buffer) /* We only emit no more pads when we have audio and video. Indeed we can * not trust the FLV header to tell us if there will be only audio or * only video and we would just break discovery of some files */ - if (demux->audio_pad && demux->video_pad) { + if (demux->audio_pad && demux->video_pad && !demux->streams_aware) { GST_DEBUG_OBJECT (demux, "emitting no more pads"); gst_element_no_more_pads (GST_ELEMENT (demux)); demux->no_more_pads = TRUE; @@ -1803,7 +1874,7 @@ gst_flv_demux_parse_tag_video (GstFlvDemux * demux, GstBuffer * buffer) demux->video_first_ts = GST_BUFFER_TIMESTAMP (outbuf); } - if (G_UNLIKELY (!demux->no_more_pads + if (G_UNLIKELY (!demux->streams_aware && !demux->no_more_pads && (GST_CLOCK_DIFF (demux->video_start, GST_BUFFER_TIMESTAMP (outbuf)) > NO_MORE_PADS_THRESHOLD))) { GST_DEBUG_OBJECT (demux, @@ -2139,6 +2210,13 @@ gst_flv_demux_cleanup (GstFlvDemux * demux) demux->audio_bitrate = 0; gst_flv_demux_clear_tags (demux); + + gst_clear_object (&demux->audio_stream); + gst_clear_object (&demux->video_stream); + g_clear_pointer (&demux->upstream_stream_id, (GDestroyNotify) g_free); + demux->streams_aware = GST_OBJECT_PARENT (demux) + && GST_OBJECT_FLAG_IS_SET (GST_OBJECT_PARENT (demux), + GST_BIN_FLAG_STREAMS_AWARE); } /* @@ -2779,8 +2857,8 @@ gst_flv_demux_loop (GstPad * pad) } /* pause if something went wrong or at end */ - if (G_UNLIKELY (ret != GST_FLOW_OK) && !(ret == GST_FLOW_NOT_LINKED - && !demux->no_more_pads)) + if (G_UNLIKELY (ret != GST_FLOW_OK) && (demux->streams_aware + || ret != GST_FLOW_NOT_LINKED || demux->no_more_pads)) goto pause; gst_object_unref (demux); @@ -2807,7 +2885,7 @@ pause: demux->segment.position = demux->segment.start; /* perform EOS logic */ - if (!demux->no_more_pads) { + if (!demux->streams_aware && !demux->no_more_pads) { gst_element_no_more_pads (GST_ELEMENT_CAST (demux)); demux->no_more_pads = TRUE; } @@ -2843,7 +2921,7 @@ pause: } } else { /* normal playback, send EOS to all linked pads */ - if (!demux->no_more_pads) { + if (!demux->streams_aware && !demux->no_more_pads) { gst_element_no_more_pads (GST_ELEMENT (demux)); demux->no_more_pads = TRUE; } @@ -3352,7 +3430,7 @@ gst_flv_demux_sink_event (GstPad * pad, GstObject * parent, GstEvent * event) ("Internal data stream error."), ("Got EOS before any data")); gst_event_unref (event); } else { - if (!demux->no_more_pads) { + if (!demux->streams_aware && !demux->no_more_pads) { gst_element_no_more_pads (GST_ELEMENT (demux)); demux->no_more_pads = TRUE; } @@ -3363,6 +3441,21 @@ gst_flv_demux_sink_event (GstPad * pad, GstObject * parent, GstEvent * event) ret = TRUE; break; } + case GST_EVENT_STREAM_START: + { + const gchar *stream_id; + + GST_DEBUG_OBJECT (demux, "received stream start"); + + gst_event_parse_stream_start (event, &stream_id); + g_clear_pointer (&demux->upstream_stream_id, (GDestroyNotify) g_free); + demux->upstream_stream_id = g_strdup (stream_id); + + ret = TRUE; + gst_event_unref (event); + + break; + } case GST_EVENT_SEGMENT: { GstSegment in_segment; diff --git a/subprojects/gst-plugins-good/gst/flv/gstflvdemux.h b/subprojects/gst-plugins-good/gst/flv/gstflvdemux.h index 6669dc4aeb..7158457717 100644 --- a/subprojects/gst-plugins-good/gst/flv/gstflvdemux.h +++ b/subprojects/gst-plugins-good/gst/flv/gstflvdemux.h @@ -64,6 +64,11 @@ struct _GstFlvDemux gboolean have_group_id; guint group_id; + gchar *upstream_stream_id; + GstStream *audio_stream; + GstStream *video_stream; + gboolean streams_aware; + /* */ GstIndex *index;