summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorWim Taymans <wim.taymans@collabora.co.uk>2010-01-06 13:39:14 +0100
committerWim Taymans <wim.taymans@collabora.co.uk>2010-01-06 13:39:14 +0100
commit73d5ae1107d2ecf5d977a7f06e077b1ffefa2ac6 (patch)
treebb8afeb295f81c847dc4b71c9f186b2e6d7d4088
parent951b8516f1229fa029df45c8b810223433ee7cfe (diff)
audiopayload: add support for buffer-lists
-rw-r--r--gst-libs/gst/rtp/gstbasertpaudiopayload.c155
1 files changed, 143 insertions, 12 deletions
diff --git a/gst-libs/gst/rtp/gstbasertpaudiopayload.c b/gst-libs/gst/rtp/gstbasertpaudiopayload.c
index 1daa783d6..dddbf4980 100644
--- a/gst-libs/gst/rtp/gstbasertpaudiopayload.c
+++ b/gst-libs/gst/rtp/gstbasertpaudiopayload.c
@@ -70,6 +70,15 @@
GST_DEBUG_CATEGORY_STATIC (basertpaudiopayload_debug);
#define GST_CAT_DEFAULT (basertpaudiopayload_debug)
+#define DEFAULT_BUFFER_LIST FALSE
+
+enum
+{
+ PROP_0,
+ PROP_BUFFER_LIST,
+ PROP_LAST
+};
+
/* function to convert bytes to a time */
typedef GstClockTime (*GetBytesToTimeFunc) (GstBaseRTPAudioPayload * payload,
guint64 bytes);
@@ -101,6 +110,8 @@ struct _GstBaseRTPAudioPayloadPrivate
guint cached_ptime;
guint cached_min_length;
guint cached_max_length;
+
+ gboolean buffer_list;
};
@@ -110,6 +121,11 @@ struct _GstBaseRTPAudioPayloadPrivate
static void gst_base_rtp_audio_payload_finalize (GObject * object);
+static void gst_base_rtp_audio_payload_set_property (GObject * object,
+ guint prop_id, const GValue * value, GParamSpec * pspec);
+static void gst_base_rtp_audio_payload_get_property (GObject * object,
+ guint prop_id, GValue * value, GParamSpec * pspec);
+
/* bytes to time functions */
static GstClockTime
gst_base_rtp_audio_payload_frame_bytes_to_time (GstBaseRTPAudioPayload *
@@ -165,6 +181,13 @@ gst_base_rtp_audio_payload_class_init (GstBaseRTPAudioPayloadClass * klass)
gstbasertppayload_class = (GstBaseRTPPayloadClass *) klass;
gobject_class->finalize = gst_base_rtp_audio_payload_finalize;
+ gobject_class->set_property = gst_base_rtp_audio_payload_set_property;
+ gobject_class->get_property = gst_base_rtp_audio_payload_get_property;
+
+ g_object_class_install_property (G_OBJECT_CLASS (klass), PROP_BUFFER_LIST,
+ g_param_spec_boolean ("buffer-list", "Buffer List",
+ "Use Buffer Lists",
+ DEFAULT_BUFFER_LIST, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
gstelement_class->change_state =
GST_DEBUG_FUNCPTR (gst_base_rtp_payload_audio_change_state);
@@ -192,6 +215,8 @@ gst_base_rtp_audio_payload_init (GstBaseRTPAudioPayload * payload,
payload->sample_size = 0;
payload->priv->adapter = gst_adapter_new ();
+
+ payload->priv->buffer_list = DEFAULT_BUFFER_LIST;
}
static void
@@ -206,6 +231,42 @@ gst_base_rtp_audio_payload_finalize (GObject * object)
GST_CALL_PARENT (G_OBJECT_CLASS, finalize, (object));
}
+static void
+gst_base_rtp_audio_payload_set_property (GObject * object,
+ guint prop_id, const GValue * value, GParamSpec * pspec)
+{
+ GstBaseRTPAudioPayload *payload;
+
+ payload = GST_BASE_RTP_AUDIO_PAYLOAD (object);
+
+ switch (prop_id) {
+ case PROP_BUFFER_LIST:
+ payload->priv->buffer_list = g_value_get_boolean (value);
+ break;
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+ break;
+ }
+}
+
+static void
+gst_base_rtp_audio_payload_get_property (GObject * object,
+ guint prop_id, GValue * value, GParamSpec * pspec)
+{
+ GstBaseRTPAudioPayload *payload;
+
+ payload = GST_BASE_RTP_AUDIO_PAYLOAD (object);
+
+ switch (prop_id) {
+ case PROP_BUFFER_LIST:
+ g_value_set_boolean (value, payload->priv->buffer_list);
+ break;
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+ break;
+ }
+}
+
/**
* gst_base_rtp_audio_payload_set_frame_based:
* @basertpaudiopayload: a pointer to the element.
@@ -414,6 +475,68 @@ gst_base_rtp_audio_payload_push (GstBaseRTPAudioPayload * baseaudiopayload,
return ret;
}
+static GstFlowReturn
+gst_base_rtp_audio_payload_push_buffer (GstBaseRTPAudioPayload *
+ baseaudiopayload, GstBuffer * buffer)
+{
+ GstBaseRTPPayload *basepayload;
+ GstBaseRTPAudioPayloadPrivate *priv;
+ GstBuffer *outbuf;
+ GstClockTime timestamp;
+ guint8 *payload;
+ guint payload_len;
+ GstFlowReturn ret;
+
+ priv = baseaudiopayload->priv;
+ basepayload = GST_BASE_RTP_PAYLOAD (baseaudiopayload);
+
+ payload_len = GST_BUFFER_SIZE (buffer);
+ timestamp = GST_BUFFER_TIMESTAMP (buffer);
+
+ GST_DEBUG_OBJECT (baseaudiopayload, "Pushing %d bytes ts %" GST_TIME_FORMAT,
+ payload_len, GST_TIME_ARGS (timestamp));
+
+ if (priv->buffer_list) {
+ /* create just the RTP header buffer */
+ outbuf = gst_rtp_buffer_new_allocate (0, 0, 0);
+ } else {
+ /* create buffer to hold the payload */
+ outbuf = gst_rtp_buffer_new_allocate (payload_len, 0, 0);
+ }
+
+ /* set metadata */
+ gst_base_rtp_audio_payload_set_meta (baseaudiopayload, outbuf, payload_len,
+ timestamp);
+
+ if (priv->buffer_list) {
+ GstBufferList *list;
+ GstBufferListIterator *it;
+
+ list = gst_buffer_list_new ();
+ it = gst_buffer_list_iterate (list);
+
+ /* add both buffers to the buffer list */
+ gst_buffer_list_iterator_add_group (it);
+ gst_buffer_list_iterator_add (it, outbuf);
+ gst_buffer_list_iterator_add (it, buffer);
+
+ gst_buffer_list_iterator_free (it);
+
+ GST_DEBUG_OBJECT (baseaudiopayload, "Pushing list %p", list);
+ ret = gst_basertppayload_push_list (basepayload, list);
+ } else {
+ /* copy payload */
+ payload = gst_rtp_buffer_get_payload (outbuf);
+ memcpy (payload, GST_BUFFER_DATA (buffer), payload_len);
+ gst_buffer_unref (buffer);
+
+ GST_DEBUG_OBJECT (baseaudiopayload, "Pushing buffer %p", outbuf);
+ ret = gst_basertppayload_push (basepayload, outbuf);
+ }
+
+ return ret;
+}
+
/**
* gst_base_rtp_audio_payload_flush:
* @baseaudiopayload: a #GstBaseRTPPayload
@@ -473,18 +596,28 @@ gst_base_rtp_audio_payload_flush (GstBaseRTPAudioPayload * baseaudiopayload,
GST_DEBUG_OBJECT (baseaudiopayload, "Pushing %d bytes ts %" GST_TIME_FORMAT,
payload_len, GST_TIME_ARGS (timestamp));
- /* create buffer to hold the payload */
- outbuf = gst_rtp_buffer_new_allocate (payload_len, 0, 0);
+ if (priv->buffer_list && gst_adapter_available_fast (adapter) >= payload_len) {
+ GstBuffer *buffer;
+ /* we can quickly take a buffer out of the adapter without having to copy
+ * anything. */
+ buffer = gst_adapter_take_buffer (adapter, payload_len);
- payload = gst_rtp_buffer_get_payload (outbuf);
- gst_adapter_copy (adapter, payload, 0, payload_len);
- gst_adapter_flush (adapter, payload_len);
+ ret = gst_base_rtp_audio_payload_push_buffer (baseaudiopayload, buffer);
+ } else {
+ /* create buffer to hold the payload */
+ outbuf = gst_rtp_buffer_new_allocate (payload_len, 0, 0);
- /* set metadata */
- gst_base_rtp_audio_payload_set_meta (baseaudiopayload, outbuf, payload_len,
- timestamp);
+ /* copy payload */
+ payload = gst_rtp_buffer_get_payload (outbuf);
+ gst_adapter_copy (adapter, payload, 0, payload_len);
+ gst_adapter_flush (adapter, payload_len);
- ret = gst_basertppayload_push (basepayload, outbuf);
+ /* set metadata */
+ gst_base_rtp_audio_payload_set_meta (baseaudiopayload, outbuf, payload_len,
+ timestamp);
+
+ ret = gst_basertppayload_push (basepayload, outbuf);
+ }
return ret;
}
@@ -720,9 +853,7 @@ gst_base_rtp_audio_payload_handle_buffer (GstBaseRTPPayload *
/* If buffer fits on an RTP packet, let's just push it through
* this will check against max_ptime and max_mtu */
GST_DEBUG_OBJECT (payload, "Fast packet push");
- ret = gst_base_rtp_audio_payload_push (payload,
- GST_BUFFER_DATA (buffer), size, GST_BUFFER_TIMESTAMP (buffer));
- gst_buffer_unref (buffer);
+ ret = gst_base_rtp_audio_payload_push_buffer (payload, buffer);
} else {
/* push the buffer in the adapter */
gst_adapter_push (priv->adapter, buffer);