[prev in list] [next in list] [prev in thread] [next in thread]
List: gstreamer-cvs
Subject: [gst-cvs] gst-plugins-base: appsink: add buffer fallback in case
From: tpm () kemper ! freedesktop ! org (Tim Müller)
Date: 2011-01-31 18:09:52
Message-ID: 20110131180952.4790210050 () kemper ! freedesktop ! org
[Download RAW message or body]
Module: gst-plugins-base
Branch: master
Commit: 33a5e3e06f091afc31ef206a267c420ae4a5bb3a
URL: http://cgit.freedesktop.org/gstreamer/gst-plugins-base/commit/?id=33a5e3e06f091afc31ef206a267c420ae4a5bb3a
Author: Tim-Philipp Müller <tim.muller@collabora.co.uk>
Date: Mon Jan 31 18:06:18 2011 +0000
appsink: add buffer fallback in case the application doesn't handle buffer lists
We shouldn't assume the application handles buffer lists, for
ease-of-use reasons and for backwards compatibility reasons.
---
gst-libs/gst/app/gstappsink.c | 62 +++++++++++++++++++++++++++-
tests/check/elements/appsink.c | 87 ++++++++++++++++++++++++++++++++++++++++
2 files changed, 147 insertions(+), 2 deletions(-)
diff --git a/gst-libs/gst/app/gstappsink.c b/gst-libs/gst/app/gstappsink.c
index 8f64aba..07a3989 100644
--- a/gst-libs/gst/app/gstappsink.c
+++ b/gst-libs/gst/app/gstappsink.c
@@ -111,6 +111,8 @@ struct _GstAppSinkPrivate
GstAppSinkCallbacks callbacks;
gpointer user_data;
GDestroyNotify notify;
+
+ gboolean buffer_lists_supported;
};
GST_DEBUG_CATEGORY_STATIC (app_sink_debug);
@@ -623,6 +625,21 @@ gst_app_sink_flush_unlocked (GstAppSink * appsink)
g_cond_signal (priv->cond);
}
+#define NEW_BUFFER_LIST_SIGID \
+ gst_app_sink_signals[SIGNAL_NEW_BUFFER_LIST]
+
+static gboolean
+gst_app_sink_check_buffer_lists_support (GstAppSink * appsink)
+{
+ gboolean ret;
+
+ ret = (appsink->priv->callbacks.new_buffer_list != NULL) ||
+ g_signal_has_handler_pending (appsink, NEW_BUFFER_LIST_SIGID, 0, FALSE);
+
+ GST_INFO_OBJECT (appsink, "application supports buffer lists: %d", ret);
+ return ret;
+}
+
static gboolean
gst_app_sink_start (GstBaseSink * psink)
{
@@ -633,6 +650,8 @@ gst_app_sink_start (GstBaseSink * psink)
GST_DEBUG_OBJECT (appsink, "starting");
priv->flushing = FALSE;
priv->started = TRUE;
+ priv->buffer_lists_supported =
+ gst_app_sink_check_buffer_lists_support (appsink);
g_mutex_unlock (priv->mutex);
return TRUE;
@@ -812,9 +831,46 @@ gst_app_sink_render (GstBaseSink * psink, GstBuffer * buffer)
}
static GstFlowReturn
-gst_app_sink_render_list (GstBaseSink * psink, GstBufferList * list)
+gst_app_sink_render_list (GstBaseSink * sink, GstBufferList * list)
{
- return gst_app_sink_render_common (psink, GST_MINI_OBJECT_CAST (list), TRUE);
+ GstBufferListIterator *it;
+ GstFlowReturn flow;
+ GstAppSink *appsink;
+ GstBuffer *group;
+
+ appsink = GST_APP_SINK_CAST (sink);
+
+ if (appsink->priv->buffer_lists_supported)
+ return gst_app_sink_render_common (sink, GST_MINI_OBJECT_CAST (list), TRUE);
+
+ /* The application doesn't support buffer lists, extract individual buffers
+ * then and push them one-by-one */
+ GST_INFO_OBJECT (sink, "chaining each group in list as a merged buffer");
+
+ 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_DEBUG_OBJECT (sink, "chaining empty group");
+ } else {
+ GST_DEBUG_OBJECT (sink, "chaining group");
+ }
+ flow = gst_app_sink_render (sink, group);
+ gst_buffer_unref (group);
+ } while (flow == GST_FLOW_OK && gst_buffer_list_iterator_next_group (it));
+ } else {
+ GST_DEBUG_OBJECT (sink, "chaining empty group");
+ group = gst_buffer_new ();
+ flow = gst_app_sink_render (sink, group);
+ gst_buffer_unref (group);
+ }
+
+ gst_buffer_list_iterator_free (it);
+
+ return flow;
}
static GstCaps *
@@ -1335,6 +1391,8 @@ gst_app_sink_set_callbacks (GstAppSink * appsink,
priv->callbacks = *callbacks;
priv->user_data = user_data;
priv->notify = notify;
+ priv->buffer_lists_supported =
+ gst_app_sink_check_buffer_lists_support (appsink);
GST_OBJECT_UNLOCK (appsink);
}
diff --git a/tests/check/elements/appsink.c b/tests/check/elements/appsink.c
index 3d03439..34982ef 100644
--- a/tests/check/elements/appsink.c
+++ b/tests/check/elements/appsink.c
@@ -317,6 +317,91 @@ GST_START_TEST (test_buffer_list)
GST_END_TEST;
+static GstFlowReturn
+callback_function_buffer (GstAppSink * appsink, gpointer p_counter)
+{
+ GstBuffer *buf;
+ gint *p_int_counter = p_counter;
+
+ buf = gst_app_sink_pull_buffer (appsink);
+ fail_unless (GST_IS_BUFFER (buf));
+
+ /* buffer list has 3 buffers in two groups */
+ switch (*p_int_counter) {
+ case 0:
+ fail_unless_equals_int (GST_BUFFER_SIZE (buf), sizeof (gint));
+ fail_unless_equals_int ((((gint *) GST_BUFFER_DATA (buf))[0]), 1);
+ break;
+ case 1:
+ fail_unless_equals_int (GST_BUFFER_SIZE (buf), 2 * sizeof (gint));
+ fail_unless_equals_int ((((gint *) GST_BUFFER_DATA (buf))[0]), 2);
+ fail_unless_equals_int ((((gint *) GST_BUFFER_DATA (buf))[1]), 4);
+ break;
+ default:
+ g_warn_if_reached ();
+ break;
+ }
+
+ gst_buffer_unref (buf);
+
+ *p_int_counter += 1;
+
+ return GST_FLOW_OK;
+}
+
+GST_START_TEST (test_buffer_list_fallback)
+{
+ GstElement *sink;
+ GstBufferList *list;
+ GstAppSinkCallbacks callbacks = { NULL };
+ gint counter = 0;
+
+ sink = setup_appsink ();
+
+ callbacks.new_buffer = callback_function_buffer;
+
+ gst_app_sink_set_callbacks (GST_APP_SINK (sink), &callbacks, &counter, NULL);
+
+ ASSERT_SET_STATE (sink, GST_STATE_PLAYING, GST_STATE_CHANGE_ASYNC);
+
+ list = create_buffer_list ();
+ fail_unless (gst_pad_push_list (mysrcpad, list) == GST_FLOW_OK);
+
+ fail_unless_equals_int (counter, 2);
+
+ ASSERT_SET_STATE (sink, GST_STATE_NULL, GST_STATE_CHANGE_SUCCESS);
+ cleanup_appsink (sink);
+}
+
+GST_END_TEST;
+
+GST_START_TEST (test_buffer_list_fallback_signal)
+{
+ GstElement *sink;
+ GstBufferList *list;
+ gint counter = 0;
+
+ sink = setup_appsink ();
+
+ /* C calling convention to the rescue.. */
+ g_signal_connect (sink, "new-buffer", G_CALLBACK (callback_function_buffer),
+ &counter);
+
+ g_object_set (sink, "emit-signals", TRUE, NULL);
+
+ ASSERT_SET_STATE (sink, GST_STATE_PLAYING, GST_STATE_CHANGE_ASYNC);
+
+ list = create_buffer_list ();
+ fail_unless (gst_pad_push_list (mysrcpad, list) == GST_FLOW_OK);
+
+ fail_unless_equals_int (counter, 2);
+
+ ASSERT_SET_STATE (sink, GST_STATE_NULL, GST_STATE_CHANGE_SUCCESS);
+ cleanup_appsink (sink);
+}
+
+GST_END_TEST;
+
static Suite *
appsink_suite (void)
{
@@ -329,6 +414,8 @@ appsink_suite (void)
tcase_add_test (tc_chain, test_notify0);
tcase_add_test (tc_chain, test_notify1);
tcase_add_test (tc_chain, test_buffer_list);
+ tcase_add_test (tc_chain, test_buffer_list_fallback);
+ tcase_add_test (tc_chain, test_buffer_list_fallback_signal);
return s;
}
------------------------------------------------------------------------------
Special Offer-- Download ArcSight Logger for FREE (a $49 USD value)!
Finally, a world-class log management solution at an even better price-free!
Download using promo code Free_Logger_4_Dev2Dev. Offer expires
February 28th, so secure your free ArcSight Logger TODAY!
http://p.sf.net/sfu/arcsight-sfd2d
_______________________________________________
gstreamer-cvs mailing list
gstreamer-cvs@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/gstreamer-cvs
[prev in list] [next in list] [prev in thread] [next in thread]
Configure |
About |
News |
Add a list |
Sponsored by KoreLogic