diff --git a/tests/check/Makefile.am b/tests/check/Makefile.am index 1d4b7ef8f6..5eae29b734 100644 --- a/tests/check/Makefile.am +++ b/tests/check/Makefile.am @@ -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 = \ diff --git a/tests/check/elements/textoverlay.c b/tests/check/elements/textoverlay.c index c11d5e5ccf..7da26a49de 100644 --- a/tests/check/elements/textoverlay.c +++ b/tests/check/elements/textoverlay.c @@ -21,6 +21,7 @@ #include #include +#include #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);