summaryrefslogtreecommitdiff
path: root/tests
diff options
context:
space:
mode:
authorThiago Santos <thiagoss@osg.samsung.com>2016-02-18 10:57:51 -0300
committerThiago Santos <thiagoss@osg.samsung.com>2016-02-25 11:43:43 -0300
commitf231598370ebc4364d16eab1c7e3dbdd7001668a (patch)
tree908895200f10c1a220be553fd9191c8c667a1fbf /tests
parent924795c85c319ea1accf00ee97ac14aeecaf375e (diff)
downloadgstreamer-plugins-bad-f231598370ebc4364d16eab1c7e3dbdd7001668a.tar.gz
videoaggregator: fix caps queries to allow proper renegotiation
When caps are already negotiated it should be possible to select formats other than the one that was negotiated. If downstream allows alpha video caps and it has already negotiated to a non-alpha format, caps queries should still return the alpha caps as a possible format as caps renegotiation can happen. Includes tests (for compositor) to check that caps queries done after a caps has been negotiated returns complete results https://bugzilla.gnome.org/show_bug.cgi?id=757610
Diffstat (limited to 'tests')
-rw-r--r--tests/check/elements/compositor.c211
1 files changed, 211 insertions, 0 deletions
diff --git a/tests/check/elements/compositor.c b/tests/check/elements/compositor.c
index 77c65cfed..cf50e1532 100644
--- a/tests/check/elements/compositor.c
+++ b/tests/check/elements/compositor.c
@@ -245,6 +245,216 @@ GST_START_TEST (test_event)
GST_END_TEST;
+static GstBuffer *
+create_video_buffer (GstCaps * caps, gint ts_in_seconds)
+{
+ GstVideoInfo info;
+ guint size;
+ GstBuffer *buf;
+ GstMapInfo mapinfo;
+
+ fail_unless (gst_video_info_from_caps (&info, caps));
+
+ size = GST_VIDEO_INFO_WIDTH (&info) * GST_VIDEO_INFO_HEIGHT (&info);
+
+ switch (GST_VIDEO_INFO_FORMAT (&info)) {
+ case GST_VIDEO_FORMAT_RGB:
+ size *= 3;
+ break;
+ case GST_VIDEO_FORMAT_RGBA:
+ case GST_VIDEO_FORMAT_ARGB:
+ size *= 4;
+ break;
+ case GST_VIDEO_FORMAT_I420:
+ size *= 2;
+ break;
+ default:
+ fail ("Unsupported test format");
+ }
+
+ buf = gst_buffer_new_and_alloc (size);
+ /* write something to avoid uninitialized error issues (valgrind) */
+ gst_buffer_map (buf, &mapinfo, GST_MAP_WRITE);
+ memset (mapinfo.data, 0, mapinfo.size);
+ gst_buffer_unmap (buf, &mapinfo);
+
+ GST_BUFFER_PTS (buf) = ts_in_seconds * GST_SECOND;
+ GST_BUFFER_DURATION (buf) = GST_SECOND;
+ return buf;
+}
+
+#define MODE_ALL 1
+#define MODE_NON_ALPHA 2
+
+/* mostly copied from videoaggregator */
+static inline GstCaps *
+_get_non_alpha_caps_from_caps (GstCaps * caps)
+{
+ GstCaps *result;
+ guint i, size;
+
+ size = gst_caps_get_size (caps);
+ result = gst_caps_new_empty ();
+ for (i = 0; i < size; i++) {
+ GstStructure *s = gst_caps_get_structure (caps, i);
+ const GValue *formats = gst_structure_get_value (s, "format");
+ GValue new_formats = { 0, };
+ gboolean has_format = FALSE;
+
+ /* FIXME what to do if formats are missing? */
+ if (formats) {
+ const GstVideoFormatInfo *info;
+
+ if (GST_VALUE_HOLDS_LIST (formats)) {
+ guint list_size = gst_value_list_get_size (formats);
+ guint index;
+
+ g_value_init (&new_formats, GST_TYPE_LIST);
+
+ for (index = 0; index < list_size; index++) {
+ const GValue *list_item = gst_value_list_get_value (formats, index);
+
+ info =
+ gst_video_format_get_info (gst_video_format_from_string
+ (g_value_get_string (list_item)));
+ if (!GST_VIDEO_FORMAT_INFO_HAS_ALPHA (info)) {
+ has_format = TRUE;
+ gst_value_list_append_value (&new_formats, list_item);
+ }
+ }
+
+ } else if (G_VALUE_HOLDS_STRING (formats)) {
+ info =
+ gst_video_format_get_info (gst_video_format_from_string
+ (g_value_get_string (formats)));
+ if (!GST_VIDEO_FORMAT_INFO_HAS_ALPHA (info)) {
+ has_format = TRUE;
+ gst_value_init_and_copy (&new_formats, formats);
+ }
+
+ } else {
+ g_assert_not_reached ();
+ GST_WARNING ("Unexpected type for video 'format' field: %s",
+ G_VALUE_TYPE_NAME (formats));
+ }
+
+ if (has_format) {
+ s = gst_structure_copy (s);
+ gst_structure_take_value (s, "format", &new_formats);
+ gst_caps_append_structure (result, s);
+ }
+
+ }
+ }
+
+ return result;
+}
+
+static void
+run_late_caps_query_test (GstCaps * input_caps, GstCaps * output_allowed_caps,
+ gint expected_caps_mode)
+{
+ GstElement *compositor, *capsfilter, *sink;
+ GstElement *pipeline;
+ gboolean res;
+ GstStateChangeReturn state_res;
+ GstPad *srcpad1, *srcpad2;
+ GstPad *sinkpad1, *sinkpad2;
+ GstSegment segment;
+ GstCaps *caps, *all_caps, *non_alpha_caps;
+
+ all_caps =
+ gst_caps_from_string (GST_VIDEO_CAPS_MAKE
+ (" { AYUV, BGRA, ARGB, RGBA, ABGR, Y444, Y42B, YUY2, UYVY, "
+ " YVYU, I420, YV12, NV12, NV21, Y41B, RGB, BGR, xRGB, xBGR, "
+ " RGBx, BGRx } "));
+ non_alpha_caps =
+ gst_caps_from_string (GST_VIDEO_CAPS_MAKE
+ (" { Y444, Y42B, YUY2, UYVY, "
+ " YVYU, I420, YV12, NV12, NV21, Y41B, RGB, BGR, xRGB, xBGR, "
+ " RGBx, BGRx } "));
+
+ compositor = gst_element_factory_make ("compositor", "compositor");
+ capsfilter = gst_element_factory_make ("capsfilter", "out-cf");
+ sink = gst_element_factory_make ("fakesink", "sink");
+ pipeline = gst_pipeline_new ("test-pipeline");
+
+ gst_bin_add_many (GST_BIN (pipeline), compositor, capsfilter, sink, NULL);
+ res = gst_element_link (compositor, capsfilter);
+ fail_unless (res == TRUE, NULL);
+ res = gst_element_link (capsfilter, sink);
+ fail_unless (res == TRUE, NULL);
+
+ sinkpad1 = gst_element_get_request_pad (compositor, "sink_%u");
+ srcpad1 = gst_pad_new ("src1", GST_PAD_SRC);
+ fail_unless (gst_pad_link (srcpad1, sinkpad1) == GST_PAD_LINK_OK);
+ gst_pad_set_active (srcpad1, TRUE);
+
+ state_res = gst_element_set_state (pipeline, GST_STATE_PLAYING);
+ fail_if (state_res == GST_STATE_CHANGE_FAILURE);
+
+ if (output_allowed_caps)
+ g_object_set (capsfilter, "caps", output_allowed_caps, NULL);
+
+ gst_segment_init (&segment, GST_FORMAT_TIME);
+ fail_unless (gst_pad_push_event (srcpad1,
+ gst_event_new_stream_start ("test-1")));
+ fail_unless (gst_pad_push_event (srcpad1, gst_event_new_caps (input_caps)));
+ fail_unless (gst_pad_push_event (srcpad1, gst_event_new_segment (&segment)));
+ fail_unless (gst_pad_push (srcpad1,
+ create_video_buffer (input_caps, 0)) == GST_FLOW_OK);
+ fail_unless (gst_pad_push (srcpad1,
+ create_video_buffer (input_caps, 1)) == GST_FLOW_OK);
+
+ /* now comes the second pad */
+ sinkpad2 = gst_element_get_request_pad (compositor, "sink_%u");
+ srcpad2 = gst_pad_new ("src2", GST_PAD_SRC);
+ fail_unless (gst_pad_link (srcpad2, sinkpad2) == GST_PAD_LINK_OK);
+ gst_pad_set_active (srcpad2, TRUE);
+ fail_unless (gst_pad_push_event (srcpad2,
+ gst_event_new_stream_start ("test-2")));
+
+ caps = gst_pad_peer_query_caps (srcpad2, NULL);
+ fail_unless (gst_caps_is_equal (caps,
+ expected_caps_mode == MODE_ALL ? all_caps : non_alpha_caps));
+ gst_caps_unref (caps);
+
+ gst_pad_set_active (srcpad1, FALSE);
+ gst_pad_set_active (srcpad2, FALSE);
+ gst_element_set_state (pipeline, GST_STATE_NULL);
+ gst_element_release_request_pad (compositor, sinkpad1);
+ gst_element_release_request_pad (compositor, sinkpad2);
+ gst_object_unref (sinkpad1);
+ gst_object_unref (sinkpad2);
+ gst_object_unref (pipeline);
+ gst_object_unref (srcpad1);
+ gst_object_unref (srcpad2);
+ gst_caps_unref (all_caps);
+ gst_caps_unref (non_alpha_caps);
+}
+
+GST_START_TEST (test_late_caps_query)
+{
+ GstCaps *rgb_caps;
+ GstCaps *non_alpha_caps;
+
+ rgb_caps = gst_caps_from_string ("video/x-raw, format=(string)RGB, "
+ "width=(int)100, height=(int)100, framerate=(fraction)1/1");
+
+ non_alpha_caps = gst_caps_from_string ("video/x-raw, format=(string)RGB");
+
+ /* check that a 2nd pad that is added late to compositor will be able to
+ * negotiate to formats that depend only on downstream caps and not on what
+ * the other pads have already negotiated */
+ run_late_caps_query_test (rgb_caps, NULL, MODE_ALL);
+ run_late_caps_query_test (rgb_caps, non_alpha_caps, MODE_NON_ALPHA);
+
+ gst_caps_unref (non_alpha_caps);
+ gst_caps_unref (rgb_caps);
+}
+
+GST_END_TEST;
+
static guint play_count = 0;
static GstEvent *play_seek_event = NULL;
@@ -1660,6 +1870,7 @@ compositor_suite (void)
suite_add_tcase (s, tc_chain);
tcase_add_test (tc_chain, test_caps);
tcase_add_test (tc_chain, test_event);
+ tcase_add_test (tc_chain, test_late_caps_query);
tcase_add_test (tc_chain, test_play_twice);
tcase_add_test (tc_chain, test_play_twice_then_add_and_play_again);
tcase_add_test (tc_chain, test_add_pad);