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
This commit is contained in:
Jan Alexander Steffens (heftig) 2016-07-06 09:24:49 +02:00 committed by Sebastian Dröge
parent a85dbfc246
commit ee44e60f7b
2 changed files with 51 additions and 56 deletions

View file

@ -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);

View file

@ -126,7 +126,6 @@ struct _GstFlvDemux
gboolean need_header;
gboolean has_audio;
gboolean has_video;
gboolean push_tags;
gboolean strict;
gboolean flushing;