From: Wim Taymans Date: Fri, 19 Jun 2009 13:52:34 +0000 (+0200) Subject: basertppayload: add support for bufferlists X-Git-Tag: 1.19.3~511^2~9517 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=85af9b82e856ffd4c5159890734d53dc44f305df;p=platform%2Fupstream%2Fgstreamer.git basertppayload: add support for bufferlists Based on patch from Ognyan Tonchev. See #585559 --- diff --git a/docs/libs/gst-plugins-base-libs-sections.txt b/docs/libs/gst-plugins-base-libs-sections.txt index c4ce069..9f42217 100644 --- a/docs/libs/gst-plugins-base-libs-sections.txt +++ b/docs/libs/gst-plugins-base-libs-sections.txt @@ -990,6 +990,7 @@ GST_BASE_RTP_PAYLOAD_SRCPAD gst_basertppayload_is_filled gst_basertppayload_push +gst_basertppayload_push_list gst_basertppayload_set_options gst_basertppayload_set_outcaps diff --git a/gst-libs/gst/rtp/gstbasertppayload.c b/gst-libs/gst/rtp/gstbasertppayload.c index 1121cc9..861bb60 100644 --- a/gst-libs/gst/rtp/gstbasertppayload.c +++ b/gst-libs/gst/rtp/gstbasertppayload.c @@ -613,87 +613,177 @@ gst_basertppayload_is_filled (GstBaseRTPPayload * payload, return FALSE; } -/** - * gst_basertppayload_push: - * @payload: a #GstBaseRTPPayload - * @buffer: a #GstBuffer - * - * Push @buffer 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 @buffer. - * - * Returns: a #GstFlowReturn. - */ -GstFlowReturn -gst_basertppayload_push (GstBaseRTPPayload * payload, GstBuffer * buffer) +typedef struct { - GstFlowReturn res; + 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; - 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; + /* 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)); + } - timestamp = GST_BUFFER_TIMESTAMP (buffer); - if (GST_CLOCK_TIME_IS_VALID (timestamp)) { + /* 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, - timestamp); + 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 */ - rtptime += rtime; + data.rtptime = payload->ts_base + rtime; } else { /* no timestamp to convert, take previous timestamp */ - rtptime = payload->timestamp; + data.rtptime = payload->timestamp; } - gst_rtp_buffer_set_timestamp (buffer, rtptime); - payload->timestamp = rtptime; + /* 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); + } - /* set caps */ - gst_buffer_set_caps (buffer, GST_PAD_CAPS (payload->srcpad)); + priv->next_seqnum = data.seqnum; + payload->timestamp = data.rtptime; 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)); + "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)); - res = gst_pad_push (payload->srcpad, buffer); - - return res; + return GST_FLOW_OK; /* 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; } } +/** + * 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 + */ +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 + * @buffer: a #GstBuffer + * + * Push @buffer 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 @buffer. + * + * Returns: a #GstFlowReturn. + */ +GstFlowReturn +gst_basertppayload_push (GstBaseRTPPayload * payload, GstBuffer * buffer) +{ + GstFlowReturn res; + + res = gst_basertppayload_prepare_push (payload, buffer, FALSE); + + if (G_LIKELY (res == GST_FLOW_OK)) + res = gst_pad_push (payload->srcpad, buffer); + else + gst_buffer_unref (buffer); + + return res; +} + static void gst_basertppayload_set_property (GObject * object, guint prop_id, const GValue * value, GParamSpec * pspec) diff --git a/gst-libs/gst/rtp/gstbasertppayload.h b/gst-libs/gst/rtp/gstbasertppayload.h index 4a1d751..b87534c 100644 --- a/gst-libs/gst/rtp/gstbasertppayload.h +++ b/gst-libs/gst/rtp/gstbasertppayload.h @@ -144,6 +144,9 @@ gboolean gst_basertppayload_is_filled (GstBaseRTPPayload *payl GstFlowReturn gst_basertppayload_push (GstBaseRTPPayload *payload, GstBuffer *buffer); +GstFlowReturn gst_basertppayload_push_list (GstBaseRTPPayload *payload, + GstBufferList *list); + G_END_DECLS #endif /* __GST_BASE_RTP_PAYLOAD_H__ */ diff --git a/win32/common/libgstrtp.def b/win32/common/libgstrtp.def index 5fb2b4b..75aaa9b 100644 --- a/win32/common/libgstrtp.def +++ b/win32/common/libgstrtp.def @@ -13,6 +13,7 @@ EXPORTS gst_basertppayload_get_type gst_basertppayload_is_filled gst_basertppayload_push + gst_basertppayload_push_list gst_basertppayload_set_options gst_basertppayload_set_outcaps gst_rtcp_buffer_add_packet