diff --git a/gst/rtp/gstrtpgstpay.c b/gst/rtp/gstrtpgstpay.c index e0d4b0e1af..77f19d5bbc 100644 --- a/gst/rtp/gstrtpgstpay.c +++ b/gst/rtp/gstrtpgstpay.c @@ -68,6 +68,8 @@ GST_STATIC_PAD_TEMPLATE ("src", "clock-rate = (int) 90000, " "encoding-name = (string) \"X-GST\"") ); +static void gst_rtp_gst_pay_finalize (GObject * obj); + static gboolean gst_rtp_gst_pay_setcaps (GstRTPBasePayload * payload, GstCaps * caps); static GstFlowReturn gst_rtp_gst_pay_handle_buffer (GstRTPBasePayload * payload, @@ -79,12 +81,16 @@ G_DEFINE_TYPE (GstRtpGSTPay, gst_rtp_gst_pay, GST_TYPE_RTP_BASE_PAYLOAD); static void gst_rtp_gst_pay_class_init (GstRtpGSTPayClass * klass) { + GObjectClass *gobject_class; GstElementClass *gstelement_class; GstRTPBasePayloadClass *gstrtpbasepayload_class; + gobject_class = (GObjectClass *) klass; gstelement_class = (GstElementClass *) klass; gstrtpbasepayload_class = (GstRTPBasePayloadClass *) klass; + gobject_class->finalize = gst_rtp_gst_pay_finalize; + gst_element_class_add_pad_template (gstelement_class, gst_static_pad_template_get (&gst_rtp_gst_pay_src_template)); gst_element_class_add_pad_template (gstelement_class, @@ -107,22 +113,48 @@ gst_rtp_gst_pay_init (GstRtpGSTPay * rtpgstpay) { } +static void +gst_rtp_gst_pay_finalize (GObject * obj) +{ + GstRtpGSTPay *rtpgstpay; + + rtpgstpay = GST_RTP_GST_PAY (obj); + + g_free (rtpgstpay->capsstr); + + G_OBJECT_CLASS (parent_class)->finalize (obj); +} + static gboolean gst_rtp_gst_pay_setcaps (GstRTPBasePayload * payload, GstCaps * caps) { + GstRtpGSTPay *rtpgstpay; gboolean res; - gchar *capsstr, *capsenc; + gchar *capsenc, *capsver; - capsstr = gst_caps_to_string (caps); - capsenc = g_base64_encode ((guchar *) capsstr, strlen (capsstr)); - g_free (capsstr); + rtpgstpay = GST_RTP_GST_PAY (payload); + + g_free (rtpgstpay->capsstr); + rtpgstpay->capsstr = gst_caps_to_string (caps); + rtpgstpay->capslen = strlen (rtpgstpay->capsstr); + rtpgstpay->current_CV = rtpgstpay->next_CV; + + /* encode without 0 byte */ + capsenc = g_base64_encode ((guchar *) rtpgstpay->capsstr, rtpgstpay->capslen); + GST_DEBUG_OBJECT (payload, "caps=%s, caps(base64)=%s", + rtpgstpay->capsstr, capsenc); + /* for 0 byte */ + rtpgstpay->capslen++; + + capsver = g_strdup_printf ("%d", rtpgstpay->current_CV); gst_rtp_base_payload_set_options (payload, "application", TRUE, "X-GST", 90000); res = gst_rtp_base_payload_set_outcaps (payload, "caps", G_TYPE_STRING, capsenc, - NULL); + "capsversion", G_TYPE_STRING, capsver, NULL); g_free (capsenc); + g_free (capsver); return res; } @@ -140,6 +172,9 @@ gst_rtp_gst_pay_handle_buffer (GstRTPBasePayload * basepayload, GstClockTime timestamp; guint32 frag_offset; guint flags; + gchar *capsstr; + guint capslen; + guint capslen_prefix_len; rtpgstpay = GST_RTP_GST_PAY (basepayload); @@ -153,6 +188,22 @@ gst_rtp_gst_pay_handle_buffer (GstRTPBasePayload * basepayload, if (GST_BUFFER_FLAG_IS_SET (buffer, GST_BUFFER_FLAG_DELTA_UNIT)) flags |= (1 << 3); + capsstr = rtpgstpay->capsstr; + capslen = rtpgstpay->capslen; + if (capslen) { + /* start of buffer, calculate length */ + capslen_prefix_len = 1; + while (capslen >> (7 * capslen_prefix_len)) + capslen_prefix_len++; + + GST_DEBUG_OBJECT (rtpgstpay, "sending inline caps"); + rtpgstpay->next_CV++; + } else { + capslen_prefix_len = 0; + } + + flags |= (rtpgstpay->current_CV << 4); + /* * 0 1 2 3 * 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 @@ -166,6 +217,8 @@ gst_rtp_gst_pay_handle_buffer (GstRTPBasePayload * basepayload, ptr = map.data; left = map.size; + GST_DEBUG_OBJECT (basepayload, "buffer size=%u", left); + while (left > 0) { guint towrite; guint8 *payload; @@ -174,7 +227,9 @@ gst_rtp_gst_pay_handle_buffer (GstRTPBasePayload * basepayload, GstRTPBuffer rtp = { NULL }; /* this will be the total lenght of the packet */ - packet_len = gst_rtp_buffer_calc_packet_len (8 + left, 0, 0); + packet_len = + gst_rtp_buffer_calc_packet_len (8 + capslen + capslen_prefix_len + left, + 0, 0); /* fill one MTU or all available bytes */ towrite = MIN (packet_len, GST_RTP_BASE_PAYLOAD_MTU (rtpgstpay)); @@ -188,6 +243,12 @@ gst_rtp_gst_pay_handle_buffer (GstRTPBasePayload * basepayload, gst_rtp_buffer_map (outbuf, GST_MAP_WRITE, &rtp); payload = gst_rtp_buffer_get_payload (&rtp); + if (capslen > 0) + flags |= (1 << 7); + + GST_DEBUG_OBJECT (basepayload, "new packet len %u, frag %u", packet_len, + frag_offset); + payload[0] = flags; payload[1] = payload[2] = payload[3] = 0; payload[4] = frag_offset >> 24; @@ -198,11 +259,49 @@ gst_rtp_gst_pay_handle_buffer (GstRTPBasePayload * basepayload, payload += 8; payload_len -= 8; - memcpy (payload, ptr, payload_len); + if (capslen) { + guint tocopy; - ptr += payload_len; - left -= payload_len; - frag_offset += payload_len; + /* we need to write caps */ + if (frag_offset == 0) { + /* write caps length */ + while (capslen_prefix_len) { + capslen_prefix_len--; + *payload++ = ((capslen_prefix_len > 0) ? 0x80 : 0) | + ((capslen >> (7 * capslen_prefix_len)) & 0x7f); + payload_len--; + frag_offset++; + } + } + + tocopy = MIN (payload_len, capslen); + GST_DEBUG_OBJECT (basepayload, "copy %u bytes from caps to payload", + tocopy); + memcpy (payload, capsstr, tocopy); + + capsstr += tocopy; + capslen -= tocopy; + payload += tocopy; + payload_len -= tocopy; + frag_offset += tocopy; + + if (capslen == 0) { + rtpgstpay->capslen = 0; + g_free (rtpgstpay->capsstr); + rtpgstpay->capsstr = NULL; + } + } + + if (capslen == 0) { + /* no more caps, continue with data */ + GST_DEBUG_OBJECT (basepayload, "copy %u bytes from buffer to payload", + payload_len); + memcpy (payload, ptr, payload_len); + + ptr += payload_len; + left -= payload_len; + frag_offset += payload_len; + } if (left == 0) gst_rtp_buffer_set_marker (&rtp, TRUE); diff --git a/gst/rtp/gstrtpgstpay.h b/gst/rtp/gstrtpgstpay.h index e10401fe02..bde2982ccb 100644 --- a/gst/rtp/gstrtpgstpay.h +++ b/gst/rtp/gstrtpgstpay.h @@ -42,6 +42,11 @@ typedef struct _GstRtpGSTPayClass GstRtpGSTPayClass; struct _GstRtpGSTPay { GstRTPBasePayload payload; + + gchar *capsstr; + guint capslen; + guint8 current_CV; /* CV field of incoming caps*/ + guint8 next_CV; }; struct _GstRtpGSTPayClass