gst-libs/gst/rtp/gstbasertpdepayload.*: Fix for RTPBuffer changes.
authorWim Taymans <wim.taymans@gmail.com>
Thu, 18 Aug 2005 10:23:54 +0000 (10:23 +0000)
committerWim Taymans <wim.taymans@gmail.com>
Thu, 18 Aug 2005 10:23:54 +0000 (10:23 +0000)
Original commit message from CVS:
* gst-libs/gst/rtp/gstbasertpdepayload.c:
(gst_base_rtp_depayload_chain),
(gst_base_rtp_depayload_add_to_queue),
(gst_base_rtp_depayload_push),
(gst_base_rtp_depayload_queue_release):
* gst-libs/gst/rtp/gstbasertpdepayload.h:
Fix for RTPBuffer changes.

* gst-libs/gst/rtp/gstrtpbuffer.c: (gst_rtpbuffer_allocate_data),
(gst_rtpbuffer_new_take_data), (gst_rtpbuffer_new_copy_data),
(gst_rtpbuffer_new_allocate), (gst_rtpbuffer_new_allocate_len),
(gst_rtpbuffer_calc_header_len), (gst_rtpbuffer_calc_packet_len),
(gst_rtpbuffer_calc_payload_len), (gst_rtpbuffer_validate_data),
(gst_rtpbuffer_validate), (gst_rtpbuffer_set_packet_len),
(gst_rtpbuffer_get_packet_len), (gst_rtpbuffer_get_version),
(gst_rtpbuffer_set_version), (gst_rtpbuffer_get_padding),
(gst_rtpbuffer_set_padding), (gst_rtpbuffer_pad_to),
(gst_rtpbuffer_get_extension), (gst_rtpbuffer_set_extension),
(gst_rtpbuffer_get_ssrc), (gst_rtpbuffer_set_ssrc),
(gst_rtpbuffer_get_csrc_count), (gst_rtpbuffer_get_csrc),
(gst_rtpbuffer_set_csrc), (gst_rtpbuffer_get_marker),
(gst_rtpbuffer_set_marker), (gst_rtpbuffer_get_payload_type),
(gst_rtpbuffer_set_payload_type), (gst_rtpbuffer_get_seq),
(gst_rtpbuffer_set_seq), (gst_rtpbuffer_get_timestamp),
(gst_rtpbuffer_set_timestamp), (gst_rtpbuffer_get_payload_len),
(gst_rtpbuffer_get_payload):
* gst-libs/gst/rtp/gstrtpbuffer.h:
Don't subclass GstBuffer but add methods and helper functions
to construct and manipulate RTP packets in regular GstBuffers.

ChangeLog
gst-libs/gst/rtp/gstbasertpdepayload.c
gst-libs/gst/rtp/gstbasertpdepayload.h
gst-libs/gst/rtp/gstrtpbuffer.c
gst-libs/gst/rtp/gstrtpbuffer.h

index 6794bb1..293cbcc 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,35 @@
+2005-08-18  Wim Taymans  <wim@fluendo.com>
+
+       * gst-libs/gst/rtp/gstbasertpdepayload.c:
+       (gst_base_rtp_depayload_chain),
+       (gst_base_rtp_depayload_add_to_queue),
+       (gst_base_rtp_depayload_push),
+       (gst_base_rtp_depayload_queue_release):
+       * gst-libs/gst/rtp/gstbasertpdepayload.h:
+       Fix for RTPBuffer changes.
+
+       * gst-libs/gst/rtp/gstrtpbuffer.c: (gst_rtpbuffer_allocate_data),
+       (gst_rtpbuffer_new_take_data), (gst_rtpbuffer_new_copy_data),
+       (gst_rtpbuffer_new_allocate), (gst_rtpbuffer_new_allocate_len),
+       (gst_rtpbuffer_calc_header_len), (gst_rtpbuffer_calc_packet_len),
+       (gst_rtpbuffer_calc_payload_len), (gst_rtpbuffer_validate_data),
+       (gst_rtpbuffer_validate), (gst_rtpbuffer_set_packet_len),
+       (gst_rtpbuffer_get_packet_len), (gst_rtpbuffer_get_version),
+       (gst_rtpbuffer_set_version), (gst_rtpbuffer_get_padding),
+       (gst_rtpbuffer_set_padding), (gst_rtpbuffer_pad_to),
+       (gst_rtpbuffer_get_extension), (gst_rtpbuffer_set_extension),
+       (gst_rtpbuffer_get_ssrc), (gst_rtpbuffer_set_ssrc),
+       (gst_rtpbuffer_get_csrc_count), (gst_rtpbuffer_get_csrc),
+       (gst_rtpbuffer_set_csrc), (gst_rtpbuffer_get_marker),
+       (gst_rtpbuffer_set_marker), (gst_rtpbuffer_get_payload_type),
+       (gst_rtpbuffer_set_payload_type), (gst_rtpbuffer_get_seq),
+       (gst_rtpbuffer_set_seq), (gst_rtpbuffer_get_timestamp),
+       (gst_rtpbuffer_set_timestamp), (gst_rtpbuffer_get_payload_len),
+       (gst_rtpbuffer_get_payload):
+       * gst-libs/gst/rtp/gstrtpbuffer.h:
+       Don't subclass GstBuffer but add methods and helper functions
+       to construct and manipulate RTP packets in regular GstBuffers.
+
 2005-08-18  Stefan Kost  <ensonic@users.sf.net>
 
        * gst/sine/gstsinesrc.c: (gst_sinesrc_src_query):
index a3d61b8..c24f1b2 100644 (file)
@@ -51,7 +51,7 @@ static void gst_base_rtp_depayload_init (GstBaseRTPDepayload * filter,
     gpointer g_class);
 
 static void gst_base_rtp_depayload_push (GstBaseRTPDepayload * filter,
-    GstRTPBuffer * rtp_buf);
+    GstBuffer * rtp_buf);
 
 GType
 gst_base_rtp_depayload_get_type (void)
@@ -91,7 +91,7 @@ static GstFlowReturn gst_base_rtp_depayload_chain (GstPad * pad,
 static GstElementStateReturn gst_base_rtp_depayload_change_state (GstElement *
     element);
 static GstFlowReturn gst_base_rtp_depayload_add_to_queue (GstBaseRTPDepayload *
-    filter, GstRTPBuffer * in);
+    filter, GstBuffer * in);
 
 static void gst_base_rtp_depayload_set_gst_timestamp
     (GstBaseRTPDepayload * filter, guint32 timestamp, GstBuffer * buf);
@@ -221,24 +221,21 @@ gst_base_rtp_depayload_chain (GstPad * pad, GstBuffer * in)
 
   g_return_val_if_fail (filter->clock_rate > 0, GST_FLOW_ERROR);
 
-  // must supply RTPBuffers here
-  g_return_val_if_fail (GST_IS_RTPBUFFER (in), GST_FLOW_ERROR);
-
   GstBaseRTPDepayloadClass *bclass = GST_BASE_RTP_DEPAYLOAD_GET_CLASS (filter);
 
   if (filter->process_only) {
     GST_DEBUG ("Pushing directly!");
-    gst_base_rtp_depayload_push (filter, GST_RTPBUFFER (in));
+    gst_base_rtp_depayload_push (filter, in);
   } else {
     if (bclass->add_to_queue)
-      ret = bclass->add_to_queue (filter, GST_RTPBUFFER (in));
+      ret = bclass->add_to_queue (filter, in);
   }
   return ret;
 }
 
 static GstFlowReturn
 gst_base_rtp_depayload_add_to_queue (GstBaseRTPDepayload * filter,
-    GstRTPBuffer * in)
+    GstBuffer * in)
 {
   GQueue *queue = filter->queue;
 
@@ -246,39 +243,55 @@ gst_base_rtp_depayload_add_to_queue (GstBaseRTPDepayload * filter,
   QUEUE_LOCK (filter);
   if (g_queue_is_empty (queue)) {
     g_queue_push_tail (queue, in);
-  } else
+  } else {
+    guint16 seqnum, queueseq;
+    guint32 timestamp;
+
+    seqnum = gst_rtpbuffer_get_seq (in);
+    queueseq = gst_rtpbuffer_get_seq (GST_BUFFER (g_queue_peek_head (queue)));
+
     // not our first packet
-  {
     // let us make sure it is not very late
-    if (in->seqnum < GST_RTPBUFFER (g_queue_peek_head (queue))->seqnum) {
-      // we need to drop this one
-      GST_DEBUG ("Packet arrived to late, dropping");
-      return GST_FLOW_OK;
-    }
+    if (seqnum < queueseq)
+      goto too_late;
+
     // look for right place to insert it
     int i = 0;
 
-    while (in->seqnum < GST_RTPBUFFER (g_queue_peek_nth (queue, i))->seqnum)
+    while (seqnum < queueseq) {
       i++;
+      queueseq =
+          gst_rtpbuffer_get_seq (GST_BUFFER (g_queue_peek_nth (queue, i)));
+    }
+
     // now insert it at that place
     g_queue_push_nth (queue, in, i);
-    GST_DEBUG ("Packet added to queue %d at pos %d timestamp %u sn %d",
-        g_queue_get_length (queue), i, in->timestamp, in->seqnum);
 
+    timestamp = gst_rtpbuffer_get_timestamp (in);
+
+    GST_DEBUG ("Packet added to queue %d at pos %d timestamp %u sn %d",
+        g_queue_get_length (queue), i, timestamp, seqnum);
   }
   QUEUE_UNLOCK (filter);
   return GST_FLOW_OK;
+
+too_late:
+  {
+    QUEUE_UNLOCK (filter);
+    // we need to drop this one
+    GST_DEBUG ("Packet arrived to late, dropping");
+    return GST_FLOW_OK;
+  }
 }
 
 static void
-gst_base_rtp_depayload_push (GstBaseRTPDepayload * filter,
-    GstRTPBuffer * rtp_buf)
+gst_base_rtp_depayload_push (GstBaseRTPDepayload * filter, GstBuffer * rtp_buf)
 {
   GstBaseRTPDepayloadClass *bclass = GST_BASE_RTP_DEPAYLOAD_GET_CLASS (filter);
   GstBuffer *out_buf;
 
   // let's send it out to processing
-  out_buf = bclass->process (filter, GST_RTPBUFFER (rtp_buf));
+  out_buf = bclass->process (filter, rtp_buf);
   if (out_buf) {
     // set the caps
     gst_buffer_set_caps (GST_BUFFER (out_buf),
@@ -330,6 +343,8 @@ static void
 gst_base_rtp_depayload_queue_release (GstBaseRTPDepayload * filter)
 {
   GQueue *queue = filter->queue;
+  guint32 headts, tailts;
+  GstBaseRTPDepayloadClass *bclass;
 
   if (g_queue_is_empty (queue))
     return;
@@ -341,18 +356,22 @@ gst_base_rtp_depayload_queue_release (GstBaseRTPDepayload * filter)
   guint maxtsunits = (gfloat) filter->clock_rate * q_size_secs;
 
   //GST_DEBUG("maxtsunit is %u", maxtsunits);
-  //GST_DEBUG("ts %d %d %d", GST_RTPBUFFER(g_queue_peek_head (queue))->timestamp, GST_RTPBUFFER(g_queue_peek_tail (queue))->timestamp);
+  //GST_DEBUG("ts %d %d %d", GST_BUFFER(g_queue_peek_head (queue))->timestamp, GST_BUFFER(g_queue_peek_tail (queue))->timestamp);
   QUEUE_LOCK (filter);
-  while (GST_RTPBUFFER (g_queue_peek_head (queue))->timestamp -
-      GST_RTPBUFFER (g_queue_peek_tail (queue))->timestamp > maxtsunits) {
+  headts = gst_rtpbuffer_get_timestamp (GST_BUFFER (g_queue_peek_head (queue)));
+  tailts = gst_rtpbuffer_get_timestamp (GST_BUFFER (g_queue_peek_tail (queue)));
+
+  bclass = GST_BASE_RTP_DEPAYLOAD_GET_CLASS (filter);
+
+  while (headts - tailts > maxtsunits) {
     //GST_DEBUG("Poping packet from queue");
-    GstBaseRTPDepayloadClass *bclass =
-        GST_BASE_RTP_DEPAYLOAD_GET_CLASS (filter);
     if (bclass->process) {
-      GstRTPBuffer *in = g_queue_pop_tail (queue);
+      GstBuffer *in = g_queue_pop_tail (queue);
 
-      gst_base_rtp_depayload_push (filter, GST_RTPBUFFER (in));
+      gst_base_rtp_depayload_push (filter, in);
     }
+    tailts =
+        gst_rtpbuffer_get_timestamp (GST_BUFFER (g_queue_peek_tail (queue)));
   }
   QUEUE_UNLOCK (filter);
 }
index 5190973..ad9f1a4 100644 (file)
@@ -89,11 +89,11 @@ struct _GstBaseRTPDepayloadClass
 
   // non-pure function, default implementation in base class
   // this does buffering, reordering and dropping
-  GstFlowReturn (*add_to_queue) (GstBaseRTPDepayload *filter, GstRTPBuffer *in);
+  GstFlowReturn (*add_to_queue) (GstBaseRTPDepayload *filter, GstBuffer *in);
 
   // pure virtual function, child must use this to process incoming
   // rtp packets
-  GstBuffer * (*process) (GstBaseRTPDepayload *base, GstRTPBuffer *in);
+  GstBuffer * (*process) (GstBaseRTPDepayload *base, GstBuffer *in);
 
   // non-pure function used to convert from RTP timestamp to GST timestamp
   // this function is used by the child class before gst_pad_pushing
index 0f03a6f..62e8fd4 100644 (file)
 
 #include "gstrtpbuffer.h"
 
-static void gst_rtpbuffer_init (GTypeInstance * instance, gpointer g_class);
-static void gst_rtpbuffer_class_init (gpointer g_class, gpointer class_data);
-static void gst_rtpbuffer_finalize (GstRTPBuffer * nbuf);
-static GstRTPBuffer *gst_rtpbuffer_copy (GstRTPBuffer * nbuf);
-
-static GstBufferClass *parent_class;
-
-GType
-gst_rtpbuffer_get_type (void)
-{
-  static GType _gst_rtpbuffer_type = 0;
-
-  if (G_UNLIKELY (_gst_rtpbuffer_type == 0)) {
-    static const GTypeInfo rtpbuffer_info = {
-      sizeof (GstRTPBufferClass),
-      NULL,
-      NULL,
-      gst_rtpbuffer_class_init,
-      NULL,
-      NULL,
-      sizeof (GstRTPBuffer),
-      0,
-      gst_rtpbuffer_init,
-      NULL
-    };
-
-    _gst_rtpbuffer_type = g_type_register_static (GST_TYPE_BUFFER,
-        "GstRTPBuffer", &rtpbuffer_info, 0);
+#define GST_RTP_HEADER_LEN 12
+
+typedef struct _GstRTPHeader
+{
+#if G_BYTE_ORDER == G_LITTLE_ENDIAN
+  unsigned int csrc_count:4;    /* CSRC count */
+  unsigned int extension:1;     /* header extension flag */
+  unsigned int padding:1;       /* padding flag */
+  unsigned int version:2;       /* protocol version */
+  unsigned int payload_type:7;  /* payload type */
+  unsigned int marker:1;        /* marker bit */
+#elif G_BYTE_ORDER == G_BIG_ENDIAN
+  unsigned int version:2;       /* protocol version */
+  unsigned int padding:1;       /* padding flag */
+  unsigned int extension:1;     /* header extension flag */
+  unsigned int csrc_count:4;    /* CSRC count */
+  unsigned int marker:1;        /* marker bit */
+  unsigned int payload_type:7;  /* payload type */
+#else
+#error "G_BYTE_ORDER should be big or little endian."
+#endif
+  guint16 seq;                  /* sequence number */
+  guint32 timestamp;            /* timestamp */
+  guint32 ssrc;                 /* synchronization source */
+  guint32 csrc[1];              /* optional CSRC list */
+} GstRTPHeader;
+
+#define GST_RTP_HEADER_VERSION(buf)    (((GstRTPHeader *)(GST_BUFFER_DATA (buf)))->version)
+#define GST_RTP_HEADER_PADDING(buf)    (((GstRTPHeader *)(GST_BUFFER_DATA (buf)))->padding)
+#define GST_RTP_HEADER_EXTENSION(buf)  (((GstRTPHeader *)(GST_BUFFER_DATA (buf)))->extension)
+#define GST_RTP_HEADER_CSRC_COUNT(buf) (((GstRTPHeader *)(GST_BUFFER_DATA (buf)))->csrc_count)
+#define GST_RTP_HEADER_MARKER(buf)     (((GstRTPHeader *)(GST_BUFFER_DATA (buf)))->marker)
+#define GST_RTP_HEADER_PAYLOAD_TYPE(buf)(((GstRTPHeader *)(GST_BUFFER_DATA (buf)))->payload_type)
+#define GST_RTP_HEADER_SEQ(buf)                (((GstRTPHeader *)(GST_BUFFER_DATA (buf)))->seq)
+#define GST_RTP_HEADER_TIMESTAMP(buf)  (((GstRTPHeader *)(GST_BUFFER_DATA (buf)))->timestamp)
+#define GST_RTP_HEADER_SSRC(buf)       (((GstRTPHeader *)(GST_BUFFER_DATA (buf)))->ssrc)
+#define GST_RTP_HEADER_CSRC(buf,i)     (((GstRTPHeader *)(GST_BUFFER_DATA (buf)))->csrc[i])
+
+#define GST_RTP_HEADER_CSRC_SIZE(buf)  (GST_RTP_HEADER_CSRC_COUNT(buf) * sizeof (guint32))
+
+void
+gst_rtpbuffer_allocate_data (GstBuffer * buffer, guint payload_len,
+    guint8 pad_len, guint8 csrc_count)
+{
+  guint len;
+
+  g_return_if_fail (csrc_count <= 15);
+  g_return_if_fail (GST_IS_BUFFER (buffer));
+
+  len = GST_RTP_HEADER_LEN + csrc_count * sizeof (guint32)
+      + payload_len + pad_len;
+
+  GST_BUFFER_MALLOCDATA (buffer) = g_malloc (len);
+  GST_BUFFER_DATA (buffer) = GST_BUFFER_MALLOCDATA (buffer);
+  GST_BUFFER_SIZE (buffer) = len;
+
+  /* fill in defaults */
+  GST_RTP_HEADER_VERSION (buffer) = GST_RTP_VERSION;
+  GST_RTP_HEADER_PADDING (buffer) = FALSE;
+  GST_RTP_HEADER_EXTENSION (buffer) = FALSE;
+  GST_RTP_HEADER_CSRC_COUNT (buffer) = 0;
+  GST_RTP_HEADER_MARKER (buffer) = FALSE;
+  GST_RTP_HEADER_PAYLOAD_TYPE (buffer) = 0;
+  GST_RTP_HEADER_SEQ (buffer) = 0;
+  GST_RTP_HEADER_TIMESTAMP (buffer) = 0;
+  GST_RTP_HEADER_SSRC (buffer) = 0;
+}
+
+GstBuffer *
+gst_rtpbuffer_new_take_data (gpointer data, guint len)
+{
+  GstBuffer *result;
+
+  g_return_val_if_fail (data != NULL, NULL);
+  g_return_val_if_fail (len > 0, NULL);
+
+  result = gst_buffer_new ();
+
+  GST_BUFFER_MALLOCDATA (result) = data;
+  GST_BUFFER_DATA (result) = data;
+  GST_BUFFER_SIZE (result) = len;
+
+  return result;
+}
+
+GstBuffer *
+gst_rtpbuffer_new_copy_data (gpointer data, guint len)
+{
+  return gst_rtpbuffer_new_take_data (g_memdup (data, len), len);
+}
+
+GstBuffer *
+gst_rtpbuffer_new_allocate (guint payload_len, guint8 pad_len,
+    guint8 csrc_count)
+{
+  GstBuffer *result;
+
+  g_return_val_if_fail (csrc_count <= 15, NULL);
+
+  result = gst_buffer_new ();
+  gst_rtpbuffer_allocate_data (result, payload_len, pad_len, csrc_count);
+
+  return result;
+}
+
+GstBuffer *
+gst_rtpbuffer_new_allocate_len (guint packet_len, guint8 pad_len,
+    guint8 csrc_count)
+{
+  guint len;
+
+  g_return_val_if_fail (csrc_count <= 15, NULL);
+
+  len = gst_rtpbuffer_calc_payload_len (packet_len, pad_len, csrc_count);
+
+  return gst_rtpbuffer_new_allocate (len, pad_len, csrc_count);
+}
+
+guint
+gst_rtpbuffer_calc_header_len (guint8 csrc_count)
+{
+  g_return_val_if_fail (csrc_count <= 15, 0);
+
+  return GST_RTP_HEADER_LEN + (csrc_count * sizeof (guint32));
+}
+
+guint
+gst_rtpbuffer_calc_packet_len (guint payload_len, guint8 pad_len,
+    guint8 csrc_count)
+{
+  g_return_val_if_fail (csrc_count <= 15, 0);
+
+  return payload_len + GST_RTP_HEADER_LEN + (csrc_count * sizeof (guint32))
+      + pad_len;
+}
+
+guint
+gst_rtpbuffer_calc_payload_len (guint packet_len, guint8 pad_len,
+    guint8 csrc_count)
+{
+  g_return_val_if_fail (csrc_count <= 15, 0);
+
+  return packet_len - GST_RTP_HEADER_LEN - (csrc_count * sizeof (guint32))
+      - pad_len;
+}
+
+gboolean
+gst_rtpbuffer_validate_data (guint8 * data, guint len)
+{
+  guint8 padding;
+  guint8 csrc_count;
+  guint header_len;
+  guint8 version;
+
+  g_return_val_if_fail (data != NULL, FALSE);
+
+  header_len = GST_RTP_HEADER_LEN;
+  if (len < header_len) {
+    GST_DEBUG ("len < header_len check failed (%d < %d)", len, header_len);
+    return FALSE;
+  }
+
+  /* check version */
+  version = (data[0] & 0xc0) >> 6;
+  if (version != GST_RTP_VERSION) {
+    GST_DEBUG ("version check failed (%d != %d)", version, GST_RTP_VERSION);
+    return FALSE;
+  }
+
+  /* calc header length with csrc */
+  csrc_count = (data[0] & 0x0f);
+  header_len += csrc_count * sizeof (guint32);
+
+  /* check for padding */
+  if (data[0] & 0x40)
+    padding = data[len - 1];
+  else
+    padding = 0;
+
+  /* check if padding not bigger than packet and header */
+  if (len - header_len <= padding) {
+    GST_DEBUG ("padding check failed (%d - %d <= %d)",
+        len, header_len, padding);
+    return FALSE;
+  }
+
+  return TRUE;
+}
+
+gboolean
+gst_rtpbuffer_validate (GstBuffer * buffer)
+{
+  guint8 *data;
+  guint len;
+
+  g_return_val_if_fail (GST_IS_BUFFER (buffer), FALSE);
+
+  data = GST_BUFFER_DATA (buffer);
+  len = GST_BUFFER_SIZE (buffer);
+
+  return gst_rtpbuffer_validate_data (data, len);
+}
+
+
+void
+gst_rtpbuffer_set_packet_len (GstBuffer * buffer, guint len)
+{
+  guint oldlen;
+
+  g_return_if_fail (GST_IS_BUFFER (buffer));
+
+  oldlen = GST_BUFFER_SIZE (buffer);
+
+  if (oldlen < len) {
+    guint8 *newdata;
+
+    newdata = g_realloc (GST_BUFFER_MALLOCDATA (buffer), len);
+    GST_BUFFER_MALLOCDATA (buffer) = newdata;
+    GST_BUFFER_DATA (buffer) = newdata;
   }
-  return _gst_rtpbuffer_type;
+  GST_BUFFER_SIZE (buffer) = len;
+
+  /* remove any padding */
+  GST_RTP_HEADER_PADDING (buffer) = FALSE;
+
+}
+
+guint
+gst_rtpbuffer_get_packet_len (GstBuffer * buffer)
+{
+  g_return_val_if_fail (GST_IS_BUFFER (buffer), 0);
+
+  return GST_BUFFER_SIZE (buffer);
+}
+
+guint8
+gst_rtpbuffer_get_version (GstBuffer * buffer)
+{
+  g_return_val_if_fail (GST_IS_BUFFER (buffer), 0);
+  g_return_val_if_fail (GST_BUFFER_DATA (buffer) != NULL, 0);
+
+  return GST_RTP_HEADER_VERSION (buffer);
+}
+
+void
+gst_rtpbuffer_set_version (GstBuffer * buffer, guint8 version)
+{
+  g_return_if_fail (GST_IS_BUFFER (buffer));
+  g_return_if_fail (version < 0x04);
+  g_return_if_fail (GST_BUFFER_DATA (buffer) != NULL);
+
+  GST_RTP_HEADER_VERSION (buffer) = version;
+}
+
+
+gboolean
+gst_rtpbuffer_get_padding (GstBuffer * buffer)
+{
+  g_return_val_if_fail (GST_IS_BUFFER (buffer), FALSE);
+  g_return_val_if_fail (GST_BUFFER_DATA (buffer) != NULL, FALSE);
+
+  return GST_RTP_HEADER_PADDING (buffer);
+}
+
+void
+gst_rtpbuffer_set_padding (GstBuffer * buffer, gboolean padding)
+{
+  g_return_if_fail (GST_IS_BUFFER (buffer));
+  g_return_if_fail (GST_BUFFER_DATA (buffer) != NULL);
+
+  GST_RTP_HEADER_PADDING (buffer) = padding;
+}
+
+void
+gst_rtpbuffer_pad_to (GstBuffer * buffer, guint len)
+{
+  g_return_if_fail (GST_IS_BUFFER (buffer));
+  g_return_if_fail (GST_BUFFER_DATA (buffer) != NULL);
+
+  if (len > 0)
+    GST_RTP_HEADER_PADDING (buffer) = TRUE;
+  else
+    GST_RTP_HEADER_PADDING (buffer) = FALSE;
+}
+
+
+gboolean
+gst_rtpbuffer_get_extension (GstBuffer * buffer)
+{
+  g_return_val_if_fail (GST_IS_BUFFER (buffer), FALSE);
+  g_return_val_if_fail (GST_BUFFER_DATA (buffer) != NULL, FALSE);
+
+  return GST_RTP_HEADER_EXTENSION (buffer);
+}
+
+void
+gst_rtpbuffer_set_extension (GstBuffer * buffer, gboolean extension)
+{
+  g_return_if_fail (GST_IS_BUFFER (buffer));
+  g_return_if_fail (GST_BUFFER_DATA (buffer) != NULL);
+
+  GST_RTP_HEADER_EXTENSION (buffer) = extension;
+}
+
+guint32
+gst_rtpbuffer_get_ssrc (GstBuffer * buffer)
+{
+  g_return_val_if_fail (GST_IS_BUFFER (buffer), 0);
+  g_return_val_if_fail (GST_BUFFER_DATA (buffer) != NULL, 0);
+
+  return g_ntohl (GST_RTP_HEADER_SSRC (buffer));
+}
+
+void
+gst_rtpbuffer_set_ssrc (GstBuffer * buffer, guint32 ssrc)
+{
+  g_return_if_fail (GST_IS_BUFFER (buffer));
+  g_return_if_fail (GST_BUFFER_DATA (buffer) != NULL);
+
+  GST_RTP_HEADER_SSRC (buffer) = g_htonl (ssrc);
+}
+
+guint8
+gst_rtpbuffer_get_csrc_count (GstBuffer * buffer)
+{
+  g_return_val_if_fail (GST_IS_BUFFER (buffer), 0);
+  g_return_val_if_fail (GST_BUFFER_DATA (buffer) != NULL, 0);
+
+  return GST_RTP_HEADER_CSRC_COUNT (buffer);
+}
+
+guint32
+gst_rtpbuffer_get_csrc (GstBuffer * buffer, guint8 idx)
+{
+  g_return_val_if_fail (GST_IS_BUFFER (buffer), 0);
+  g_return_val_if_fail (GST_BUFFER_DATA (buffer) != NULL, 0);
+  g_return_val_if_fail (GST_RTP_HEADER_CSRC_COUNT (buffer) < idx, 0);
+
+  return g_ntohl (GST_RTP_HEADER_CSRC (buffer, idx));
+}
+
+void
+gst_rtpbuffer_set_csrc (GstBuffer * buffer, guint8 idx, guint32 csrc)
+{
+  g_return_if_fail (GST_IS_BUFFER (buffer));
+  g_return_if_fail (GST_BUFFER_DATA (buffer) != NULL);
+  g_return_if_fail (GST_RTP_HEADER_CSRC_COUNT (buffer) < idx);
+
+  GST_RTP_HEADER_CSRC (buffer, idx) = g_htonl (csrc);
+}
+
+gboolean
+gst_rtpbuffer_get_marker (GstBuffer * buffer)
+{
+  g_return_val_if_fail (GST_IS_BUFFER (buffer), FALSE);
+  g_return_val_if_fail (GST_BUFFER_DATA (buffer) != NULL, FALSE);
+
+  return GST_RTP_HEADER_MARKER (buffer);
+}
+
+void
+gst_rtpbuffer_set_marker (GstBuffer * buffer, gboolean marker)
+{
+  g_return_if_fail (GST_IS_BUFFER (buffer));
+  g_return_if_fail (GST_BUFFER_DATA (buffer) != NULL);
+
+  GST_RTP_HEADER_MARKER (buffer) = marker;
 }
 
-static void
-gst_rtpbuffer_class_init (gpointer g_class, gpointer class_data)
+
+guint8
+gst_rtpbuffer_get_payload_type (GstBuffer * buffer)
 {
-  GstMiniObjectClass *mo_class = GST_MINI_OBJECT_CLASS (g_class);
+  g_return_val_if_fail (GST_IS_BUFFER (buffer), 0);
+  g_return_val_if_fail (GST_BUFFER_DATA (buffer) != NULL, 0);
+
+  return GST_RTP_HEADER_PAYLOAD_TYPE (buffer);
+}
 
-  parent_class = g_type_class_ref (GST_TYPE_BUFFER);
+void
+gst_rtpbuffer_set_payload_type (GstBuffer * buffer, guint8 payload_type)
+{
+  g_return_if_fail (GST_IS_BUFFER (buffer));
+  g_return_if_fail (GST_BUFFER_DATA (buffer) != NULL);
+  g_return_if_fail (payload_type < 0x80);
 
-  mo_class->copy = (GstMiniObjectCopyFunction) gst_rtpbuffer_copy;
-  mo_class->finalize = (GstMiniObjectFinalizeFunction) gst_rtpbuffer_finalize;
+  GST_RTP_HEADER_PAYLOAD_TYPE (buffer) = payload_type;
 }
 
-static void
-gst_rtpbuffer_init (GTypeInstance * instance, gpointer g_class)
+
+guint16
+gst_rtpbuffer_get_seq (GstBuffer * buffer)
 {
+  g_return_val_if_fail (GST_IS_BUFFER (buffer), 0);
+  g_return_val_if_fail (GST_BUFFER_DATA (buffer) != NULL, 0);
+
+  return g_ntohs (GST_RTP_HEADER_SEQ (buffer));
 }
 
-static void
-gst_rtpbuffer_finalize (GstRTPBuffer * nbuf)
+void
+gst_rtpbuffer_set_seq (GstBuffer * buffer, guint16 seq)
 {
-  GST_MINI_OBJECT_CLASS (parent_class)->finalize (GST_MINI_OBJECT (nbuf));
+  g_return_if_fail (GST_IS_BUFFER (buffer));
+  g_return_if_fail (GST_BUFFER_DATA (buffer) != NULL);
+
+  GST_RTP_HEADER_SEQ (buffer) = g_htons (seq);
 }
 
-static GstRTPBuffer *
-gst_rtpbuffer_copy (GstRTPBuffer * nbuf)
+
+guint32
+gst_rtpbuffer_get_timestamp (GstBuffer * buffer)
 {
-  GstRTPBuffer *copy;
+  g_return_val_if_fail (GST_IS_BUFFER (buffer), 0);
+  g_return_val_if_fail (GST_BUFFER_DATA (buffer) != NULL, 0);
 
-  copy =
-      (GstRTPBuffer *) GST_MINI_OBJECT_CLASS (parent_class)->
-      copy (GST_MINI_OBJECT (nbuf));
+  return g_ntohl (GST_RTP_HEADER_TIMESTAMP (buffer));
+}
 
-  copy->pt = nbuf->pt;
-  copy->seqnum = nbuf->seqnum;
-  copy->timestamp = nbuf->timestamp;
-  copy->timestampinc = nbuf->timestampinc;
-  copy->mark = nbuf->mark;
+void
+gst_rtpbuffer_set_timestamp (GstBuffer * buffer, guint32 timestamp)
+{
+  g_return_if_fail (GST_IS_BUFFER (buffer));
+  g_return_if_fail (GST_BUFFER_DATA (buffer) != NULL);
 
-  return copy;
+  GST_RTP_HEADER_TIMESTAMP (buffer) = g_htonl (timestamp);
 }
 
-GstRTPBuffer *
-gst_rtpbuffer_new (void)
+
+guint
+gst_rtpbuffer_get_payload_len (GstBuffer * buffer)
 {
-  GstRTPBuffer *buf;
+  guint len;
+
+  g_return_val_if_fail (GST_IS_BUFFER (buffer), 0);
+  g_return_val_if_fail (GST_BUFFER_DATA (buffer) != NULL, 0);
+
+  len = GST_BUFFER_SIZE (buffer)
+      - GST_RTP_HEADER_LEN - GST_RTP_HEADER_CSRC_SIZE (buffer);
 
-  buf = (GstRTPBuffer *) gst_mini_object_new (GST_TYPE_RTPBUFFER);
+  if (GST_RTP_HEADER_PADDING (buffer))
+    len -= ((guint8 *) GST_BUFFER_DATA (buffer))[GST_BUFFER_SIZE (buffer) - 1];
+
+  return len;
+}
+
+gpointer
+gst_rtpbuffer_get_payload (GstBuffer * buffer)
+{
+  g_return_val_if_fail (GST_IS_BUFFER (buffer), NULL);
+  g_return_val_if_fail (GST_BUFFER_DATA (buffer) != NULL, NULL);
 
-  return buf;
+  return GST_BUFFER_DATA (buffer) + GST_RTP_HEADER_LEN
+      + GST_RTP_HEADER_CSRC_SIZE (buffer);
 }
index 097a37a..8bc3f5a 100644 (file)
@@ -1,5 +1,9 @@
 /* GStreamer
  * Copyright (C) <2005> Philippe Khalaf <burger@speedy.org>
+ *               <2005> Wim Taymans <wim@fluendo.com>
+ *
+ * gstrtpbuffer.h: various helper functions to manipulate buffers
+ *     with RTP payload.
  *
  * This library is free software; you can redistribute it and/or
  * modify it under the terms of the GNU Library General Public
 
 G_BEGIN_DECLS
 
-typedef struct _GstRTPBuffer GstRTPBuffer;
-typedef struct _GstRTPBufferClass GstRTPBufferClass;
+#define GST_RTP_VERSION 2
+
+typedef enum
+{
+  /* Audio: */
+  GST_RTP_PAYLOAD_PCMU = 0,             /* ITU-T G.711. mu-law audio (RFC 3551) */
+  GST_RTP_PAYLOAD_GSM = 3,
+  GST_RTP_PAYLOAD_PCMA = 8,             /* ITU-T G.711 A-law audio (RFC 3551) */
+  GST_RTP_PAYLOAD_L16_STEREO = 10,
+  GST_RTP_PAYLOAD_L16_MONO = 11,
+  GST_RTP_PAYLOAD_MPA = 14,             /* Audio MPEG 1-3 */
+  GST_RTP_PAYLOAD_G723_63 = 16,         /* Not standard */
+  GST_RTP_PAYLOAD_G723_53 = 17,         /* Not standard */
+  GST_RTP_PAYLOAD_TS48 = 18,            /* Not standard */
+  GST_RTP_PAYLOAD_TS41 = 19,            /* Not standard */
+  GST_RTP_PAYLOAD_G728 = 20,            /* Not standard */
+  GST_RTP_PAYLOAD_G729 = 21,            /* Not standard */
+
+  /* Video: */
+  GST_RTP_PAYLOAD_MPV = 32,             /* Video MPEG 1 & 2 */
+
+  /* BOTH */
+  GST_RTP_PAYLOAD_BMPEG = 34            /* Not Standard */
+} GstRTPPayload;
 
-#define GST_TYPE_RTPBUFFER            (gst_rtpbuffer_get_type())
-#define GST_IS_RTPBUFFER(obj)         (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GST_TYPE_RTPBUFFER))
-#define GST_IS_RTPBUFFER_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GST_TYPE_RTPBUFFER))
-#define GST_RTPBUFFER_GET_CLASS(obj)  (G_TYPE_INSTANCE_GET_CLASS ((obj), GST_TYPE_RTPBUFFER, GstRTPBufferClass))
-#define GST_RTPBUFFER(obj)            (G_TYPE_CHECK_INSTANCE_CAST ((obj), GST_TYPE_RTPBUFFER, GstRTPBuffer))
-#define GST_RTPBUFFER_CLASS(klass)    (G_TYPE_CHECK_CLASS_CAST ((klass), GST_TYPE_RTPBUFFER, GstRTPBufferClass))
+/* creating buffers */
+GstBuffer*     gst_rtpbuffer_new               (void);
+void           gst_rtpbuffer_allocate_data     (GstBuffer *buffer, guint payload_len, 
+                                                guint8 pad_len, guint8 csrc_count);
 
-/* buffer for use rtp packets
- *
- * It contains the payload type, timestamp, timestamp increment 
- * and mark of the rtp packet
- */
+GstBuffer*     gst_rtpbuffer_new_take_data     (gpointer data, guint len);
+GstBuffer*     gst_rtpbuffer_new_copy_data     (gpointer data, guint len);
+GstBuffer*     gst_rtpbuffer_new_allocate      (guint payload_len, guint8 pad_len, guint8 csrc_count);
+GstBuffer*     gst_rtpbuffer_new_allocate_len  (guint packet_len, guint8 pad_len, guint8 csrc_count);
 
-struct _GstRTPBuffer {
-  GstBuffer buffer;
+guint          gst_rtpbuffer_calc_header_len   (guint8 csrc_count);
+guint          gst_rtpbuffer_calc_packet_len   (guint payload_len, guint8 pad_len, guint8 csrc_count);
+guint          gst_rtpbuffer_calc_payload_len  (guint packet_len, guint8 pad_len, guint8 csrc_count);
 
-  guint8 pt;
-  guint16 seqnum;
-  guint32 timestamp;
-  guint32 timestampinc;
-  gboolean mark;
+gboolean       gst_rtpbuffer_validate_data     (guint8 *data, guint len);
+gboolean       gst_rtpbuffer_validate          (GstBuffer *buffer);
 
-  /*< private >*/
-  gpointer _gst_reserved[GST_PADDING];
-};
+void           gst_rtpbuffer_set_packet_len    (GstBuffer *buffer, guint len);
+guint          gst_rtpbuffer_get_packet_len    (GstBuffer *buffer);
 
-struct _GstRTPBufferClass {
-  GstBufferClass  buffer_class;
+guint8                 gst_rtpbuffer_get_version       (GstBuffer *buffer);
+void           gst_rtpbuffer_set_version       (GstBuffer *buffer, guint8 version);
 
-  /*< private >*/
-  gpointer _gst_reserved[GST_PADDING];
-};
+gboolean       gst_rtpbuffer_get_padding       (GstBuffer *buffer);
+void           gst_rtpbuffer_set_padding       (GstBuffer *buffer, gboolean padding);
+void           gst_rtpbuffer_pad_to            (GstBuffer *buffer, guint len);
 
-/* creating buffers */
-GType          gst_rtpbuffer_get_type          (void);
+gboolean       gst_rtpbuffer_get_extension     (GstBuffer *buffer);
+void           gst_rtpbuffer_set_extension     (GstBuffer *buffer, gboolean extension);
+
+guint32        gst_rtpbuffer_get_ssrc          (GstBuffer *buffer);
+void           gst_rtpbuffer_set_ssrc          (GstBuffer *buffer, guint32 ssrc);
+
+guint8                 gst_rtpbuffer_get_csrc_count    (GstBuffer *buffer);
+guint32        gst_rtpbuffer_get_csrc          (GstBuffer *buffer, guint8 idx);
+void           gst_rtpbuffer_set_csrc          (GstBuffer *buffer, guint8 idx, guint32 csrc);
+
+gboolean       gst_rtpbuffer_get_marker        (GstBuffer *buffer);
+void           gst_rtpbuffer_set_marker        (GstBuffer *buffer, gboolean marker);
+
+guint8                 gst_rtpbuffer_get_payload_type  (GstBuffer *buffer);
+void           gst_rtpbuffer_set_payload_type  (GstBuffer *buffer, guint8 payload_type);
+
+guint16        gst_rtpbuffer_get_seq           (GstBuffer *buffer);
+void           gst_rtpbuffer_set_seq           (GstBuffer *buffer, guint16 seq);
+
+guint32        gst_rtpbuffer_get_timestamp     (GstBuffer *buffer);
+void           gst_rtpbuffer_set_timestamp     (GstBuffer *buffer, guint32 timestamp);
 
-GstRTPBuffer*  gst_rtpbuffer_new               (void);
+guint          gst_rtpbuffer_get_payload_len   (GstBuffer *buffer);
+gpointer       gst_rtpbuffer_get_payload       (GstBuffer *buffer);
 
 G_END_DECLS