From 5b442d0712bf1b7665fa5ea552fb6e1dd670301c Mon Sep 17 00:00:00 2001 From: Arun Raghavan Date: Thu, 18 Nov 2010 13:39:23 +0530 Subject: [PATCH] mpeg4videoparse: Set srcpad caps before forwarding newsegment This holds all newsegement and most other events till there is enough data to set srcpad caps, so that the downstream link is properly negotiated before data starts flowing. https://bugzilla.gnome.org/show_bug.cgi?id=635204 --- gst/mpeg4videoparse/mpeg4videoparse.c | 55 ++++++++++++++++++++++++++- gst/mpeg4videoparse/mpeg4videoparse.h | 4 ++ 2 files changed, 58 insertions(+), 1 deletion(-) diff --git a/gst/mpeg4videoparse/mpeg4videoparse.c b/gst/mpeg4videoparse/mpeg4videoparse.c index 969ca7e393..9e58a9e35c 100644 --- a/gst/mpeg4videoparse/mpeg4videoparse.c +++ b/gst/mpeg4videoparse/mpeg4videoparse.c @@ -118,6 +118,22 @@ gst_mpeg4vparse_set_new_caps (GstMpeg4VParse * parse, res = gst_pad_set_caps (parse->srcpad, out_caps); gst_caps_unref (out_caps); + parse->have_src_caps = TRUE; + if (parse->pending_segment != NULL) { + /* We can send pending events since we now have caps for the srcpad */ + gst_pad_push_event (parse->srcpad, parse->pending_segment); + parse->pending_segment = NULL; + + if (G_UNLIKELY (parse->pending_events != NULL)) { + GList *l; + + for (l = parse->pending_events; l != NULL; l = l->next) + gst_pad_push_event (parse->srcpad, GST_EVENT (l->data)); + + g_list_free (parse->pending_events); + parse->pending_events = NULL; + } + } return res; } @@ -794,6 +810,11 @@ gst_mpeg4vparse_sink_event (GstPad * pad, GstEvent * event) parse->offset = 0; break; case GST_EVENT_EOS: + if (parse->pending_segment != NULL) { + /* Send pending newsegment before EOS */ + gst_pad_push_event (parse->srcpad, parse->pending_segment); + parse->pending_segment = NULL; + } if (parse->state == PARSE_VOP_FOUND) { /* If we've found the start of the VOP assume what's left in the * adapter is the complete VOP. This might cause us to send an @@ -802,11 +823,25 @@ gst_mpeg4vparse_sink_event (GstPad * pad, GstEvent * event) gst_mpeg4vparse_push (parse, gst_adapter_available (parse->adapter)); } /* fallthrough */ + case GST_EVENT_FLUSH_START: + res = gst_pad_event_default (pad, event); + break; + case GST_EVENT_NEWSEGMENT: + gst_event_replace (&parse->pending_segment, event); + gst_event_unref (event); + res = TRUE; + break; default: + if (G_UNLIKELY (!parse->have_src_caps || parse->pending_segment)) { + /* We don't yet have enough data to set caps on the srcpad, so collect + * non-critical events till we do */ + parse->pending_events = g_list_append (parse->pending_events, event); + res = TRUE; + } else + res = gst_pad_event_default (pad, event); break; } - res = gst_pad_event_default (pad, event); gst_object_unref (parse); return res; @@ -879,6 +914,16 @@ gst_mpeg4vparse_cleanup (GstMpeg4VParse * parse) parse->config = NULL; } + if (parse->pending_segment) + gst_event_unref (parse->pending_segment); + parse->pending_segment = NULL; + + g_list_foreach (parse->pending_events, (GFunc) gst_event_unref, NULL); + g_list_free (parse->pending_events); + parse->pending_events = NULL; + + parse->have_src_caps = FALSE; + parse->state = PARSE_NEED_START; parse->have_config = FALSE; parse->offset = 0; @@ -918,6 +963,14 @@ gst_mpeg4vparse_dispose (GObject * object) parse->config = NULL; } + if (parse->pending_segment) + gst_event_unref (parse->pending_segment); + parse->pending_segment = NULL; + + g_list_foreach (parse->pending_events, (GFunc) gst_event_unref, NULL); + g_list_free (parse->pending_events); + parse->pending_events = NULL; + GST_CALL_PARENT (G_OBJECT_CLASS, dispose, (object)); } diff --git a/gst/mpeg4videoparse/mpeg4videoparse.h b/gst/mpeg4videoparse/mpeg4videoparse.h index 3c114caef8..29f7fa1834 100644 --- a/gst/mpeg4videoparse/mpeg4videoparse.h +++ b/gst/mpeg4videoparse/mpeg4videoparse.h @@ -73,6 +73,10 @@ struct _GstMpeg4VParse { GstClockTime frame_duration; gboolean drop; + + gboolean have_src_caps; + GstEvent *pending_segment; + GList *pending_events; }; struct _GstMpeg4VParseClass {