summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorWim Taymans <wim.taymans@collabora.co.uk>2011-03-31 13:23:09 +0200
committerWim Taymans <wim.taymans@collabora.co.uk>2011-03-31 13:23:09 +0200
commit2e45698e56147b82bb24e5957dbd58950592221d (patch)
treea845fcd210321a61a45744e0c0c986a540539b08
parent34da2a68f93c2597b9a72112f1d3329c41d71842 (diff)
bufferlist: attempt at removing bufferlists0.11-bufferlist-remove
An attempt ar removing the bufferlist but instead use a simple array of GstBuffer objects to gst_pad_chain_array(). It turns out that this is a bad idea, basesink needs lots of changes and refcounting of the buffers in the list is probelematic.
-rw-r--r--gst/Makefile.am2
-rw-r--r--gst/gst.c3
-rw-r--r--gst/gst.h1
-rw-r--r--gst/gstghostpad.c11
-rw-r--r--gst/gstpad.c226
-rw-r--r--gst/gstpad.h35
-rw-r--r--libs/gst/base/gstbasesink.c330
-rw-r--r--libs/gst/base/gstbasesink.h8
-rw-r--r--plugins/elements/gsttee.c16
-rw-r--r--tests/check/Makefile.am1
10 files changed, 301 insertions, 332 deletions
diff --git a/gst/Makefile.am b/gst/Makefile.am
index 633756594..0689fb611 100644
--- a/gst/Makefile.am
+++ b/gst/Makefile.am
@@ -50,7 +50,6 @@ libgstreamer_@GST_MAJORMINOR@_la_SOURCES = \
gstobject.c \
gstbin.c \
gstbuffer.c \
- gstbufferlist.c \
gstbufferpool.c \
gstbus.c \
gstcaps.c \
@@ -144,7 +143,6 @@ gst_headers = \
gstobject.h \
gstbin.h \
gstbuffer.h \
- gstbufferlist.h \
gstbufferpool.h \
gstbus.h \
gstcaps.h \
diff --git a/gst/gst.c b/gst/gst.c
index 5227bf2b6..6027d6943 100644
--- a/gst/gst.c
+++ b/gst/gst.c
@@ -688,7 +688,6 @@ init_post (GOptionContext * context, GOptionGroup * group, gpointer data,
g_type_class_ref (gst_bin_flags_get_type ());
g_type_class_ref (gst_buffer_flag_get_type ());
g_type_class_ref (gst_buffer_copy_flags_get_type ());
- g_type_class_ref (gst_buffer_list_item_get_type ());
g_type_class_ref (gst_bus_flags_get_type ());
g_type_class_ref (gst_bus_sync_reply_get_type ());
g_type_class_ref (gst_caps_flags_get_type ());
@@ -760,7 +759,6 @@ init_post (GOptionContext * context, GOptionGroup * group, gpointer data,
_gst_event_initialize ();
_gst_buffer_initialize ();
_gst_message_initialize ();
- _gst_buffer_list_initialize ();
_gst_value_initialize ();
g_type_class_ref (gst_param_spec_fraction_get_type ());
_gst_tag_initialize ();
@@ -1052,7 +1050,6 @@ gst_deinit (void)
g_type_class_unref (g_type_class_peek (gst_bin_flags_get_type ()));
g_type_class_unref (g_type_class_peek (gst_buffer_flag_get_type ()));
g_type_class_unref (g_type_class_peek (gst_buffer_copy_flags_get_type ()));
- g_type_class_unref (g_type_class_peek (gst_buffer_list_item_get_type ()));
g_type_class_unref (g_type_class_peek (gst_bus_flags_get_type ()));
g_type_class_unref (g_type_class_peek (gst_bus_sync_reply_get_type ()));
g_type_class_unref (g_type_class_peek (gst_caps_flags_get_type ()));
diff --git a/gst/gst.h b/gst/gst.h
index 954fd6c88..2f23977ce 100644
--- a/gst/gst.h
+++ b/gst/gst.h
@@ -33,7 +33,6 @@
#include <gst/gstbin.h>
#include <gst/gstbuffer.h>
-#include <gst/gstbufferlist.h>
#include <gst/gstbufferpool.h>
#include <gst/gstcaps.h>
#include <gst/gstchildproxy.h>
diff --git a/gst/gstghostpad.c b/gst/gstghostpad.c
index 451123b16..11f8b5a30 100644
--- a/gst/gstghostpad.c
+++ b/gst/gstghostpad.c
@@ -159,12 +159,13 @@ gst_proxy_pad_do_chain (GstPad * pad, GstBuffer * buffer)
}
static GstFlowReturn
-gst_proxy_pad_do_chain_list (GstPad * pad, GstBufferList * list)
+gst_proxy_pad_do_chain_array (GstPad * pad, GstBuffer ** buffers,
+ guint n_buffers)
{
GstFlowReturn res;
GstPad *internal = GST_PROXY_PAD_INTERNAL (pad);
- res = gst_pad_push_list (internal, list);
+ res = gst_pad_push_array (internal, buffers, n_buffers);
return res;
}
@@ -389,7 +390,7 @@ gst_proxy_pad_class_init (GstProxyPadClass * klass)
GST_DEBUG_REGISTER_FUNCPTR (gst_proxy_pad_do_unlink);
GST_DEBUG_REGISTER_FUNCPTR (gst_proxy_pad_do_bufferalloc);
GST_DEBUG_REGISTER_FUNCPTR (gst_proxy_pad_do_chain);
- GST_DEBUG_REGISTER_FUNCPTR (gst_proxy_pad_do_chain_list);
+ GST_DEBUG_REGISTER_FUNCPTR (gst_proxy_pad_do_chain_array);
GST_DEBUG_REGISTER_FUNCPTR (gst_proxy_pad_do_getrange);
GST_DEBUG_REGISTER_FUNCPTR (gst_proxy_pad_do_checkgetrange);
}
@@ -835,7 +836,7 @@ gst_ghost_pad_construct (GstGhostPad * gpad)
if (dir == GST_PAD_SINK) {
gst_pad_set_bufferalloc_function (pad, gst_proxy_pad_do_bufferalloc);
gst_pad_set_chain_function (pad, gst_proxy_pad_do_chain);
- gst_pad_set_chain_list_function (pad, gst_proxy_pad_do_chain_list);
+ gst_pad_set_chain_array_function (pad, gst_proxy_pad_do_chain_array);
} else {
gst_pad_set_getrange_function (pad, gst_proxy_pad_do_getrange);
gst_pad_set_checkgetrange_function (pad, gst_proxy_pad_do_checkgetrange);
@@ -864,7 +865,7 @@ gst_ghost_pad_construct (GstGhostPad * gpad)
if (dir == GST_PAD_SRC) {
gst_pad_set_bufferalloc_function (internal, gst_proxy_pad_do_bufferalloc);
gst_pad_set_chain_function (internal, gst_proxy_pad_do_chain);
- gst_pad_set_chain_list_function (internal, gst_proxy_pad_do_chain_list);
+ gst_pad_set_chain_array_function (internal, gst_proxy_pad_do_chain_array);
} else {
gst_pad_set_getrange_function (internal, gst_proxy_pad_do_getrange);
gst_pad_set_checkgetrange_function (internal,
diff --git a/gst/gstpad.c b/gst/gstpad.c
index e0643869a..315fc2d05 100644
--- a/gst/gstpad.c
+++ b/gst/gstpad.c
@@ -1269,9 +1269,9 @@ gst_pad_set_chain_function (GstPad * pad, GstPadChainFunction chain)
}
/**
- * gst_pad_set_chain_list_function:
+ * gst_pad_set_chain_array_function:
* @pad: a sink #GstPad.
- * @chainlist: the #GstPadChainListFunction to set.
+ * @chainarray: the #GstPadChainArrayFunction to set.
*
* Sets the given chain list function for the pad. The chainlist function is
* called to process a #GstBufferList input buffer list. See
@@ -1280,15 +1280,15 @@ gst_pad_set_chain_function (GstPad * pad, GstPadChainFunction chain)
* Since: 0.10.24
*/
void
-gst_pad_set_chain_list_function (GstPad * pad,
- GstPadChainListFunction chainlist)
+gst_pad_set_chain_array_function (GstPad * pad,
+ GstPadChainArrayFunction chainarray)
{
g_return_if_fail (GST_IS_PAD (pad));
g_return_if_fail (GST_PAD_IS_SINK (pad));
- GST_PAD_CHAINLISTFUNC (pad) = chainlist;
- GST_CAT_DEBUG_OBJECT (GST_CAT_PADS, pad, "chainlistfunc set to %s",
- GST_DEBUG_FUNCPTR_NAME (chainlist));
+ GST_PAD_CHAINARRAYFUNC (pad) = chainarray;
+ GST_CAT_DEBUG_OBJECT (GST_CAT_PADS, pad, "chainarrayfunc set to %s",
+ GST_DEBUG_FUNCPTR_NAME (chainarray));
}
/**
@@ -3665,40 +3665,20 @@ gst_pad_emit_have_data_signal (GstPad * pad, GstMiniObject * obj)
return res;
}
+/* unref the buffers after idx */
static void
-gst_pad_data_unref (gboolean is_buffer, void *data)
+gst_pad_data_unref (GstBuffer ** buffers, guint n_buffers, guint idx)
{
- if (G_LIKELY (is_buffer)) {
- gst_buffer_unref (data);
- } else {
- gst_buffer_list_unref (data);
- }
-}
-
-static GstCaps *
-gst_pad_data_get_caps (gboolean is_buffer, void *data)
-{
- GstCaps *caps;
-
- if (G_LIKELY (is_buffer)) {
- caps = GST_BUFFER_CAPS (data);
- } else {
- GstBuffer *buf;
-
- if ((buf = gst_buffer_list_get (GST_BUFFER_LIST_CAST (data), 0, 0)))
- caps = GST_BUFFER_CAPS (buf);
- else
- caps = NULL;
- }
- return caps;
+ for (; idx < n_buffers; idx++)
+ gst_buffer_unref (buffers[idx]);
}
/* this is the chain function that does not perform the additional argument
* checking for that little extra speed.
*/
static inline GstFlowReturn
-gst_pad_chain_data_unchecked (GstPad * pad, gboolean is_buffer, void *data,
- GstPadPushCache * cache)
+gst_pad_chain_data_unchecked (GstPad * pad, GstBuffer ** buffers,
+ guint n_buffers, GstPadPushCache * cache)
{
GstCaps *caps;
gboolean caps_changed;
@@ -3711,7 +3691,7 @@ gst_pad_chain_data_unchecked (GstPad * pad, gboolean is_buffer, void *data,
if (G_UNLIKELY (GST_PAD_IS_FLUSHING (pad)))
goto flushing;
- caps = gst_pad_data_get_caps (is_buffer, data);
+ caps = GST_BUFFER_CAPS (buffers[0]);
caps_changed = caps && caps != GST_PAD_CAPS (pad);
emit_signal = GST_PAD_DO_BUFFER_SIGNALS (pad) > 0;
@@ -3721,13 +3701,14 @@ gst_pad_chain_data_unchecked (GstPad * pad, gboolean is_buffer, void *data,
* we might drop the buffer and do capsnego for nothing. */
if (G_UNLIKELY (emit_signal)) {
cache = NULL;
- if (G_LIKELY (is_buffer)) {
- if (!gst_pad_emit_have_data_signal (pad, GST_MINI_OBJECT_CAST (data)))
+ if (n_buffers == 1) {
+ if (!gst_pad_emit_have_data_signal (pad,
+ GST_MINI_OBJECT_CAST (buffers[0])))
goto dropping;
} else {
- /* chain all groups in the buffer list one by one to avoid problems with
+ /* chain all buffers in the array one by one to avoid problems with
* buffer probes that push buffers or events */
- goto chain_groups;
+ goto chain_array;
}
}
@@ -3743,7 +3724,7 @@ gst_pad_chain_data_unchecked (GstPad * pad, gboolean is_buffer, void *data,
* the data to the wrong function. This is not really a
* problem since functions are assigned at creation time
* and don't change that often... */
- if (G_LIKELY (is_buffer)) {
+ if (n_buffers == 1) {
GstPadChainFunction chainfunc;
if (G_UNLIKELY ((chainfunc = GST_PAD_CHAINFUNC (pad)) == NULL))
@@ -3757,71 +3738,56 @@ gst_pad_chain_data_unchecked (GstPad * pad, gboolean is_buffer, void *data,
cache->caps = caps ? gst_caps_ref (caps) : NULL;
}
- ret = chainfunc (pad, GST_BUFFER_CAST (data));
+ ret = chainfunc (pad, buffers[0]);
GST_CAT_LOG_OBJECT (GST_CAT_SCHEDULING, pad,
"called chainfunction &%s, returned %s",
GST_DEBUG_FUNCPTR_NAME (chainfunc), gst_flow_get_name (ret));
} else {
- GstPadChainListFunction chainlistfunc;
+ GstPadChainArrayFunction chainarrayfunc;
- if (G_UNLIKELY ((chainlistfunc = GST_PAD_CHAINLISTFUNC (pad)) == NULL))
- goto chain_groups;
+ if (G_UNLIKELY ((chainarrayfunc = GST_PAD_CHAINARRAYFUNC (pad)) == NULL))
+ goto chain_array;
GST_CAT_LOG_OBJECT (GST_CAT_SCHEDULING, pad,
- "calling chainlistfunction &%s",
- GST_DEBUG_FUNCPTR_NAME (chainlistfunc));
+ "calling chainarrayfunction &%s",
+ GST_DEBUG_FUNCPTR_NAME (chainarrayfunc));
- ret = chainlistfunc (pad, GST_BUFFER_LIST_CAST (data));
+ ret = chainarrayfunc (pad, buffers, n_buffers);
GST_CAT_LOG_OBJECT (GST_CAT_SCHEDULING, pad,
- "called chainlistfunction &%s, returned %s",
- GST_DEBUG_FUNCPTR_NAME (chainlistfunc), gst_flow_get_name (ret));
+ "called chainarrayfunction &%s, returned %s",
+ GST_DEBUG_FUNCPTR_NAME (chainarrayfunc), gst_flow_get_name (ret));
}
GST_PAD_STREAM_UNLOCK (pad);
return ret;
-chain_groups:
+chain_array:
{
- GstBufferList *list;
- GstBufferListIterator *it;
- GstBuffer *group;
+ guint idx;
GST_PAD_STREAM_UNLOCK (pad);
- GST_INFO_OBJECT (pad, "chaining each group in list as a merged buffer");
+ GST_INFO_OBJECT (pad, "chaining each buffer in array");
- list = GST_BUFFER_LIST_CAST (data);
- it = gst_buffer_list_iterate (list);
-
- if (gst_buffer_list_iterator_next_group (it)) {
- do {
- group = gst_buffer_list_iterator_merge_group (it);
- if (group == NULL) {
- group = gst_buffer_new ();
- GST_CAT_INFO_OBJECT (GST_CAT_SCHEDULING, pad, "chaining empty group");
- } else {
- GST_CAT_INFO_OBJECT (GST_CAT_SCHEDULING, pad, "chaining group");
- }
- ret = gst_pad_chain_data_unchecked (pad, TRUE, group, NULL);
- } while (ret == GST_FLOW_OK && gst_buffer_list_iterator_next_group (it));
- } else {
- GST_CAT_INFO_OBJECT (GST_CAT_SCHEDULING, pad, "chaining empty group");
- ret = gst_pad_chain_data_unchecked (pad, TRUE, gst_buffer_new (), NULL);
+ ret = GST_FLOW_OK;
+ for (idx = 0; idx < n_buffers; idx++) {
+ ret = gst_pad_chain_data_unchecked (pad, &buffers[idx], 1, NULL);
+ if (ret != GST_FLOW_OK)
+ break;
}
-
- gst_buffer_list_iterator_free (it);
- gst_buffer_list_unref (list);
-
+ /* flush buffers we could not push, idx was the last one pushed and
+ * unreffed */
+ gst_pad_data_unref (buffers, n_buffers, idx + 1);
return ret;
}
/* ERRORS */
flushing:
{
- gst_pad_data_unref (is_buffer, data);
+ gst_pad_data_unref (buffers, n_buffers, 0);
GST_CAT_LOG_OBJECT (GST_CAT_SCHEDULING, pad,
"pushing, but pad was flushing");
GST_OBJECT_UNLOCK (pad);
@@ -3830,14 +3796,14 @@ flushing:
}
dropping:
{
- gst_pad_data_unref (is_buffer, data);
+ gst_pad_data_unref (buffers, n_buffers, 0);
GST_DEBUG_OBJECT (pad, "Dropping buffer due to FALSE probe return");
GST_PAD_STREAM_UNLOCK (pad);
return GST_FLOW_OK;
}
not_negotiated:
{
- gst_pad_data_unref (is_buffer, data);
+ gst_pad_data_unref (buffers, n_buffers, 0);
GST_CAT_LOG_OBJECT (GST_CAT_SCHEDULING, pad,
"pushing data but pad did not accept");
GST_PAD_STREAM_UNLOCK (pad);
@@ -3845,7 +3811,7 @@ not_negotiated:
}
no_function:
{
- gst_pad_data_unref (is_buffer, data);
+ gst_pad_data_unref (buffers, n_buffers, 0);
GST_CAT_LOG_OBJECT (GST_CAT_SCHEDULING, pad,
"pushing, but not chainhandler");
GST_ELEMENT_ERROR (GST_PAD_PARENT (pad), CORE, PAD, (NULL),
@@ -3890,16 +3856,17 @@ gst_pad_chain (GstPad * pad, GstBuffer * buffer)
g_return_val_if_fail (GST_PAD_IS_SINK (pad), GST_FLOW_ERROR);
g_return_val_if_fail (GST_IS_BUFFER (buffer), GST_FLOW_ERROR);
- return gst_pad_chain_data_unchecked (pad, TRUE, buffer, NULL);
+ return gst_pad_chain_data_unchecked (pad, &buffer, 1, NULL);
}
/**
- * gst_pad_chain_list:
+ * gst_pad_chain_array:
* @pad: a sink #GstPad, returns GST_FLOW_ERROR if not.
- * @list: (transfer full): the #GstBufferList to send, return GST_FLOW_ERROR
- * if not.
+ * @buffers: (transfer full): an array of #GstBuffer to send,
+ * return GST_FLOW_ERROR if not.
+ * @n_buffers: the length of the array
*
- * Chain a bufferlist to @pad.
+ * Chain a bufferarray to @pad.
*
* The function returns #GST_FLOW_WRONG_STATE if the pad was flushing.
*
@@ -3923,17 +3890,18 @@ gst_pad_chain (GstPad * pad, GstBuffer * buffer)
* Since: 0.10.24
*/
GstFlowReturn
-gst_pad_chain_list (GstPad * pad, GstBufferList * list)
+gst_pad_chain_array (GstPad * pad, GstBuffer ** buffers, guint n_buffers)
{
g_return_val_if_fail (GST_IS_PAD (pad), GST_FLOW_ERROR);
g_return_val_if_fail (GST_PAD_IS_SINK (pad), GST_FLOW_ERROR);
- g_return_val_if_fail (GST_IS_BUFFER_LIST (list), GST_FLOW_ERROR);
+ g_return_val_if_fail (buffers != NULL, GST_FLOW_ERROR);
+ g_return_val_if_fail (n_buffers > 0, GST_FLOW_ERROR);
- return gst_pad_chain_data_unchecked (pad, FALSE, list, NULL);
+ return gst_pad_chain_data_unchecked (pad, buffers, n_buffers, NULL);
}
static GstFlowReturn
-gst_pad_push_data (GstPad * pad, gboolean is_buffer, void *data,
+gst_pad_push_data (GstPad * pad, GstBuffer ** buffers, guint n_buffers,
GstPadPushCache * cache)
{
GstPad *peer;
@@ -3956,14 +3924,15 @@ gst_pad_push_data (GstPad * pad, gboolean is_buffer, void *data,
/* unlock before emitting */
GST_OBJECT_UNLOCK (pad);
- if (G_LIKELY (is_buffer)) {
+ if (G_LIKELY (n_buffers == 1)) {
/* if the signal handler returned FALSE, it means we should just drop the
* buffer */
- if (!gst_pad_emit_have_data_signal (pad, GST_MINI_OBJECT_CAST (data)))
+ if (!gst_pad_emit_have_data_signal (pad,
+ GST_MINI_OBJECT_CAST (buffers[0])))
goto dropped;
} else {
- /* push all buffers in the list */
- goto push_groups;
+ /* push all buffers in the array */
+ goto push_array;
}
GST_OBJECT_LOCK (pad);
}
@@ -3973,7 +3942,7 @@ gst_pad_push_data (GstPad * pad, gboolean is_buffer, void *data,
/* Before pushing the buffer to the peer pad, ensure that caps
* are set on this pad */
- caps = gst_pad_data_get_caps (is_buffer, data);
+ caps = GST_BUFFER_CAPS (buffers[0]);
caps_changed = caps && caps != GST_PAD_CAPS (pad);
/* take ref to peer pad before releasing the lock */
@@ -3989,62 +3958,49 @@ gst_pad_push_data (GstPad * pad, gboolean is_buffer, void *data,
goto not_negotiated;
}
- ret = gst_pad_chain_data_unchecked (peer, is_buffer, data, cache);
+ ret = gst_pad_chain_data_unchecked (peer, buffers, n_buffers, cache);
gst_object_unref (peer);
return ret;
-push_groups:
+push_array:
{
- GstBufferList *list;
- GstBufferListIterator *it;
- GstBuffer *group;
+ guint idx;
- GST_INFO_OBJECT (pad, "pushing each group in list as a merged buffer");
+ GST_PAD_STREAM_UNLOCK (pad);
- list = GST_BUFFER_LIST_CAST (data);
- it = gst_buffer_list_iterate (list);
+ GST_INFO_OBJECT (pad, "pushing each buffer in array");
- if (gst_buffer_list_iterator_next_group (it)) {
- do {
- group = gst_buffer_list_iterator_merge_group (it);
- if (group == NULL) {
- group = gst_buffer_new ();
- GST_CAT_INFO_OBJECT (GST_CAT_SCHEDULING, pad, "pushing empty group");
- } else {
- GST_CAT_INFO_OBJECT (GST_CAT_SCHEDULING, pad, "pushing group");
- }
- ret = gst_pad_push_data (pad, TRUE, group, NULL);
- } while (ret == GST_FLOW_OK && gst_buffer_list_iterator_next_group (it));
- } else {
- GST_CAT_INFO_OBJECT (GST_CAT_SCHEDULING, pad, "pushing empty group");
- ret = gst_pad_push_data (pad, TRUE, gst_buffer_new (), NULL);
+ ret = GST_FLOW_OK;
+ for (idx = 0; idx < n_buffers; idx++) {
+ ret = gst_pad_push_data (pad, &buffers[idx], 1, NULL);
+ if (ret != GST_FLOW_OK)
+ break;
}
-
- gst_buffer_list_iterator_free (it);
- gst_buffer_list_unref (list);
-
+ /* flush buffers we could not push, idx was the last one pushed and
+ * unreffed */
+ gst_pad_data_unref (buffers, n_buffers, idx + 1);
return ret;
}
/* ERROR recovery here */
flushed:
{
- gst_pad_data_unref (is_buffer, data);
+ gst_pad_data_unref (buffers, n_buffers, 0);
GST_DEBUG_OBJECT (pad, "pad block stopped by flush");
GST_OBJECT_UNLOCK (pad);
return ret;
}
dropped:
{
- gst_pad_data_unref (is_buffer, data);
+ gst_pad_data_unref (buffers, n_buffers, 0);
GST_DEBUG_OBJECT (pad, "Dropping buffer due to FALSE probe return");
return GST_FLOW_OK;
}
not_linked:
{
- gst_pad_data_unref (is_buffer, data);
+ gst_pad_data_unref (buffers, n_buffers, 0);
GST_CAT_LOG_OBJECT (GST_CAT_SCHEDULING, pad,
"pushing, but it was not linked");
GST_OBJECT_UNLOCK (pad);
@@ -4052,7 +4008,7 @@ not_linked:
}
not_negotiated:
{
- gst_pad_data_unref (is_buffer, data);
+ gst_pad_data_unref (buffers, n_buffers, 0);
gst_object_unref (peer);
GST_CAT_DEBUG_OBJECT (GST_CAT_SCHEDULING, pad,
"element pushed data then refused to accept the caps");
@@ -4213,7 +4169,7 @@ slow_path:
GST_LOG_OBJECT (pad, "Taking slow path");
- ret = gst_pad_push_data (pad, TRUE, buffer, &scache);
+ ret = gst_pad_push_data (pad, &buffer, 1, &scache);
if (scache.peer) {
GstPadPushCache *ncache;
@@ -4237,12 +4193,13 @@ invalid:
}
/**
- * gst_pad_push_list:
+ * gst_pad_push_array:
* @pad: a source #GstPad, returns #GST_FLOW_ERROR if not.
- * @list: (transfer full): the #GstBufferList to push returns GST_FLOW_ERROR
+ * @buffers: (transfer full): an array of #GstBuffer to push returns GST_FLOW_ERROR
* if not.
+ * @n_buffers: the amount of buffers in @buffers
*
- * Pushes a buffer list to the peer of @pad.
+ * Pushes a buffer array to the peer of @pad.
*
* This function will call an installed pad block before triggering any
* installed pad probes.
@@ -4269,13 +4226,10 @@ invalid:
* Returns: a #GstFlowReturn from the peer pad.
*
* MT safe.
- *
- * Since: 0.10.24
*/
GstFlowReturn
-gst_pad_push_list (GstPad * pad, GstBufferList * list)
+gst_pad_push_array (GstPad * pad, GstBuffer ** buffers, guint n_buffers)
{
- GstBuffer *buf;
GstPadPushCache *cache;
GstFlowReturn ret;
gpointer *cache_ptr;
@@ -4284,7 +4238,8 @@ gst_pad_push_list (GstPad * pad, GstBufferList * list)
g_return_val_if_fail (GST_IS_PAD (pad), GST_FLOW_ERROR);
g_return_val_if_fail (GST_PAD_IS_SRC (pad), GST_FLOW_ERROR);
- g_return_val_if_fail (GST_IS_BUFFER_LIST (list), GST_FLOW_ERROR);
+ g_return_val_if_fail (buffers != NULL, GST_FLOW_ERROR);
+ g_return_val_if_fail (n_buffers > 0, GST_FLOW_ERROR);
cache_ptr = (gpointer *) & pad->priv->cache_ptr;
@@ -4294,10 +4249,7 @@ gst_pad_push_list (GstPad * pad, GstBufferList * list)
goto slow_path;
/* check caps */
- if ((buf = gst_buffer_list_get (list, 0, 0)))
- caps = GST_BUFFER_CAPS (buf);
- else
- caps = NULL;
+ caps = GST_BUFFER_CAPS (buffers[0]);
if (G_UNLIKELY (caps && caps != cache->caps)) {
pad_free_cache (cache);
@@ -4310,7 +4262,7 @@ gst_pad_push_list (GstPad * pad, GstBufferList * list)
if (G_UNLIKELY (g_atomic_pointer_get (cache_ptr) == PAD_CACHE_INVALID))
goto invalid;
- ret = GST_PAD_CHAINLISTFUNC (peer) (peer, list);
+ ret = GST_PAD_CHAINARRAYFUNC (peer) (peer, buffers, n_buffers);
GST_PAD_STREAM_UNLOCK (peer);
@@ -4325,7 +4277,7 @@ slow_path:
GST_LOG_OBJECT (pad, "Taking slow path");
- ret = gst_pad_push_data (pad, FALSE, list, &scache);
+ ret = gst_pad_push_data (pad, buffers, n_buffers, &scache);
if (scache.peer) {
GstPadPushCache *ncache;
diff --git a/gst/gstpad.h b/gst/gstpad.h
index da94c1646..3f4881f8f 100644
--- a/gst/gstpad.h
+++ b/gst/gstpad.h
@@ -266,23 +266,30 @@ typedef gboolean (*GstPadActivateModeFunction) (GstPad *pad, gboolean active);
typedef GstFlowReturn (*GstPadChainFunction) (GstPad *pad, GstBuffer *buffer);
/**
- * GstPadChainListFunction:
+ * GstPadChainArrayFunction:
* @pad: the sink #GstPad that performed the chain.
- * @list: the #GstBufferList that is chained, not %NULL.
+ * @buffers: an array of #GstBuffer that is chained, not %NULL.
+ * @n_buffer: the number of buffers in the array
*
- * A function that will be called on sinkpads when chaining buffer lists.
- * The function typically processes the data contained in the buffer list and
+ * A function that will be called on sinkpads when chaining an array of buffers.
+ * The function typically processes the data contained in the buffer array and
* either consumes the data or passes it on to the internally linked pad(s).
*
- * The implementer of this function receives a refcount to @list and
- * should gst_buffer_list_unref() when the list is no longer needed.
+ * The implementer of this function does not own the pointer to the array buta
+ * it owns the buffers inside the array. This means that the array should not be
+ * freed, the caller of this function will do that. This allows the caller to
+ * allocate the array on the stack, when needed, or reuse its internal array.
*
- * When a chainlist function detects an error in the data stream, it must
+ * When a chainarray function detects an error in the data stream, it must
* post an error on the bus and return an appropriate #GstFlowReturn value.
*
+ * The default chainarray function on a pad will call GstPadChainFunction
+ * repeadedly for each buffer in the array.
+ *
* Returns: #GST_FLOW_OK for success
*/
-typedef GstFlowReturn (*GstPadChainListFunction) (GstPad *pad, GstBufferList *list);
+typedef GstFlowReturn (*GstPadChainArrayFunction) (GstPad *pad, GstBuffer **buffers,
+ guint n_buffers);
/**
* GstPadGetRangeFunction:
@@ -646,7 +653,7 @@ struct _GstPad {
/* data transport functions */
GstPadChainFunction chainfunc;
- GstPadChainListFunction chainlistfunc;
+ GstPadChainArrayFunction chainarrayfunc;
GstPadCheckGetRangeFunction checkgetrangefunc;
GstPadGetRangeFunction getrangefunc;
GstPadEventFunction eventfunc;
@@ -701,7 +708,7 @@ struct _GstPadClass {
#define GST_PAD_ACTIVATEPUSHFUNC(pad) (GST_PAD_CAST(pad)->activatepushfunc)
#define GST_PAD_ACTIVATEPULLFUNC(pad) (GST_PAD_CAST(pad)->activatepullfunc)
#define GST_PAD_CHAINFUNC(pad) (GST_PAD_CAST(pad)->chainfunc)
-#define GST_PAD_CHAINLISTFUNC(pad) (GST_PAD_CAST(pad)->chainlistfunc)
+#define GST_PAD_CHAINARRAYFUNC(pad) (GST_PAD_CAST(pad)->chainarrayfunc)
#define GST_PAD_CHECKGETRANGEFUNC(pad) (GST_PAD_CAST(pad)->checkgetrangefunc)
#define GST_PAD_GETRANGEFUNC(pad) (GST_PAD_CAST(pad)->getrangefunc)
#define GST_PAD_EVENTFUNC(pad) (GST_PAD_CAST(pad)->eventfunc)
@@ -858,7 +865,7 @@ void gst_pad_set_activate_function (GstPad *pad, GstPadActivateFunction activ
void gst_pad_set_activatepull_function (GstPad *pad, GstPadActivateModeFunction activatepull);
void gst_pad_set_activatepush_function (GstPad *pad, GstPadActivateModeFunction activatepush);
void gst_pad_set_chain_function (GstPad *pad, GstPadChainFunction chain);
-void gst_pad_set_chain_list_function (GstPad *pad, GstPadChainListFunction chainlist);
+void gst_pad_set_chain_array_function (GstPad *pad, GstPadChainArrayFunction chainarray);
void gst_pad_set_getrange_function (GstPad *pad, GstPadGetRangeFunction get);
void gst_pad_set_checkgetrange_function (GstPad *pad, GstPadCheckGetRangeFunction check);
void gst_pad_set_event_function (GstPad *pad, GstPadEventFunction event);
@@ -898,7 +905,8 @@ GstCaps * gst_pad_get_negotiated_caps (GstPad * pad);
/* data passing functions to peer */
GstFlowReturn gst_pad_push (GstPad *pad, GstBuffer *buffer);
-GstFlowReturn gst_pad_push_list (GstPad *pad, GstBufferList *list);
+GstFlowReturn gst_pad_push_array (GstPad *pad, GstBuffer **buffers,
+ guint n_buffers);
gboolean gst_pad_check_pull_range (GstPad *pad);
GstFlowReturn gst_pad_pull_range (GstPad *pad, guint64 offset, guint size,
GstBuffer **buffer);
@@ -907,7 +915,8 @@ gboolean gst_pad_event_default (GstPad *pad, GstEvent *event);
/* data passing functions on pad */
GstFlowReturn gst_pad_chain (GstPad *pad, GstBuffer *buffer);
-GstFlowReturn gst_pad_chain_list (GstPad *pad, GstBufferList *list);
+GstFlowReturn gst_pad_chain_array (GstPad *pad, GstBuffer **buffers,
+ guint n_buffers);
GstFlowReturn gst_pad_get_range (GstPad *pad, guint64 offset, guint size,
GstBuffer **buffer);
gboolean gst_pad_send_event (GstPad *pad, GstEvent *event);
diff --git a/libs/gst/base/gstbasesink.c b/libs/gst/base/gstbasesink.c
index 356aa4134..504cb3b11 100644
--- a/libs/gst/base/gstbasesink.c
+++ b/libs/gst/base/gstbasesink.c
@@ -279,18 +279,80 @@ struct _GstBaseSinkPrivate
#define UPDATE_RUNNING_AVG_P(avg,val) DO_RUNNING_AVG(avg,val,16)
#define UPDATE_RUNNING_AVG_N(avg,val) DO_RUNNING_AVG(avg,val,4)
-enum
+typedef enum
{
_PR_IS_NOTHING = 1 << 0,
_PR_IS_BUFFER = 1 << 1,
- _PR_IS_BUFFERLIST = 1 << 2,
+ _PR_IS_BUFFERARRAY = 1 << 2,
_PR_IS_EVENT = 1 << 3
} PrivateObjectType;
-#define OBJ_IS_BUFFER(a) ((a) & _PR_IS_BUFFER)
-#define OBJ_IS_BUFFERLIST(a) ((a) & _PR_IS_BUFFERLIST)
-#define OBJ_IS_EVENT(a) ((a) & _PR_IS_EVENT)
-#define OBJ_IS_BUFFERFULL(a) ((a) & (_PR_IS_BUFFER | _PR_IS_BUFFERLIST))
+typedef struct
+{
+ PrivateObjectType type;
+ gpointer obj;
+ gpointer *objs;
+ guint n_objs;
+} SinkObject;
+
+static void
+sink_object_init (SinkObject * obj, gpointer mobj)
+{
+ if (GST_IS_BUFFER (mobj))
+ obj->type = _PR_IS_BUFFER;
+ if (GST_IS_EVENT (mobj))
+ obj->type = _PR_IS_EVENT;
+ else
+ obj->type = _PR_IS_NOTHING;
+ obj->obj = mobj;
+ obj->objs = &obj->obj;
+ obj->n_objs = 1;
+}
+
+static void
+sink_object_init_array (SinkObject * obj, gpointer * objs, guint n_objs)
+{
+ obj->type = _PR_IS_BUFFERARRAY;
+ obj->objs = objs;
+ obj->n_objs = n_objs;
+}
+
+static SinkObject *
+sink_object_dup (SinkObject * obj)
+{
+ SinkObject *res;
+
+ res = g_slice_new (SinkObject);
+ memcpy (res, obj, sizeof (SinkObject));
+ memset (obj, 0, sizeof (SinkObject));
+
+ return res;
+}
+
+#define OBJ_GET_ITEM(obj) (GST_EVENT_CAST ((obj)->objs[0]))
+#define OBJ_GET_BUFFER(obj,i) (GST_BUFFER_CAST ((obj)->objs[i]))
+#define OBJ_GET_EVENT(obj) (OBJ_GET_ITEM (obj))
+
+static void
+sink_object_clear (SinkObject * obj)
+{
+ guint i, len;
+
+ len = obj->n_objs;
+ for (i = 0; i < len; i++)
+ gst_mini_object_unref (GST_MINI_OBJECT_CAST (obj->objs[i]));
+}
+
+static void
+sink_object_free (SinkObject * obj)
+{
+ g_slice_free (SinkObject, obj);
+}
+
+#define OBJ_IS_BUFFER(obj) ((obj->type) & _PR_IS_BUFFER)
+#define OBJ_IS_BUFFERARRAY(obj) ((obj->type) & _PR_IS_BUFFERARRAY)
+#define OBJ_IS_EVENT(obj) ((obj->type) & _PR_IS_EVENT)
+#define OBJ_IS_BUFFERFULL(obj) ((obj->type) & (_PR_IS_BUFFER | _PR_IS_BUFFERARRAY))
/* BaseSink properties */
@@ -386,8 +448,8 @@ static GstStateChangeReturn gst_base_sink_change_state (GstElement * element,
GstStateChange transition);
static GstFlowReturn gst_base_sink_chain (GstPad * pad, GstBuffer * buffer);
-static GstFlowReturn gst_base_sink_chain_list (GstPad * pad,
- GstBufferList * list);
+static GstFlowReturn gst_base_sink_chain_array (GstPad * pad,
+ GstBuffer ** buffers, guint n_buffers);
static void gst_base_sink_loop (GstPad * pad);
static gboolean gst_base_sink_pad_activate (GstPad * pad);
@@ -405,10 +467,10 @@ static GstFlowReturn gst_base_sink_pad_buffer_alloc (GstPad * pad,
/* check if an object was too late */
static gboolean gst_base_sink_is_too_late (GstBaseSink * basesink,
- GstMiniObject * obj, GstClockTime rstart, GstClockTime rstop,
+ SinkObject * obj, GstClockTime rstart, GstClockTime rstop,
GstClockReturn status, GstClockTimeDiff jitter);
static GstFlowReturn gst_base_sink_preroll_object (GstBaseSink * basesink,
- guint8 obj_type, GstMiniObject * obj);
+ SinkObject * obj);
static void
gst_base_sink_class_init (GstBaseSinkClass * klass)
@@ -571,7 +633,7 @@ gst_base_sink_class_init (GstBaseSinkClass * klass)
GST_DEBUG_REGISTER_FUNCPTR (gst_base_sink_pad_activate_pull);
GST_DEBUG_REGISTER_FUNCPTR (gst_base_sink_event);
GST_DEBUG_REGISTER_FUNCPTR (gst_base_sink_chain);
- GST_DEBUG_REGISTER_FUNCPTR (gst_base_sink_chain_list);
+ GST_DEBUG_REGISTER_FUNCPTR (gst_base_sink_chain_array);
}
static GstCaps *
@@ -691,7 +753,8 @@ gst_base_sink_init (GstBaseSink * basesink, gpointer g_class)
gst_base_sink_pad_activate_pull);
gst_pad_set_event_function (basesink->sinkpad, gst_base_sink_event);
gst_pad_set_chain_function (basesink->sinkpad, gst_base_sink_chain);
- gst_pad_set_chain_list_function (basesink->sinkpad, gst_base_sink_chain_list);
+ gst_pad_set_chain_array_function (basesink->sinkpad,
+ gst_base_sink_chain_array);
gst_element_add_pad (GST_ELEMENT_CAST (basesink), basesink->sinkpad);
basesink->pad_mode = GST_ACTIVATE_NONE;
@@ -1474,12 +1537,13 @@ gst_base_sink_buffer_alloc (GstBaseSink * sink, guint64 offset, guint size,
static void
gst_base_sink_preroll_queue_flush (GstBaseSink * basesink, GstPad * pad)
{
- GstMiniObject *obj;
+ SinkObject *obj;
GST_DEBUG_OBJECT (basesink, "flushing queue %p", basesink);
while ((obj = g_queue_pop_head (basesink->preroll_queue))) {
GST_DEBUG_OBJECT (basesink, "popped %p", obj);
- gst_mini_object_unref (obj);
+ sink_object_clear (obj);
+ sink_object_free (obj);
}
/* we can't have EOS anymore now */
basesink->eos = FALSE;
@@ -1901,11 +1965,11 @@ handle_stepping (GstBaseSink * sink, GstSegment * segment,
* rrstart/rrstop contain the start/stop in running time.
*/
static gboolean
-gst_base_sink_get_sync_times (GstBaseSink * basesink, GstMiniObject * obj,
+gst_base_sink_get_sync_times (GstBaseSink * basesink, SinkObject * obj,
GstClockTime * rsstart, GstClockTime * rsstop,
GstClockTime * rrstart, GstClockTime * rrstop, gboolean * do_sync,
gboolean * stepped, GstSegment * segment, GstStepInfo * step,
- gboolean * step_end, guint8 obj_type)
+ gboolean * step_end)
{
GstBaseSinkClass *bclass;
GstBuffer *buffer;
@@ -1922,8 +1986,8 @@ gst_base_sink_get_sync_times (GstBaseSink * basesink, GstMiniObject * obj,
/* start with nothing */
start = stop = GST_CLOCK_TIME_NONE;
- if (G_UNLIKELY (OBJ_IS_EVENT (obj_type))) {
- GstEvent *event = GST_EVENT_CAST (obj);
+ if (G_UNLIKELY (OBJ_IS_EVENT (obj))) {
+ GstEvent *event = GST_EVENT_CAST (obj->objs[0]);
switch (GST_EVENT_TYPE (event)) {
/* EOS event needs syncing */
@@ -2268,22 +2332,6 @@ step_unlocked:
}
}
-static inline guint8
-get_object_type (GstMiniObject * obj)
-{
- guint8 obj_type;
-
- if (G_LIKELY (GST_IS_BUFFER (obj)))
- obj_type = _PR_IS_BUFFER;
- else if (GST_IS_EVENT (obj))
- obj_type = _PR_IS_EVENT;
- else if (GST_IS_BUFFER_LIST (obj))
- obj_type = _PR_IS_BUFFERLIST;
- else
- obj_type = _PR_IS_NOTHING;
-
- return obj_type;
-}
/**
* gst_base_sink_do_preroll:
@@ -2308,12 +2356,13 @@ gst_base_sink_do_preroll (GstBaseSink * sink, GstMiniObject * obj)
GstFlowReturn ret;
while (G_UNLIKELY (sink->need_preroll)) {
- guint8 obj_type;
+ SinkObject sobj;
+
GST_DEBUG_OBJECT (sink, "prerolling object %p", obj);
- obj_type = get_object_type (obj);
+ sink_object_init (&sobj, obj);
- ret = gst_base_sink_preroll_object (sink, obj_type, obj);
+ ret = gst_base_sink_preroll_object (sink, &sobj);
if (ret != GST_FLOW_OK)
goto preroll_failed;
@@ -2437,7 +2486,7 @@ flushing:
*/
static GstFlowReturn
gst_base_sink_do_sync (GstBaseSink * basesink, GstPad * pad,
- GstMiniObject * obj, gboolean * late, gboolean * step_end, guint8 obj_type)
+ SinkObject * obj, gboolean * late, gboolean * step_end)
{
GstClockTimeDiff jitter = 0;
gboolean syncable;
@@ -2465,7 +2514,7 @@ do_step:
/* get timing information for this object against the render segment */
syncable = gst_base_sink_get_sync_times (basesink, obj,
&sstart, &sstop, &rstart, &rstop, &do_sync, &stepped, &basesink->segment,
- current, step_end, obj_type);
+ current, step_end);
if (G_UNLIKELY (stepped))
goto step_skipped;
@@ -2507,7 +2556,7 @@ again:
/* first do preroll, this makes sure we commit our state
* to PAUSED and can continue to PLAYING. We cannot perform
* any clock sync in PAUSED because there is no clock. */
- ret = gst_base_sink_do_preroll (basesink, obj);
+ ret = gst_base_sink_do_preroll (basesink, obj->objs[0]);
if (G_UNLIKELY (ret != GST_FLOW_OK))
goto preroll_failed;
@@ -2796,7 +2845,7 @@ gst_base_sink_reset_qos (GstBaseSink * sink)
* returns TRUE if the buffer was too late.
*/
static gboolean
-gst_base_sink_is_too_late (GstBaseSink * basesink, GstMiniObject * obj,
+gst_base_sink_is_too_late (GstBaseSink * basesink, SinkObject * obj,
GstClockTime rstart, GstClockTime rstop,
GstClockReturn status, GstClockTimeDiff jitter)
{
@@ -2819,7 +2868,7 @@ gst_base_sink_is_too_late (GstBaseSink * basesink, GstMiniObject * obj,
goto no_drop;
/* only check for buffers */
- if (G_UNLIKELY (!GST_IS_BUFFER (obj)))
+ if (G_UNLIKELY (!OBJ_IS_BUFFERFULL (obj)))
goto not_buffer;
/* can't do check if we don't have a timestamp */
@@ -2925,49 +2974,35 @@ gst_base_sink_do_render_stats (GstBaseSink * basesink, gboolean start)
*/
static GstFlowReturn
gst_base_sink_render_object (GstBaseSink * basesink, GstPad * pad,
- guint8 obj_type, gpointer obj)
+ SinkObject * obj)
{
GstFlowReturn ret;
GstBaseSinkClass *bclass;
gboolean late, step_end;
- gpointer sync_obj;
GstBaseSinkPrivate *priv;
priv = basesink->priv;
- if (OBJ_IS_BUFFERLIST (obj_type)) {
- /*
- * If buffer list, use the first group buffer within the list
- * for syncing
- */
- sync_obj = gst_buffer_list_get (GST_BUFFER_LIST_CAST (obj), 0, 0);
- g_assert (NULL != sync_obj);
- } else {
- sync_obj = obj;
- }
-
again:
late = FALSE;
step_end = FALSE;
/* synchronize this object, non syncable objects return OK
* immediatly. */
- ret =
- gst_base_sink_do_sync (basesink, pad, sync_obj, &late, &step_end,
- obj_type);
+ ret = gst_base_sink_do_sync (basesink, pad, obj, &late, &step_end);
if (G_UNLIKELY (ret != GST_FLOW_OK))
goto sync_failed;
/* and now render, event or buffer/buffer list. */
- if (G_LIKELY (OBJ_IS_BUFFERFULL (obj_type))) {
+ if (G_LIKELY (OBJ_IS_BUFFERFULL (obj))) {
/* drop late buffers unconditionally, let's hope it's unlikely */
if (G_UNLIKELY (late))
goto dropped;
bclass = GST_BASE_SINK_GET_CLASS (basesink);
- if (G_LIKELY ((OBJ_IS_BUFFERLIST (obj_type) && bclass->render_list) ||
- (!OBJ_IS_BUFFERLIST (obj_type) && bclass->render))) {
+ if (G_LIKELY ((OBJ_IS_BUFFERARRAY (obj) && bclass->render_array) ||
+ (!OBJ_IS_BUFFERARRAY (obj) && bclass->render))) {
gint do_qos;
/* read once, to get same value before and after */
@@ -2979,22 +3014,24 @@ again:
if (do_qos)
gst_base_sink_do_render_stats (basesink, TRUE);
- if (!OBJ_IS_BUFFERLIST (obj_type)) {
+ if (!OBJ_IS_BUFFERARRAY (obj)) {
GstBuffer *buf;
/* For buffer lists do not set last buffer. Creating buffer
* with meaningful data can be done only with memcpy which will
* significantly affect performance */
- buf = GST_BUFFER_CAST (obj);
+ buf = OBJ_GET_BUFFER (obj, 0);
gst_base_sink_set_last_buffer (basesink, buf);
ret = bclass->render (basesink, buf);
} else {
- GstBufferList *buflist;
+ GstBuffer **buffers;
+ guint n_buffers;
- buflist = GST_BUFFER_LIST_CAST (obj);
+ buffers = (GstBuffer **) obj->objs;
+ n_buffers = obj->n_objs;
- ret = bclass->render_list (basesink, buflist);
+ ret = bclass->render_array (basesink, buffers, n_buffers);
}
if (do_qos)
@@ -3008,8 +3045,8 @@ again:
priv->rendered++;
}
- } else if (G_LIKELY (OBJ_IS_EVENT (obj_type))) {
- GstEvent *event = GST_EVENT_CAST (obj);
+ } else if (G_LIKELY (OBJ_IS_EVENT (obj))) {
+ GstEvent *event = OBJ_GET_EVENT (obj);
gboolean event_res = TRUE;
GstEventType type;
@@ -3088,7 +3125,7 @@ done:
gst_base_sink_perform_qos (basesink, late);
GST_DEBUG_OBJECT (basesink, "object unref after render %p", obj);
- gst_mini_object_unref (GST_MINI_OBJECT_CAST (obj));
+ sink_object_clear (obj);
return ret;
/* ERRORS */
@@ -3105,9 +3142,12 @@ dropped:
if (g_atomic_int_get (&priv->qos_enabled)) {
GstMessage *qos_msg;
GstClockTime timestamp, duration;
+ GstBuffer *buf;
- timestamp = GST_BUFFER_TIMESTAMP (GST_BUFFER_CAST (sync_obj));
- duration = GST_BUFFER_DURATION (GST_BUFFER_CAST (sync_obj));
+ buf = OBJ_GET_BUFFER (obj, 0);
+
+ timestamp = GST_BUFFER_TIMESTAMP (buf);
+ duration = GST_BUFFER_DURATION (buf);
GST_CAT_DEBUG_OBJECT (GST_CAT_QOS, basesink,
"qos: dropped buffer rt %" GST_TIME_FORMAT ", st %" GST_TIME_FORMAT
@@ -3133,7 +3173,7 @@ dropped:
flushing:
{
GST_DEBUG_OBJECT (basesink, "we are flushing, ignore object");
- gst_mini_object_unref (obj);
+ sink_object_clear (obj);
return GST_FLOW_WRONG_STATE;
}
}
@@ -3147,39 +3187,26 @@ flushing:
* function does not take ownership of obj.
*/
static GstFlowReturn
-gst_base_sink_preroll_object (GstBaseSink * basesink, guint8 obj_type,
- GstMiniObject * obj)
+gst_base_sink_preroll_object (GstBaseSink * basesink, SinkObject * obj)
{
GstFlowReturn ret;
GST_DEBUG_OBJECT (basesink, "prerolling object %p", obj);
/* if it's a buffer, we need to call the preroll method */
- if (G_LIKELY (OBJ_IS_BUFFERFULL (obj_type) && basesink->priv->call_preroll)) {
+ if (G_LIKELY (OBJ_IS_BUFFERFULL (obj) && basesink->priv->call_preroll)) {
GstBaseSinkClass *bclass;
GstBuffer *buf;
GstClockTime timestamp;
- if (OBJ_IS_BUFFERLIST (obj_type)) {
- buf = gst_buffer_list_get (GST_BUFFER_LIST_CAST (obj), 0, 0);
- g_assert (NULL != buf);
- } else {
- buf = GST_BUFFER_CAST (obj);
- }
+ buf = OBJ_GET_BUFFER (obj, 0);
timestamp = GST_BUFFER_TIMESTAMP (buf);
GST_DEBUG_OBJECT (basesink, "preroll buffer %" GST_TIME_FORMAT,
GST_TIME_ARGS (timestamp));
- /*
- * For buffer lists do not set last buffer. Creating buffer
- * with meaningful data can be done only with memcpy which will
- * significantly affect performance
- */
- if (!OBJ_IS_BUFFERLIST (obj_type)) {
- gst_base_sink_set_last_buffer (basesink, buf);
- }
+ gst_base_sink_set_last_buffer (basesink, buf);
bclass = GST_BASE_SINK_GET_CLASS (basesink);
if (bclass->preroll)
@@ -3221,7 +3248,7 @@ stopping:
*/
static GstFlowReturn
gst_base_sink_queue_object_unlocked (GstBaseSink * basesink, GstPad * pad,
- guint8 obj_type, gpointer obj, gboolean prerollable)
+ SinkObject * obj, gboolean prerollable)
{
GstFlowReturn ret = GST_FLOW_OK;
gint length;
@@ -3237,7 +3264,7 @@ gst_base_sink_queue_object_unlocked (GstBaseSink * basesink, GstPad * pad,
/* first prerollable item needs to finish the preroll */
if (length == 1) {
- ret = gst_base_sink_preroll_object (basesink, obj_type, obj);
+ ret = gst_base_sink_preroll_object (basesink, obj);
if (G_UNLIKELY (ret != GST_FLOW_OK))
goto preroll_failed;
}
@@ -3254,22 +3281,21 @@ gst_base_sink_queue_object_unlocked (GstBaseSink * basesink, GstPad * pad,
* if any. */
q = basesink->preroll_queue;
while (G_UNLIKELY (!g_queue_is_empty (q))) {
- GstMiniObject *o;
- guint8 ot;
+ SinkObject *o;
o = g_queue_pop_head (q);
GST_DEBUG_OBJECT (basesink, "rendering queued object %p", o);
- ot = get_object_type (o);
-
/* do something with the return value */
- ret = gst_base_sink_render_object (basesink, pad, ot, o);
+ ret = gst_base_sink_render_object (basesink, pad, o);
+ sink_object_free (o);
+
if (ret != GST_FLOW_OK)
goto dequeue_failed;
}
/* now render the object */
- ret = gst_base_sink_render_object (basesink, pad, obj_type, obj);
+ ret = gst_base_sink_render_object (basesink, pad, obj);
basesink->preroll_queued = 0;
return ret;
@@ -3279,7 +3305,7 @@ preroll_failed:
{
GST_DEBUG_OBJECT (basesink, "preroll failed, reason %s",
gst_flow_get_name (ret));
- gst_mini_object_unref (GST_MINI_OBJECT_CAST (obj));
+ sink_object_clear (obj);
return ret;
}
more_preroll:
@@ -3287,14 +3313,14 @@ more_preroll:
/* add object to the queue and return */
GST_DEBUG_OBJECT (basesink, "need more preroll data %d <= %d",
length, basesink->preroll_queue_max_len);
- g_queue_push_tail (basesink->preroll_queue, obj);
+ g_queue_push_tail (basesink->preroll_queue, sink_object_dup (obj));
return GST_FLOW_OK;
}
dequeue_failed:
{
GST_DEBUG_OBJECT (basesink, "rendering queued objects failed, reason %s",
gst_flow_get_name (ret));
- gst_mini_object_unref (GST_MINI_OBJECT_CAST (obj));
+ sink_object_clear (obj);
return ret;
}
}
@@ -3310,7 +3336,7 @@ dequeue_failed:
*/
static GstFlowReturn
gst_base_sink_queue_object (GstBaseSink * basesink, GstPad * pad,
- GstMiniObject * obj, gboolean prerollable)
+ SinkObject * obj, gboolean prerollable)
{
GstFlowReturn ret;
@@ -3321,9 +3347,7 @@ gst_base_sink_queue_object (GstBaseSink * basesink, GstPad * pad,
if (G_UNLIKELY (basesink->priv->received_eos))
goto was_eos;
- ret =
- gst_base_sink_queue_object_unlocked (basesink, pad, _PR_IS_EVENT, obj,
- prerollable);
+ ret = gst_base_sink_queue_object_unlocked (basesink, pad, obj, prerollable);
GST_BASE_SINK_PREROLL_UNLOCK (basesink);
return ret;
@@ -3333,7 +3357,7 @@ flushing:
{
GST_DEBUG_OBJECT (basesink, "sink is flushing");
GST_BASE_SINK_PREROLL_UNLOCK (basesink);
- gst_mini_object_unref (obj);
+ sink_object_clear (obj);
return GST_FLOW_WRONG_STATE;
}
was_eos:
@@ -3341,7 +3365,7 @@ was_eos:
GST_DEBUG_OBJECT (basesink,
"we are EOS, dropping object, return UNEXPECTED");
GST_BASE_SINK_PREROLL_UNLOCK (basesink);
- gst_mini_object_unref (obj);
+ sink_object_clear (obj);
return GST_FLOW_UNEXPECTED;
}
}
@@ -3400,11 +3424,14 @@ gst_base_sink_event (GstPad * pad, GstEvent * event)
GstBaseSink *basesink;
gboolean result = TRUE;
GstBaseSinkClass *bclass;
+ SinkObject obj;
basesink = GST_BASE_SINK (gst_pad_get_parent (pad));
bclass = GST_BASE_SINK_GET_CLASS (basesink);
+ sink_object_init (&obj, event);
+
GST_DEBUG_OBJECT (basesink, "received event %p %" GST_PTR_FORMAT, event,
event);
@@ -3428,8 +3455,7 @@ gst_base_sink_event (GstPad * pad, GstEvent * event)
/* EOS is a prerollable object, we call the unlocked version because it
* does not check the received_eos flag. */
- ret = gst_base_sink_queue_object_unlocked (basesink, pad,
- _PR_IS_EVENT, GST_MINI_OBJECT_CAST (event), TRUE);
+ ret = gst_base_sink_queue_object_unlocked (basesink, pad, &obj, TRUE);
if (G_UNLIKELY (ret != GST_FLOW_OK))
result = FALSE;
}
@@ -3461,9 +3487,7 @@ gst_base_sink_event (GstPad * pad, GstEvent * event)
gst_base_sink_configure_segment (basesink, pad, event,
basesink->clip_segment);
- ret =
- gst_base_sink_queue_object_unlocked (basesink, pad,
- _PR_IS_EVENT, GST_MINI_OBJECT_CAST (event), FALSE);
+ ret = gst_base_sink_queue_object_unlocked (basesink, pad, &obj, FALSE);
if (G_UNLIKELY (ret != GST_FLOW_OK))
result = FALSE;
else {
@@ -3499,12 +3523,11 @@ gst_base_sink_event (GstPad * pad, GstEvent * event)
/* other events are sent to queue or subclass depending on if they
* are serialized. */
if (GST_EVENT_IS_SERIALIZED (event)) {
- gst_base_sink_queue_object (basesink, pad,
- GST_MINI_OBJECT_CAST (event), FALSE);
+ gst_base_sink_queue_object (basesink, pad, &obj, FALSE);
} else {
if (bclass->event)
bclass->event (basesink, event);
- gst_event_unref (event);
+ sink_object_clear (&obj);
}
break;
}
@@ -3519,7 +3542,7 @@ flushing:
GST_DEBUG_OBJECT (basesink, "we are flushing");
GST_BASE_SINK_PREROLL_UNLOCK (basesink);
result = FALSE;
- gst_event_unref (event);
+ sink_object_clear (&obj);
goto done;
}
}
@@ -3574,7 +3597,7 @@ gst_base_sink_needs_preroll (GstBaseSink * basesink)
*/
static GstFlowReturn
gst_base_sink_chain_unlocked (GstBaseSink * basesink, GstPad * pad,
- guint8 obj_type, gpointer obj)
+ SinkObject * obj)
{
GstBaseSinkClass *bclass;
GstFlowReturn result;
@@ -3588,12 +3611,7 @@ gst_base_sink_chain_unlocked (GstBaseSink * basesink, GstPad * pad,
if (G_UNLIKELY (basesink->priv->received_eos))
goto was_eos;
- if (OBJ_IS_BUFFERLIST (obj_type)) {
- time_buf = gst_buffer_list_get (GST_BUFFER_LIST_CAST (obj), 0, 0);
- g_assert (NULL != time_buf);
- } else {
- time_buf = GST_BUFFER_CAST (obj);
- }
+ time_buf = OBJ_GET_BUFFER (obj, 0);
/* for code clarity */
clip_segment = basesink->clip_segment;
@@ -3644,28 +3662,27 @@ gst_base_sink_chain_unlocked (GstBaseSink * basesink, GstPad * pad,
/* now we can process the buffer in the queue, this function takes ownership
* of the buffer */
- result = gst_base_sink_queue_object_unlocked (basesink, pad,
- obj_type, obj, TRUE);
+ result = gst_base_sink_queue_object_unlocked (basesink, pad, obj, TRUE);
return result;
/* ERRORS */
flushing:
{
GST_DEBUG_OBJECT (basesink, "sink is flushing");
- gst_mini_object_unref (GST_MINI_OBJECT_CAST (obj));
+ sink_object_clear (obj);
return GST_FLOW_WRONG_STATE;
}
was_eos:
{
GST_DEBUG_OBJECT (basesink,
"we are EOS, dropping object, return UNEXPECTED");
- gst_mini_object_unref (GST_MINI_OBJECT_CAST (obj));
+ sink_object_clear (obj);
return GST_FLOW_UNEXPECTED;
}
out_of_segment:
{
GST_DEBUG_OBJECT (basesink, "dropping buffer, out of clipping segment");
- gst_mini_object_unref (GST_MINI_OBJECT_CAST (obj));
+ sink_object_clear (obj);
return GST_FLOW_OK;
}
}
@@ -3674,7 +3691,7 @@ out_of_segment:
*/
static GstFlowReturn
gst_base_sink_chain_main (GstBaseSink * basesink, GstPad * pad,
- guint8 obj_type, gpointer obj)
+ SinkObject * obj)
{
GstFlowReturn result;
@@ -3682,7 +3699,7 @@ gst_base_sink_chain_main (GstBaseSink * basesink, GstPad * pad,
goto wrong_mode;
GST_BASE_SINK_PREROLL_LOCK (basesink);
- result = gst_base_sink_chain_unlocked (basesink, pad, obj_type, obj);
+ result = gst_base_sink_chain_unlocked (basesink, pad, obj);
GST_BASE_SINK_PREROLL_UNLOCK (basesink);
done:
@@ -3696,7 +3713,7 @@ wrong_mode:
"Push on pad %s:%s, but it was not activated in push mode",
GST_DEBUG_PAD_NAME (pad));
GST_OBJECT_UNLOCK (pad);
- gst_mini_object_unref (GST_MINI_OBJECT_CAST (obj));
+ sink_object_clear (obj);
/* we don't post an error message this will signal to the peer
* pushing that EOS is reached. */
result = GST_FLOW_UNEXPECTED;
@@ -3708,52 +3725,44 @@ static GstFlowReturn
gst_base_sink_chain (GstPad * pad, GstBuffer * buf)
{
GstBaseSink *basesink;
+ SinkObject obj;
basesink = GST_BASE_SINK (GST_OBJECT_PARENT (pad));
- return gst_base_sink_chain_main (basesink, pad, _PR_IS_BUFFER, buf);
+ obj.type = _PR_IS_BUFFER;
+ obj.objs[0] = buf;
+ obj.n_objs = 1;
+
+ return gst_base_sink_chain_main (basesink, pad, &obj);
}
static GstFlowReturn
-gst_base_sink_chain_list (GstPad * pad, GstBufferList * list)
+gst_base_sink_chain_array (GstPad * pad, GstBuffer ** buffers, guint n_buffers)
{
GstBaseSink *basesink;
GstBaseSinkClass *bclass;
GstFlowReturn result;
+ SinkObject obj;
basesink = GST_BASE_SINK (GST_OBJECT_PARENT (pad));
bclass = GST_BASE_SINK_GET_CLASS (basesink);
- if (G_LIKELY (bclass->render_list)) {
- result = gst_base_sink_chain_main (basesink, pad, _PR_IS_BUFFERLIST, list);
- } else {
- GstBufferListIterator *it;
- GstBuffer *group;
+ if (G_LIKELY (bclass->render_array)) {
+ sink_object_init_array (&obj, (gpointer *) buffers, n_buffers);
- GST_INFO_OBJECT (pad, "chaining each group in list as a merged buffer");
+ result = gst_base_sink_chain_main (basesink, pad, &obj);
+ } else {
+ guint idx;
- it = gst_buffer_list_iterate (list);
+ GST_INFO_OBJECT (pad, "chaining each buffer in array");
- if (gst_buffer_list_iterator_next_group (it)) {
- do {
- group = gst_buffer_list_iterator_merge_group (it);
- if (group == NULL) {
- group = gst_buffer_new ();
- GST_CAT_INFO_OBJECT (GST_CAT_SCHEDULING, pad, "chaining empty group");
- } else {
- GST_CAT_INFO_OBJECT (GST_CAT_SCHEDULING, pad, "chaining group");
- }
- result = gst_base_sink_chain_main (basesink, pad, _PR_IS_BUFFER, group);
- } while (result == GST_FLOW_OK
- && gst_buffer_list_iterator_next_group (it));
- } else {
- GST_CAT_INFO_OBJECT (GST_CAT_SCHEDULING, pad, "chaining empty group");
- result =
- gst_base_sink_chain_main (basesink, pad, _PR_IS_BUFFER,
- gst_buffer_new ());
+ result = GST_FLOW_OK;
+ for (idx = 0; idx < n_buffers; idx++) {
+ if (G_LIKELY (result == GST_FLOW_OK)) {
+ result = gst_base_sink_chain (pad, buffers[idx]);
+ } else
+ gst_buffer_unref (buffers[idx]);
}
- gst_buffer_list_iterator_free (it);
- gst_buffer_list_unref (list);
}
return result;
}
@@ -4068,6 +4077,7 @@ gst_base_sink_loop (GstPad * pad)
GstFlowReturn result;
guint blocksize;
guint64 offset;
+ SinkObject obj;
basesink = GST_BASE_SINK (GST_OBJECT_PARENT (pad));
@@ -4088,12 +4098,14 @@ gst_base_sink_loop (GstPad * pad)
if (G_UNLIKELY (buf == NULL))
goto no_buffer;
+ sink_object_init (&obj, buf);
+
offset += gst_buffer_get_size (buf);
gst_segment_set_last_stop (&basesink->segment, GST_FORMAT_BYTES, offset);
GST_BASE_SINK_PREROLL_LOCK (basesink);
- result = gst_base_sink_chain_unlocked (basesink, pad, _PR_IS_BUFFER, buf);
+ result = gst_base_sink_chain_unlocked (basesink, pad, &obj);
GST_BASE_SINK_PREROLL_UNLOCK (basesink);
if (G_UNLIKELY (result != GST_FLOW_OK))
goto paused;
diff --git a/libs/gst/base/gstbasesink.h b/libs/gst/base/gstbasesink.h
index 92ee1f784..17e0e2022 100644
--- a/libs/gst/base/gstbasesink.h
+++ b/libs/gst/base/gstbasesink.h
@@ -130,8 +130,8 @@ struct _GstBaseSink {
* @preroll: Called to present the preroll buffer if desired
* @render: Called when a buffer should be presented or output, at the
* correct moment if the #GstBaseSink has been set to sync to the clock.
- * @render_list: Same as @render but used whith buffer lists instead of
- * buffers. Since: 0.10.24
+ * @render_array: Same as @render but used whith buffer arrays instead of
+ * buffers.
* @async_play: Subclasses should override this when they need to perform
* special processing when changing to the PLAYING state asynchronously.
* Called with the OBJECT_LOCK held.
@@ -186,8 +186,8 @@ struct _GstBaseSinkClass {
GstFlowReturn (*preroll) (GstBaseSink *sink, GstBuffer *buffer);
GstFlowReturn (*render) (GstBaseSink *sink, GstBuffer *buffer);
- /* Render a BufferList */
- GstFlowReturn (*render_list) (GstBaseSink *sink, GstBufferList *buffer_list);
+ /* Render a buffer array */
+ GstFlowReturn (*render_array) (GstBaseSink *sink, GstBuffer **buffers, guint n_buffers);
/*< private >*/
gpointer _gst_reserved[GST_PADDING_LARGE];
diff --git a/plugins/elements/gsttee.c b/plugins/elements/gsttee.c
index ef80db475..20fe1d56f 100644
--- a/plugins/elements/gsttee.c
+++ b/plugins/elements/gsttee.c
@@ -135,7 +135,8 @@ static void gst_tee_get_property (GObject * object, guint prop_id,
static void gst_tee_dispose (GObject * object);
static GstFlowReturn gst_tee_chain (GstPad * pad, GstBuffer * buffer);
-static GstFlowReturn gst_tee_chain_list (GstPad * pad, GstBufferList * list);
+static GstFlowReturn gst_tee_chain_array (GstPad * pad, GstBuffer ** buffers,
+ guint n_buffers);
static GstFlowReturn gst_tee_buffer_alloc (GstPad * pad, guint64 offset,
guint size, GstCaps * caps, GstBuffer ** buf);
static gboolean gst_tee_sink_acceptcaps (GstPad * pad, GstCaps * caps);
@@ -266,8 +267,8 @@ gst_tee_init (GstTee * tee, GstTeeClass * g_class)
gst_pad_set_activatepush_function (tee->sinkpad,
GST_DEBUG_FUNCPTR (gst_tee_sink_activate_push));
gst_pad_set_chain_function (tee->sinkpad, GST_DEBUG_FUNCPTR (gst_tee_chain));
- gst_pad_set_chain_list_function (tee->sinkpad,
- GST_DEBUG_FUNCPTR (gst_tee_chain_list));
+ gst_pad_set_chain_array_function (tee->sinkpad,
+ GST_DEBUG_FUNCPTR (gst_tee_chain_array));
gst_element_add_pad (GST_ELEMENT (tee), tee->sinkpad);
tee->last_message = NULL;
@@ -665,7 +666,7 @@ gst_tee_do_push (GstTee * tee, GstPad * pad, gpointer data, gboolean is_list)
res = GST_FLOW_OK;
} else if (is_list) {
res =
- gst_pad_push_list (pad,
+ gst_pad_push_array (pad,
gst_buffer_list_ref (GST_BUFFER_LIST_CAST (data)));
} else {
res = gst_pad_push (pad, gst_buffer_ref (GST_BUFFER_CAST (data)));
@@ -688,7 +689,8 @@ clear_pads (GstPad * pad, GstTee * tee)
}
static GstFlowReturn
-gst_tee_handle_data (GstTee * tee, gpointer data, gboolean is_list)
+gst_tee_handle_data (GstTee * tee, gpointer data, guint n_data,
+ gboolean is_list)
{
GList *pads;
guint32 cookie;
@@ -713,7 +715,7 @@ gst_tee_handle_data (GstTee * tee, gpointer data, gboolean is_list)
if (pad == tee->pull_pad) {
ret = GST_FLOW_OK;
} else if (is_list) {
- ret = gst_pad_push_list (pad, GST_BUFFER_LIST_CAST (data));
+ ret = gst_pad_push_array (pad, (GstBuffer **) data, n_data);
} else {
ret = gst_pad_push (pad, GST_BUFFER_CAST (data));
}
@@ -829,7 +831,7 @@ gst_tee_chain (GstPad * pad, GstBuffer * buffer)
}
static GstFlowReturn
-gst_tee_chain_list (GstPad * pad, GstBufferList * list)
+gst_tee_chain_array (GstPad * pad, GstBuffer ** buffer)
{
GstFlowReturn res;
GstTee *tee;
diff --git a/tests/check/Makefile.am b/tests/check/Makefile.am
index b8968df4f..90dd63ecf 100644
--- a/tests/check/Makefile.am
+++ b/tests/check/Makefile.am
@@ -101,7 +101,6 @@ endif
check_PROGRAMS = \
$(ABI_CHECKS) \
gst/gstbuffer \
- gst/gstbufferlist \
gst/gstmeta \
gst/gstbus \
gst/gstcaps \