summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorWim Taymans <wim.taymans@collabora.co.uk>2012-11-01 10:52:25 +0000
committerWim Taymans <wim.taymans@collabora.co.uk>2012-11-01 10:56:59 +0000
commit7f46a80cf0d9145a05674ae3b64b3ee36d5e6f08 (patch)
tree5e31a7ad2517250150c19ea92c2a8df2439d73c4
parentb8ba24e5eb4c7a95c6005c0cc3363fd7a18e7032 (diff)
gstpay: send caps inline
Place the capsversion on the outgoing caps so that they end up in an SDP as well. Receivers need to know what capsversion a particular caps is for to be able to match the caps to the CV in the RTP packets. Place the caps inside the RTP packet whenever the caps change. Based on patch by Andrzej Bieniek <andrzej.bieniek@pure.com>
-rw-r--r--gst/rtp/gstrtpgstpay.c120
-rw-r--r--gst/rtp/gstrtpgstpay.h5
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