summaryrefslogtreecommitdiffstats
path: root/tests
diff options
context:
space:
mode:
authorMichael Smith <msmith@xiph.org>2006-02-24 19:07:10 +0000
committerMichael Smith <msmith@xiph.org>2006-02-24 19:07:10 +0000
commit73ce8c5b9e9a9cb27c1307dbfee300939265650c (patch)
tree207f645f3849f86026894e7411d9335353a12e53 /tests
parentdd8f37faac9ea109550d630f4d7dcbf295cd5fc1 (diff)
Add Annodex elements from Alessendro Decina: skeleton and CMML.
Original commit message from CVS: * configure.ac: * docs/plugins/gst-plugins-good-plugins-sections.txt: * ext/Makefile.am: * ext/annodex/Makefile.am: * ext/annodex/gstannodex.c: * ext/annodex/gstannodex.h: * ext/annodex/gstcmmldec.c: * ext/annodex/gstcmmldec.h: * ext/annodex/gstcmmlenc.c: * ext/annodex/gstcmmlenc.h: * ext/annodex/gstcmmlparser.c: * ext/annodex/gstcmmlparser.h: * ext/annodex/gstcmmltag.c: * ext/annodex/gstcmmltag.h: * ext/annodex/gstcmmlutils.c: * ext/annodex/gstcmmlutils.h: * ext/annodex/gstskeldec.c: * ext/annodex/gstskeldec.h: * ext/annodex/gstskeltag.c: * ext/annodex/gstskeltag.h: * tests/check/Makefile.am: * tests/check/elements/cmmldec.c: * tests/check/elements/cmmlenc.c: * tests/check/elements/skeldec.c: Add Annodex elements from Alessendro Decina: skeleton and CMML. Includes tests & docs, oh my! Passes Thomas's -good checklist entirely. Wow.
Diffstat (limited to 'tests')
-rw-r--r--tests/check/Makefile.am5
-rw-r--r--tests/check/elements/cmmldec.c409
-rw-r--r--tests/check/elements/cmmlenc.c361
-rw-r--r--tests/check/elements/skeldec.c258
4 files changed, 1032 insertions, 1 deletions
diff --git a/tests/check/Makefile.am b/tests/check/Makefile.am
index 4826e4ec..70a7fbfe 100644
--- a/tests/check/Makefile.am
+++ b/tests/check/Makefile.am
@@ -19,7 +19,10 @@ TESTS = $(check_PROGRAMS)
check_PROGRAMS = \
elements/level \
- elements/matroskamux
+ elements/matroskamux \
+ elements/cmmldec \
+ elements/cmmlenc \
+ elements/skeldec
# these tests don't even pass
diff --git a/tests/check/elements/cmmldec.c b/tests/check/elements/cmmldec.c
new file mode 100644
index 00000000..f2498d22
--- /dev/null
+++ b/tests/check/elements/cmmldec.c
@@ -0,0 +1,409 @@
+/*
+ * cmmldec.c - GStreamer CMML decoder test suite
+ * Copyright (C) 2005 Alessandro Decina
+ *
+ * Authors:
+ * Alessandro Decina <alessandro@nnva.org>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+#include <gst/check/gstcheck.h>
+
+#define SINK_CAPS "text/xml"
+#define SRC_CAPS "text/x-cmml"
+
+#define IDENT_HEADER \
+ "CMML\x00\x00\x00\x00"\
+ "\x03\x00\x00\x00"\
+ "\x01\x00\x00\x00\x00\x00\x00\x00"\
+ "\xe8\x03\x00\x00\x00\x00\x00\x00"\
+ "\x20"
+
+#define XML_PREAMBLE \
+ "<?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 >"
+
+#define HEAD_TAG \
+ "<head>"\
+ "<title>The Research Hunter</title>"\
+ "<meta name=\"DC.audience\" content=\"General\"/>"\
+ "<meta name=\"DC.author\" content=\"CSIRO Publishing\"/>"\
+ "<meta name=\"DC.format\" content=\"video\"/>"\
+ "<meta name=\"DC.language\" content=\"English\"/>"\
+ "<meta name=\"DC.publisher\" content=\"CSIRO Australia\"/>"\
+ "</head>"
+
+#define HEAD_TAG_DECODED HEAD_TAG
+
+#define CLIP_TEMPLATE \
+ "<clip id=\"%s\" track=\"%s\">"\
+ "<a href=\"http://www.csiro.au/\">http://www.csiro.au</a>"\
+ "<img src=\"images/index1.jpg\"/>"\
+ "<desc>Welcome to CSIRO</desc>"\
+ "<meta name=\"test\" content=\"test content\"/>"\
+ "</clip>"
+
+#define CLIP_TEMPLATE_DECODED \
+ "<clip id=\"%s\" track=\"%s\" start=\"%s\">"\
+ "<a href=\"http://www.csiro.au/\">http://www.csiro.au</a>"\
+ "<img src=\"images/index1.jpg\"/>"\
+ "<desc>Welcome to CSIRO</desc>"\
+ "<meta name=\"test\" content=\"test content\"/>"\
+ "</clip>"
+
+#define END_TAG \
+ "</cmml>"
+
+GList *buffers;
+GList *current_buf = NULL;
+gint64 granulerate;
+guint8 granuleshift;
+
+GstPad *srcpad, *sinkpad;
+
+static GstStaticPadTemplate sinktemplate = GST_STATIC_PAD_TEMPLATE ("sink",
+ GST_PAD_SINK,
+ GST_PAD_ALWAYS,
+ GST_STATIC_CAPS (SINK_CAPS)
+ );
+
+static GstStaticPadTemplate srctemplate = GST_STATIC_PAD_TEMPLATE ("src",
+ GST_PAD_SRC,
+ GST_PAD_ALWAYS,
+ GST_STATIC_CAPS (SRC_CAPS)
+ );
+
+static GstBuffer *
+buffer_new (const gchar * buffer_data, guint size)
+{
+ GstBuffer *buffer;
+ GstCaps *caps;
+
+ buffer = gst_buffer_new_and_alloc (size);
+ memcpy (GST_BUFFER_DATA (buffer), buffer_data, size);
+ caps = gst_caps_from_string (SRC_CAPS);
+ gst_buffer_set_caps (buffer, caps);
+ gst_caps_unref (caps);
+
+ return buffer;
+}
+
+static void
+buffer_unref (void *buffer, void *user_data)
+{
+ ASSERT_OBJECT_REFCOUNT (buffer, "buf", 1);
+ gst_buffer_unref (GST_BUFFER (buffer));
+}
+
+GstElement *
+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);
+ sinkpad = gst_check_setup_sink_pad (cmmldec, &sinktemplate, NULL);
+
+ bus = gst_bus_new ();
+ gst_element_set_bus (cmmldec, bus);
+
+ fail_unless (gst_element_set_state (cmmldec,
+ GST_STATE_PLAYING) != GST_STATE_CHANGE_FAILURE,
+ "could not set to playing");
+
+ granulerate = GST_SECOND / 1000;
+ granuleshift = 32;
+ buffers = NULL;
+
+ return cmmldec;
+}
+
+static void
+cleanup_cmmldec (GstElement * cmmldec)
+{
+ GstBus *bus;
+
+ g_list_foreach (buffers, buffer_unref, NULL);
+ g_list_free (buffers);
+
+ bus = GST_ELEMENT_BUS (cmmldec);
+ gst_bus_set_flushing (bus, TRUE);
+ gst_object_unref (bus);
+
+ GST_DEBUG ("cleanup_cmmldec");
+ gst_check_teardown_src_pad (cmmldec);
+ gst_check_teardown_sink_pad (cmmldec);
+ gst_check_teardown_element (cmmldec);
+}
+
+static void
+check_output_buffer_is_equal (const gchar * name,
+ const gchar * data, gint refcount)
+{
+ GstBuffer *buffer = GST_BUFFER (current_buf->data);
+
+ ASSERT_OBJECT_REFCOUNT (buffer, name, refcount);
+ fail_unless (memcmp (GST_BUFFER_DATA (buffer), data,
+ GST_BUFFER_SIZE (buffer)) == 0,
+ "'%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)
+{
+ 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);
+}
+
+static void
+check_headers ()
+{
+ /* 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);
+ /* push the head tag */
+ push_data ("head", HEAD_TAG, strlen (HEAD_TAG), 0, GST_FLOW_OK);
+
+ current_buf = buffers;
+ fail_unless_equals_int (g_list_length (current_buf), 2);
+
+ /* check the 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);
+}
+
+static void
+push_clip (const gchar * name, const gchar * track, GstClockTime prev,
+ GstClockTime start, GstClockTime end, GstFlowReturn expected_return)
+{
+ gchar *clip;
+ gint64 keyindex, keyoffset, granulepos;
+
+ if (track == NULL)
+ track = "default";
+
+ 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);
+ g_free (clip);
+}
+
+static void
+check_clip (const gchar * name, const gchar * track,
+ const gchar * start, const gchar * end)
+{
+ gchar *decoded_clip;
+
+ 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 ();
+
+ 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);
+ /* send EOS to flush clip-2 and clip-3 */
+ gst_pad_send_event (GST_PAD_PEER (srcpad), gst_event_new_eos ());
+
+ printf ("Check1\n");
+ check_clip ("clip-1", "default", "0:00:01.234", NULL);
+ printf ("Check2\n");
+ check_clip ("clip-2", "othertrack", "0:00:04.321", NULL);
+ printf ("Check3\n");
+ check_clip ("clip-3", "default", "100:59:59.678", NULL);
+ check_end ();
+
+ cleanup_cmmldec (cmmldec);
+}
+
+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;
+ gchar *anchor_href, *anchor_text;
+ gchar *img_src, *img_alt;
+ gchar *desc;
+ GValueArray *meta;
+
+ cmmldec = setup_cmmldec ();
+ bus = gst_element_get_bus (cmmldec);
+
+ 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);
+
+ 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 (tags != 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);
+ fail_unless (tag != NULL);
+
+ g_object_get (tag, "id", &id, "empty", &empty, "track", &track,
+ "start-time", &start_time, "end-time", &end_time,
+ "anchor-uri", &anchor_href, "anchor-text", &anchor_text,
+ "img-uri", &img_src, "img-alt", &img_alt,
+ "description", &desc, "meta", &meta, NULL);
+
+ fail_unless (empty == FALSE);
+ fail_unless_equals_string (id, "clip-1");
+ fail_unless_equals_string (track, "default");
+ fail_unless_equals_int (start_time, 1 * GST_SECOND + 234 * GST_MSECOND);
+ fail_unless_equals_uint64 (end_time, GST_CLOCK_TIME_NONE);
+ fail_unless_equals_string (anchor_href, "http://www.csiro.au/");
+ fail_unless_equals_string (anchor_text, "http://www.csiro.au");
+ fail_unless_equals_string (img_src, "images/index1.jpg");
+ fail_unless (img_alt == NULL);
+ fail_unless_equals_string (desc, "Welcome to CSIRO");
+ fail_unless (meta != NULL);
+ fail_unless_equals_int (meta->n_values, 2);
+
+ g_free (id);
+ g_free (track);
+ g_free (anchor_href);
+ g_free (anchor_text);
+ g_free (img_src);
+ 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);
+}
+
+GST_END_TEST;
+
+Suite *
+cmmldec_suite ()
+{
+ Suite *s = suite_create ("cmmldec");
+ TCase *tc_chain = tcase_create ("general");
+
+ suite_add_tcase (s, tc_chain);
+ tcase_add_test (tc_chain, test_dec);
+ tcase_add_test (tc_chain, test_tags);
+
+ return s;
+}
+
+int
+main (int argc, char **argv)
+{
+ int nf;
+
+ Suite *s = cmmldec_suite ();
+ SRunner *sr = srunner_create (s);
+
+ gst_check_init (&argc, &argv);
+
+ srunner_run_all (sr, CK_NORMAL);
+ nf = srunner_ntests_failed (sr);
+ srunner_free (sr);
+
+ return nf;
+}
diff --git a/tests/check/elements/cmmlenc.c b/tests/check/elements/cmmlenc.c
new file mode 100644
index 00000000..da01984b
--- /dev/null
+++ b/tests/check/elements/cmmlenc.c
@@ -0,0 +1,361 @@
+/*
+ * cmmlenc.c - GStreamer CMML decoder test suite
+ * Copyright (C) 2005 Alessandro Decina
+ *
+ * Authors:
+ * Alessandro Decina <alessandro@nnva.org>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+#include <gst/check/gstcheck.h>
+
+#define SINK_CAPS "text/x-cmml"
+#define SRC_CAPS "text/xml"
+
+#define IDENT_HEADER \
+ "CMML\x00\x00\x00\x00"\
+ "\x03\x00\x00\x00"\
+ "\x01\x00\x00\x00\x00\x00\x00\x00"\
+ "\xe8\x03\x00\x00\x00\x00\x00\x00"\
+ "\x20"
+
+#define XML_PREAMBLE \
+ "<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"yes\"?>\n"\
+ "<!DOCTYPE cmml SYSTEM \"cmml.dtd\">\n"
+
+#define START_TAG \
+ "<cmml>"
+
+#define PROCESSING_INSTRUCTION \
+ "<?cmml ?>"
+
+#define PREAMBLE \
+ XML_PREAMBLE START_TAG
+
+#define PREAMBLE_ENCODED \
+ XML_PREAMBLE PROCESSING_INSTRUCTION
+
+#define STREAM_TAG \
+ "<stream timebase=\"10\">"\
+ "<import src=\"test.ogg\"/>"\
+ "<import src=\"test1.ogg\"/>"\
+ "</stream>"
+
+#define STREAM_TAG_ENCODED STREAM_TAG
+
+#define HEAD_TAG \
+ "<head>"\
+ "<title>The Research Hunter</title>"\
+ "<meta name=\"DC.audience\" content=\"General\"/>"\
+ "<meta name=\"DC.author\" content=\"CSIRO Publishing\"/>"\
+ "<meta name=\"DC.format\" content=\"video\"/>"\
+ "<meta name=\"DC.language\" content=\"English\"/>"\
+ "<meta name=\"DC.publisher\" content=\"CSIRO Australia\"/>"\
+ "</head>"
+
+#define HEAD_TAG_ENCODED HEAD_TAG
+
+#define END_TAG \
+ "</cmml>"
+
+#define CLIP_TEMPLATE \
+ "<clip id=\"%s\" track=\"%s\" start=\"%s\">"\
+ "<a href=\"http://www.annodex.org/\">http://www.annodex.org</a>"\
+ "<img src=\"images/index.jpg\"/>"\
+ "<desc>Annodex Foundation</desc>"\
+ "<meta name=\"test\" content=\"test content\"/>"\
+ "</clip>"
+
+#define CLIP_TEMPLATE_ENCODED \
+ "<clip id=\"%s\" track=\"%s\">"\
+ "<a href=\"http://www.annodex.org/\">http://www.annodex.org</a>"\
+ "<img src=\"images/index.jpg\"/>"\
+ "<desc>Annodex Foundation</desc>"\
+ "<meta name=\"test\" content=\"test content\"/>"\
+ "</clip>"
+
+GList *buffers;
+GList *current_buf = NULL;
+guint64 granulerate;
+guint8 granuleshift;
+
+GstPad *srcpad, *sinkpad;
+
+static GstStaticPadTemplate sinktemplate = GST_STATIC_PAD_TEMPLATE ("sink",
+ GST_PAD_SINK,
+ GST_PAD_ALWAYS,
+ GST_STATIC_CAPS (SINK_CAPS)
+ );
+
+static GstStaticPadTemplate srctemplate = GST_STATIC_PAD_TEMPLATE ("src",
+ GST_PAD_SRC,
+ GST_PAD_ALWAYS,
+ GST_STATIC_CAPS (SRC_CAPS)
+ );
+
+GstBuffer *
+buffer_new (const gchar * buffer_data, guint size)
+{
+ GstBuffer *buffer;
+ GstCaps *caps;
+
+ buffer = gst_buffer_new_and_alloc (size);
+ memcpy (GST_BUFFER_DATA (buffer), buffer_data, size);
+ caps = gst_caps_from_string (SRC_CAPS);
+ gst_buffer_set_caps (buffer, caps);
+ gst_caps_unref (caps);
+
+ return buffer;
+}
+
+static void
+buffer_unref (void *buffer, void *user_data)
+{
+ gst_buffer_unref (GST_BUFFER (buffer));
+}
+
+GstElement *
+setup_cmmlenc ()
+{
+ GstElement *cmmlenc;
+ GstBus *bus;
+ guint64 granulerate_n, granulerate_d;
+
+ GST_DEBUG ("setup_cmmlenc");
+
+ cmmlenc = gst_check_setup_element ("cmmlenc");
+ srcpad = gst_check_setup_src_pad (cmmlenc, &srctemplate, NULL);
+ sinkpad = gst_check_setup_sink_pad (cmmlenc, &sinktemplate, NULL);
+
+ bus = gst_bus_new ();
+ gst_element_set_bus (cmmlenc, bus);
+
+ fail_unless (gst_element_set_state (cmmlenc,
+ GST_STATE_PLAYING) != GST_STATE_CHANGE_FAILURE,
+ "could not set to playing");
+
+ g_object_get (cmmlenc, "granule-rate-numerator", &granulerate_n,
+ "granule-rate-denominator", &granulerate_d,
+ "granule-shift", &granuleshift, NULL);
+
+ granulerate = GST_SECOND * granulerate_n / granulerate_d;
+ buffers = NULL;
+ return cmmlenc;
+}
+
+static void
+cleanup_cmmlenc (GstElement * cmmlenc)
+{
+ GstBus *bus;
+
+ /* free encoded buffers */
+ g_list_foreach (buffers, buffer_unref, NULL);
+ g_list_free (buffers);
+ buffers = NULL;
+
+ bus = GST_ELEMENT_BUS (cmmlenc);
+ gst_bus_set_flushing (bus, TRUE);
+ gst_object_unref (bus);
+
+ GST_DEBUG ("cleanup_cmmlenc");
+ gst_check_teardown_src_pad (cmmlenc);
+ gst_check_teardown_sink_pad (cmmlenc);
+ gst_check_teardown_element (cmmlenc);
+}
+
+static void
+check_output_buffer_is_equal (const gchar * name,
+ const gchar * data, gint refcount)
+{
+ GstBuffer *buffer = GST_BUFFER (current_buf->data);
+
+ ASSERT_OBJECT_REFCOUNT (buffer, name, refcount);
+ fail_unless (memcmp (GST_BUFFER_DATA (buffer), data,
+ GST_BUFFER_SIZE (buffer)) == 0,
+ "'%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, GstFlowReturn expected_return)
+{
+ GstBuffer *buffer;
+ GstFlowReturn res;
+
+ buffer = buffer_new (data, size);
+ res = gst_pad_push (srcpad, buffer);
+ fail_unless (res == expected_return,
+ "pushing %s returned %d not %d", name, res, expected_return);
+}
+
+static void
+check_headers ()
+{
+ /* push the cmml start tag */
+ push_data ("preamble", PREAMBLE, strlen (PREAMBLE), GST_FLOW_OK);
+ /* push the stream tag */
+ push_data ("stream", STREAM_TAG, strlen (STREAM_TAG), GST_FLOW_OK);
+ /* push the head tag */
+ push_data ("head", HEAD_TAG, strlen (HEAD_TAG), GST_FLOW_OK);
+
+ /* should output the cmml ident header and the cmml start tag transformed
+ * into a processing instruction */
+ current_buf = buffers;
+ fail_unless_equals_int (g_list_length (current_buf), 3);
+
+ /* check the ident header */
+ check_output_buffer_is_equal ("cmml-ident-buffer", IDENT_HEADER, 2);
+
+ /* check the cmml processing instruction */
+ current_buf = current_buf->next;
+ check_output_buffer_is_equal ("cmml-preamble-buffer", PREAMBLE_ENCODED, 2);
+
+ /* check the encoded head tag */
+ current_buf = current_buf->next;
+ check_output_buffer_is_equal ("head-tag-buffer", HEAD_TAG_ENCODED, 2);
+}
+
+static void
+push_clip (const gchar * name, const gchar * track,
+ const gchar * start, const gchar * end, GstFlowReturn expected_return)
+{
+ gchar *clip;
+
+ if (track == NULL)
+ track = "default";
+
+ clip = g_strdup_printf (CLIP_TEMPLATE, name, track, start, end);
+ push_data (name, clip, strlen (clip), expected_return);
+ g_free (clip);
+}
+
+static void
+check_clip (const gchar * name, const gchar * track,
+ GstClockTime start, GstClockTime prev)
+{
+ gchar *encoded_clip;
+ GstBuffer *buffer;
+ gint64 keyindex, keyoffset, granulepos;
+
+ if (track == NULL)
+ track = "default";
+
+ current_buf = current_buf->next;
+ fail_unless (g_list_length (current_buf));
+ encoded_clip = g_strdup_printf (CLIP_TEMPLATE_ENCODED, name, track);
+ check_output_buffer_is_equal (name, encoded_clip, 1);
+ g_free (encoded_clip);
+ buffer = GST_BUFFER (current_buf->data);
+ granulepos = GST_BUFFER_OFFSET_END (GST_BUFFER (buffer));
+ keyindex = granulepos >> granuleshift;
+ keyoffset = granulepos - (keyindex << granuleshift);
+ fail_unless_equals_uint64 (keyindex * granulerate, prev);
+ fail_unless_equals_uint64 ((keyindex + keyoffset) * granulerate, start);
+}
+
+static void
+push_end ()
+{
+ push_data ("end", END_TAG, strlen (END_TAG), GST_FLOW_OK);
+}
+
+static void
+check_end ()
+{
+ /* should output the EOS page */
+ current_buf = current_buf->next;
+ fail_unless_equals_int (g_list_length (current_buf), 1);
+ check_output_buffer_is_equal ("cmml-eos-buffer", NULL, 1);
+}
+
+GST_START_TEST (test_enc)
+{
+ GstElement *cmmlenc;
+
+ cmmlenc = setup_cmmlenc ();
+
+ check_headers ();
+
+ push_clip ("clip-1", "default", "1.234", NULL, GST_FLOW_OK);
+ check_clip ("clip-1", "default", 1234 * granulerate, 0);
+
+ push_clip ("clip-2", NULL, "5.678", NULL, GST_FLOW_OK);
+ check_clip ("clip-2", "default", 5678 * granulerate, 1234 * granulerate);
+
+ push_clip ("clip-3", "othertrack", "9.123", NULL, GST_FLOW_OK);
+ check_clip ("clip-3", "othertrack", 9123 * granulerate, 0);
+
+ push_end ();
+ check_end ();
+
+ cleanup_cmmlenc (cmmlenc);
+}
+
+GST_END_TEST;
+
+GST_START_TEST (test_bad_start_time)
+{
+ GstElement *cmmlenc;
+
+ cmmlenc = setup_cmmlenc ();
+
+ check_headers ();
+
+ push_clip ("clip-1", "default", "1.234", NULL, GST_FLOW_OK);
+ check_clip ("clip-1", "default", 1234 * granulerate, 0);
+
+ push_clip ("clip-bad", "default", "1.1000", NULL, GST_FLOW_ERROR);
+
+ push_clip ("clip-2", NULL, "5.678", NULL, GST_FLOW_OK);
+ check_clip ("clip-2", "default", 5678 * granulerate, 1234 * granulerate);
+
+ push_clip ("clip-3", "othertrack", "9.123", NULL, GST_FLOW_OK);
+ check_clip ("clip-3", "othertrack", 9123 * granulerate, 0);
+
+ push_end ();
+ check_end ();
+
+ cleanup_cmmlenc (cmmlenc);
+}
+GST_END_TEST static Suite *
+cmmlenc_suite ()
+{
+ Suite *s = suite_create ("cmmlenc");
+ TCase *tc_chain = tcase_create ("general");
+
+ suite_add_tcase (s, tc_chain);
+ tcase_add_test (tc_chain, test_enc);
+ tcase_add_test (tc_chain, test_bad_start_time);
+ return s;
+}
+
+int
+main (int argc, char **argv)
+{
+ int nf;
+
+ Suite *s = cmmlenc_suite ();
+ SRunner *sr = srunner_create (s);
+
+ gst_check_init (&argc, &argv);
+
+ srunner_run_all (sr, CK_NORMAL);
+ nf = srunner_ntests_failed (sr);
+ srunner_free (sr);
+
+ return nf;
+}
diff --git a/tests/check/elements/skeldec.c b/tests/check/elements/skeldec.c
new file mode 100644
index 00000000..04d6dd3b
--- /dev/null
+++ b/tests/check/elements/skeldec.c
@@ -0,0 +1,258 @@
+/*
+ * skeldec.c - GStreamer annodex skeleton decoder test suite
+ * Copyright (C) 2005 Alessandro Decina
+ *
+ * Authors:
+ * Alessandro Decina <alessandro@nnva.org>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+#include <gst/check/gstcheck.h>
+
+GList *buffers;
+
+GstPad *srcpad, *sinkpad;
+
+#define SKELETON_CAPS "application/x-ogg-skeleton"
+
+#define SKELETON_FISHEAD \
+ "fishead\0"\
+ "\x03\0\0\0"\
+ "\x39\x30\0\0\0\0\0\0"\
+ "\x39\x30\0\0\0\0\0\0"\
+ "\x39\x30\0\0\0\0\0\0"\
+ "\x39\x30\0\0\0\0\0\0"\
+ "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+
+#define SKELETON_FISHEAD_SIZE 64
+
+#define SKELETON_FISBONE \
+ "fisbone\0"\
+ "\x2c\0\0\0"\
+ "\x39\x30\0\0"\
+ "\x39\x30\0\0"\
+ "\x39\x30\0\0\0\0\0\0"\
+ "\x39\x30\0\0\0\0\0\0"\
+ "\x39\x30\0\0\0\0\0\0"\
+ "\x39\x30\0\0"\
+ "\x20"\
+ "\0\0\0"\
+ "Content-Type: application/ogg; UTF-8\r\n"
+
+#define SKELETON_FISBONE_SIZE 90
+
+static GstStaticPadTemplate sinktemplate = GST_STATIC_PAD_TEMPLATE ("sink",
+ GST_PAD_SINK,
+ GST_PAD_ALWAYS,
+ GST_STATIC_CAPS_ANY);
+
+static GstStaticPadTemplate srctemplate = GST_STATIC_PAD_TEMPLATE ("src",
+ GST_PAD_SRC,
+ GST_PAD_ALWAYS,
+ GST_STATIC_CAPS (SKELETON_CAPS)
+ );
+
+static GstElement *
+setup_skeldec ()
+{
+ GstElement *skeldec;
+
+ GST_DEBUG ("setup_skeldec");
+ skeldec = gst_check_setup_element ("skeldec");
+ srcpad = gst_check_setup_src_pad (skeldec, &srctemplate, NULL);
+ sinkpad = gst_check_setup_sink_pad (skeldec, &sinktemplate, NULL);
+
+ return skeldec;
+}
+
+static void
+cleanup_skeldec (GstElement * skeldec)
+{
+ GST_DEBUG ("cleanup_skeldec");
+
+ gst_check_teardown_src_pad (skeldec);
+ gst_check_teardown_sink_pad (skeldec);
+ gst_check_teardown_element (skeldec);
+}
+
+static void
+skel_buffer_unref (void *buf, void *user_data)
+{
+ GstBuffer *buffer = GST_BUFFER (buf);
+
+ ASSERT_OBJECT_REFCOUNT (buffer, "skel-buffer", 1);
+ gst_buffer_unref (buffer);
+}
+
+static GstBuffer *
+skel_buffer_new (gchar * buffer_data, guint size)
+{
+ GstBuffer *buffer;
+ GstCaps *caps;
+
+ buffer = gst_buffer_new_and_alloc (size);
+ memcpy (GST_BUFFER_DATA (buffer), buffer_data, size);
+ caps = gst_caps_from_string (SKELETON_CAPS);
+ gst_buffer_set_caps (buffer, caps);
+ gst_caps_unref (caps);
+
+ return buffer;
+}
+
+GST_START_TEST (test_dec)
+{
+ GstElement *skeldec;
+ GstBus *bus;
+ GstBuffer *inbuffer;
+ GstMessage *message;
+ GstTagList *tags;
+ const GValue *tag_val, *val;
+ GObject *tag;
+ gint major, minor;
+ gint64 prestime_n, prestime_d;
+ gint64 basetime_n, basetime_d;
+ guint serial_number;
+ gint64 granule_rate_n, granule_rate_d;
+ gint64 granule_start;
+ guint64 preroll;
+ guint granule_shift;
+ GValueArray *headers;
+ gchar *content_type;
+ gchar *encoding;
+
+ skeldec = setup_skeldec ();
+
+ bus = gst_bus_new ();
+ gst_element_set_bus (skeldec, bus);
+
+ fail_unless (gst_element_set_state (skeldec,
+ GST_STATE_PLAYING) == GST_STATE_CHANGE_SUCCESS,
+ "could not set to playing");
+
+ /* test the fishead */
+ inbuffer = skel_buffer_new (SKELETON_FISHEAD, SKELETON_FISHEAD_SIZE);
+ fail_unless_equals_int (gst_pad_push (srcpad, inbuffer), GST_FLOW_OK);
+
+ message = gst_bus_poll (bus, GST_MESSAGE_TAG, -1);
+ fail_unless (GST_MESSAGE_SRC (message) == GST_OBJECT (skeldec));
+
+ gst_message_parse_tag (message, &tags);
+ fail_unless (tags != NULL);
+ fail_unless_equals_int (gst_tag_list_get_tag_size (tags,
+ GST_TAG_SKELETON_FISHEAD), 1);
+
+ tag_val = gst_tag_list_get_value_index (tags, GST_TAG_SKELETON_FISHEAD, 0);
+ fail_unless (tag_val != NULL);
+
+ tag = g_value_get_object (tag_val);
+ fail_unless (tag != NULL);
+
+ g_object_get (tag,
+ "version-major", &major, "version-minor", &minor,
+ "presentation-time-numerator", &prestime_n,
+ "presentation-time-denominator", &prestime_d,
+ "base-time-numerator", &basetime_n,
+ "base-time-denominator", &basetime_d, NULL);
+
+ fail_unless_equals_int (major, 3);
+ fail_unless_equals_int (minor, 0);
+ fail_unless_equals_int (prestime_n, 12345);
+ fail_unless_equals_int (prestime_d, 12345);
+ fail_unless_equals_int (basetime_n, 12345);
+ fail_unless_equals_int (basetime_d, 12345);
+
+ gst_tag_list_free (tags);
+ gst_message_unref (message);
+
+ /* test the fisbone */
+ inbuffer = skel_buffer_new (SKELETON_FISBONE, SKELETON_FISBONE_SIZE);
+ fail_unless_equals_int (gst_pad_push (srcpad, inbuffer), GST_FLOW_OK);
+
+ message = gst_bus_poll (bus, GST_MESSAGE_TAG, -1);
+ fail_unless (GST_MESSAGE_SRC (message) == GST_OBJECT (skeldec));
+
+ gst_message_parse_tag (message, &tags);
+ fail_unless (tags != NULL);
+ fail_unless_equals_int (gst_tag_list_get_tag_size (tags,
+ GST_TAG_SKELETON_FISBONE), 1);
+
+ tag_val = gst_tag_list_get_value_index (tags, GST_TAG_SKELETON_FISBONE, 0);
+ fail_unless (tag_val != NULL);
+
+ tag = g_value_get_object (tag_val);
+ fail_unless (tag != NULL);
+
+ g_object_get (tag, "serial-number", &serial_number,
+ "granule-rate-numerator", &granule_rate_n,
+ "granule-rate-denominator", &granule_rate_d,
+ "granule-start", &granule_start,
+ "granule-shift", &granule_shift,
+ "preroll", &preroll,
+ "headers", &headers,
+ "content-type", &content_type, "encoding", &encoding, NULL);
+
+ fail_unless_equals_int (serial_number, 12345);
+ fail_unless_equals_int (granule_rate_n, 12345);
+ fail_unless_equals_int (granule_rate_d, 12345);
+ fail_unless_equals_int (granule_start, 12345);
+ fail_unless_equals_int (preroll, 12345);
+ fail_unless_equals_int (granule_shift, 32);
+ fail_unless_equals_int (headers->n_values, 2);
+ fail_unless_equals_string (content_type, "application/ogg");
+ fail_unless_equals_string (encoding, "UTF-8");
+
+ g_value_array_free (headers);
+ g_free (content_type);
+ g_free (encoding);
+ gst_tag_list_free (tags);
+ gst_message_unref (message);
+ gst_bus_set_flushing (bus, TRUE);
+ gst_object_unref (bus);
+ g_list_foreach (buffers, skel_buffer_unref, NULL);
+ cleanup_skeldec (skeldec);
+}
+
+GST_END_TEST;
+
+static Suite *
+skeldec_suite ()
+{
+ Suite *s = suite_create ("skeldec");
+ TCase *tc_chain = tcase_create ("general");
+
+ suite_add_tcase (s, tc_chain);
+ tcase_add_test (tc_chain, test_dec);
+
+ return s;
+}
+
+int
+main (int argc, char **argv)
+{
+ int nf;
+
+ Suite *s = skeldec_suite ();
+ SRunner *sr = srunner_create (s);
+
+ gst_check_init (&argc, &argv);
+
+ srunner_run_all (sr, CK_NORMAL);
+ nf = srunner_ntests_failed (sr);
+ srunner_free (sr);
+
+ return nf;
+}