diff -r 567bb019e3e3 -r 7e817e7e631c gst_plugins_base/gst-libs/gst/rtp/gstbasertppayload.c --- 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;