mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer.git
synced 2025-01-13 19:05:37 +00:00
tests: add textoverlay passthrough with composition feature unit tests
https://bugzilla.gnome.org/show_bug.cgi?id=721953
This commit is contained in:
parent
ed8e7d4275
commit
c904661dc3
2 changed files with 235 additions and 6 deletions
|
@ -492,7 +492,7 @@ elements_audioresample_LDADD = \
|
||||||
$(GST_BASE_LIBS) \
|
$(GST_BASE_LIBS) \
|
||||||
$(LDADD)
|
$(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_textoverlay_CFLAGS = $(GST_BASE_CFLAGS) $(AM_CFLAGS)
|
||||||
|
|
||||||
elements_volume_LDADD = \
|
elements_volume_LDADD = \
|
||||||
|
|
|
@ -21,6 +21,7 @@
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
|
|
||||||
#include <gst/check/gstcheck.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_Y_ROWSTRIDE(width) (GST_ROUND_UP_4(width))
|
||||||
#define I420_U_ROWSTRIDE(width) (GST_ROUND_UP_8(width)/2)
|
#define I420_U_ROWSTRIDE(width) (GST_ROUND_UP_8(width)/2)
|
||||||
|
@ -51,11 +52,43 @@ static GstPad *myvideosrcpad, *mytextsrcpad, *mysinkpad;
|
||||||
"video/x-raw, " \
|
"video/x-raw, " \
|
||||||
"format = (string) I420"
|
"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",
|
static GstStaticPadTemplate sinktemplate = GST_STATIC_PAD_TEMPLATE ("sink",
|
||||||
GST_PAD_SINK,
|
GST_PAD_SINK,
|
||||||
GST_PAD_ALWAYS,
|
GST_PAD_ALWAYS,
|
||||||
GST_STATIC_CAPS (VIDEO_CAPS_TEMPLATE_STRING)
|
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",
|
static GstStaticPadTemplate text_srctemplate = GST_STATIC_PAD_TEMPLATE ("src",
|
||||||
GST_PAD_SRC,
|
GST_PAD_SRC,
|
||||||
GST_PAD_ALWAYS,
|
GST_PAD_ALWAYS,
|
||||||
|
@ -68,6 +101,20 @@ static GstStaticPadTemplate video_srctemplate = GST_STATIC_PAD_TEMPLATE ("src",
|
||||||
GST_STATIC_CAPS (VIDEO_CAPS_TEMPLATE_STRING)
|
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
|
static void
|
||||||
gst_check_setup_events_textoverlay (GstPad * srcpad, GstElement * element,
|
gst_check_setup_events_textoverlay (GstPad * srcpad, GstElement * element,
|
||||||
GstCaps * caps, GstFormat format, const gchar * stream_id)
|
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)));
|
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
|
/* 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 */
|
* which sink template of the element to use, if there are multiple ones */
|
||||||
static GstPad *
|
static GstPad *
|
||||||
|
@ -145,20 +216,28 @@ notgst_check_teardown_src_pad2 (GstElement * element,
|
||||||
}
|
}
|
||||||
|
|
||||||
static GstElement *
|
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;
|
GstElement *textoverlay;
|
||||||
|
|
||||||
GST_DEBUG ("setup_textoverlay");
|
GST_DEBUG ("setup_textoverlay");
|
||||||
textoverlay = gst_check_setup_element ("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 =
|
myvideosrcpad =
|
||||||
notgst_check_setup_src_pad2 (textoverlay, &video_srctemplate, NULL,
|
notgst_check_setup_src_pad2 (textoverlay, srcpad_template, NULL,
|
||||||
"video_sink");
|
"video_sink");
|
||||||
|
|
||||||
if (!video_only_no_text) {
|
if (textpad_template) {
|
||||||
mytextsrcpad =
|
mytextsrcpad =
|
||||||
notgst_check_setup_src_pad2 (textoverlay, &text_srctemplate, NULL,
|
notgst_check_setup_src_pad2 (textoverlay, textpad_template, NULL,
|
||||||
"text_sink");
|
"text_sink");
|
||||||
gst_pad_set_active (mytextsrcpad, TRUE);
|
gst_pad_set_active (mytextsrcpad, TRUE);
|
||||||
} else {
|
} else {
|
||||||
|
@ -171,6 +250,22 @@ setup_textoverlay (gboolean video_only_no_text)
|
||||||
return textoverlay;
|
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
|
static gboolean
|
||||||
buffer_is_all_black (GstBuffer * buf, GstCaps * caps)
|
buffer_is_all_black (GstBuffer * buf, GstCaps * caps)
|
||||||
{
|
{
|
||||||
|
@ -422,6 +517,137 @@ GST_START_TEST (test_video_passthrough)
|
||||||
|
|
||||||
GST_END_TEST;
|
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)
|
GST_START_TEST (test_video_render_static_text)
|
||||||
{
|
{
|
||||||
GstElement *textoverlay;
|
GstElement *textoverlay;
|
||||||
|
@ -813,6 +1039,9 @@ textoverlay_suite (void)
|
||||||
suite_add_tcase (s, tc_chain);
|
suite_add_tcase (s, tc_chain);
|
||||||
|
|
||||||
tcase_add_test (tc_chain, test_video_passthrough);
|
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_video_render_static_text);
|
||||||
tcase_add_test (tc_chain, test_render_continuity);
|
tcase_add_test (tc_chain, test_render_continuity);
|
||||||
tcase_add_test (tc_chain, test_video_waits_for_text);
|
tcase_add_test (tc_chain, test_video_waits_for_text);
|
||||||
|
|
Loading…
Reference in a new issue