diff options
Diffstat (limited to 'gst/rtp')
-rw-r--r-- | gst/rtp/gstrtpgstpay.c | 120 | ||||
-rw-r--r-- | gst/rtp/gstrtpgstpay.h | 5 |
2 files changed, 114 insertions, 11 deletions
diff --git a/gst/rtp/gstrtpgstpay.c b/gst/rtp/gstrtpgstpay.c index a6ce29fca..a2f0a3027 100644 --- a/gst/rtp/gstrtpgstpay.c +++ b/gst/rtp/gstrtpgstpay.c @@ -71,6 +71,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 (GstBaseRTPPayload * payload, GstCaps * caps); static GstFlowReturn gst_rtp_gst_pay_handle_buffer (GstBaseRTPPayload * payload, @@ -97,10 +99,14 @@ GST_BOILERPLATE (GstRtpGSTPay, gst_rtp_gst_pay, GstBaseRTPPayload, static void gst_rtp_gst_pay_class_init (GstRtpGSTPayClass * klass) { + GObjectClass *gobject_class; GstBaseRTPPayloadClass *gstbasertppayload_class; + gobject_class = (GObjectClass *) klass; gstbasertppayload_class = (GstBaseRTPPayloadClass *) klass; + gobject_class->finalize = gst_rtp_gst_pay_finalize; + gstbasertppayload_class->set_caps = gst_rtp_gst_pay_setcaps; gstbasertppayload_class->handle_buffer = gst_rtp_gst_pay_handle_buffer; @@ -113,21 +119,47 @@ gst_rtp_gst_pay_init (GstRtpGSTPay * rtpgstpay, GstRtpGSTPayClass * klass) { } +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 (GstBaseRTPPayload * payload, GstCaps * caps) { + GstRtpGSTPay *rtpgstpay; gboolean res; - gchar *capsstr, *capsenc; + gchar *capsenc, *capsver; + + 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; - capsstr = gst_caps_to_string (caps); - capsenc = g_base64_encode ((guchar *) capsstr, strlen (capsstr)); - g_free (capsstr); + /* 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_basertppayload_set_options (payload, "application", TRUE, "X-GST", 90000); res = gst_basertppayload_set_outcaps (payload, "caps", G_TYPE_STRING, capsenc, - NULL); + "capsversion", G_TYPE_STRING, capsver, NULL); g_free (capsenc); + g_free (capsver); return res; } @@ -144,6 +176,9 @@ gst_rtp_gst_pay_handle_buffer (GstBaseRTPPayload * basepayload, GstClockTime timestamp; guint32 frag_offset; guint flags; + gchar *capsstr; + guint capslen; + guint capslen_prefix_len; rtpgstpay = GST_RTP_GST_PAY (basepayload); @@ -164,6 +199,22 @@ gst_rtp_gst_pay_handle_buffer (GstBaseRTPPayload * basepayload, if (GST_BUFFER_FLAG_IS_SET (buffer, GST_BUFFER_FLAG_MEDIA3)) flags |= (1 << 0); + 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 @@ -174,6 +225,7 @@ gst_rtp_gst_pay_handle_buffer (GstBaseRTPPayload * basepayload, * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ */ frag_offset = 0; + GST_DEBUG_OBJECT (basepayload, "buffer size=%u", size); while (size > 0) { guint towrite; @@ -182,7 +234,9 @@ gst_rtp_gst_pay_handle_buffer (GstBaseRTPPayload * basepayload, guint packet_len; /* this will be the total lenght of the packet */ - packet_len = gst_rtp_buffer_calc_packet_len (8 + size, 0, 0); + packet_len = + gst_rtp_buffer_calc_packet_len (8 + capslen + capslen_prefix_len + size, + 0, 0); /* fill one MTU or all available bytes */ towrite = MIN (packet_len, GST_BASE_RTP_PAYLOAD_MTU (rtpgstpay)); @@ -194,6 +248,12 @@ gst_rtp_gst_pay_handle_buffer (GstBaseRTPPayload * basepayload, outbuf = gst_rtp_buffer_new_allocate (payload_len, 0, 0); payload = gst_rtp_buffer_get_payload (outbuf); + 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; @@ -204,11 +264,49 @@ gst_rtp_gst_pay_handle_buffer (GstBaseRTPPayload * basepayload, payload += 8; payload_len -= 8; - memcpy (payload, data, payload_len); - - data += payload_len; - size -= payload_len; - frag_offset += payload_len; + if (capslen) { + guint tocopy; + + /* 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, data, payload_len); + + data += payload_len; + size -= payload_len; + frag_offset += payload_len; + } if (size == 0) gst_rtp_buffer_set_marker (outbuf, TRUE); diff --git a/gst/rtp/gstrtpgstpay.h b/gst/rtp/gstrtpgstpay.h index c7a7c0274..6eeb8cc7b 100644 --- a/gst/rtp/gstrtpgstpay.h +++ b/gst/rtp/gstrtpgstpay.h @@ -42,6 +42,11 @@ typedef struct _GstRtpGSTPayClass GstRtpGSTPayClass; struct _GstRtpGSTPay { GstBaseRTPPayload payload; + + gchar *capsstr; + guint capslen; + guint8 current_CV; /* CV field of incoming caps*/ + guint8 next_CV; }; struct _GstRtpGSTPayClass |