summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorNirbheek Chauhan <nirbheek@centricular.com>2015-03-13 00:40:52 (GMT)
committerTim-Philipp Müller <tim@centricular.com>2015-05-01 10:57:00 (GMT)
commit105a5cce923caa6e4454c2e1fc077614c598c108 (patch)
treefb6313f11dd57d832e7e2d7b81ad957dab70c58b
parent1c60de8ad73b134df44fc30b45fdee87e28ccacc (diff)
downloadgst-plugins-bad-105a5cce923caa6e4454c2e1fc077614c598c108.tar.gz
gst-plugins-bad-105a5cce923caa6e4454c2e1fc077614c598c108.tar.xz
tests: Add a check for the new compositor pad-is-obscured optimization
We verify that all the buffers on an obscured sinkpad are skipped by overriding the map() function in the GstVideoMeta of the buffers to set a variable when called. We also test that the buffers do get mapped when they're not obscured. Blame^WCredit for the GstVideoMeta map() idea goes to Tim. https://bugzilla.gnome.org/show_bug.cgi?id=746147
-rw-r--r--tests/check/Makefile.am8
-rw-r--r--tests/check/elements/compositor.c209
2 files changed, 215 insertions, 2 deletions
diff --git a/tests/check/Makefile.am b/tests/check/Makefile.am
index ddd74f9..04e5d5d 100644
--- a/tests/check/Makefile.am
+++ b/tests/check/Makefile.am
@@ -517,8 +517,12 @@ libs_aggregator_CFLAGS = \
-DGST_USE_UNSTABLE_API \
$(GST_BASE_CFLAGS) $(GST_CFLAGS) $(AM_CFLAGS)
-elements_compositor_LDADD = $(LDADD) $(GST_BASE_LIBS)
-elements_compositor_CFLAGS = $(GST_BASE_CFLAGS) $(CFLAGS) $(AM_CFLAGS)
+elements_compositor_LDADD = \
+ $(GST_PLUGINS_BASE_LIBS) -lgstvideo-$(GST_API_VERSION) \
+ $(GST_BASE_LIBS) $(LDADD)
+elements_compositor_CFLAGS = \
+ $(GST_PLUGINS_BASE_CFLAGS) \
+ $(GST_BASE_CFLAGS) $(CFLAGS) $(AM_CFLAGS)
elements_hlsdemux_m3u8_CFLAGS = $(GST_BASE_CFLAGS) $(AM_CFLAGS) -I$(top_srcdir)/ext/hls
elements_hlsdemux_m3u8_LDADD = $(GST_BASE_LIBS) $(LDADD)
diff --git a/tests/check/elements/compositor.c b/tests/check/elements/compositor.c
index dab259b..4ff890b 100644
--- a/tests/check/elements/compositor.c
+++ b/tests/check/elements/compositor.c
@@ -33,6 +33,7 @@
#include <gst/check/gstcheck.h>
#include <gst/check/gstconsistencychecker.h>
+#include <gst/video/gstvideometa.h>
#include <gst/base/gstbasesrc.h>
#define VIDEO_CAPS_STRING \
@@ -1096,6 +1097,213 @@ GST_START_TEST (test_segment_base_handling)
GST_END_TEST;
+static gboolean buffer_mapped;
+static gboolean (*default_map) (GstVideoMeta * meta, guint plane,
+ GstMapInfo * info, gpointer * data, gint * stride, GstMapFlags flags);
+
+static gboolean
+test_obscured_new_videometa_map (GstVideoMeta * meta, guint plane,
+ GstMapInfo * info, gpointer * data, gint * stride, GstMapFlags flags)
+{
+ buffer_mapped = TRUE;
+ return default_map (meta, plane, info, data, stride, flags);
+}
+
+static GstPadProbeReturn
+test_obscured_pad_probe_cb (GstPad * srcpad, GstPadProbeInfo * info,
+ gpointer user_data)
+{
+ GstBuffer *obuf, *nbuf;
+ GstVideoMeta *meta;
+
+ GST_DEBUG ("pad probe called");
+ /* We need to deep-copy the buffer here because videotestsrc reuses buffers
+ * and hence the GstVideoMap associated with the buffers, and that causes a
+ * segfault inside videotestsrc when it tries to reuse the buffer */
+ obuf = GST_PAD_PROBE_INFO_BUFFER (info);
+ nbuf = gst_buffer_new ();
+ gst_buffer_copy_into (nbuf, obuf, GST_BUFFER_COPY_ALL | GST_BUFFER_COPY_DEEP,
+ 0, -1);
+ meta = gst_buffer_get_video_meta (nbuf);
+ /* Override the default map() function to set also buffer_mapped */
+ default_map = meta->map;
+ meta->map = test_obscured_new_videometa_map;
+ /* Replace the buffer that's going downstream */
+ GST_PAD_PROBE_INFO_DATA (info) = nbuf;
+ gst_buffer_unref (obuf);
+
+ return GST_PAD_PROBE_PASS;
+}
+
+static void
+_test_obscured (const gchar * caps_str, gint xpos0, gint ypos0, gint width0,
+ gint height0, gdouble alpha0, gint xpos1, gint ypos1, gint width1,
+ gint height1, gdouble alpha1)
+{
+ GstElement *pipeline, *sink, *mix, *src0, *cfilter0, *src1, *cfilter1;
+ GstPad *srcpad, *sinkpad;
+ GstSample *last_sample = NULL;
+ GstSample *sample;
+ GstCaps *caps;
+
+ GST_INFO ("preparing test");
+
+ pipeline = gst_pipeline_new ("pipeline");
+ src0 = gst_element_factory_make ("videotestsrc", "src0");
+ g_object_set (src0, "num-buffers", 5, NULL);
+ cfilter0 = gst_element_factory_make ("capsfilter", "capsfilter0");
+ caps = gst_caps_from_string (caps_str);
+ g_object_set (cfilter0, "caps", caps, NULL);
+ gst_caps_unref (caps);
+
+ src1 = gst_element_factory_make ("videotestsrc", "src1");
+ g_object_set (src1, "num-buffers", 5, NULL);
+ cfilter1 = gst_element_factory_make ("capsfilter", "capsfilter1");
+ caps = gst_caps_from_string (caps_str);
+ g_object_set (cfilter1, "caps", caps, NULL);
+ gst_caps_unref (caps);
+
+ mix = gst_element_factory_make ("compositor", "compositor");
+ sink = gst_element_factory_make ("appsink", "sink");
+ gst_bin_add_many (GST_BIN (pipeline), src0, cfilter0, src1, cfilter1, mix,
+ sink, NULL);
+ fail_unless (gst_element_link (src0, cfilter0));
+ fail_unless (gst_element_link (src1, cfilter1));
+ fail_unless (gst_element_link (mix, sink));
+
+ srcpad = gst_element_get_static_pad (cfilter0, "src");
+ sinkpad = gst_element_get_request_pad (mix, "sink_0");
+ g_object_set (sinkpad, "xpos", xpos0, "ypos", ypos0, "width", width0,
+ "height", height0, "alpha", alpha0, NULL);
+ fail_unless (gst_pad_link (srcpad, sinkpad) == GST_PAD_LINK_OK);
+ gst_pad_add_probe (srcpad, GST_PAD_PROBE_TYPE_BUFFER,
+ test_obscured_pad_probe_cb, NULL, NULL);
+ gst_object_unref (sinkpad);
+ gst_object_unref (srcpad);
+
+ srcpad = gst_element_get_static_pad (cfilter1, "src");
+ sinkpad = gst_element_get_request_pad (mix, "sink_1");
+ g_object_set (sinkpad, "xpos", xpos1, "ypos", ypos1, "width", width1,
+ "height", height1, "alpha", alpha1, NULL);
+ fail_unless (gst_pad_link (srcpad, sinkpad) == GST_PAD_LINK_OK);
+ gst_object_unref (sinkpad);
+ gst_object_unref (srcpad);
+
+ GST_INFO ("sample prepared");
+ gst_element_set_state (pipeline, GST_STATE_PLAYING);
+
+ do {
+ GST_DEBUG ("sample pulling");
+ g_signal_emit_by_name (sink, "pull-sample", &sample);
+ if (sample == NULL)
+ break;
+ if (last_sample)
+ gst_sample_unref (last_sample);
+ last_sample = sample;
+ GST_DEBUG ("sample pulled");
+ } while (TRUE);
+ gst_sample_unref (last_sample);
+
+ gst_element_set_state (pipeline, GST_STATE_NULL);
+ gst_object_unref (pipeline);
+}
+
+GST_START_TEST (test_obscured_skipped)
+{
+ gint xpos0, xpos1;
+ gint ypos0, ypos1;
+ gint width0, width1;
+ gint height0, height1;
+ gdouble alpha0, alpha1;
+ const gchar *caps_str;
+
+ caps_str = "video/x-raw";
+ buffer_mapped = FALSE;
+ /* Set else to compositor defaults */
+ alpha0 = alpha1 = 1.0;
+ xpos0 = xpos1 = ypos0 = ypos1 = 0;
+ width0 = width1 = height0 = height1 = 0;
+
+ GST_INFO ("testing defaults");
+ /* With everything at defaults, sink_1 will obscure sink_0, so buffers from
+ * sink_0 will never get mapped by compositor. To verify, run with
+ * GST_DEBUG=compositor:6 and look for "Obscured by" messages */
+ _test_obscured (caps_str, xpos0, ypos0, width0, height0, alpha0, xpos1, ypos1,
+ width1, height1, alpha1);
+ fail_unless (buffer_mapped == FALSE);
+ buffer_mapped = FALSE;
+
+ caps_str = "video/x-raw,format=ARGB";
+ GST_INFO ("testing video with alpha channel");
+ _test_obscured (caps_str, xpos0, ypos0, width0, height0, alpha0, xpos1, ypos1,
+ width1, height1, alpha1);
+ fail_unless (buffer_mapped == TRUE);
+ caps_str = "video/x-raw";
+ buffer_mapped = FALSE;
+
+ alpha1 = 0.0;
+ GST_INFO ("testing alpha1 = %.2g", alpha1);
+ _test_obscured (caps_str, xpos0, ypos0, width0, height0, alpha0, xpos1, ypos1,
+ width1, height1, alpha1);
+ fail_unless (buffer_mapped == TRUE);
+ alpha1 = 1.0;
+ buffer_mapped = FALSE;
+
+ /* Test 0.1, ..., 0.9 */
+ for (alpha1 = 1; alpha1 < 10; alpha1 += 1) {
+ GST_INFO ("testing alpha1 = %.2g", alpha1 / 10);
+ _test_obscured (caps_str, xpos0, ypos0, width0, height0, alpha0, xpos1,
+ ypos1, width1, height1, alpha1 / 10);
+ fail_unless (buffer_mapped == TRUE);
+ }
+ alpha1 = 1.0;
+ buffer_mapped = FALSE;
+
+ width1 = height1 = 10;
+ GST_INFO ("testing smaller sink_1");
+ _test_obscured (caps_str, xpos0, ypos0, width0, height0, alpha0, xpos1, ypos1,
+ width1, height1, alpha1);
+ fail_unless (buffer_mapped == TRUE);
+ width1 = height1 = 0;
+ buffer_mapped = FALSE;
+
+ width0 = height0 = width1 = height1 = 10;
+ GST_INFO ("testing smaller sink_1 and sink0 (same sizes)");
+ _test_obscured (caps_str, xpos0, ypos0, width0, height0, alpha0, xpos1, ypos1,
+ width1, height1, alpha1);
+ fail_unless (buffer_mapped == FALSE);
+ width0 = height0 = width1 = height1 = 0;
+ buffer_mapped = FALSE;
+
+ width0 = height0 = 20;
+ width1 = height1 = 10;
+ GST_INFO ("testing smaller sink_1 and sink0 (sink_0 > sink_1)");
+ _test_obscured (caps_str, xpos0, ypos0, width0, height0, alpha0, xpos1, ypos1,
+ width1, height1, alpha1);
+ fail_unless (buffer_mapped == TRUE);
+ width0 = height0 = width1 = height1 = 0;
+ buffer_mapped = FALSE;
+
+ width0 = height0 = 10;
+ width1 = height1 = 20;
+ GST_INFO ("testing smaller sink_1 and sink0 (sink_0 < sink_1)");
+ _test_obscured (caps_str, xpos0, ypos0, width0, height0, alpha0, xpos1, ypos1,
+ width1, height1, alpha1);
+ fail_unless (buffer_mapped == FALSE);
+ width0 = height0 = width1 = height1 = 0;
+ buffer_mapped = FALSE;
+
+ xpos0 = ypos0 = 10000;
+ GST_INFO ("testing sink_0 outside the frame");
+ _test_obscured (caps_str, xpos0, ypos0, width0, height0, alpha0, xpos1, ypos1,
+ width1, height1, alpha1);
+ fail_unless (buffer_mapped == FALSE);
+ xpos0 = ypos0 = 0;
+ buffer_mapped = FALSE;
+}
+
+GST_END_TEST;
+
static Suite *
compositor_suite (void)
{
@@ -1115,6 +1323,7 @@ compositor_suite (void)
tcase_add_test (tc_chain, test_loop);
tcase_add_test (tc_chain, test_flush_start_flush_stop);
tcase_add_test (tc_chain, test_segment_base_handling);
+ tcase_add_test (tc_chain, test_obscured_skipped);
/* Use a longer timeout */
#ifdef HAVE_VALGRIND