From 24b523e129d55c8ace7afdfffa341909431082e9 Mon Sep 17 00:00:00 2001 From: Thiago Santos Date: Wed, 22 Sep 2010 14:10:18 -0300 Subject: appsrc: Do not override buffer caps if appsrc caps is null Make appsrc not set caps on buffers when its own caps is NULL. This avoids calling make_metadata_writable on all buffers and prevents losing buffer caps in case we are not replacing it with something meaningful. https://bugzilla.gnome.org/show_bug.cgi?id=630353 --- gst-libs/gst/app/gstappsrc.c | 6 +- tests/check/Makefile.am | 9 ++ tests/check/elements/appsrc.c | 188 ++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 201 insertions(+), 2 deletions(-) create mode 100644 tests/check/elements/appsrc.c diff --git a/gst-libs/gst/app/gstappsrc.c b/gst-libs/gst/app/gstappsrc.c index 90f07c3aa..b5baefa2f 100644 --- a/gst-libs/gst/app/gstappsrc.c +++ b/gst-libs/gst/app/gstappsrc.c @@ -996,8 +996,10 @@ gst_app_src_create (GstBaseSrc * bsrc, guint64 offset, guint size, /* only update the offset when in random_access mode */ if (priv->stream_type == GST_APP_STREAM_TYPE_RANDOM_ACCESS) priv->offset += buf_size; - *buf = gst_buffer_make_metadata_writable (*buf); - gst_buffer_set_caps (*buf, caps); + if (caps) { + *buf = gst_buffer_make_metadata_writable (*buf); + gst_buffer_set_caps (*buf, caps); + } /* signal that we removed an item */ g_cond_broadcast (priv->cond); diff --git a/tests/check/Makefile.am b/tests/check/Makefile.am index df3031ec1..c605275e7 100644 --- a/tests/check/Makefile.am +++ b/tests/check/Makefile.am @@ -99,6 +99,7 @@ check_PROGRAMS = \ $(check_theora) \ elements/adder \ elements/appsink \ + elements/appsrc \ elements/audioconvert \ elements/audiorate \ elements/audioresample \ @@ -242,6 +243,14 @@ elements_appsink_LDADD = \ $(top_builddir)/gst-libs/gst/app/libgstapp-@GST_MAJORMINOR@.la \ $(LDADD) +elements_appsrc_CFLAGS = \ + $(GST_PLUGINS_BASE_CFLAGS) \ + $(AM_CFLAGS) + +elements_appsrc_LDADD = \ + $(top_builddir)/gst-libs/gst/app/libgstapp-@GST_MAJORMINOR@.la \ + $(LDADD) + elements_alsa_CFLAGS = \ $(GST_PLUGINS_BASE_CFLAGS) \ $(AM_CFLAGS) diff --git a/tests/check/elements/appsrc.c b/tests/check/elements/appsrc.c new file mode 100644 index 000000000..b888f4802 --- /dev/null +++ b/tests/check/elements/appsrc.c @@ -0,0 +1,188 @@ +/* GStreamer + * + * Copyright (C) 2010, Thiago Santos + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#include +#include + +#define SAMPLE_CAPS "application/x-gst-check-test" + +static GstPad *mysinkpad; + +static GstStaticPadTemplate sinktemplate = GST_STATIC_PAD_TEMPLATE ("sink", + GST_PAD_SINK, + GST_PAD_ALWAYS, + GST_STATIC_CAPS_ANY); + +static GstElement * +setup_appsrc (void) +{ + GstElement *appsrc; + + GST_DEBUG ("setup_appsrc"); + appsrc = gst_check_setup_element ("appsrc"); + mysinkpad = gst_check_setup_sink_pad (appsrc, &sinktemplate, NULL); + + gst_pad_set_active (mysinkpad, TRUE); + + return appsrc; +} + +static void +cleanup_appsrc (GstElement * appsrc) +{ + GST_DEBUG ("cleanup_appsrc"); + + gst_check_teardown_sink_pad (appsrc); + gst_check_teardown_element (appsrc); +} + + +/* + * Pushes 4 buffers into appsrc and checks the caps on them on the output. + * + * Appsrc is configured with caps=null, so the buffers should have the + * same caps that they were pushed with. + * + * The 4 buffers have NULL, SAMPLE_CAPS, NULL, SAMPLE_CAPS caps, + * respectively. + */ +GST_START_TEST (test_appsrc_null_caps) +{ + GstElement *src; + GstBuffer *buffer; + GList *iter; + GstCaps *caps; + + src = setup_appsrc (); + + g_object_set (src, "caps", NULL, NULL); + caps = gst_caps_from_string (SAMPLE_CAPS); + + ASSERT_SET_STATE (src, GST_STATE_PLAYING, GST_STATE_CHANGE_SUCCESS); + + buffer = gst_buffer_new_and_alloc (4); + fail_unless (gst_app_src_push_buffer (GST_APP_SRC (src), + buffer) == GST_FLOW_OK); + + buffer = gst_buffer_new_and_alloc (4); + gst_buffer_set_caps (buffer, caps); + fail_unless (gst_app_src_push_buffer (GST_APP_SRC (src), + buffer) == GST_FLOW_OK); + + fail_unless (gst_app_src_end_of_stream (GST_APP_SRC (src)) == GST_FLOW_OK); + + /* Give some time to the appsrc loop to push the buffers */ + g_usleep (G_USEC_PER_SEC * 3); + + /* Check the output caps */ + fail_unless (g_list_length (buffers) == 2); + iter = buffers; + buffer = (GstBuffer *) iter->data; + fail_unless (GST_BUFFER_CAPS (buffer) == NULL); + + iter = g_list_next (iter); + buffer = (GstBuffer *) iter->data; + fail_unless (gst_caps_is_equal (GST_BUFFER_CAPS (buffer), caps)); + + ASSERT_SET_STATE (src, GST_STATE_NULL, GST_STATE_CHANGE_SUCCESS); + gst_caps_unref (caps); + cleanup_appsrc (src); +} + +GST_END_TEST; + + +/* + * Pushes 4 buffers into appsrc and checks the caps on them on the output. + * + * Appsrc is configured with caps=SAMPLE_CAPS, so the buffers should have the + * same caps that they were pushed with. + * + * The 4 buffers have NULL, SAMPLE_CAPS, NULL, SAMPLE_CAPS caps, + * respectively. + */ +GST_START_TEST (test_appsrc_non_null_caps) +{ + GstElement *src; + GstBuffer *buffer; + GList *iter; + GstCaps *caps; + + src = setup_appsrc (); + + caps = gst_caps_from_string (SAMPLE_CAPS); + g_object_set (src, "caps", caps, NULL); + + ASSERT_SET_STATE (src, GST_STATE_PLAYING, GST_STATE_CHANGE_SUCCESS); + + buffer = gst_buffer_new_and_alloc (4); + fail_unless (gst_app_src_push_buffer (GST_APP_SRC (src), + buffer) == GST_FLOW_OK); + + buffer = gst_buffer_new_and_alloc (4); + gst_buffer_set_caps (buffer, caps); + fail_unless (gst_app_src_push_buffer (GST_APP_SRC (src), + buffer) == GST_FLOW_OK); + + buffer = gst_buffer_new_and_alloc (4); + fail_unless (gst_app_src_push_buffer (GST_APP_SRC (src), + buffer) == GST_FLOW_OK); + + buffer = gst_buffer_new_and_alloc (4); + gst_buffer_set_caps (buffer, caps); + fail_unless (gst_app_src_push_buffer (GST_APP_SRC (src), + buffer) == GST_FLOW_OK); + + fail_unless (gst_app_src_end_of_stream (GST_APP_SRC (src)) == GST_FLOW_OK); + + /* Give some time to the appsrc loop to push the buffers */ + g_usleep (G_USEC_PER_SEC * 3); + + /* Check the output caps */ + fail_unless (g_list_length (buffers) == 4); + for (iter = buffers; iter; iter = g_list_next (iter)) { + GstBuffer *buf = (GstBuffer *) iter->data; + + fail_unless (gst_caps_is_equal (GST_BUFFER_CAPS (buf), caps)); + } + + ASSERT_SET_STATE (src, GST_STATE_NULL, GST_STATE_CHANGE_SUCCESS); + gst_caps_unref (caps); + cleanup_appsrc (src); +} + +GST_END_TEST; + + +static Suite * +appsrc_suite (void) +{ + Suite *s = suite_create ("appsrc"); + TCase *tc_chain = tcase_create ("general"); + + tcase_add_test (tc_chain, test_appsrc_null_caps); + tcase_add_test (tc_chain, test_appsrc_non_null_caps); + + suite_add_tcase (s, tc_chain); + + return s; +} + +GST_CHECK_MAIN (appsrc); -- cgit v1.2.3