tests: add textoverlay passthrough with composition feature unit tests
authorMatthieu Bouron <matthieu.bouron@collabora.com>
Thu, 30 Jan 2014 15:41:49 +0000 (15:41 +0000)
committerSebastian Dröge <sebastian@centricular.com>
Wed, 5 Mar 2014 19:39:01 +0000 (20:39 +0100)
https://bugzilla.gnome.org/show_bug.cgi?id=721953

tests/check/Makefile.am
tests/check/elements/textoverlay.c

index 1d4b7ef8f636dbcbe48e2075614619b5314a056d..5eae29b7348c9f9ba3fcf05350e970ea74a6f944 100644 (file)
@@ -492,7 +492,7 @@ elements_audioresample_LDADD = \
        $(GST_BASE_LIBS) \
        $(LDADD)
 
-elements_textoverlay_LDADD = $(GST_BASE_LIBS) $(LDADD)
+elements_textoverlay_LDADD = $(GST_BASE_LIBS) -lgstvideo-@GST_API_VERSION@ $(LDADD)
 elements_textoverlay_CFLAGS = $(GST_BASE_CFLAGS) $(AM_CFLAGS)
 
 elements_volume_LDADD = \
index c11d5e5ccfaafa2bc8b83d2d15b336485e98726e..7da26a49de74f4a1e63c3f75eb7264b2e852fd3e 100644 (file)
@@ -21,6 +21,7 @@
 #include <unistd.h>
 
 #include <gst/check/gstcheck.h>
+#include <gst/video/video-overlay-composition.h>
 
 #define I420_Y_ROWSTRIDE(width) (GST_ROUND_UP_4(width))
 #define I420_U_ROWSTRIDE(width) (GST_ROUND_UP_8(width)/2)
@@ -51,11 +52,43 @@ static GstPad *myvideosrcpad, *mytextsrcpad, *mysinkpad;
     "video/x-raw, "                 \
     "format = (string) I420"
 
+#define VIDEO_CAPS_TEMPLATE_WITH_FEATURE_STRING                              \
+    "video/x-raw(" GST_CAPS_FEATURE_META_GST_VIDEO_OVERLAY_COMPOSITION "), " \
+    "format = (string) I420;"                                                \
+    "video/x-raw, "                                                          \
+    "format = (string) I420;"
+
+#define UNSUPPORTED_VIDEO_CAPS_STRING                                            \
+    "video/x-raw(" GST_CAPS_FEATURE_META_GST_VIDEO_GL_TEXTURE_UPLOAD_META "), "  \
+    "format = (string) I420, "                                                   \
+    "framerate = (fraction) 1/1, "                                               \
+    "width = (int) 240, "                                                        \
+    "height = (int) 120"
+
+#define UNSUPPORTED_VIDEO_CAPS_TEMPLATE_STRING                                  \
+    "video/x-raw(" GST_CAPS_FEATURE_META_GST_VIDEO_GL_TEXTURE_UPLOAD_META "), " \
+    "format = (string) I420"
+
+#define UNSUPPORTED_VIDEO_CAPS_TEMPLATE_WITH_FEATURE_STRING                     \
+    "video/x-raw(" GST_CAPS_FEATURE_META_GST_VIDEO_GL_TEXTURE_UPLOAD_META ","   \
+                   GST_CAPS_FEATURE_META_GST_VIDEO_OVERLAY_COMPOSITION "), "    \
+    "format = (string) I420;"                                                   \
+    "video/x-raw(" GST_CAPS_FEATURE_META_GST_VIDEO_GL_TEXTURE_UPLOAD_META "), " \
+    "format = (string) I420"
+
 static GstStaticPadTemplate sinktemplate = GST_STATIC_PAD_TEMPLATE ("sink",
     GST_PAD_SINK,
     GST_PAD_ALWAYS,
     GST_STATIC_CAPS (VIDEO_CAPS_TEMPLATE_STRING)
     );
+
+static GstStaticPadTemplate sinktemplate_with_features =
+GST_STATIC_PAD_TEMPLATE ("sink",
+    GST_PAD_SINK,
+    GST_PAD_ALWAYS,
+    GST_STATIC_CAPS (VIDEO_CAPS_TEMPLATE_WITH_FEATURE_STRING)
+    );
+
 static GstStaticPadTemplate text_srctemplate = GST_STATIC_PAD_TEMPLATE ("src",
     GST_PAD_SRC,
     GST_PAD_ALWAYS,
@@ -68,6 +101,20 @@ static GstStaticPadTemplate video_srctemplate = GST_STATIC_PAD_TEMPLATE ("src",
     GST_STATIC_CAPS (VIDEO_CAPS_TEMPLATE_STRING)
     );
 
+static GstStaticPadTemplate unsupported_sinktemplate_with_features =
+GST_STATIC_PAD_TEMPLATE ("sink",
+    GST_PAD_SINK,
+    GST_PAD_ALWAYS,
+    GST_STATIC_CAPS (UNSUPPORTED_VIDEO_CAPS_TEMPLATE_WITH_FEATURE_STRING)
+    );
+
+static GstStaticPadTemplate unsupported_video_srctemplate =
+GST_STATIC_PAD_TEMPLATE ("src",
+    GST_PAD_SRC,
+    GST_PAD_ALWAYS,
+    GST_STATIC_CAPS (UNSUPPORTED_VIDEO_CAPS_TEMPLATE_STRING)
+    );
+
 static void
 gst_check_setup_events_textoverlay (GstPad * srcpad, GstElement * element,
     GstCaps * caps, GstFormat format, const gchar * stream_id)
@@ -83,6 +130,30 @@ gst_check_setup_events_textoverlay (GstPad * srcpad, GstElement * element,
   fail_unless (gst_pad_push_event (srcpad, gst_event_new_segment (&segment)));
 }
 
+
+static gboolean
+sink_query_handler (GstPad * pad, GstObject * parent, GstQuery * query)
+{
+  gboolean ret = FALSE;
+  GstQueryType type = GST_QUERY_TYPE (query);
+
+  switch (type) {
+    case GST_QUERY_ALLOCATION:{
+      gst_query_add_allocation_meta (query,
+          GST_VIDEO_OVERLAY_COMPOSITION_META_API_TYPE, NULL);
+
+      ret = TRUE;
+
+      break;
+    }
+    default:{
+      ret = gst_pad_query_default (pad, parent, query);
+      break;
+    }
+  }
+  return ret;
+}
+
 /* much like gst_check_setup_src_pad(), but with possibility to give a hint
  * which sink template of the element to use, if there are multiple ones */
 static GstPad *
@@ -145,20 +216,28 @@ notgst_check_teardown_src_pad2 (GstElement * element,
 }
 
 static GstElement *
-setup_textoverlay (gboolean video_only_no_text)
+setup_textoverlay_with_templates (GstStaticPadTemplate * srcpad_template,
+    GstStaticPadTemplate * textpad_template,
+    GstStaticPadTemplate * sinkpad_template, gboolean enable_allocation_query)
 {
   GstElement *textoverlay;
 
   GST_DEBUG ("setup_textoverlay");
   textoverlay = gst_check_setup_element ("textoverlay");
-  mysinkpad = gst_check_setup_sink_pad (textoverlay, &sinktemplate);
+  mysinkpad = gst_check_setup_sink_pad (textoverlay, sinkpad_template);
+
+  if (enable_allocation_query) {
+    GST_PAD_SET_PROXY_ALLOCATION (mysinkpad);
+    gst_pad_set_query_function (mysinkpad, sink_query_handler);
+  }
+
   myvideosrcpad =
-      notgst_check_setup_src_pad2 (textoverlay, &video_srctemplate, NULL,
+      notgst_check_setup_src_pad2 (textoverlay, srcpad_template, NULL,
       "video_sink");
 
-  if (!video_only_no_text) {
+  if (textpad_template) {
     mytextsrcpad =
-        notgst_check_setup_src_pad2 (textoverlay, &text_srctemplate, NULL,
+        notgst_check_setup_src_pad2 (textoverlay, textpad_template, NULL,
         "text_sink");
     gst_pad_set_active (mytextsrcpad, TRUE);
   } else {
@@ -171,6 +250,22 @@ setup_textoverlay (gboolean video_only_no_text)
   return textoverlay;
 }
 
+static GstElement *
+setup_textoverlay (gboolean video_only_no_text)
+{
+  GstStaticPadTemplate *srcpad_template = NULL;
+  GstStaticPadTemplate *textpad_template = NULL;
+  GstStaticPadTemplate *sinkpad_template = NULL;
+
+  srcpad_template = &video_srctemplate;
+  if (!video_only_no_text)
+    textpad_template = &text_srctemplate;
+  sinkpad_template = &sinktemplate;
+
+  return setup_textoverlay_with_templates (srcpad_template,
+      textpad_template, sinkpad_template, FALSE);
+}
+
 static gboolean
 buffer_is_all_black (GstBuffer * buf, GstCaps * caps)
 {
@@ -422,6 +517,137 @@ GST_START_TEST (test_video_passthrough)
 
 GST_END_TEST;
 
+GST_START_TEST (test_video_passthrough_with_feature)
+{
+  GstElement *textoverlay;
+  GstBuffer *inbuffer, *outbuffer;
+  GstCaps *incaps, *outcaps;
+  GstVideoOverlayCompositionMeta *comp_meta;
+
+  textoverlay = setup_textoverlay_with_templates (&video_srctemplate,
+      NULL, &sinktemplate_with_features, TRUE);
+
+  /* set static text to render */
+  g_object_set (textoverlay, "text", "XLX", NULL);
+
+  fail_unless (gst_element_set_state (textoverlay,
+          GST_STATE_PLAYING) == GST_STATE_CHANGE_SUCCESS,
+      "could not set to playing");
+
+  incaps = create_video_caps (VIDEO_CAPS_STRING);
+  gst_check_setup_events_textoverlay (myvideosrcpad, textoverlay, incaps,
+      GST_FORMAT_TIME, "video");
+  inbuffer = create_black_buffer (incaps);
+  gst_caps_unref (incaps);
+  ASSERT_BUFFER_REFCOUNT (inbuffer, "inbuffer", 1);
+
+  GST_BUFFER_TIMESTAMP (inbuffer) = 0;
+  GST_BUFFER_DURATION (inbuffer) = GST_SECOND / 10;
+
+  /* take additional ref to keep it alive */
+  gst_buffer_ref (inbuffer);
+  ASSERT_BUFFER_REFCOUNT (inbuffer, "inbuffer", 2);
+
+  /* pushing gives away one of the two references we have ... */
+  fail_unless (gst_pad_push (myvideosrcpad, inbuffer) == GST_FLOW_OK);
+
+  /* should have been dropped in favour of a new writable buffer */
+  ASSERT_BUFFER_REFCOUNT (inbuffer, "inbuffer", 1);
+  fail_unless_equals_int (g_list_length (buffers), 1);
+  outbuffer = GST_BUFFER_CAST (buffers->data);
+  outcaps = gst_pad_get_current_caps (mysinkpad);
+  fail_unless (outbuffer != inbuffer);
+
+  /* output buffer should be black */
+  fail_unless (buffer_is_all_black (outbuffer, outcaps) == TRUE);
+  gst_caps_unref (outcaps);
+
+  /* output buffer should have the composition meta */
+  comp_meta = gst_buffer_get_video_overlay_composition_meta (outbuffer);
+  fail_unless (comp_meta != NULL);
+
+  fail_unless (GST_BUFFER_TIMESTAMP (outbuffer) == 0);
+  fail_unless (GST_BUFFER_DURATION (outbuffer) == (GST_SECOND / 10));
+
+  /* and clean up */
+  g_list_foreach (buffers, (GFunc) gst_mini_object_unref, NULL);
+  g_list_free (buffers);
+  buffers = NULL;
+  ASSERT_BUFFER_REFCOUNT (inbuffer, "inbuffer", 1);
+
+  /* cleanup */
+  cleanup_textoverlay (textoverlay);
+  gst_buffer_unref (inbuffer);
+}
+
+GST_END_TEST;
+
+GST_START_TEST (test_video_passthrough_with_feature_and_unsupported_caps)
+{
+  GstElement *textoverlay;
+  GstBuffer *inbuffer, *outbuffer;
+  GstCaps *incaps, *outcaps;
+  GstVideoOverlayCompositionMeta *comp_meta;
+
+  textoverlay =
+      setup_textoverlay_with_templates (&unsupported_video_srctemplate, NULL,
+      &unsupported_sinktemplate_with_features, TRUE);
+
+  /* set static text to render */
+  g_object_set (textoverlay, "text", "XLX", NULL);
+
+  fail_unless (gst_element_set_state (textoverlay,
+          GST_STATE_PLAYING) == GST_STATE_CHANGE_SUCCESS,
+      "could not set to playing");
+
+  incaps = create_video_caps (UNSUPPORTED_VIDEO_CAPS_STRING);
+  gst_check_setup_events_textoverlay (myvideosrcpad, textoverlay, incaps,
+      GST_FORMAT_TIME, "video");
+  inbuffer = create_black_buffer (incaps);
+  gst_caps_unref (incaps);
+  ASSERT_BUFFER_REFCOUNT (inbuffer, "inbuffer", 1);
+
+  GST_BUFFER_TIMESTAMP (inbuffer) = 0;
+  GST_BUFFER_DURATION (inbuffer) = GST_SECOND / 10;
+
+  /* take additional ref to keep it alive */
+  gst_buffer_ref (inbuffer);
+  ASSERT_BUFFER_REFCOUNT (inbuffer, "inbuffer", 2);
+
+  /* pushing gives away one of the two references we have ... */
+  fail_unless (gst_pad_push (myvideosrcpad, inbuffer) == GST_FLOW_OK);
+
+  /* should have been dropped in favour of a new writable buffer */
+  ASSERT_BUFFER_REFCOUNT (inbuffer, "inbuffer", 1);
+  fail_unless_equals_int (g_list_length (buffers), 1);
+  outbuffer = GST_BUFFER_CAST (buffers->data);
+  outcaps = gst_pad_get_current_caps (mysinkpad);
+  fail_unless (outbuffer != inbuffer);
+
+  /* output buffer should be black */
+  fail_unless (buffer_is_all_black (outbuffer, outcaps) == TRUE);
+  gst_caps_unref (outcaps);
+
+  /* output buffer should have the composition meta */
+  comp_meta = gst_buffer_get_video_overlay_composition_meta (outbuffer);
+  fail_unless (comp_meta != NULL);
+
+  fail_unless (GST_BUFFER_TIMESTAMP (outbuffer) == 0);
+  fail_unless (GST_BUFFER_DURATION (outbuffer) == (GST_SECOND / 10));
+
+  /* and clean up */
+  g_list_foreach (buffers, (GFunc) gst_mini_object_unref, NULL);
+  g_list_free (buffers);
+  buffers = NULL;
+  ASSERT_BUFFER_REFCOUNT (inbuffer, "inbuffer", 1);
+
+  /* cleanup */
+  cleanup_textoverlay (textoverlay);
+  gst_buffer_unref (inbuffer);
+}
+
+GST_END_TEST;
+
 GST_START_TEST (test_video_render_static_text)
 {
   GstElement *textoverlay;
@@ -813,6 +1039,9 @@ textoverlay_suite (void)
   suite_add_tcase (s, tc_chain);
 
   tcase_add_test (tc_chain, test_video_passthrough);
+  tcase_add_test (tc_chain, test_video_passthrough_with_feature);
+  tcase_add_test (tc_chain,
+      test_video_passthrough_with_feature_and_unsupported_caps);
   tcase_add_test (tc_chain, test_video_render_static_text);
   tcase_add_test (tc_chain, test_render_continuity);
   tcase_add_test (tc_chain, test_video_waits_for_text);