summaryrefslogtreecommitdiffstats
path: root/tests/check/elements/cmmldec.c
diff options
context:
space:
mode:
Diffstat (limited to 'tests/check/elements/cmmldec.c')
-rw-r--r--tests/check/elements/cmmldec.c439
1 files changed, 297 insertions, 142 deletions
diff --git a/tests/check/elements/cmmldec.c b/tests/check/elements/cmmldec.c
index 0b87a3ff..f7f21ca2 100644
--- a/tests/check/elements/cmmldec.c
+++ b/tests/check/elements/cmmldec.c
@@ -22,7 +22,6 @@
*/
#include <gst/check/gstcheck.h>
-
#include <gst/tag/tag.h>
#define SINK_CAPS "text/x-cmml"
@@ -34,16 +33,13 @@
"\xe8\x03\x00\x00\x00\x00\x00\x00"\
"\x01\x00\x00\x00\x00\x00\x00\x00"\
"\x20"
+#define IDENT_HEADER_SIZE 29
-#define XML_PREAMBLE \
+#define PREAMBLE_NO_PI \
"<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"yes\"?>\n"\
- "<!DOCTYPE cmml SYSTEM \"cmml.dtd\">\n"\
-
-#define PREAMBLE \
- XML_PREAMBLE "<?cmml?>"
-
-#define PREAMBLE_DECODED \
- XML_PREAMBLE "<cmml >"
+ "<!DOCTYPE cmml SYSTEM \"cmml.dtd\">\n"
+#define PREAMBLE PREAMBLE_NO_PI "<?cmml?>"
+#define PREAMBLE_DECODED PREAMBLE_NO_PI "<cmml >"
#define HEAD_TAG \
"<head>"\
@@ -73,15 +69,31 @@
"<meta name=\"test\" content=\"test content\"/>"\
"</clip>"
+#define EMPTY_CLIP_TEMPLATE \
+ "<clip id=\"%s\" track=\"%s\" />"
+
#define END_TAG \
"</cmml>"
+#define fail_unless_equals_flow_return(a, b) \
+G_STMT_START { \
+ gchar *a_up = g_ascii_strup (gst_flow_get_name (a), -1); \
+ gchar *b_up = g_ascii_strup (gst_flow_get_name (b), -1); \
+ fail_unless (a == b, \
+ "'" #a "' (GST_FLOW_%s) is not equal to '" #b "' (GST_FLOW_%s)", \
+ a_up, b_up); \
+ g_free (a_up); \
+ g_free (b_up); \
+} G_STMT_END;
+
+static GstElement *cmmldec;
+static GstBus *bus;
+static GstFlowReturn flow;
GList *buffers;
-GList *current_buf = NULL;
-gint64 granulerate;
-guint8 granuleshift;
-
-GstPad *srcpad, *sinkpad;
+static GList *current_buf;
+static gint64 granulerate;
+static guint8 granuleshift;
+static GstPad *srcpad, *sinkpad;
static GstStaticPadTemplate sinktemplate = GST_STATIC_PAD_TEMPLATE ("sink",
GST_PAD_SINK,
@@ -117,12 +129,9 @@ buffer_unref (void *buffer, void *user_data)
gst_buffer_unref (GST_BUFFER (buffer));
}
-GstElement *
+static void
setup_cmmldec ()
{
- GstElement *cmmldec;
- GstBus *bus;
-
GST_DEBUG ("setup_cmmldec");
cmmldec = gst_check_setup_element ("cmmldec");
srcpad = gst_check_setup_src_pad (cmmldec, &srctemplate, NULL);
@@ -138,23 +147,20 @@ setup_cmmldec ()
granulerate = GST_SECOND / 1000;
granuleshift = 32;
buffers = NULL;
-
- return cmmldec;
}
static void
-cleanup_cmmldec (GstElement * cmmldec)
+teardown_cmmldec ()
{
- GstBus *bus;
-
g_list_foreach (buffers, buffer_unref, NULL);
g_list_free (buffers);
+ buffers = NULL;
+ current_buf = NULL;
- bus = GST_ELEMENT_BUS (cmmldec);
gst_bus_set_flushing (bus, TRUE);
gst_object_unref (bus);
- GST_DEBUG ("cleanup_cmmldec");
+ GST_DEBUG ("teardown_cmmldec");
gst_check_teardown_src_pad (cmmldec);
gst_check_teardown_sink_pad (cmmldec);
gst_check_teardown_element (cmmldec);
@@ -164,7 +170,16 @@ static void
check_output_buffer_is_equal (const gchar * name,
const gchar * data, gint refcount)
{
- GstBuffer *buffer = GST_BUFFER (current_buf->data);
+ GstBuffer *buffer;
+
+ if (current_buf == NULL)
+ current_buf = buffers;
+ else
+ current_buf = g_list_next (current_buf);
+
+ fail_unless (current_buf != NULL);
+
+ buffer = GST_BUFFER (current_buf->data);
ASSERT_OBJECT_REFCOUNT (buffer, name, refcount);
fail_unless (memcmp (GST_BUFFER_DATA (buffer), data,
@@ -172,63 +187,128 @@ check_output_buffer_is_equal (const gchar * name,
"'%s' (%s) is not equal to (%s)", name, GST_BUFFER_DATA (buffer), data);
}
-static void
-push_data (const gchar * name,
- const gchar * data, gint size, gint64 granulepos,
- GstFlowReturn expected_return)
+static GstFlowReturn
+push_data (const gchar * name, const gchar * data, gint size, gint64 granulepos)
{
GstBuffer *buffer;
- GstFlowReturn res;
buffer = buffer_new (data, size);
GST_BUFFER_OFFSET_END (buffer) = granulepos;
- res = gst_pad_push (srcpad, buffer);
- fail_unless (res == expected_return,
- "pushing %s returned %d not %d", name, res, expected_return);
+ return gst_pad_push (srcpad, buffer);
+}
+
+static GObject *
+cmml_tag_message_pop (GstBus * bus, const gchar * tag)
+{
+ GstMessage *message;
+ GstTagList *taglist;
+ const GValue *value;
+ GObject *obj;
+
+ message = gst_bus_poll (bus, GST_MESSAGE_TAG, 0);
+ if (message == NULL)
+ return NULL;
+
+ gst_message_parse_tag (message, &taglist);
+ value = gst_tag_list_get_value_index (taglist, tag, 0);
+ if (value == NULL) {
+ gst_message_unref (message);
+ gst_tag_list_free (taglist);
+ return NULL;
+ }
+
+ obj = g_value_dup_object (value);
+ gst_message_unref (message);
+ gst_tag_list_free (taglist);
+
+ return obj;
}
static void
check_headers ()
{
+ GObject *head_tag;
+ gchar *title, *base;
+ GValueArray *meta;
+
/* push the ident header */
- push_data ("ident-header", IDENT_HEADER, 29, 0, GST_FLOW_OK);
- /* push the cmml start tag */
- push_data ("preamble", PREAMBLE, strlen (PREAMBLE), 0, GST_FLOW_OK);
+ flow = push_data ("ident-header", IDENT_HEADER, IDENT_HEADER_SIZE, 0);
+ fail_unless_equals_flow_return (flow, GST_FLOW_OK);
+
+ /* push the cmml preamble */
+ flow = push_data ("preamble", PREAMBLE, strlen (PREAMBLE), 0);
+ fail_unless_equals_flow_return (flow, GST_FLOW_OK);
+
/* push the head tag */
- push_data ("head", HEAD_TAG, strlen (HEAD_TAG), 0, GST_FLOW_OK);
+ flow = push_data ("head", HEAD_TAG, strlen (HEAD_TAG), 0);
+ fail_unless_equals_flow_return (flow, GST_FLOW_OK);
- current_buf = buffers;
- fail_unless_equals_int (g_list_length (current_buf), 2);
+ fail_unless_equals_int (g_list_length (buffers), 2);
- /* check the preamble */
+ /* check the decoded preamble */
check_output_buffer_is_equal ("cmml-preamble-buffer", PREAMBLE_DECODED, 1);
/* check the decoded head tag */
- current_buf = current_buf->next;
check_output_buffer_is_equal ("head-tag-buffer", HEAD_TAG_DECODED, 1);
+
+ /* check the GstCmmlTagHead tag object */
+ head_tag = cmml_tag_message_pop (bus, GST_TAG_CMML_HEAD);
+ fail_unless (head_tag != NULL);
+ g_object_get (head_tag,
+ "title", &title, "base-uri", &base, "meta", &meta, NULL);
+ fail_unless_equals_string ("The Research Hunter", title);
+ fail_unless (base == NULL);
+ fail_unless (meta != NULL);
+ fail_unless_equals_int (meta->n_values, 10);
+
+ g_free (title);
+ g_free (base);
+ g_value_array_free (meta);
+ g_object_unref (head_tag);
}
-static void
-push_clip (const gchar * name, const gchar * track, GstClockTime prev,
- GstClockTime start, GstClockTime end, GstFlowReturn expected_return)
+static GstFlowReturn
+push_clip_full (const gchar * name, const gchar * track, const gchar * template,
+ GstClockTime prev, GstClockTime start)
{
gchar *clip;
gint64 keyindex, keyoffset, granulepos;
+ GstFlowReturn res;
if (track == NULL)
track = "default";
+ if (prev == GST_CLOCK_TIME_NONE)
+ prev = 0;
+
keyindex = prev / granulerate << granuleshift;
keyoffset = (start - prev) / granulerate;
granulepos = keyindex + keyoffset;
- clip = g_strdup_printf (CLIP_TEMPLATE, name, track);
- push_data (name, clip, strlen (clip), granulepos, expected_return);
+ clip = g_strdup_printf (template, name, track);
+ res = push_data (name, clip, strlen (clip), granulepos);
g_free (clip);
+
+ return res;
}
+static GstFlowReturn
+push_clip (const gchar * name, const gchar * track,
+ GstClockTime prev, GstClockTime start)
+{
+ return push_clip_full (name, track, CLIP_TEMPLATE, prev, start);
+}
+
+static GstFlowReturn
+push_empty_clip (const gchar * name, const gchar * track, GstClockTime start)
+{
+ return push_clip_full (name, track,
+ EMPTY_CLIP_TEMPLATE, GST_CLOCK_TIME_NONE, start);
+}
+
+
static void
-check_clip (const gchar * name, const gchar * track,
+check_output_clip (const gchar * name, const gchar * track,
const gchar * start, const gchar * end)
{
gchar *decoded_clip;
@@ -236,58 +316,60 @@ check_clip (const gchar * name, const gchar * track,
if (track == NULL)
track = "default";
- current_buf = current_buf->next;
- fail_unless (g_list_length (current_buf));
decoded_clip = g_strdup_printf (CLIP_TEMPLATE_DECODED, name, track, start);
check_output_buffer_is_equal (name, decoded_clip, 1);
g_free (decoded_clip);
}
-static void
-check_end ()
-{
- current_buf = current_buf->next;
- check_output_buffer_is_equal ("cmml-end-tag", END_TAG, 1);
-}
-
GST_START_TEST (test_dec)
{
- GstElement *cmmldec;
-
- cmmldec = setup_cmmldec ();
+ GstClockTime clip1_start = 1 * GST_SECOND + 234 * GST_MSECOND;
+ GstClockTime clip2_start = clip1_start;
+ GstClockTime clip3_start =
+ ((100 * 3600) + (59 * 60) + 59) * GST_SECOND + 678 * GST_MSECOND;
check_headers ();
- push_clip ("clip-1", "default",
- 0, 1 * GST_SECOND + 234 * GST_MSECOND, 0, GST_FLOW_OK);
- push_clip ("clip-2", "othertrack",
- 0, 4 * GST_SECOND + 321 * GST_MSECOND, 0, GST_FLOW_OK);
- push_clip ("clip-3", "default",
- 1 * GST_SECOND + 234 * GST_MSECOND,
- ((100 * 3600) + (59 * 60) + 59) * GST_SECOND + 678 * GST_MSECOND, 0,
- GST_FLOW_OK);
+ flow = push_clip ("clip-1", "default", GST_CLOCK_TIME_NONE, clip1_start);
+ fail_unless_equals_flow_return (flow, GST_FLOW_OK);
+
+ flow = push_clip ("clip-2", "othertrack", GST_CLOCK_TIME_NONE, clip2_start);
+ fail_unless_equals_flow_return (flow, GST_FLOW_OK);
+
+ flow = push_clip ("clip-3", "default", clip1_start, clip3_start);
+ fail_unless_equals_flow_return (flow, GST_FLOW_OK);
+
/* send EOS to flush clip-2 and clip-3 */
gst_pad_send_event (GST_PAD_PEER (srcpad), gst_event_new_eos ());
- check_clip ("clip-1", "default", "0:00:01.234", NULL);
- check_clip ("clip-2", "othertrack", "0:00:04.321", NULL);
- check_clip ("clip-3", "default", "100:59:59.678", NULL);
- check_end ();
+ check_output_clip ("clip-1", "default", "0:00:01.234", NULL);
+ check_output_clip ("clip-2", "othertrack", "0:00:01.234", NULL);
+ check_output_clip ("clip-3", "default", "100:59:59.678", NULL);
+ check_output_buffer_is_equal ("cmml-end-tag", END_TAG, 1);
+}
+
+GST_END_TEST;
- cleanup_cmmldec (cmmldec);
+GST_START_TEST (test_preamble_no_pi)
+{
+ flow = push_data ("ident-header", IDENT_HEADER, IDENT_HEADER_SIZE, 0);
+ fail_unless_equals_flow_return (flow, GST_FLOW_OK);
+ fail_unless_equals_int (g_list_length (buffers), 0);
+
+ flow = push_data ("preamble-no-pi",
+ PREAMBLE_NO_PI, strlen (PREAMBLE_NO_PI), 0);
+ fail_unless_equals_flow_return (flow, GST_FLOW_OK);
+ fail_unless_equals_int (g_list_length (buffers), 1);
+
+ check_output_buffer_is_equal ("cmml-preamble-buffer",
+ PREAMBLE_NO_PI "<cmml>", 1);
}
GST_END_TEST;
GST_START_TEST (test_tags)
{
- GstElement *cmmldec;
- GstBus *bus;
- GstMessage *message;
- GstTagList *tags;
- const GValue *tag_val;
GObject *tag;
- gchar *title, *base;
gboolean empty;
gchar *id, *track;
gint64 start_time, end_time;
@@ -295,51 +377,15 @@ GST_START_TEST (test_tags)
gchar *img_src, *img_alt;
gchar *desc;
GValueArray *meta;
-
- cmmldec = setup_cmmldec ();
- bus = gst_element_get_bus (cmmldec);
+ GstClockTime clip1_start;
check_headers ();
- /* read the GstCmmlTagHead tag */
- message = gst_bus_poll (bus, GST_MESSAGE_TAG, -1);
- fail_unless (message != NULL);
-
- gst_message_parse_tag (message, &tags);
- fail_unless (tags != NULL);
+ clip1_start = 1 * GST_SECOND + 234 * GST_MSECOND;
+ flow = push_clip ("clip-1", "default", 0, clip1_start);
+ fail_unless_equals_flow_return (flow, GST_FLOW_OK);
- tag_val = gst_tag_list_get_value_index (tags, GST_TAG_CMML_HEAD, 0);
- fail_unless (tag_val != NULL);
-
- tag = g_value_get_object (tag_val);
- fail_unless (tag != NULL);
-
- g_object_get (tag, "title", &title, "base-uri", &base, "meta", &meta, NULL);
- fail_unless_equals_string ("The Research Hunter", title);
- fail_unless (base == NULL);
- fail_unless (meta != NULL);
- fail_unless_equals_int (meta->n_values, 10);
-
- gst_message_unref (message);
- gst_tag_list_free (tags);
- g_free (title);
- g_free (base);
- g_value_array_free (meta);
-
- push_clip ("clip-1", "default",
- 0, 1 * GST_SECOND + 234 * GST_MSECOND, 0, GST_FLOW_OK);
-
- /* read the GstCmmlTagClip */
- message = gst_bus_poll (bus, GST_MESSAGE_TAG, -1);
- fail_unless (message != NULL);
-
- gst_message_parse_tag (message, &tags);
- fail_unless (tags != NULL);
-
- tag_val = gst_tag_list_get_value_index (tags, GST_TAG_CMML_CLIP, 0);
- fail_unless (tag_val != NULL);
-
- tag = g_value_get_object (tag_val);
+ tag = cmml_tag_message_pop (bus, GST_TAG_CMML_CLIP);
fail_unless (tag != NULL);
g_object_get (tag, "id", &id, "empty", &empty, "track", &track,
@@ -369,40 +415,149 @@ GST_START_TEST (test_tags)
g_free (img_alt);
g_free (desc);
g_value_array_free (meta);
- gst_tag_list_free (tags);
- gst_message_unref (message);
- gst_object_unref (bus);
- cleanup_cmmldec (cmmldec);
+ g_object_unref (tag);
}
GST_END_TEST;
-Suite *
-cmmldec_suite ()
+GST_START_TEST (test_wait_clip_end)
{
- Suite *s = suite_create ("cmmldec");
- TCase *tc_chain = tcase_create ("general");
+ GObject *tag;
+ gchar *id;
+ GstClockTime end_time = 0;
- suite_add_tcase (s, tc_chain);
- tcase_add_test (tc_chain, test_dec);
- tcase_add_test (tc_chain, test_tags);
+ g_object_set (cmmldec, "wait-clip-end-time", TRUE, NULL);
- return s;
+ check_headers ();
+
+ GstClockTime clip1_start = 1 * GST_SECOND + 234 * GST_MSECOND;
+ GstClockTime clip2_start = 2 * GST_SECOND + 234 * GST_MSECOND;
+ GstClockTime clip3_start = 3 * GST_SECOND + 234 * GST_MSECOND;
+ GstClockTime clip3_end = 4 * GST_SECOND + 234 * GST_MSECOND;
+ GstClockTime clip4_start = 5 * GST_SECOND + 234 * GST_MSECOND;
+
+ flow = push_clip ("clip-1", "default", 0, clip1_start);
+ fail_unless_equals_flow_return (flow, GST_FLOW_OK);
+ /* no tag has been posted yet */
+ fail_unless (cmml_tag_message_pop (bus, GST_TAG_CMML_CLIP) == NULL);
+
+ flow = push_clip ("clip-2", "default", clip1_start, clip2_start);
+ fail_unless_equals_flow_return (flow, GST_FLOW_OK);
+
+ tag = cmml_tag_message_pop (bus, GST_TAG_CMML_CLIP);
+ fail_unless (tag != NULL);
+ g_object_get (tag, "id", &id, "end-time", &end_time, NULL);
+ /* clip-1 is posted when clip-2 is decoded. clip-1 ends when clip-2 starts */
+ fail_unless_equals_string (id, "clip-1");
+ fail_unless_equals_int (end_time, clip2_start);
+ g_free (id);
+ g_object_unref (tag);
+
+ flow = push_clip ("clip-3", "default", clip2_start, clip3_start);
+ fail_unless_equals_flow_return (flow, GST_FLOW_OK);
+
+ tag = cmml_tag_message_pop (bus, GST_TAG_CMML_CLIP);
+ fail_unless (tag != NULL);
+ g_object_get (tag, "id", &id, "end-time", &end_time, NULL);
+ /* clip-2 is posted when clip-3 is decoded. It ends when clip-3 starts */
+ fail_unless_equals_string (id, "clip-2");
+ fail_unless_equals_int (end_time, clip3_start);
+ g_free (id);
+ g_object_unref (tag);
+
+ flow = push_empty_clip ("empty-clip", "default", clip3_end);
+ tag = cmml_tag_message_pop (bus, GST_TAG_CMML_CLIP);
+ fail_unless (tag != NULL);
+ g_object_get (tag, "id", &id, "end-time", &end_time, NULL);
+ /* clip-3 ends when empty-clip is decoded */
+ fail_unless_equals_string (id, "clip-3");
+ fail_unless_equals_int (end_time, clip3_end);
+ g_free (id);
+ g_object_unref (tag);
+
+ flow = push_clip ("clip-4", "default", clip3_start, clip4_start);
+ fail_unless_equals_flow_return (flow, GST_FLOW_OK);
+
+ /* an empty clip just marks the end of the previous one, so no tag is posted
+ * for empty-clip */
+ fail_unless (cmml_tag_message_pop (bus, GST_TAG_CMML_CLIP) == NULL);
+ /* send EOS to flush clip-4 */
+ gst_pad_send_event (GST_PAD_PEER (srcpad), gst_event_new_eos ());
+
+ tag = cmml_tag_message_pop (bus, GST_TAG_CMML_CLIP);
+ fail_unless (tag != NULL);
+ g_object_get (tag, "id", &id, NULL);
+ fail_unless_equals_string (id, "clip-4");
+ g_free (id);
+ g_object_unref (tag);
+}
+
+GST_END_TEST;
+
+GST_START_TEST (test_weird_input)
+{
+ const gchar *bad_xml = "<?xml version=\"1.0\"?><a><b></a>";
+
+ /* malformed ident header */
+ flow = push_data ("bad-ident-header", "CMML\0\0\0\0garbage", 15, 0);
+ fail_unless_equals_flow_return (flow, GST_FLOW_ERROR);
+
+ /* push invalid xml */
+ flow = push_data ("bad-xml", bad_xml, strlen (bad_xml), 0);
+ fail_unless_equals_flow_return (flow, GST_FLOW_ERROR);
+
+ /* and now for something completely different: an empty buffer. This is valid
+ * as 'NIL' EOS pages are allowed */
+ flow = push_data ("empty-eos", NULL, 0, 0);
+ fail_unless_equals_flow_return (flow, GST_FLOW_OK);
}
-int
-main (int argc, char **argv)
+GST_END_TEST;
+
+GST_START_TEST (test_sink_query_convert)
{
- int nf;
+ guint64 keyindex, keyoffset, granulepos;
+ GstClockTime index_time, offset_time;
+ GstFormat dstfmt = GST_FORMAT_TIME;
+ gint64 dstval;
- Suite *s = cmmldec_suite ();
- SRunner *sr = srunner_create (s);
+ /* send headers to set the granulerate */
+ check_headers ();
- gst_check_init (&argc, &argv);
+ /* create a 1|1 granulepos */
+ index_time = 1 * GST_SECOND;
+ offset_time = 1 * GST_SECOND;
+
+ keyindex = (index_time / granulerate) << granuleshift;
+ keyoffset = offset_time / granulerate;
+ granulepos = keyindex + keyoffset;
- srunner_run_all (sr, CK_NORMAL);
- nf = srunner_ntests_failed (sr);
- srunner_free (sr);
+ fail_unless (gst_pad_query_convert (GST_PAD_PEER (srcpad),
+ GST_FORMAT_DEFAULT, granulepos, &dstfmt, &dstval));
- return nf;
+ fail_unless (dstfmt == GST_FORMAT_TIME);
+ /* fail unless dstval == index + offset */
+ fail_unless_equals_int (2 * GST_SECOND, dstval);
}
+
+GST_END_TEST;
+
+Suite *
+cmmldec_suite ()
+{
+ Suite *s = suite_create ("cmmldec");
+ TCase *tc_general = tcase_create ("general");
+
+ suite_add_tcase (s, tc_general);
+ tcase_add_checked_fixture (tc_general, setup_cmmldec, teardown_cmmldec);
+ tcase_add_test (tc_general, test_dec);
+ tcase_add_test (tc_general, test_tags);
+ tcase_add_test (tc_general, test_preamble_no_pi);
+ tcase_add_test (tc_general, test_wait_clip_end);
+ tcase_add_test (tc_general, test_sink_query_convert);
+ tcase_add_test (tc_general, test_weird_input);
+
+ return s;
+}
+
+GST_CHECK_MAIN (cmmldec);