gst_plugins_base/gst-libs/gst/rtp/gstbasertppayload.c
branchRCL_3
changeset 30 7e817e7e631c
parent 29 567bb019e3e3
--- a/gst_plugins_base/gst-libs/gst/rtp/gstbasertppayload.c	Tue Aug 31 15:30:33 2010 +0300
+++ b/gst_plugins_base/gst-libs/gst/rtp/gstbasertppayload.c	Wed Sep 01 12:16:41 2010 +0100
@@ -45,6 +45,8 @@
   gboolean seqnum_offset_random;
   gboolean ssrc_random;
   guint16 next_seqnum;
+
+  GstClockTime rt_base;
 };
 
 /* BaseRTPPayload signals and args */
@@ -88,8 +90,8 @@
     gpointer g_class);
 static void gst_basertppayload_finalize (GObject * object);
 
-static gboolean gst_basertppayload_sink_setcaps (GstPad * pad, GstCaps * caps);
-static GstCaps *gst_basertppayload_sink_getcaps (GstPad * pad);
+static gboolean gst_basertppayload_setcaps (GstPad * pad, GstCaps * caps);
+static GstCaps *gst_basertppayload_getcaps (GstPad * pad);
 static gboolean gst_basertppayload_event (GstPad * pad, GstEvent * event);
 static GstFlowReturn gst_basertppayload_chain (GstPad * pad,
     GstBuffer * buffer);
@@ -161,31 +163,28 @@
   g_object_class_install_property (G_OBJECT_CLASS (klass), PROP_MTU,
       g_param_spec_uint ("mtu", "MTU",
           "Maximum size of one packet",
-          28, G_MAXUINT, DEFAULT_MTU,
-          G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
+          28, G_MAXUINT, DEFAULT_MTU, G_PARAM_READWRITE));
   g_object_class_install_property (G_OBJECT_CLASS (klass), PROP_PT,
       g_param_spec_uint ("pt", "payload type",
-          "The payload type of the packets", 0, 0x80, DEFAULT_PT,
-          G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
+          "The payload type of the packets",
+          0, 0x80, DEFAULT_PT, G_PARAM_READWRITE));
   g_object_class_install_property (G_OBJECT_CLASS (klass), PROP_SSRC,
       g_param_spec_uint ("ssrc", "SSRC",
-          "The SSRC of the packets (default == random)", 0, G_MAXUINT32,
-          DEFAULT_SSRC, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
+          "The SSRC of the packets (default == random)",
+          0, G_MAXUINT32, DEFAULT_SSRC, G_PARAM_READWRITE));
   g_object_class_install_property (G_OBJECT_CLASS (klass),
       PROP_TIMESTAMP_OFFSET, g_param_spec_uint ("timestamp-offset",
           "Timestamp Offset",
           "Offset to add to all outgoing timestamps (default = random)", 0,
-          G_MAXUINT32, DEFAULT_TIMESTAMP_OFFSET,
-          G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
+          G_MAXUINT32, DEFAULT_TIMESTAMP_OFFSET, G_PARAM_READWRITE));
   g_object_class_install_property (G_OBJECT_CLASS (klass), PROP_SEQNUM_OFFSET,
       g_param_spec_int ("seqnum-offset", "Sequence number Offset",
           "Offset to add to all outgoing seqnum (-1 = random)", -1, G_MAXUINT16,
-          DEFAULT_SEQNUM_OFFSET, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
+          DEFAULT_SEQNUM_OFFSET, G_PARAM_READWRITE));
   g_object_class_install_property (G_OBJECT_CLASS (klass), PROP_MAX_PTIME,
       g_param_spec_int64 ("max-ptime", "Max packet time",
           "Maximum duration of the packet data in ns (-1 = unlimited up to MTU)",
-          -1, G_MAXINT64, DEFAULT_MAX_PTIME,
-          G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
+          -1, G_MAXINT64, DEFAULT_MAX_PTIME, G_PARAM_READWRITE));
   /**
    * GstBaseRTPAudioPayload:min-ptime:
    *
@@ -196,17 +195,16 @@
   g_object_class_install_property (G_OBJECT_CLASS (klass), PROP_MIN_PTIME,
       g_param_spec_int64 ("min-ptime", "Min packet time",
           "Minimum duration of the packet data in ns (can't go above MTU)",
-          0, G_MAXINT64, DEFAULT_MIN_PTIME,
-          G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
+          0, G_MAXINT64, DEFAULT_MIN_PTIME, G_PARAM_READWRITE));
 
   g_object_class_install_property (G_OBJECT_CLASS (klass), PROP_TIMESTAMP,
       g_param_spec_uint ("timestamp", "Timestamp",
           "The RTP timestamp of the last processed packet",
-          0, G_MAXUINT32, 0, G_PARAM_READABLE | G_PARAM_STATIC_STRINGS));
+          0, G_MAXUINT32, 0, G_PARAM_READABLE));
   g_object_class_install_property (G_OBJECT_CLASS (klass), PROP_SEQNUM,
       g_param_spec_uint ("seqnum", "Sequence number",
           "The RTP sequence number of the last processed packet",
-          0, G_MAXUINT16, 0, G_PARAM_READABLE | G_PARAM_STATIC_STRINGS));
+          0, G_MAXUINT16, 0, G_PARAM_READABLE));
 
   gstelement_class->change_state = gst_basertppayload_change_state;
 
@@ -236,9 +234,9 @@
 
   basertppayload->sinkpad = gst_pad_new_from_template (templ, "sink");
   gst_pad_set_setcaps_function (basertppayload->sinkpad,
-      gst_basertppayload_sink_setcaps);
+      gst_basertppayload_setcaps);
   gst_pad_set_getcaps_function (basertppayload->sinkpad,
-      gst_basertppayload_sink_getcaps);
+      gst_basertppayload_getcaps);
   gst_pad_set_event_function (basertppayload->sinkpad,
       gst_basertppayload_event);
   gst_pad_set_chain_function (basertppayload->sinkpad,
@@ -290,7 +288,7 @@
 }
 
 static gboolean
-gst_basertppayload_sink_setcaps (GstPad * pad, GstCaps * caps)
+gst_basertppayload_setcaps (GstPad * pad, GstCaps * caps)
 {
   GstBaseRTPPayload *basertppayload;
   GstBaseRTPPayloadClass *basertppayload_class;
@@ -309,7 +307,7 @@
 }
 
 static GstCaps *
-gst_basertppayload_sink_getcaps (GstPad * pad)
+gst_basertppayload_getcaps (GstPad * pad)
 {
   GstBaseRTPPayload *basertppayload;
   GstBaseRTPPayloadClass *basertppayload_class;
@@ -479,9 +477,8 @@
     ...)
 {
   GstCaps *srccaps, *peercaps;
-  gboolean res;
 
-  /* fill in the defaults, their properties cannot be negotiated. */
+  /* fill in the defaults, there properties cannot be negotiated. */
   srccaps = gst_caps_new_simple ("application/x-rtp",
       "media", G_TYPE_STRING, payload->media,
       "clock-rate", G_TYPE_INT, payload->clock_rate,
@@ -594,10 +591,10 @@
     GST_DEBUG_OBJECT (payload, "with peer caps: %" GST_PTR_FORMAT, srccaps);
   }
 
-  res = gst_pad_set_caps (GST_BASE_RTP_PAYLOAD_SRCPAD (payload), srccaps);
+  gst_pad_set_caps (GST_BASE_RTP_PAYLOAD_SRCPAD (payload), srccaps);
   gst_caps_unref (srccaps);
 
-  return res;
+  return TRUE;
 }
 
 /**
@@ -606,7 +603,7 @@
  * @size: the size of the packet
  * @duration: the duration of the packet
  *
- * Check if the packet with @size and @duration would exceed the configured
+ * Check if the packet with @size and @duration would exceed the configure
  * maximum size.
  *
  * Returns: %TRUE if the packet of @size and @duration would exceed the
@@ -629,155 +626,6 @@
   return FALSE;
 }
 
-typedef struct
-{
-  GstBaseRTPPayload *payload;
-  guint32 ssrc;
-  guint16 seqnum;
-  guint8 pt;
-  GstCaps *caps;
-  GstClockTime timestamp;
-  guint32 rtptime;
-} HeaderData;
-
-static GstBufferListItem
-find_timestamp (GstBuffer ** buffer, guint group, guint idx, HeaderData * data)
-{
-  data->timestamp = GST_BUFFER_TIMESTAMP (*buffer);
-
-  /* stop when we find a timestamp */
-  if (data->timestamp != -1)
-    return GST_BUFFER_LIST_END;
-  else
-    return GST_BUFFER_LIST_CONTINUE;
-}
-
-static GstBufferListItem
-set_headers (GstBuffer ** buffer, guint group, guint idx, HeaderData * data)
-{
-  gst_rtp_buffer_set_ssrc (*buffer, data->ssrc);
-  gst_rtp_buffer_set_payload_type (*buffer, data->pt);
-  gst_rtp_buffer_set_seq (*buffer, data->seqnum);
-  gst_rtp_buffer_set_timestamp (*buffer, data->rtptime);
-  gst_buffer_set_caps (*buffer, data->caps);
-  data->seqnum++;
-
-  return GST_BUFFER_LIST_SKIP_GROUP;
-}
-
-/* Updates the SSRC, payload type, seqnum and timestamp of the RTP buffer
- * before the buffer is pushed. */
-static GstFlowReturn
-gst_basertppayload_prepare_push (GstBaseRTPPayload * payload,
-    gpointer obj, gboolean is_list)
-{
-  GstBaseRTPPayloadPrivate *priv;
-  HeaderData data;
-
-  if (payload->clock_rate == 0)
-    goto no_rate;
-
-  priv = payload->priv;
-
-  /* update first, so that the property is set to the last
-   * seqnum pushed */
-  payload->seqnum = priv->next_seqnum;
-
-  /* fill in the fields we want to set on all headers */
-  data.payload = payload;
-  data.seqnum = payload->seqnum;
-  data.ssrc = payload->current_ssrc;
-  data.pt = payload->pt;
-  data.caps = GST_PAD_CAPS (payload->srcpad);
-  data.timestamp = -1;
-
-  /* find the first buffer with a timestamp */
-  if (is_list) {
-    gst_buffer_list_foreach (GST_BUFFER_LIST_CAST (obj),
-        (GstBufferListFunc) find_timestamp, &data);
-  } else {
-    data.timestamp = GST_BUFFER_TIMESTAMP (GST_BUFFER_CAST (obj));
-  }
-
-  /* convert to RTP time */
-  if (GST_CLOCK_TIME_IS_VALID (data.timestamp)) {
-    gint64 rtime;
-
-    rtime = gst_segment_to_running_time (&payload->segment, GST_FORMAT_TIME,
-        data.timestamp);
-
-    rtime = gst_util_uint64_scale_int (rtime, payload->clock_rate, GST_SECOND);
-
-    /* add running_time in clock-rate units to the base timestamp */
-    data.rtptime = payload->ts_base + rtime;
-  } else {
-    /* no timestamp to convert, take previous timestamp */
-    data.rtptime = payload->timestamp;
-  }
-
-  /* set ssrc, payload type, seq number, caps and rtptime */
-  if (is_list) {
-    gst_buffer_list_foreach (GST_BUFFER_LIST_CAST (obj),
-        (GstBufferListFunc) set_headers, &data);
-  } else {
-    GstBuffer *buf = GST_BUFFER_CAST (obj);
-    set_headers (&buf, 0, 0, &data);
-  }
-
-  priv->next_seqnum = data.seqnum;
-  payload->timestamp = data.rtptime;
-
-  GST_LOG_OBJECT (payload,
-      "Preparing to push packet with size %d, seq=%d, rtptime=%u, timestamp %"
-      GST_TIME_FORMAT, (is_list) ? -1 :
-      GST_BUFFER_SIZE (GST_BUFFER (obj)), payload->seqnum, data.rtptime,
-      GST_TIME_ARGS (data.timestamp));
-
-  return GST_FLOW_OK;
-
-  /* ERRORS */
-no_rate:
-  {
-    GST_ELEMENT_ERROR (payload, STREAM, NOT_IMPLEMENTED, (NULL),
-        ("subclass did not specify clock-rate"));
-    return GST_FLOW_ERROR;
-  }
-}
-
-/**
- * gst_basertppayload_push_list:
- * @payload: a #GstBaseRTPPayload
- * @list: a #GstBufferList
- *
- * Push @list to the peer element of the payloader. The SSRC, payload type,
- * seqnum and timestamp of the RTP buffer will be updated first.
- *
- * This function takes ownership of @list.
- *
- * Returns: a #GstFlowReturn.
- *
- * Since: 0.10.24
- */
- 
-#ifdef __SYMBIAN32__
-EXPORT_C
-#endif
-
-GstFlowReturn
-gst_basertppayload_push_list (GstBaseRTPPayload * payload, GstBufferList * list)
-{
-  GstFlowReturn res;
-
-  res = gst_basertppayload_prepare_push (payload, list, TRUE);
-
-  if (G_LIKELY (res == GST_FLOW_OK))
-    res = gst_pad_push_list (payload->srcpad, list);
-  else
-    gst_buffer_list_unref (list);
-
-  return res;
-}
-
 /**
  * gst_basertppayload_push:
  * @payload: a #GstBaseRTPPayload
@@ -798,15 +646,78 @@
 gst_basertppayload_push (GstBaseRTPPayload * payload, GstBuffer * buffer)
 {
   GstFlowReturn res;
+  GstClockTime timestamp;
+  guint32 rtptime;
+  GstBaseRTPPayloadPrivate *priv;
 
-  res = gst_basertppayload_prepare_push (payload, buffer, FALSE);
+  if (payload->clock_rate == 0)
+    goto no_rate;
+
+  priv = payload->priv;
+
+  gst_rtp_buffer_set_ssrc (buffer, payload->current_ssrc);
+
+  gst_rtp_buffer_set_payload_type (buffer, payload->pt);
+
+  /* update first, so that the property is set to the last
+   * seqnum pushed */
+  payload->seqnum = priv->next_seqnum;
+  gst_rtp_buffer_set_seq (buffer, payload->seqnum);
+
+  /* can wrap around, which is perfectly fine */
+  priv->next_seqnum++;
+
+  /* add our random offset to the timestamp */
+  rtptime = payload->ts_base;
+
+  timestamp = GST_BUFFER_TIMESTAMP (buffer);
+  if (GST_CLOCK_TIME_IS_VALID (timestamp)) {
+    gint64 rtime;
+
+    rtime = gst_segment_to_running_time (&payload->segment, GST_FORMAT_TIME,
+        timestamp);
 
-  if (G_LIKELY (res == GST_FLOW_OK))
-    res = gst_pad_push (payload->srcpad, buffer);
-  else
-    gst_buffer_unref (buffer);
+    /* take first timestamp as base, we want to calculate the RTP timestamp
+     * starting from the ts_base */
+    if (priv->rt_base == -1) {
+      priv->rt_base = rtime;
+      GST_LOG_OBJECT (payload, "first timestamp %" GST_TIME_FORMAT,
+          GST_TIME_ARGS (rtime));
+    }
+    rtime -= priv->rt_base;
+
+    rtime = gst_util_uint64_scale_int (rtime, payload->clock_rate, GST_SECOND);
+
+    /* add running_time in clock-rate units to the base timestamp */
+    rtptime += rtime;
+  } else {
+    /* no timestamp to convert, take previous timestamp */
+    rtptime = payload->timestamp;
+  }
+  gst_rtp_buffer_set_timestamp (buffer, rtptime);
+
+  payload->timestamp = rtptime;
+
+  /* set caps */
+  gst_buffer_set_caps (buffer, GST_PAD_CAPS (payload->srcpad));
+
+  GST_LOG_OBJECT (payload,
+      "Pushing packet size %d, seq=%d, rtptime=%u, timestamp %" GST_TIME_FORMAT,
+      GST_BUFFER_SIZE (buffer), payload->seqnum, rtptime,
+      GST_TIME_ARGS (timestamp));
+
+  res = gst_pad_push (payload->srcpad, buffer);
 
   return res;
+
+  /* ERRORS */
+no_rate:
+  {
+    GST_ELEMENT_ERROR (payload, STREAM, NOT_IMPLEMENTED, (NULL),
+        ("subclass did not specify clock-rate"));
+    gst_buffer_unref (buffer);
+    return GST_FLOW_ERROR;
+  }
 }
 
 static void
@@ -932,7 +843,6 @@
       else
         basertppayload->seqnum_base = basertppayload->seqnum_offset;
       priv->next_seqnum = basertppayload->seqnum_base;
-      basertppayload->seqnum = basertppayload->seqnum_base;
 
       if (priv->ssrc_random)
         basertppayload->current_ssrc = g_rand_int (basertppayload->ssrc_rand);
@@ -943,7 +853,8 @@
         basertppayload->ts_base = g_rand_int (basertppayload->ts_rand);
       else
         basertppayload->ts_base = basertppayload->ts_offset;
-      basertppayload->timestamp = basertppayload->ts_base;
+
+      priv->rt_base = -1;
       break;
     default:
       break;