From ee44e60f7b8e0cd6ee30944cee24b691b1cdf0d5 Mon Sep 17 00:00:00 2001 From: "Jan Alexander Steffens (heftig)" Date: Wed, 6 Jul 2016 09:24:49 +0200 Subject: [PATCH] flvdemux: Refactor metadata tag handling The FLV header cannot be trusted to indicate video or audio presence, as the comments already mention. Don't delay pushing tags waiting for streams that might never appear. Tags are now pushed immediately after they change: - After parsing an onMetaData script object - After negotiating caps on a pad https://bugzilla.gnome.org/show_bug.cgi?id=768440 --- gst/flv/gstflvdemux.c | 106 ++++++++++++++++++++---------------------- gst/flv/gstflvdemux.h | 1 - 2 files changed, 51 insertions(+), 56 deletions(-) diff --git a/gst/flv/gstflvdemux.c b/gst/flv/gstflvdemux.c index f226907d7d..60b52379e6 100644 --- a/gst/flv/gstflvdemux.c +++ b/gst/flv/gstflvdemux.c @@ -114,6 +114,8 @@ static gboolean gst_flv_demux_src_event (GstPad * pad, GstObject * parent, static GstIndex *gst_flv_demux_get_index (GstElement * element); +static void gst_flv_demux_push_tags (GstFlvDemux * demux); + static void gst_flv_demux_parse_and_add_index_entry (GstFlvDemux * demux, GstClockTime ts, guint64 pos, gboolean keyframe) @@ -561,6 +563,18 @@ error: return FALSE; } +static void +gst_flv_demux_clear_tags (GstFlvDemux * demux) +{ + GST_DEBUG_OBJECT (demux, "clearing taglist"); + + if (demux->taglist) { + gst_tag_list_unref (demux->taglist); + } + demux->taglist = gst_tag_list_new_empty (); + gst_tag_list_set_scope (demux->taglist, GST_TAG_SCOPE_GLOBAL); +} + static GstFlowReturn gst_flv_demux_parse_tag_script (GstFlvDemux * demux, GstBuffer * buffer) { @@ -594,6 +608,8 @@ gst_flv_demux_parse_tag_script (GstFlvDemux * demux, GstBuffer * buffer) gboolean end_marker = FALSE; GST_DEBUG_OBJECT (demux, "we have a metadata script object"); + gst_flv_demux_clear_tags (demux); + if (!gst_byte_reader_get_uint8 (&reader, &type)) { g_free (function_name); goto cleanup; @@ -636,7 +652,7 @@ gst_flv_demux_parse_tag_script (GstFlvDemux * demux, GstBuffer * buffer) goto cleanup; } - demux->push_tags = TRUE; + gst_flv_demux_push_tags (demux); } g_free (function_name); @@ -689,7 +705,6 @@ gst_flv_demux_audio_negotiate (GstFlvDemux * demux, guint32 codec_tag, guint32 rate, guint32 channels, guint32 width) { GstCaps *caps = NULL, *old_caps; - gchar *codec_name = NULL; gboolean ret = FALSE; guint adjusted_rate = rate; GstEvent *event; @@ -871,18 +886,10 @@ done: demux->width = width; if (caps) { - codec_name = gst_pb_utils_get_codec_description (caps); - - if (codec_name) { - if (demux->taglist == NULL) - demux->taglist = gst_tag_list_new_empty (); - gst_tag_list_add (demux->taglist, GST_TAG_MERGE_REPLACE, - GST_TAG_AUDIO_CODEC, codec_name, NULL); - g_free (codec_name); - } - GST_DEBUG_OBJECT (demux->audio_pad, "successfully negotiated caps %" GST_PTR_FORMAT, caps); + + gst_flv_demux_push_tags (demux); } else { GST_DEBUG_OBJECT (demux->audio_pad, "delayed setting caps"); } @@ -914,27 +921,37 @@ gst_flv_demux_push_src_event (GstFlvDemux * demux, GstEvent * event) return ret; } +static void +gst_flv_demux_add_codec_tag (GstFlvDemux * demux, const gchar * tag, + GstPad * pad) +{ + if (pad) { + GstCaps *caps = gst_pad_get_current_caps (pad); + + if (caps) { + gchar *codec_name = gst_pb_utils_get_codec_description (caps); + + if (codec_name) { + gst_tag_list_add (demux->taglist, GST_TAG_MERGE_REPLACE, + tag, codec_name, NULL); + g_free (codec_name); + } + + gst_caps_unref (caps); + } + } +} + static void gst_flv_demux_push_tags (GstFlvDemux * demux) { - if (demux->has_audio && !demux->audio_pad) { - GST_DEBUG_OBJECT (demux, - "Waiting for audio stream pad to come up before we can push tags"); - return; - } - if (demux->has_video && !demux->video_pad) { - GST_DEBUG_OBJECT (demux, - "Waiting for video stream pad to come up before we can push tags"); - return; - } - if (demux->taglist) { - GST_DEBUG_OBJECT (demux, "pushing tags out %" GST_PTR_FORMAT, - demux->taglist); - gst_tag_list_set_scope (demux->taglist, GST_TAG_SCOPE_GLOBAL); - gst_flv_demux_push_src_event (demux, gst_event_new_tag (demux->taglist)); - demux->taglist = gst_tag_list_new_empty (); - demux->push_tags = FALSE; - } + gst_flv_demux_add_codec_tag (demux, GST_TAG_AUDIO_CODEC, demux->audio_pad); + gst_flv_demux_add_codec_tag (demux, GST_TAG_VIDEO_CODEC, demux->video_pad); + + GST_DEBUG_OBJECT (demux, "pushing %" GST_PTR_FORMAT, demux->taglist); + + gst_flv_demux_push_src_event (demux, + gst_event_new_tag (gst_tag_list_copy (demux->taglist))); } static gboolean @@ -1137,7 +1154,6 @@ gst_flv_demux_parse_tag_audio (GstFlvDemux * demux, GstBuffer * buffer) GST_DEBUG_OBJECT (demux, "emitting no more pads"); gst_element_no_more_pads (GST_ELEMENT (demux)); demux->no_more_pads = TRUE; - demux->push_tags = TRUE; } } @@ -1156,10 +1172,6 @@ gst_flv_demux_parse_tag_audio (GstFlvDemux * demux, GstBuffer * buffer) } } - /* Push taglist if present */ - if (G_UNLIKELY (demux->push_tags)) - gst_flv_demux_push_tags (demux); - /* Check if we have anything to push */ if (demux->tag_data_size <= codec_data) { GST_LOG_OBJECT (demux, "Nothing left in this tag, returning"); @@ -1241,7 +1253,6 @@ gst_flv_demux_parse_tag_audio (GstFlvDemux * demux, GstBuffer * buffer) " after 6 seconds of audio"); gst_element_no_more_pads (GST_ELEMENT_CAST (demux)); demux->no_more_pads = TRUE; - demux->push_tags = TRUE; } /* Push downstream */ @@ -1273,7 +1284,6 @@ gst_flv_demux_video_negotiate (GstFlvDemux * demux, guint32 codec_tag) { gboolean ret = FALSE; GstCaps *caps = NULL, *old_caps; - gchar *codec_name = NULL; GstEvent *event; gchar *stream_id; @@ -1378,18 +1388,10 @@ done: demux->video_codec_tag = codec_tag; if (caps) { - codec_name = gst_pb_utils_get_codec_description (caps); - - if (codec_name) { - if (demux->taglist == NULL) - demux->taglist = gst_tag_list_new_empty (); - gst_tag_list_add (demux->taglist, GST_TAG_MERGE_REPLACE, - GST_TAG_VIDEO_CODEC, codec_name, NULL); - g_free (codec_name); - } - GST_DEBUG_OBJECT (demux->video_pad, "successfully negotiated caps %" GST_PTR_FORMAT, caps); + + gst_flv_demux_push_tags (demux); } else { GST_DEBUG_OBJECT (demux->video_pad, "delayed setting caps"); } @@ -1568,7 +1570,6 @@ gst_flv_demux_parse_tag_video (GstFlvDemux * demux, GstBuffer * buffer) GST_DEBUG_OBJECT (demux, "emitting no more pads"); gst_element_no_more_pads (GST_ELEMENT (demux)); demux->no_more_pads = TRUE; - demux->push_tags = TRUE; } } @@ -1587,10 +1588,6 @@ gst_flv_demux_parse_tag_video (GstFlvDemux * demux, GstBuffer * buffer) demux->got_par = FALSE; } - /* Push taglist if present */ - if (G_UNLIKELY (demux->push_tags)) - gst_flv_demux_push_tags (demux); - /* Check if we have anything to push */ if (demux->tag_data_size <= codec_data) { GST_LOG_OBJECT (demux, "Nothing left in this tag, returning"); @@ -1677,7 +1674,6 @@ gst_flv_demux_parse_tag_video (GstFlvDemux * demux, GstBuffer * buffer) " after 6 seconds of video"); gst_element_no_more_pads (GST_ELEMENT_CAST (demux)); demux->no_more_pads = TRUE; - demux->push_tags = TRUE; } /* Push downstream */ @@ -1925,7 +1921,6 @@ gst_flv_demux_cleanup (GstFlvDemux * demux) demux->has_audio = FALSE; demux->has_video = FALSE; - demux->push_tags = FALSE; demux->got_par = FALSE; demux->indexed = FALSE; @@ -1997,6 +1992,8 @@ gst_flv_demux_cleanup (GstFlvDemux * demux) g_array_free (demux->filepositions, TRUE); demux->filepositions = NULL; } + + gst_flv_demux_clear_tags (demux); } /* @@ -3588,7 +3585,6 @@ gst_flv_demux_init (GstFlvDemux * demux) gst_element_add_pad (GST_ELEMENT (demux), demux->sinkpad); demux->adapter = gst_adapter_new (); - demux->taglist = gst_tag_list_new_empty (); demux->flowcombiner = gst_flow_combiner_new (); gst_segment_init (&demux->segment, GST_FORMAT_TIME); diff --git a/gst/flv/gstflvdemux.h b/gst/flv/gstflvdemux.h index aa8d6ac9fc..ff670d19b8 100644 --- a/gst/flv/gstflvdemux.h +++ b/gst/flv/gstflvdemux.h @@ -126,7 +126,6 @@ struct _GstFlvDemux gboolean need_header; gboolean has_audio; gboolean has_video; - gboolean push_tags; gboolean strict; gboolean flushing;