diff options
author | Wim Taymans <wim.taymans@collabora.co.uk> | 2013-04-09 12:53:30 +0200 |
---|---|---|
committer | Wim Taymans <wim.taymans@collabora.co.uk> | 2013-04-09 12:53:30 +0200 |
commit | dfc722d7a499ff770ae0c6fb950b9c00b7340018 (patch) | |
tree | 949e246ff4d486396aae3da26318c042267dc079 | |
parent | 16dfcbe706d8d3dddfbc00c60145a1381a77fdc3 (diff) |
pay: cache events until caps are known
We want to cache the events until we know the caps of the outgoing buffers and
we can place those caps on the buffers generated from the events. Otherwise we
and up with buffers without caps in the sink.
-rw-r--r-- | gst/rtp/gstrtpgstpay.c | 146 | ||||
-rw-r--r-- | gst/rtp/gstrtpgstpay.h | 2 |
2 files changed, 110 insertions, 38 deletions
diff --git a/gst/rtp/gstrtpgstpay.c b/gst/rtp/gstrtpgstpay.c index 78148623d..14804591c 100644 --- a/gst/rtp/gstrtpgstpay.c +++ b/gst/rtp/gstrtpgstpay.c @@ -77,10 +77,13 @@ GST_STATIC_PAD_TEMPLATE ("src", static void gst_rtp_gst_pay_finalize (GObject * obj); +static GstStateChangeReturn +gst_rtp_gst_pay_change_state (GstElement * element, GstStateChange transition); + static gboolean gst_rtp_gst_pay_setcaps (GstBaseRTPPayload * payload, GstCaps * caps); -static GstFlowReturn gst_rtp_gst_pay_handle_buffer (GstBaseRTPPayload * payload, - GstBuffer * buffer); +static GstFlowReturn gst_rtp_gst_pay_handle_buffer (GstBaseRTPPayload * + payload, GstBuffer * buffer); static gboolean gst_rtp_gst_pay_handle_event (GstPad * pad, GstEvent * event); GST_BOILERPLATE (GstRtpGSTPay, gst_rtp_gst_pay, GstBaseRTPPayload, @@ -105,13 +108,17 @@ static void gst_rtp_gst_pay_class_init (GstRtpGSTPayClass * klass) { GObjectClass *gobject_class; + GstElementClass *gstelement_class; GstBaseRTPPayloadClass *gstbasertppayload_class; gobject_class = (GObjectClass *) klass; + gstelement_class = (GstElementClass *) klass; gstbasertppayload_class = (GstBaseRTPPayloadClass *) klass; gobject_class->finalize = gst_rtp_gst_pay_finalize; + gstelement_class->change_state = gst_rtp_gst_pay_change_state; + gstbasertppayload_class->set_caps = gst_rtp_gst_pay_setcaps; gstbasertppayload_class->handle_buffer = gst_rtp_gst_pay_handle_buffer; gstbasertppayload_class->handle_event = gst_rtp_gst_pay_handle_event; @@ -129,12 +136,22 @@ gst_rtp_gst_pay_init (GstRtpGSTPay * rtpgstpay, GstRtpGSTPayClass * klass) } static void +gst_rtp_gst_pay_reset (GstRtpGSTPay * rtpgstpay) +{ + g_list_foreach (rtpgstpay->events, (GFunc) gst_event_unref, NULL); + g_list_free (rtpgstpay->events); + rtpgstpay->events = NULL; + rtpgstpay->have_caps = FALSE; +} + +static void gst_rtp_gst_pay_finalize (GObject * obj) { GstRtpGSTPay *rtpgstpay; rtpgstpay = GST_RTP_GST_PAY (obj); + gst_rtp_gst_pay_reset (rtpgstpay); g_object_unref (rtpgstpay->adapter); G_OBJECT_CLASS (parent_class)->finalize (obj); @@ -253,6 +270,43 @@ make_data_buffer (GstRtpGSTPay * rtpgstpay, gchar * data, guint size) return outbuf; } +static void +process_event (GstRtpGSTPay * rtpgstpay, GstEvent * event) +{ + switch (GST_EVENT_TYPE (event)) { + case GST_EVENT_TAG: + rtpgstpay->etype = 1; + break; + case GST_EVENT_CUSTOM_DOWNSTREAM: + rtpgstpay->etype = 2; + break; + case GST_EVENT_CUSTOM_BOTH: + rtpgstpay->etype = 2; + break; + default: + break; + } + if (rtpgstpay->etype) { + const GstStructure *s; + gchar *estr; + guint elen; + GstBuffer *outbuf; + + GST_DEBUG_OBJECT (rtpgstpay, "make event type %d", rtpgstpay->etype); + s = gst_event_get_structure (event); + + estr = gst_structure_to_string (s); + elen = strlen (estr); + outbuf = make_data_buffer (rtpgstpay, estr, elen); + g_free (estr); + + gst_adapter_push (rtpgstpay->adapter, outbuf); + /* flush the adapter immediately */ + gst_rtp_gst_pay_flush (rtpgstpay, GST_CLOCK_TIME_NONE); + } +} + + static gboolean gst_rtp_gst_pay_setcaps (GstBaseRTPPayload * payload, GstCaps * caps) { @@ -261,6 +315,7 @@ gst_rtp_gst_pay_setcaps (GstBaseRTPPayload * payload, GstCaps * caps) gchar *capsstr, *capsenc, *capsver; guint capslen; GstBuffer *outbuf; + GList *walk; rtpgstpay = GST_RTP_GST_PAY (payload); @@ -275,6 +330,23 @@ gst_rtp_gst_pay_setcaps (GstBaseRTPPayload * payload, GstCaps * caps) /* for 0 byte */ capslen++; + /* make caps for SDP */ + capsver = g_strdup_printf ("%d", rtpgstpay->current_CV); + res = + gst_basertppayload_set_outcaps (payload, "caps", G_TYPE_STRING, capsenc, + "capsversion", G_TYPE_STRING, capsver, NULL); + + rtpgstpay->have_caps = TRUE; + + for (walk = rtpgstpay->events; walk; walk = g_list_next (walk)) { + GstEvent *event = walk->data; + + process_event (rtpgstpay, event); + gst_event_unref (event); + } + g_list_free (rtpgstpay->events); + rtpgstpay->events = NULL; + /* make a data buffer of it */ outbuf = make_data_buffer (rtpgstpay, capsstr, capslen); g_free (capsstr); @@ -284,11 +356,6 @@ gst_rtp_gst_pay_setcaps (GstBaseRTPPayload * payload, GstCaps * caps) rtpgstpay->next_CV = (rtpgstpay->next_CV + 1) & 0x7; gst_adapter_push (rtpgstpay->adapter, outbuf); - /* make caps for SDP */ - capsver = g_strdup_printf ("%d", rtpgstpay->current_CV); - res = - gst_basertppayload_set_outcaps (payload, "caps", G_TYPE_STRING, capsenc, - "capsversion", G_TYPE_STRING, capsver, NULL); g_free (capsenc); g_free (capsver); @@ -302,38 +369,12 @@ gst_rtp_gst_pay_handle_event (GstPad * pad, GstEvent * event) rtpgstpay = GST_RTP_GST_PAY (GST_PAD_PARENT (pad)); - switch (GST_EVENT_TYPE (event)) { - case GST_EVENT_TAG: - rtpgstpay->etype = 1; - break; - case GST_EVENT_CUSTOM_DOWNSTREAM: - rtpgstpay->etype = 2; - break; - case GST_EVENT_CUSTOM_BOTH: - rtpgstpay->etype = 2; - break; - default: - break; + if (!rtpgstpay->have_caps) { + rtpgstpay->events = + g_list_append (rtpgstpay->events, gst_event_ref (event)); + } else { + process_event (rtpgstpay, event); } - if (rtpgstpay->etype) { - const GstStructure *s; - gchar *estr; - guint elen; - GstBuffer *outbuf; - - GST_DEBUG_OBJECT (rtpgstpay, "make event type %d", rtpgstpay->etype); - s = gst_event_get_structure (event); - - estr = gst_structure_to_string (s); - elen = strlen (estr); - outbuf = make_data_buffer (rtpgstpay, estr, elen); - g_free (estr); - - gst_adapter_push (rtpgstpay->adapter, outbuf); - /* flush the adapter immediately */ - gst_rtp_gst_pay_flush (rtpgstpay, GST_CLOCK_TIME_NONE); - } - /* FALSE to let base class handle it as well */ return FALSE; } @@ -366,6 +407,35 @@ gst_rtp_gst_pay_handle_buffer (GstBaseRTPPayload * basepayload, return ret; } +static GstStateChangeReturn +gst_rtp_gst_pay_change_state (GstElement * element, GstStateChange transition) +{ + GstRtpGSTPay *rtpgstpay; + GstStateChangeReturn ret; + + rtpgstpay = GST_RTP_GST_PAY (element); + + switch (transition) { + case GST_STATE_CHANGE_READY_TO_PAUSED: + gst_rtp_gst_pay_reset (rtpgstpay); + break; + default: + break; + } + + ret = GST_ELEMENT_CLASS (parent_class)->change_state (element, transition); + + switch (transition) { + case GST_STATE_CHANGE_PAUSED_TO_READY: + gst_rtp_gst_pay_reset (rtpgstpay); + break; + default: + break; + } + return ret; +} + + gboolean gst_rtp_gst_pay_plugin_init (GstPlugin * plugin) { diff --git a/gst/rtp/gstrtpgstpay.h b/gst/rtp/gstrtpgstpay.h index 999b42a3e..31cbd49bf 100644 --- a/gst/rtp/gstrtpgstpay.h +++ b/gst/rtp/gstrtpgstpay.h @@ -47,6 +47,8 @@ struct _GstRtpGSTPay GstAdapter *adapter; guint8 flags; guint8 etype; + gboolean have_caps; + GList *events; guint8 current_CV; /* CV field of incoming caps*/ guint8 next_CV; |