From 2b75eb85c4610fdb00e89041946fbc62f0080556 Mon Sep 17 00:00:00 2001 From: =?utf8?q?Olivier=20Cr=C3=AAte?= Date: Tue, 19 Nov 2013 20:12:54 -0500 Subject: [PATCH] srtpdec: Make sure that stream-id/caps/segment are sent before buffers It may be possible that only one of the two sink pads is linked in that case, the events need to be created from the other pad. --- ext/srtp/gstsrtpdec.c | 117 ++++++++++++++++++++++++++++++++++++++++++++------ ext/srtp/gstsrtpdec.h | 3 ++ 2 files changed, 108 insertions(+), 12 deletions(-) diff --git a/ext/srtp/gstsrtpdec.c b/ext/srtp/gstsrtpdec.c index ae64109..a47b205 100644 --- a/ext/srtp/gstsrtpdec.c +++ b/ext/srtp/gstsrtpdec.c @@ -685,31 +685,50 @@ gst_srtp_dec_sink_setcaps (GstPad * pad, GstObject * parent, } static gboolean -gst_srtp_dec_sink_event (GstPad * pad, GstObject * parent, - GstEvent * event, gboolean is_rtcp) +gst_srtp_dec_sink_event_rtp (GstPad * pad, GstObject * parent, GstEvent * event) { GstCaps *caps; + GstSrtpDec *filter = GST_SRTP_DEC (parent); switch (GST_EVENT_TYPE (event)) { case GST_EVENT_CAPS: gst_event_parse_caps (event, &caps); - return gst_srtp_dec_sink_setcaps (pad, parent, caps, is_rtcp); + return gst_srtp_dec_sink_setcaps (pad, parent, caps, FALSE); + case GST_EVENT_SEGMENT: + filter->rtp_has_segment = TRUE; + break; + case GST_EVENT_FLUSH_STOP: + filter->rtp_has_segment = FALSE; + break; default: - return gst_pad_event_default (pad, parent, event); + break; } -} -static gboolean -gst_srtp_dec_sink_event_rtp (GstPad * pad, GstObject * parent, GstEvent * event) -{ - return gst_srtp_dec_sink_event (pad, parent, event, FALSE); + return gst_pad_event_default (pad, parent, event); } static gboolean gst_srtp_dec_sink_event_rtcp (GstPad * pad, GstObject * parent, GstEvent * event) { - return gst_srtp_dec_sink_event (pad, parent, event, TRUE); + GstCaps *caps; + GstSrtpDec *filter = GST_SRTP_DEC (parent); + + switch (GST_EVENT_TYPE (event)) { + case GST_EVENT_CAPS: + gst_event_parse_caps (event, &caps); + return gst_srtp_dec_sink_setcaps (pad, parent, caps, TRUE); + case GST_EVENT_SEGMENT: + filter->rtcp_has_segment = TRUE; + break; + case GST_EVENT_FLUSH_STOP: + filter->rtcp_has_segment = FALSE; + break; + default: + break; + } + + return gst_pad_event_default (pad, parent, event); } static gboolean @@ -842,6 +861,71 @@ gst_srtp_dec_iterate_internal_links_rtcp (GstPad * pad, GstObject * parent) return gst_srtp_dec_iterate_internal_links (pad, parent, TRUE); } +static void +gst_srtp_dec_push_early_events (GstSrtpDec * filter, GstPad * pad, + GstPad * otherpad, gboolean is_rtcp) +{ + GstEvent *otherev, *ev; + + ev = gst_pad_get_sticky_event (pad, GST_EVENT_STREAM_START, 0); + if (ev) { + gst_event_unref (ev); + } else { + gchar *new_stream_id; + + otherev = gst_pad_get_sticky_event (otherpad, GST_EVENT_STREAM_START, 0); + + if (otherev) { + const gchar *other_stream_id; + + gst_event_parse_stream_start (otherev, &other_stream_id); + + new_stream_id = g_strdup_printf ("%s/%s", other_stream_id, + is_rtcp ? "rtcp" : "rtp"); + gst_event_unref (otherev); + } else { + new_stream_id = gst_pad_create_stream_id (pad, GST_ELEMENT (filter), + is_rtcp ? "rtcp" : "rtp"); + } + + ev = gst_event_new_stream_start (new_stream_id); + g_free (new_stream_id); + + gst_pad_push_event (pad, ev); + } + + ev = gst_pad_get_sticky_event (pad, GST_EVENT_CAPS, 0); + if (ev) { + gst_event_unref (ev); + } else { + GstCaps *caps; + + if (is_rtcp) + caps = gst_caps_new_empty_simple ("application/x-rtcp"); + else + caps = gst_caps_new_empty_simple ("application/x-rtp"); + + gst_pad_set_caps (pad, caps); + gst_caps_unref (caps); + } + + ev = gst_pad_get_sticky_event (pad, GST_EVENT_SEGMENT, 0); + if (ev) { + gst_event_unref (ev); + } else { + ev = gst_pad_get_sticky_event (otherpad, GST_EVENT_SEGMENT, 0); + + if (ev) + gst_pad_push_event (pad, ev); + } + + if (is_rtcp) + filter->rtcp_has_segment = TRUE; + else + filter->rtp_has_segment = TRUE; + +} + static GstFlowReturn gst_srtp_dec_chain (GstPad * pad, GstObject * parent, GstBuffer * buf, gboolean is_rtcp) @@ -939,10 +1023,17 @@ unprotect: push_out: /* Push buffer to source pad */ - if (is_rtcp) + if (is_rtcp) { otherpad = filter->rtcp_srcpad; - else + if (!filter->rtcp_has_segment) + gst_srtp_dec_push_early_events (filter, filter->rtcp_srcpad, + filter->rtp_srcpad, TRUE); + } else { otherpad = filter->rtp_srcpad; + if (!filter->rtp_has_segment) + gst_srtp_dec_push_early_events (filter, filter->rtp_srcpad, + filter->rtcp_srcpad, FALSE); + } ret = gst_pad_push (otherpad, buf); return ret; @@ -980,6 +1071,8 @@ gst_srtp_dec_change_state (GstElement * element, GstStateChange transition) case GST_STATE_CHANGE_READY_TO_PAUSED: filter->streams = g_hash_table_new_full (g_direct_hash, g_direct_equal, NULL, (GDestroyNotify) clear_stream); + filter->rtp_has_segment = FALSE; + filter->rtcp_has_segment = FALSE; break; case GST_STATE_CHANGE_PAUSED_TO_PLAYING: break; diff --git a/ext/srtp/gstsrtpdec.h b/ext/srtp/gstsrtpdec.h index 633818b..9d210fa 100644 --- a/ext/srtp/gstsrtpdec.h +++ b/ext/srtp/gstsrtpdec.h @@ -78,6 +78,9 @@ struct _GstSrtpDec srtp_t session; gboolean first_session; GHashTable *streams; + + gboolean rtp_has_segment; + gboolean rtcp_has_segment; }; struct _GstSrtpDecClass -- 2.7.4