--- a/gst_plugins_base/gst-libs/gst/rtp/gstbasertppayload.c Wed Mar 24 17:58:42 2010 -0500
+++ b/gst_plugins_base/gst-libs/gst/rtp/gstbasertppayload.c Wed Mar 24 18:04:17 2010 -0500
@@ -45,8 +45,6 @@
gboolean seqnum_offset_random;
gboolean ssrc_random;
guint16 next_seqnum;
-
- GstClockTime rt_base;
};
/* BaseRTPPayload signals and args */
@@ -90,8 +88,8 @@
gpointer g_class);
static void gst_basertppayload_finalize (GObject * object);
-static gboolean gst_basertppayload_setcaps (GstPad * pad, GstCaps * caps);
-static GstCaps *gst_basertppayload_getcaps (GstPad * pad);
+static gboolean gst_basertppayload_sink_setcaps (GstPad * pad, GstCaps * caps);
+static GstCaps *gst_basertppayload_sink_getcaps (GstPad * pad);
static gboolean gst_basertppayload_event (GstPad * pad, GstEvent * event);
static GstFlowReturn gst_basertppayload_chain (GstPad * pad,
GstBuffer * buffer);
@@ -163,28 +161,31 @@
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));
+ 28, G_MAXUINT, DEFAULT_MTU,
+ G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
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));
+ "The payload type of the packets", 0, 0x80, DEFAULT_PT,
+ G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
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));
+ "The SSRC of the packets (default == random)", 0, G_MAXUINT32,
+ DEFAULT_SSRC, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
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_MAXUINT32, DEFAULT_TIMESTAMP_OFFSET,
+ G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
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));
+ DEFAULT_SEQNUM_OFFSET, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
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));
+ -1, G_MAXINT64, DEFAULT_MAX_PTIME,
+ G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
/**
* GstBaseRTPAudioPayload:min-ptime:
*
@@ -195,16 +196,17 @@
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));
+ 0, G_MAXINT64, DEFAULT_MIN_PTIME,
+ G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
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));
+ 0, G_MAXUINT32, 0, G_PARAM_READABLE | G_PARAM_STATIC_STRINGS));
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));
+ 0, G_MAXUINT16, 0, G_PARAM_READABLE | G_PARAM_STATIC_STRINGS));
gstelement_class->change_state = gst_basertppayload_change_state;
@@ -234,9 +236,9 @@
basertppayload->sinkpad = gst_pad_new_from_template (templ, "sink");
gst_pad_set_setcaps_function (basertppayload->sinkpad,
- gst_basertppayload_setcaps);
+ gst_basertppayload_sink_setcaps);
gst_pad_set_getcaps_function (basertppayload->sinkpad,
- gst_basertppayload_getcaps);
+ gst_basertppayload_sink_getcaps);
gst_pad_set_event_function (basertppayload->sinkpad,
gst_basertppayload_event);
gst_pad_set_chain_function (basertppayload->sinkpad,
@@ -288,7 +290,7 @@
}
static gboolean
-gst_basertppayload_setcaps (GstPad * pad, GstCaps * caps)
+gst_basertppayload_sink_setcaps (GstPad * pad, GstCaps * caps)
{
GstBaseRTPPayload *basertppayload;
GstBaseRTPPayloadClass *basertppayload_class;
@@ -307,7 +309,7 @@
}
static GstCaps *
-gst_basertppayload_getcaps (GstPad * pad)
+gst_basertppayload_sink_getcaps (GstPad * pad)
{
GstBaseRTPPayload *basertppayload;
GstBaseRTPPayloadClass *basertppayload_class;
@@ -477,8 +479,9 @@
...)
{
GstCaps *srccaps, *peercaps;
+ gboolean res;
- /* fill in the defaults, there properties cannot be negotiated. */
+ /* fill in the defaults, their 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,
@@ -591,10 +594,10 @@
GST_DEBUG_OBJECT (payload, "with peer caps: %" GST_PTR_FORMAT, srccaps);
}
- gst_pad_set_caps (GST_BASE_RTP_PAYLOAD_SRCPAD (payload), srccaps);
+ res = gst_pad_set_caps (GST_BASE_RTP_PAYLOAD_SRCPAD (payload), srccaps);
gst_caps_unref (srccaps);
- return TRUE;
+ return res;
}
/**
@@ -603,7 +606,7 @@
* @size: the size of the packet
* @duration: the duration of the packet
*
- * Check if the packet with @size and @duration would exceed the configure
+ * Check if the packet with @size and @duration would exceed the configured
* maximum size.
*
* Returns: %TRUE if the packet of @size and @duration would exceed the
@@ -626,6 +629,155 @@
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
@@ -646,78 +798,15 @@
gst_basertppayload_push (GstBaseRTPPayload * payload, GstBuffer * buffer)
{
GstFlowReturn res;
- GstClockTime timestamp;
- guint32 rtptime;
- GstBaseRTPPayloadPrivate *priv;
- 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);
+ res = gst_basertppayload_prepare_push (payload, buffer, FALSE);
- /* 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);
+ if (G_LIKELY (res == GST_FLOW_OK))
+ res = gst_pad_push (payload->srcpad, buffer);
+ else
+ gst_buffer_unref (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
@@ -843,6 +932,7 @@
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);
@@ -853,8 +943,7 @@
basertppayload->ts_base = g_rand_int (basertppayload->ts_rand);
else
basertppayload->ts_base = basertppayload->ts_offset;
-
- priv->rt_base = -1;
+ basertppayload->timestamp = basertppayload->ts_base;
break;
default:
break;