aboutsummaryrefslogtreecommitdiff
path: root/tests/check/elements
diff options
context:
space:
mode:
authorOlivier Naudan <o-naudan@ti.com>2012-04-16 08:10:18 -0400
committerOlivier Naudan <o-naudan@ti.com>2012-04-16 08:10:18 -0400
commitb28313f8d15c35cc3b5ef6f975d24dcaef9736cf (patch)
tree82fce69684830e7e0b9563d7161e57a608b2b8c5 /tests/check/elements
Imported Upstream version 0.11.90upstream/0.11.90
Diffstat (limited to 'tests/check/elements')
-rw-r--r--tests/check/elements/asfmux.c222
-rw-r--r--tests/check/elements/assrender.c298
-rw-r--r--tests/check/elements/autoconvert.c243
-rw-r--r--tests/check/elements/autovideoconvert.c139
-rw-r--r--tests/check/elements/baseaudiovisualizer.c179
-rw-r--r--tests/check/elements/camerabin.c847
-rw-r--r--tests/check/elements/camerabin2.c1585
-rw-r--r--tests/check/elements/dataurisrc.c233
-rw-r--r--tests/check/elements/faac.c260
-rw-r--r--tests/check/elements/faad.c221
-rw-r--r--tests/check/elements/h263parse.c175
-rw-r--r--tests/check/elements/h264parse.c402
-rw-r--r--tests/check/elements/id3mux.c557
-rw-r--r--tests/check/elements/jifmux.c1239
-rw-r--r--tests/check/elements/jpegparse.c402
-rw-r--r--tests/check/elements/kate.c858
-rw-r--r--tests/check/elements/legacyresample.c574
-rw-r--r--tests/check/elements/logoinsert.c252
-rw-r--r--tests/check/elements/mpeg2enc.c208
-rw-r--r--tests/check/elements/mpeg4videoparse.c200
-rw-r--r--tests/check/elements/mpegtsmux.c323
-rw-r--r--tests/check/elements/mpegvideoparse.c275
-rw-r--r--tests/check/elements/mplex.c314
-rw-r--r--tests/check/elements/mxfdemux.c280
-rw-r--r--tests/check/elements/mxfdemux.h2552
-rw-r--r--tests/check/elements/mxfmux.c261
-rw-r--r--tests/check/elements/neonhttpsrc.c190
-rw-r--r--tests/check/elements/ofa.c396
-rw-r--r--tests/check/elements/opus.c385
-rw-r--r--tests/check/elements/parser.c428
-rw-r--r--tests/check/elements/parser.h117
-rw-r--r--tests/check/elements/rtpmux.c305
-rw-r--r--tests/check/elements/schroenc.c177
-rw-r--r--tests/check/elements/timidity.c89
-rw-r--r--tests/check/elements/viewfinderbin.c103
-rw-r--r--tests/check/elements/voaacenc.c263
-rw-r--r--tests/check/elements/voamrwbenc.c194
-rw-r--r--tests/check/elements/vp8dec.c178
-rw-r--r--tests/check/elements/vp8enc.c168
-rw-r--r--tests/check/elements/zbar.c116
40 files changed, 16208 insertions, 0 deletions
diff --git a/tests/check/elements/asfmux.c b/tests/check/elements/asfmux.c
new file mode 100644
index 00000000..de0007e3
--- /dev/null
+++ b/tests/check/elements/asfmux.c
@@ -0,0 +1,222 @@
+/* GStreamer
+ *
+ * unit test for asfmux
+ *
+ * Copyright (C) <2008> Thiago Santos <thiagoss@embedded.ufcg.edu.br>
+ *
+ * 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 <unistd.h>
+
+#include <gst/check/gstcheck.h>
+
+/* For ease of programming we use globals to keep refs for our floating
+ * src and sink pads we create; otherwise we always have to do get_pad,
+ * get_peer, and then remove references in every test function */
+static GstPad *mysrcpad, *mysinkpad;
+
+#define AUDIO_CAPS_STRING "audio/x-wma, " \
+ "channels = (int) 2, " \
+ "rate = (int) 8000, " \
+ "wmaversion = (int) 2, " \
+ "block-align = (int) 14, " \
+ "bitrate = (int) 64000"
+
+#define VIDEO_CAPS_STRING "video/x-wmv, " \
+ "width = (int) 384, " \
+ "height = (int) 288, " \
+ "framerate = (fraction) 25/1, " \
+ "wmvversion = (int) 2"
+
+static GstStaticPadTemplate sinktemplate = GST_STATIC_PAD_TEMPLATE ("sink",
+ GST_PAD_SINK,
+ GST_PAD_ALWAYS,
+ GST_STATIC_CAPS ("video/x-ms-asf"));
+static GstStaticPadTemplate srcvideotemplate = GST_STATIC_PAD_TEMPLATE ("src",
+ GST_PAD_SRC,
+ GST_PAD_ALWAYS,
+ GST_STATIC_CAPS (VIDEO_CAPS_STRING));
+static GstStaticPadTemplate srcaudiotemplate = GST_STATIC_PAD_TEMPLATE ("src",
+ GST_PAD_SRC,
+ GST_PAD_ALWAYS,
+ GST_STATIC_CAPS (AUDIO_CAPS_STRING));
+
+static GstPad *
+setup_src_pad (GstElement * element,
+ GstStaticPadTemplate * template, GstCaps * caps, const gchar * sinkname)
+{
+ GstPad *srcpad, *sinkpad;
+
+ GST_DEBUG_OBJECT (element, "setting up sending pad");
+ /* sending pad */
+ srcpad = gst_pad_new_from_static_template (template, "src");
+ fail_if (srcpad == NULL, "Could not create a srcpad");
+ ASSERT_OBJECT_REFCOUNT (srcpad, "srcpad", 1);
+
+ if (!(sinkpad = gst_element_get_static_pad (element, sinkname)))
+ sinkpad = gst_element_get_request_pad (element, sinkname);
+ fail_if (sinkpad == NULL, "Could not get sink pad from %s",
+ GST_ELEMENT_NAME (element));
+ /* references are owned by: 1) us, 2) asfmux, 3) collect pads */
+ ASSERT_OBJECT_REFCOUNT (sinkpad, "sinkpad", 3);
+ if (caps)
+ fail_unless (gst_pad_set_caps (srcpad, caps));
+ fail_unless (gst_pad_link (srcpad, sinkpad) == GST_PAD_LINK_OK,
+ "Could not link source and %s sink pads", GST_ELEMENT_NAME (element));
+ gst_object_unref (sinkpad); /* because we got it higher up */
+
+ /* references are owned by: 1) asfmux, 2) collect pads */
+ ASSERT_OBJECT_REFCOUNT (sinkpad, "sinkpad", 2);
+
+ return srcpad;
+}
+
+static void
+teardown_src_pad (GstElement * element, const gchar * sinkname)
+{
+ GstPad *srcpad, *sinkpad;
+ gchar *padname;
+
+ /* clean up floating src pad */
+ padname = g_strdup_printf (sinkname, 1);
+ if (!(sinkpad = gst_element_get_static_pad (element, padname)))
+ sinkpad = gst_element_get_request_pad (element, padname);
+ g_free (padname);
+
+ fail_if (sinkpad == NULL, "sinkpad is null");
+
+ /* pad refs held by 1) asfmux 2) collectpads and 3) us (through _get) */
+ ASSERT_OBJECT_REFCOUNT (sinkpad, "sinkpad", 3);
+ fail_unless (gst_pad_is_linked (sinkpad));
+ srcpad = gst_pad_get_peer (sinkpad);
+
+ fail_if (srcpad == NULL, "Couldn't get srcpad");
+ gst_pad_unlink (srcpad, sinkpad);
+
+ /* after unlinking, pad refs still held by
+ * 1) asfmux and 2) collectpads and 3) us (through _get) */
+ ASSERT_OBJECT_REFCOUNT (sinkpad, "sinkpad", 3);
+ gst_object_unref (sinkpad);
+ /* one more ref is held by element itself */
+
+ /* pad refs held by both creator and this function (through _get_peer) */
+ ASSERT_OBJECT_REFCOUNT (srcpad, "srcpad", 2);
+ gst_object_unref (srcpad);
+ gst_object_unref (srcpad);
+}
+
+static GstElement *
+setup_asfmux (GstStaticPadTemplate * srctemplate, const gchar * sinkname)
+{
+ GstElement *asfmux;
+
+ GST_DEBUG ("setup_asfmux");
+ asfmux = gst_check_setup_element ("asfmux");
+
+ mysrcpad = setup_src_pad (asfmux, srctemplate, NULL, sinkname);
+ mysinkpad = gst_check_setup_sink_pad (asfmux, &sinktemplate);
+ gst_pad_set_active (mysrcpad, TRUE);
+ gst_pad_set_active (mysinkpad, TRUE);
+ return asfmux;
+}
+
+static void
+cleanup_asfmux (GstElement * asfmux, const gchar * sinkname)
+{
+ GST_DEBUG ("cleanup_asfmux");
+ gst_element_set_state (asfmux, GST_STATE_NULL);
+ gst_pad_set_active (mysrcpad, FALSE);
+ gst_pad_set_active (mysinkpad, FALSE);
+ teardown_src_pad (asfmux, sinkname);
+ gst_check_teardown_sink_pad (asfmux);
+ gst_check_teardown_element (asfmux);
+}
+
+static void
+check_asfmux_pad (GstStaticPadTemplate * srctemplate,
+ const gchar * src_caps_string, const gchar * sinkname)
+{
+ GstElement *asfmux;
+ GstBuffer *inbuffer;
+ GstCaps *caps;
+ GstFlowReturn ret;
+ GList *l;
+
+ asfmux = setup_asfmux (srctemplate, sinkname);
+ fail_unless (gst_element_set_state (asfmux,
+ GST_STATE_PLAYING) == GST_STATE_CHANGE_SUCCESS,
+ "could not set to playing");
+
+ inbuffer = gst_buffer_new_and_alloc (1);
+ caps = gst_caps_from_string (src_caps_string);
+ gst_pad_set_caps (mysrcpad, caps);
+ gst_caps_unref (caps);
+ GST_BUFFER_TIMESTAMP (inbuffer) = 0;
+ ASSERT_BUFFER_REFCOUNT (inbuffer, "inbuffer", 1);
+ ret = gst_pad_push (mysrcpad, inbuffer);
+ fail_unless (ret == GST_FLOW_OK, "Pad push returned: %d", ret);
+
+ cleanup_asfmux (asfmux, sinkname);
+ for (l = buffers; l; l = l->next)
+ gst_buffer_unref (l->data);
+ g_list_free (buffers);
+ buffers = NULL;
+}
+
+GST_START_TEST (test_video_pad)
+{
+ check_asfmux_pad (&srcvideotemplate, VIDEO_CAPS_STRING, "video_%u");
+}
+
+GST_END_TEST;
+
+GST_START_TEST (test_audio_pad)
+{
+ check_asfmux_pad (&srcaudiotemplate, AUDIO_CAPS_STRING, "audio_%u");
+}
+
+GST_END_TEST;
+
+static Suite *
+asfmux_suite (void)
+{
+ Suite *s = suite_create ("asfmux");
+ TCase *tc_chain = tcase_create ("general");
+ tcase_add_test (tc_chain, test_video_pad);
+ tcase_add_test (tc_chain, test_audio_pad);
+
+ suite_add_tcase (s, tc_chain);
+
+ return s;
+}
+
+int
+main (int argc, char **argv)
+{
+ int nf;
+
+ Suite *s = asfmux_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/assrender.c b/tests/check/elements/assrender.c
new file mode 100644
index 00000000..c07c36ed
--- /dev/null
+++ b/tests/check/elements/assrender.c
@@ -0,0 +1,298 @@
+/* GStreamer
+ * Copyright (C) 2010 Sebastian Dröge <sebastian.droege@collabora.co.uk>
+ *
+ * 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 <string.h>
+
+#include <gst/check/gstcheck.h>
+#include <gst/video/video.h>
+#include <gst/app/gstappsrc.h>
+
+static gboolean
+bus_handler (GstBus * bus, GstMessage * message, gpointer data)
+{
+ GMainLoop *loop = (GMainLoop *) data;
+
+ switch (message->type) {
+ case GST_MESSAGE_EOS:
+ g_main_loop_quit (loop);
+ break;
+ case GST_MESSAGE_WARNING:
+ case GST_MESSAGE_ERROR:{
+ GError *gerror;
+ gchar *debug;
+
+ if (message->type == GST_MESSAGE_WARNING)
+ gst_message_parse_warning (message, &gerror, &debug);
+ else
+ gst_message_parse_error (message, &gerror, &debug);
+ gst_object_default_error (GST_MESSAGE_SRC (message), gerror, debug);
+ gst_message_unref (message);
+ g_error_free (gerror);
+ g_free (debug);
+ g_main_loop_quit (loop);
+ break;
+ }
+ default:
+ break;
+ }
+
+ return TRUE;
+}
+
+typedef struct
+{
+ GstClockTime ts;
+ GstClockTime duration;
+ const gchar buf[];
+} TestBuffer;
+
+static const TestBuffer buf0 = {
+ 0,
+ 0,
+ "[Script Info]\n"
+ "; This is a Sub Station Alpha v4 script.\n"
+ "; For Sub Station Alpha info and downloads,\n"
+ "; go to http://www.eswat.demon.co.uk/\n"
+ "Title: Some Test\n"
+ "Script Updated By: version 2.8.01\n"
+ "ScriptType: v4.00\n"
+ "Collisions: Normal\n"
+ "PlayResY: 200\n"
+ "PlayDepth: 0\n"
+ "Timer: 100,0000\n"
+ " \n"
+ "[V4 Styles]\n"
+ "Format: Name, Fontname, Fontsize, PrimaryColour, SecondaryColour, TertiaryColour, BackColour, Bold, Italic, BorderStyle, Outline, Shadow, \n"
+ " Alignment, MarginL, MarginR, MarginV, AlphaLevel, Encoding\n"
+ "Style: DefaultVCD, Arial,28,11861244,11861244,11861244,-2147483640,-1,0,1,1,2,2,30,30,30,0,0\n"
+ " \n"
+ "[Events]\n"
+ "Format: Marked, Start, End, Style, Name, MarginL, MarginR, MarginV, Effect, Text"
+};
+
+static const TestBuffer buf1 = {
+ 40 * GST_MSECOND,
+ 60 * GST_MSECOND,
+ "1,,DefaultVCD, NTP,0000,0000,0000,,Some Test Blabla"
+};
+
+static void
+sink_handoff_cb_xRGB (GstElement * object, GstBuffer * buffer, GstPad * pad,
+ gpointer user_data)
+{
+ guint *sink_pos = (guint *) user_data;
+ gboolean contains_text = (*sink_pos == 1 || *sink_pos == 2);
+ guint i, j;
+ GstMapInfo map;
+ gboolean all_red = TRUE;
+
+ gst_buffer_map (buffer, &map, GST_MAP_READ);
+
+ fail_unless_equals_int (map.size, 640 * 480 * 4);
+
+ for (i = 0; i < 640; i++) {
+ for (j = 0; j < 480; j++) {
+ all_red = all_red && (map.data[i * 480 * 4 + j * 4 + 1] == 255 &&
+ map.data[i * 480 * 4 + j * 4 + 2] == 0 &&
+ map.data[i * 480 * 4 + j * 4 + 3] == 0);
+ }
+ }
+ gst_buffer_unmap (buffer, &map);
+
+ fail_unless (contains_text != all_red,
+ "Frame %d is incorrect (all red %d, contains text %d)", *sink_pos,
+ all_red, contains_text);
+ *sink_pos = *sink_pos + 1;
+}
+
+static void
+sink_handoff_cb_I420 (GstElement * object, GstBuffer * buffer, GstPad * pad,
+ gpointer user_data)
+{
+ guint *sink_pos = (guint *) user_data;
+ gboolean contains_text = (*sink_pos == 1 || *sink_pos == 2);
+ guint c, i, j;
+ gboolean all_red = TRUE;
+ guint8 *comp;
+ gint comp_stride, comp_width, comp_height;
+ const guint8 color[] = { 81, 90, 240 };
+ GstVideoInfo info;
+ GstVideoFrame frame;
+
+ gst_video_info_init (&info);
+ gst_video_info_set_format (&info, GST_VIDEO_FORMAT_I420, 640, 480);
+
+ gst_video_frame_map (&frame, &info, buffer, GST_MAP_READ);
+
+ for (c = 0; c < 3; c++) {
+ comp = GST_VIDEO_FRAME_COMP_DATA (&frame, c);
+ comp_stride = GST_VIDEO_FRAME_COMP_STRIDE (&frame, c);
+ comp_width = GST_VIDEO_FRAME_COMP_WIDTH (&frame, c);
+ comp_height = GST_VIDEO_FRAME_COMP_HEIGHT (&frame, c);
+
+ for (i = 0; i < comp_height; i++) {
+ for (j = 0; j < comp_width; j++) {
+ all_red = all_red && (comp[i * comp_stride + j] == color[c]);
+ }
+ }
+ }
+ gst_video_frame_unmap (&frame);
+
+ fail_unless (contains_text != all_red,
+ "Frame %d is incorrect (all red %d, contains text %d)", *sink_pos,
+ all_red, contains_text);
+ *sink_pos = *sink_pos + 1;
+}
+
+static gulong probe_id = 0;
+
+static GstPadProbeReturn
+src_buffer_probe_cb (GstPad * pad, GstPadProbeInfo * info, gpointer user_data)
+{
+ GstBuffer *buffer = GST_PAD_PROBE_INFO_BUFFER (info);
+ GstPad *otherpad = GST_PAD (user_data);
+
+ if (GST_BUFFER_TIMESTAMP (buffer) == buf1.ts)
+ gst_pad_remove_probe (otherpad, probe_id);
+
+ return GST_PAD_PROBE_OK;
+}
+
+#define CREATE_BASIC_TEST(format) \
+GST_START_TEST (test_assrender_basic_##format) \
+{ \
+ GstElement *pipeline; \
+ GstElement *appsrc, *videotestsrc, *capsfilter, *assrender, *fakesink; \
+ guint sink_pos = 0; \
+ GstCaps *video_caps; \
+ GstCaps *text_caps; \
+ GstBuffer *buf; \
+ GstBus *bus; \
+ GMainLoop *loop; \
+ GstPad *pad, *blocked_pad; \
+ guint bus_watch = 0; \
+ GstVideoInfo info; \
+ \
+ pipeline = gst_pipeline_new ("pipeline"); \
+ fail_unless (pipeline != NULL); \
+ \
+ capsfilter = gst_element_factory_make ("capsfilter", NULL); \
+ fail_unless (capsfilter != NULL); \
+ gst_video_info_init (&info); \
+ gst_video_info_set_format (&info, GST_VIDEO_FORMAT_##format, 640, 480); \
+ info.fps_n = 25; \
+ info.fps_d = 1; \
+ video_caps = gst_video_info_to_caps (&info); \
+ g_object_set (capsfilter, "caps", video_caps, NULL); \
+ gst_caps_unref (video_caps); \
+ blocked_pad = gst_element_get_static_pad (capsfilter, "src"); \
+ gst_pad_add_probe (blocked_pad, GST_PAD_PROBE_TYPE_BLOCK_DOWNSTREAM, NULL, NULL, NULL); \
+ \
+ appsrc = gst_element_factory_make ("appsrc", NULL); \
+ fail_unless (appsrc != NULL); \
+ buf = gst_buffer_new_and_alloc (strlen (buf0.buf) + 1); \
+ gst_buffer_fill (buf, 0, buf0.buf, strlen (buf0.buf) + 1); \
+ GST_BUFFER_TIMESTAMP (buf) = buf0.ts; \
+ GST_BUFFER_DURATION (buf) = buf0.duration; \
+ text_caps = \
+ gst_caps_new_simple ("application/x-ssa", "codec_data", GST_TYPE_BUFFER, \
+ buf, NULL); \
+ gst_buffer_unref (buf); \
+ gst_app_src_set_caps (GST_APP_SRC (appsrc), text_caps); \
+ g_object_set (appsrc, "format", GST_FORMAT_TIME, NULL); \
+ pad = gst_element_get_static_pad (appsrc, "src"); \
+ probe_id = gst_pad_add_probe (pad, GST_PAD_PROBE_TYPE_BUFFER, src_buffer_probe_cb, \
+ gst_object_ref (blocked_pad), (GDestroyNotify) gst_object_unref); \
+ gst_object_unref (blocked_pad); \
+ gst_object_unref (pad); \
+ \
+ videotestsrc = gst_element_factory_make ("videotestsrc", NULL); \
+ fail_unless (videotestsrc != NULL); \
+ g_object_set (videotestsrc, "num-buffers", 5, "pattern", 4, NULL); \
+ \
+ assrender = gst_element_factory_make ("assrender", NULL); \
+ fail_unless (assrender != NULL); \
+ \
+ fakesink = gst_element_factory_make ("fakesink", NULL); \
+ fail_unless (fakesink != NULL); \
+ g_object_set (fakesink, "signal-handoffs", TRUE, "async", FALSE, NULL); \
+ g_signal_connect (fakesink, "handoff", G_CALLBACK (sink_handoff_cb_##format), \
+ &sink_pos); \
+ \
+ gst_bin_add_many (GST_BIN (pipeline), appsrc, videotestsrc, capsfilter, \
+ assrender, fakesink, NULL); \
+ \
+ fail_unless (gst_element_link_pads (appsrc, "src", assrender, "text_sink")); \
+ fail_unless (gst_element_link_pads (videotestsrc, "src", capsfilter, "sink")); \
+ fail_unless (gst_element_link_pads (capsfilter, "src", assrender, \
+ "video_sink")); \
+ fail_unless (gst_element_link_pads (assrender, "src", fakesink, "sink")); \
+ \
+ loop = g_main_loop_new (NULL, TRUE); \
+ fail_unless (loop != NULL); \
+ \
+ bus = gst_element_get_bus (pipeline); \
+ fail_unless (bus != NULL); \
+ bus_watch = gst_bus_add_watch (bus, bus_handler, loop); \
+ gst_object_unref (bus); \
+ \
+ fail_unless_equals_int (gst_element_set_state (pipeline, GST_STATE_PLAYING), \
+ GST_STATE_CHANGE_SUCCESS); \
+ \
+ buf = gst_buffer_new_and_alloc (strlen (buf1.buf) + 1); \
+ gst_buffer_fill (buf, 0, buf1.buf, strlen (buf1.buf) + 1); \
+ GST_BUFFER_TIMESTAMP (buf) = buf1.ts; \
+ GST_BUFFER_DURATION (buf) = buf1.duration; \
+ gst_app_src_push_buffer (GST_APP_SRC (appsrc), buf); \
+ gst_caps_unref (text_caps); \
+ gst_app_src_end_of_stream (GST_APP_SRC (appsrc)); \
+ \
+ g_main_loop_run (loop); \
+ \
+ gst_element_set_state (pipeline, GST_STATE_NULL); \
+ \
+ fail_unless_equals_int (sink_pos, 5); \
+ \
+ g_object_unref (pipeline); \
+ g_main_loop_unref (loop); \
+ g_source_remove (bus_watch); \
+} \
+\
+GST_END_TEST;
+
+CREATE_BASIC_TEST (xRGB);
+CREATE_BASIC_TEST (I420);
+
+static Suite *
+assrender_suite (void)
+{
+ Suite *s = suite_create ("assrender");
+ TCase *tc_chain = tcase_create ("linear");
+
+ /* time out after 120s, not the default 3 */
+ tcase_set_timeout (tc_chain, 120);
+
+ suite_add_tcase (s, tc_chain);
+ tcase_add_test (tc_chain, test_assrender_basic_xRGB);
+ tcase_add_test (tc_chain, test_assrender_basic_I420);
+
+ return s;
+}
+
+GST_CHECK_MAIN (assrender);
diff --git a/tests/check/elements/autoconvert.c b/tests/check/elements/autoconvert.c
new file mode 100644
index 00000000..680464c1
--- /dev/null
+++ b/tests/check/elements/autoconvert.c
@@ -0,0 +1,243 @@
+/* GStreamer
+ *
+ * unit test for autoconvert element
+ * Copyright (C) 2009 Jan Schmidt <thaytan@noraisin.net>
+ *
+ * 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.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <gst/gst.h>
+#include <gst/check/gstcheck.h>
+
+/* Define 2 element factories for testing with */
+typedef GstBin TestElement1;
+typedef GstBinClass TestElement1Class;
+typedef GstBin TestElement2;
+typedef GstBinClass TestElement2Class;
+
+GType test_element1_get_type (void);
+G_DEFINE_TYPE (TestElement1, test_element1, GST_TYPE_BIN);
+GType test_element2_get_type (void);
+G_DEFINE_TYPE (TestElement2, test_element2, GST_TYPE_BIN);
+
+static GstStaticPadTemplate src_factory = GST_STATIC_PAD_TEMPLATE ("src",
+ GST_PAD_SRC, GST_PAD_ALWAYS,
+ GST_STATIC_CAPS ("test/caps,type=(int)[1,2]"));
+static GstStaticPadTemplate sink_factory = GST_STATIC_PAD_TEMPLATE ("sink",
+ GST_PAD_SINK, GST_PAD_ALWAYS,
+ GST_STATIC_CAPS ("test/caps,type=(int)[1,2]"));
+
+static void
+setup (void)
+{
+ /* Register our test elements */
+ fail_unless (gst_element_register (NULL, "testelement1", GST_RANK_NONE,
+ test_element1_get_type ()));
+ fail_unless (gst_element_register (NULL, "testelement2", GST_RANK_NONE,
+ test_element2_get_type ()));
+}
+
+static void
+teardown (void)
+{
+}
+
+static void
+set_autoconvert_factories (GstElement * autoconvert)
+{
+ const gchar *desired_features[] = { "testelement1", "testelement2" };
+ GstElementFactory *feature;
+ GList *factories = NULL;
+ gint i;
+
+ for (i = 0; i < G_N_ELEMENTS (desired_features); i++) {
+ feature =
+ GST_ELEMENT_FACTORY_CAST (gst_registry_find_feature
+ (gst_registry_get (), desired_features[i], GST_TYPE_ELEMENT_FACTORY));
+ fail_if (feature == NULL, "Test element %s was not found in registry",
+ desired_features[i]);
+ factories = g_list_prepend (factories, feature);
+ }
+
+ g_object_set (G_OBJECT (autoconvert), "factories", factories, NULL);
+
+ g_list_free (factories);
+}
+
+typedef struct
+{
+ gint n;
+ GstCaps *caps;
+} TestContext;
+
+static void
+generate_test_buffer (GstPad * src, TestContext * ctx)
+{
+ GstBuffer *buf;
+
+ if (ctx->n == 0) {
+ ctx->caps = gst_caps_from_string ("test/caps,type=(int)1");
+ } else if (ctx->n == 10) {
+ gst_caps_unref (ctx->caps);
+ ctx->caps = gst_caps_from_string ("test/caps,type=(int)2");
+ }
+
+ buf = gst_buffer_new_and_alloc (4096);
+ gst_pad_set_caps (src, ctx->caps);
+
+ GST_LOG ("Pushing test buffer, caps %" GST_PTR_FORMAT, ctx->caps);
+ fail_unless (gst_pad_push (src, buf) == GST_FLOW_OK);
+}
+
+GST_START_TEST (test_autoconvert_simple)
+{
+ GstPad *test_src_pad, *test_sink_pad;
+ GstElement *autoconvert = gst_check_setup_element ("autoconvert");
+ GstBus *bus = gst_bus_new ();
+ TestContext ctx = { 0 };
+
+ set_autoconvert_factories (autoconvert);
+
+ test_src_pad = gst_check_setup_src_pad (autoconvert, &src_factory);
+ gst_pad_set_active (test_src_pad, TRUE);
+ test_sink_pad = gst_check_setup_sink_pad (autoconvert, &sink_factory);
+ gst_pad_set_active (test_sink_pad, TRUE);
+
+ gst_element_set_state (GST_ELEMENT_CAST (autoconvert), GST_STATE_PLAYING);
+
+ /* Push 20 items */
+ for (ctx.n = 0; ctx.n < 20; ctx.n++)
+ generate_test_buffer (test_src_pad, &ctx);
+
+ /* Check all the items arrived */
+ fail_unless_equals_int (g_list_length (buffers), 20);
+
+ while (TRUE) {
+ GstMessage *msg = gst_bus_pop (bus);
+ if (!msg)
+ break;
+
+ GST_DEBUG ("got message %s",
+ gst_message_type_get_name (GST_MESSAGE_TYPE (msg)));
+ fail_if (GST_MESSAGE_TYPE (msg) == GST_MESSAGE_ERROR);
+ }
+
+ gst_element_set_state ((GstElement *) autoconvert, GST_STATE_NULL);
+
+ gst_bus_set_flushing (bus, TRUE);
+ gst_object_unref (bus);
+
+ gst_pad_set_active (test_src_pad, FALSE);
+ gst_pad_set_active (test_sink_pad, FALSE);
+ gst_check_teardown_src_pad (autoconvert);
+ gst_check_teardown_sink_pad (autoconvert);
+ gst_check_teardown_element (autoconvert);
+}
+
+GST_END_TEST;
+
+static Suite *
+autoconvert_suite (void)
+{
+ Suite *s = suite_create ("autoconvert");
+ TCase *tc_basic = tcase_create ("general");
+
+ suite_add_tcase (s, tc_basic);
+ tcase_add_checked_fixture (tc_basic, setup, teardown);
+ tcase_add_test (tc_basic, test_autoconvert_simple);
+
+ return s;
+}
+
+/* Implementation of the test elements */
+
+static void
+configure_test_element (GstBin * bin, const gchar * capsfilter)
+{
+ GstElement *filter;
+ GstElement *identity;
+ GstPad *pad, *ghostpad;
+ GstPadTemplate *test_static_templ;
+
+ filter = gst_element_factory_make ("capsfilter", NULL);
+ fail_unless (filter != NULL);
+ gst_util_set_object_arg (G_OBJECT (filter), "caps", capsfilter);
+
+ identity = gst_element_factory_make ("identity", NULL);
+ fail_unless (identity != NULL);
+
+ gst_bin_add_many (bin, filter, identity, NULL);
+ fail_unless (gst_element_link_many (filter, identity, NULL) == TRUE);
+
+
+ test_static_templ = gst_static_pad_template_get (&sink_factory);
+ pad = gst_element_get_static_pad (filter, "sink");
+ ghostpad = gst_ghost_pad_new_from_template ("sink", pad, test_static_templ);
+ gst_element_add_pad (GST_ELEMENT_CAST (bin), ghostpad);
+ gst_object_unref (pad);
+ gst_object_unref (test_static_templ);
+
+ test_static_templ = gst_static_pad_template_get (&src_factory);
+ pad = gst_element_get_static_pad (identity, "src");
+ ghostpad = gst_ghost_pad_new_from_template ("src", pad, test_static_templ);
+ gst_element_add_pad (GST_ELEMENT_CAST (bin), ghostpad);
+ gst_object_unref (pad);
+ gst_object_unref (test_static_templ);
+}
+
+static void
+test_element1_class_init (TestElement1Class * klass)
+{
+ GstElementClass *element_class = GST_ELEMENT_CLASS (klass);
+ GstPadTemplate *src_template, *sink_template;
+
+ src_template = gst_static_pad_template_get (&src_factory);
+ gst_element_class_add_pad_template (element_class, src_template);
+
+ sink_template = gst_static_pad_template_get (&sink_factory);
+ gst_element_class_add_pad_template (element_class, sink_template);
+}
+
+static void
+test_element1_init (TestElement1 * elem)
+{
+ configure_test_element (GST_BIN_CAST (elem), "test/caps,type=(int)1");
+}
+
+static void
+test_element2_class_init (TestElement2Class * klass)
+{
+ GstElementClass *element_class = GST_ELEMENT_CLASS (klass);
+ GstPadTemplate *src_template, *sink_template;
+
+ src_template = gst_static_pad_template_get (&src_factory);
+ gst_element_class_add_pad_template (element_class, src_template);
+
+ sink_template = gst_static_pad_template_get (&sink_factory);
+ gst_element_class_add_pad_template (element_class, sink_template);
+}
+
+static void
+test_element2_init (TestElement2 * elem)
+{
+ configure_test_element (GST_BIN_CAST (elem), "test/caps,type=(int)2");
+}
+
+GST_CHECK_MAIN (autoconvert);
diff --git a/tests/check/elements/autovideoconvert.c b/tests/check/elements/autovideoconvert.c
new file mode 100644
index 00000000..609c730a
--- /dev/null
+++ b/tests/check/elements/autovideoconvert.c
@@ -0,0 +1,139 @@
+/* GStreamer
+ *
+ * unit test for autovideoconvert element
+ * Copyright (C) 2009 Jan Schmidt <thaytan@noraisin.net>
+ * Copyright (C) 2010 ST-Ericsson SA
+ * @author: Benjamin Gaignard <benjamin.gaignard@stericsson.com>
+ *
+ * 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.
+ */
+
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+#include <gst/gst.h>
+#include <gst/check/gstcheck.h>
+
+typedef struct
+{
+ GMainLoop *loop;
+ gboolean eos;
+} OnMessageUserData;
+
+static void
+on_message_cb (GstBus * bus, GstMessage * message, gpointer user_data)
+{
+ OnMessageUserData *d = user_data;
+
+ switch (GST_MESSAGE_TYPE (message)) {
+ case GST_MESSAGE_ERROR:
+ case GST_MESSAGE_WARNING:
+ g_assert_not_reached ();
+ break;
+ case GST_MESSAGE_EOS:
+ g_main_loop_quit (d->loop);
+ d->eos = TRUE;
+ break;
+ default:
+ break;
+ }
+}
+
+static void
+run_test (const gchar * pipeline_string)
+{
+ GstElement *pipeline;
+ GstBus *bus;
+ GMainLoop *loop;
+ OnMessageUserData omud = { NULL, };
+ GstStateChangeReturn ret;
+
+ GST_DEBUG ("Testing pipeline '%s'", pipeline_string);
+
+ pipeline = gst_parse_launch (pipeline_string, NULL);
+ fail_unless (pipeline != NULL);
+ loop = g_main_loop_new (NULL, FALSE);
+
+ bus = gst_element_get_bus (pipeline);
+ fail_unless (bus != NULL);
+ gst_bus_add_signal_watch (bus);
+
+ omud.loop = loop;
+ omud.eos = FALSE;
+
+ g_signal_connect (bus, "message", (GCallback) on_message_cb, &omud);
+
+ gst_object_unref (bus);
+
+ ret = gst_element_set_state (pipeline, GST_STATE_PLAYING);
+ fail_unless (ret == GST_STATE_CHANGE_SUCCESS
+ || ret == GST_STATE_CHANGE_ASYNC);
+
+ g_main_loop_run (loop);
+
+ fail_unless (gst_element_set_state (pipeline,
+ GST_STATE_NULL) == GST_STATE_CHANGE_SUCCESS);
+
+ fail_unless (omud.eos == TRUE);
+
+ gst_object_unref (pipeline);
+ g_main_loop_unref (loop);
+
+}
+
+GST_START_TEST (test_autovideoconvert_rbg2bayer)
+{
+ gchar *pipeline;
+
+ pipeline =
+ g_strdup_printf
+ ("videotestsrc num-buffers=1 ! video/x-raw,format=ARGB,depth=32,width=100,height=100,framerate=10/1 ! autovideoconvert ! video/x-bayer,width=100,height=100,format=bggr,framerate=10/1 ! fakesink");
+
+ run_test (pipeline);
+ g_free (pipeline);
+}
+
+GST_END_TEST;
+
+GST_START_TEST (test_autovideoconvert_videoconvert)
+{
+ gchar *pipeline;
+
+ pipeline =
+ g_strdup_printf
+ ("videotestsrc num-buffers=1 ! video/x-raw, format=RGB,width=100,height=100,framerate=10/1 ! autovideoconvert ! video/x-raw,format=BGR,width=100,height=100,framerate=10/1 ! fakesink");
+
+ run_test (pipeline);
+ g_free (pipeline);
+}
+
+GST_END_TEST;
+
+static Suite *
+autovideoconvert_suite (void)
+{
+ Suite *s = suite_create ("autovideoconvert");
+ TCase *tc_basic = tcase_create ("general");
+
+ suite_add_tcase (s, tc_basic);
+ tcase_add_test (tc_basic, test_autovideoconvert_rbg2bayer);
+ tcase_add_test (tc_basic, test_autovideoconvert_videoconvert);
+
+ return s;
+}
+
+GST_CHECK_MAIN (autovideoconvert);
diff --git a/tests/check/elements/baseaudiovisualizer.c b/tests/check/elements/baseaudiovisualizer.c
new file mode 100644
index 00000000..f1458a28
--- /dev/null
+++ b/tests/check/elements/baseaudiovisualizer.c
@@ -0,0 +1,179 @@
+/* GStreamer
+ * Copyright (C) <2011> Stefan Kost <ensonic@users.sf.net>
+ *
+ * unit test for the baseaudiovisualizer class
+ *
+ * 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>
+
+#include <gst/gst.h>
+#include <string.h>
+
+#include "gstbaseaudiovisualizer.h"
+
+/* dummy subclass for testing */
+
+#define GST_TYPE_TEST_SCOPE (gst_test_scope_get_type())
+#define GST_TEST_SCOPE(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_TEST_SCOPE,GstTestScope))
+#define GST_TEST_SCOPE_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass),GST_TYPE_TEST_SCOPE,GstTestScopeClass))
+typedef struct _GstTestScope GstTestScope;
+typedef struct _GstTestScopeClass GstTestScopeClass;
+
+struct _GstTestScope
+{
+ GstBaseAudioVisualizer parent;
+};
+
+struct _GstTestScopeClass
+{
+ GstBaseAudioVisualizerClass parent_class;
+};
+
+static GstStaticPadTemplate gst_test_scope_src_template =
+GST_STATIC_PAD_TEMPLATE ("src",
+ GST_PAD_SRC,
+ GST_PAD_ALWAYS,
+ GST_STATIC_CAPS (GST_VIDEO_CAPS_MAKE ("xRGB"))
+ );
+
+static GstStaticPadTemplate gst_test_scope_sink_template =
+GST_STATIC_PAD_TEMPLATE ("sink",
+ GST_PAD_SINK,
+ GST_PAD_ALWAYS,
+ GST_STATIC_CAPS ("audio/x-raw, "
+ "format = (string) " GST_AUDIO_NE (S16) ", "
+ "layout = (string) interleaved, "
+ "channels = (int) 2, "
+ "channel-mask = (bitmask) 3, " "rate = (int) 44100")
+ );
+
+static GType gst_test_scope_get_type (void);
+
+G_DEFINE_TYPE (GstTestScope, gst_test_scope, GST_TYPE_BASE_AUDIO_VISUALIZER);
+
+static void
+gst_test_scope_class_init (GstTestScopeClass * g_class)
+{
+ GstElementClass *element_class = GST_ELEMENT_CLASS (g_class);
+
+ gst_element_class_set_details_simple (element_class, "test scope",
+ "Visualization",
+ "Dummy test scope", "Stefan Kost <ensonic@users.sf.net>");
+
+ gst_element_class_add_pad_template (element_class,
+ gst_static_pad_template_get (&gst_test_scope_src_template));
+ gst_element_class_add_pad_template (element_class,
+ gst_static_pad_template_get (&gst_test_scope_sink_template));
+}
+
+static void
+gst_test_scope_init (GstTestScope * scope)
+{
+ /* do nothing */
+}
+
+/* tests */
+#define CAPS "audio/x-raw, " \
+ "format = (string) " GST_AUDIO_NE (S16) ", " \
+ "layout = (string) interleaved, " \
+ "rate = (int) 44100, " \
+ "channels = (int) 2, " \
+ "channel-mask = (bitmask) 3"
+
+static GstStaticPadTemplate sinktemplate = GST_STATIC_PAD_TEMPLATE ("sink",
+ GST_PAD_SINK,
+ GST_PAD_ALWAYS,
+ GST_STATIC_CAPS ("video/x-raw, "
+ "format = (string) xRGB, "
+ "width = (int) 320, "
+ "height = (int) 240, " "framerate = (fraction) 30/1")
+ );
+static GstStaticPadTemplate srctemplate = GST_STATIC_PAD_TEMPLATE ("src",
+ GST_PAD_SRC,
+ GST_PAD_ALWAYS,
+ GST_STATIC_CAPS (CAPS)
+ );
+
+GST_START_TEST (count_in_out)
+{
+ GstElement *elem;
+ GstPad *srcpad, *sinkpad;
+ GstBuffer *buffer;
+ GstCaps *caps;
+
+ /* setup up */
+ elem = gst_check_setup_element ("testscope");
+ srcpad = gst_check_setup_src_pad (elem, &srctemplate);
+ sinkpad = gst_check_setup_sink_pad (elem, &sinktemplate);
+ gst_pad_set_active (srcpad, TRUE);
+ gst_pad_set_active (sinkpad, TRUE);
+
+ fail_unless (gst_element_set_state (elem,
+ GST_STATE_PLAYING) == GST_STATE_CHANGE_SUCCESS,
+ "could not set to playing");
+
+ caps = gst_caps_from_string (CAPS);
+ gst_pad_set_caps (srcpad, caps);
+ gst_caps_unref (caps);
+
+ /* push 1s audio to get 30 video-frames */
+ buffer = gst_buffer_new_and_alloc (44100 * 2 * sizeof (gint16));
+ ASSERT_BUFFER_REFCOUNT (buffer, "buffer", 1);
+
+ /* pushing gives away my reference ... */
+ fail_unless (gst_pad_push (srcpad, buffer) == GST_FLOW_OK);
+ /* ... but it ends up being collected on the global buffer list */
+ ASSERT_BUFFER_REFCOUNT (buffer, "buffer", 1);
+ fail_unless_equals_int (g_list_length (buffers), 30);
+
+ /* clean up */
+ g_list_foreach (buffers, (GFunc) gst_mini_object_unref, NULL);
+ g_list_free (buffers);
+ buffers = NULL;
+
+ gst_pad_set_active (srcpad, FALSE);
+ gst_pad_set_active (sinkpad, FALSE);
+ gst_check_teardown_src_pad (elem);
+ gst_check_teardown_sink_pad (elem);
+ gst_check_teardown_element (elem);
+}
+
+GST_END_TEST;
+
+static void
+baseaudiovisualizer_init (void)
+{
+ gst_element_register (NULL, "testscope", GST_RANK_NONE, GST_TYPE_TEST_SCOPE);
+}
+
+static Suite *
+baseaudiovisualizer_suite (void)
+{
+ Suite *s = suite_create ("baseaudiovisualizer");
+ TCase *tc_chain = tcase_create ("general");
+
+ suite_add_tcase (s, tc_chain);
+ tcase_add_checked_fixture (tc_chain, baseaudiovisualizer_init, NULL);
+
+ tcase_add_test (tc_chain, count_in_out);
+
+ return s;
+}
+
+
+GST_CHECK_MAIN (baseaudiovisualizer);
diff --git a/tests/check/elements/camerabin.c b/tests/check/elements/camerabin.c
new file mode 100644
index 00000000..6d353d97
--- /dev/null
+++ b/tests/check/elements/camerabin.c
@@ -0,0 +1,847 @@
+/* GStreamer
+ *
+ * unit test for camerabin basic operations
+ * Copyright (C) 2008 Nokia Corporation <multimedia@maemo.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.
+ */
+
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+#include <unistd.h>
+#include <glib.h>
+#include <glib/gstdio.h>
+#include <gst/gst.h>
+#include <gst/check/gstcheck.h>
+#include <gst/interfaces/photography.h>
+
+#define SINGLE_IMAGE_FILENAME "image"
+#define SINGLE_IMAGE_WITH_FLAGS_FILENAME "image_with_flags"
+#define SEQUENTIAL_IMAGES_FILENAME "sequential_image"
+#define BURST_IMAGE_FILENAME "burst_image"
+#define VIDEO_FILENAME "video"
+#define VIDEO_WITH_FLAGS_FILENAME "video_with_flags"
+#define VIDEO_PAUSE_FILENAME "video_pause"
+#define VIDEO_NOAUDIO_FILENAME "video_noaudio"
+#define CYCLE_IMAGE_FILENAME "cycle_image"
+#define CYCLE_VIDEO_FILENAME "cycle_video"
+#define TAGLISTS_COUNT 3
+#define CYCLE_COUNT_MAX 2
+#define SEQUENTIAL_IMAGES_COUNT 3
+#define MAX_BURST_IMAGES 10
+#define PHOTO_SETTING_DELAY_US 0
+
+static GstElement *camera;
+static guint bus_source;
+static GMainLoop *main_loop;
+static guint cycle_count = 0;
+static gboolean received_preview_msg = FALSE;
+static GstTagList *taglists[TAGLISTS_COUNT];
+static GstTagList *validation_taglist;
+
+/* helper function for filenames */
+static const gchar *
+make_test_file_name (const gchar * base_name, gint num)
+{
+ static gchar file_name[1000];
+
+ g_snprintf (file_name, 999, "%s" G_DIR_SEPARATOR_S
+ "gstcamerabintest_%s_%03d.cap", g_get_tmp_dir (), base_name, num);
+
+ GST_INFO ("capturing to: %s (cycle: %d)", file_name, cycle_count);
+ return file_name;
+}
+
+/* burst capture is not supported in camerabin for the moment */
+#ifdef ENABLE_BURST_CAPTURE
+static const gchar *
+make_test_seq_file_name (const gchar * base_name)
+{
+ static gchar file_name[1000];
+
+ g_snprintf (file_name, 999, "%s" G_DIR_SEPARATOR_S "%02u_%s",
+ g_get_tmp_dir (), captured_images, base_name);
+
+ GST_INFO ("capturing to: %s", file_name);
+ return file_name;
+}
+#endif
+/* signal handlers */
+
+static gboolean
+handle_image_captured_cb (gpointer data)
+{
+ GMainLoop *loop = (GMainLoop *) data;
+
+ /* unblock viewfinder */
+ g_object_set (camera, "block-after-capture", FALSE, NULL);
+
+ GST_DEBUG ("handle_image_captured_cb, cycle: %d", cycle_count);
+ if (cycle_count == 0) {
+ GST_DEBUG ("all cycles done");
+ g_main_loop_quit (loop);
+ } else {
+ /* Set video recording mode */
+ g_object_set (camera, "mode", 1,
+ "filename", make_test_file_name (CYCLE_VIDEO_FILENAME, cycle_count),
+ NULL);
+ /* Record video */
+ g_signal_emit_by_name (camera, "capture-start", NULL);
+ g_usleep (G_USEC_PER_SEC);
+ g_signal_emit_by_name (camera, "capture-stop", NULL);
+ GST_DEBUG ("video captured");
+
+ /* Set still image mode */
+ g_object_set (camera, "mode", 0,
+ "filename", make_test_file_name (CYCLE_IMAGE_FILENAME, cycle_count),
+ NULL);
+
+ cycle_count--;
+ GST_DEBUG ("next cycle: %d", cycle_count);
+
+ /* Take a picture */
+ g_signal_emit_by_name (camera, "capture-start", NULL);
+ }
+ GST_DEBUG ("handle_image_captured_cb done");
+ return FALSE;
+}
+
+static gboolean
+capture_done (GstElement * elem, const gchar * filename, gpointer user_data)
+{
+ GMainLoop *loop = (GMainLoop *) user_data;
+
+ g_idle_add ((GSourceFunc) handle_image_captured_cb, loop);
+
+ GST_INFO ("image saved");
+
+ return FALSE;
+}
+
+/* configuration */
+
+static gboolean
+set_and_check_camerabin_element (GstElement * camera, const char *property,
+ GstElement * element)
+{
+ GstElement *element_check;
+ gboolean ret = FALSE;
+
+ if (element) {
+ g_object_set (camera, property, element, NULL);
+ g_object_get (camera, property, &element_check, NULL);
+ if (element_check == element)
+ ret = TRUE;
+ if (element_check)
+ g_object_unref (element_check);
+ }
+ return ret;
+}
+
+static void
+setup_camerabin_elements (GstElement * camera)
+{
+ GstElement *vfsink, *audiosrc, *videosrc, *audioenc, *videoenc, *imageenc,
+ *videomux, *viewfinder_filter, *imagepp, *videopp, *formatter;
+ GstCaps *audiocaps, *videocaps;
+
+ /* Use fakesink for view finder */
+ vfsink = gst_element_factory_make ("fakesink", NULL);
+ g_object_set (vfsink, "sync", TRUE, NULL);
+ audiosrc = gst_element_factory_make ("audiotestsrc", NULL);
+ g_object_set (audiosrc, "is-live", TRUE, NULL);
+ videosrc = gst_element_factory_make ("videotestsrc", NULL);
+ /* Set pattern to white (3) to avoid timeouts */
+ g_object_set (videosrc, "is-live", TRUE, "pattern", 3, NULL);
+ audioenc = gst_element_factory_make ("capsfilter", NULL);
+ audiocaps = gst_caps_from_string ("audio/x-raw-int");
+ g_object_set (audioenc, "caps", audiocaps, NULL);
+ gst_caps_unref (audiocaps);
+ videoenc = gst_element_factory_make ("capsfilter", NULL);
+ videocaps = gst_caps_from_string ("video/x-raw-yuv");
+ g_object_set (videoenc, "caps", videocaps, NULL);
+ gst_caps_unref (videocaps);
+ videomux = gst_element_factory_make ("avimux", NULL);
+ imageenc = gst_element_factory_make ("jpegenc", NULL);
+ viewfinder_filter = gst_element_factory_make ("identity", NULL);
+ imagepp = gst_element_factory_make ("identity", NULL);
+ videopp = gst_element_factory_make ("identity", NULL);
+ formatter = gst_element_factory_make ("jifmux", NULL);
+
+ if (set_and_check_camerabin_element (camera, "viewfinder-sink", vfsink)
+ && set_and_check_camerabin_element (camera, "audio-source", audiosrc)
+ && set_and_check_camerabin_element (camera, "video-source", videosrc)
+ && set_and_check_camerabin_element (camera, "audio-encoder", audioenc)
+ && set_and_check_camerabin_element (camera, "video-encoder", videoenc)
+ && set_and_check_camerabin_element (camera, "image-encoder", imageenc)
+ && set_and_check_camerabin_element (camera, "video-muxer", videomux)
+ && set_and_check_camerabin_element (camera, "viewfinder-filter",
+ viewfinder_filter)
+ && set_and_check_camerabin_element (camera, "image-post-processing",
+ imagepp)
+ && set_and_check_camerabin_element (camera, "video-post-processing",
+ videopp)
+ && set_and_check_camerabin_element (camera, "image-formatter", formatter)) {
+ GST_INFO ("element properties set and checked");
+ } else {
+ GST_WARNING ("error setting up test plugins");
+ }
+}
+
+static gboolean
+capture_bus_cb (GstBus * bus, GstMessage * message, gpointer data)
+{
+ GMainLoop *loop = (GMainLoop *) data;
+ const GstStructure *st;
+
+ switch (GST_MESSAGE_TYPE (message)) {
+ case GST_MESSAGE_ERROR:{
+ GError *err = NULL;
+ gchar *debug = NULL;
+
+ gst_message_parse_error (message, &err, &debug);
+ GST_WARNING ("ERROR: %s [%s]", err->message, debug);
+ g_error_free (err);
+ g_free (debug);
+ /* Write debug graph to file */
+ GST_DEBUG_BIN_TO_DOT_FILE_WITH_TS (GST_BIN (camera),
+ GST_DEBUG_GRAPH_SHOW_ALL, "camerabin.error");
+
+ fail_if (TRUE, "error while capturing");
+ g_main_loop_quit (loop);
+ break;
+ }
+ case GST_MESSAGE_WARNING:{
+ GError *err = NULL;
+ gchar *debug = NULL;
+
+ gst_message_parse_warning (message, &err, &debug);
+ GST_WARNING ("WARNING: %s [%s]", err->message, debug);
+ g_error_free (err);
+ g_free (debug);
+ /* Write debug graph to file */
+ GST_DEBUG_BIN_TO_DOT_FILE_WITH_TS (GST_BIN (camera),
+ GST_DEBUG_GRAPH_SHOW_ALL, "camerabin.warning");
+ break;
+ }
+ case GST_MESSAGE_EOS:
+ GST_DEBUG ("eos");
+ g_main_loop_quit (loop);
+ break;
+ default:
+ st = gst_message_get_structure (message);
+ if (st && gst_structure_has_name (st, "image-captured")) {
+ gboolean ready = FALSE;
+ GST_INFO ("image captured");
+ g_object_get (camera, "ready-for-capture", &ready, NULL);
+ fail_if (!ready, "not ready for capture");
+ }
+ break;
+ }
+ return TRUE;
+}
+
+static GstBusSyncReply
+bus_sync_callback (GstBus * bus, GstMessage * message, gpointer data)
+{
+ const GstStructure *st;
+ st = gst_message_get_structure (message);
+ if (st) {
+ if (gst_structure_has_name (st, "preview-image")) {
+ GST_DEBUG ("get preview-image message");
+ received_preview_msg = TRUE;
+ }
+ }
+
+
+ return GST_BUS_PASS;
+
+}
+
+static void
+setup (void)
+{
+ GstTagSetter *setter;
+ gchar *desc_str;
+ GstCaps *filter_caps;
+ GstBus *bus;
+ gint i;
+
+ GST_INFO ("init");
+
+ main_loop = g_main_loop_new (NULL, TRUE);
+
+ camera = gst_check_setup_element ("camerabin");
+
+ setup_camerabin_elements (camera);
+
+ g_signal_connect (camera, "image-done", G_CALLBACK (capture_done), main_loop);
+
+ bus = gst_pipeline_get_bus (GST_PIPELINE (camera));
+ bus_source = gst_bus_add_watch (bus, (GstBusFunc) capture_bus_cb, main_loop);
+ gst_bus_set_sync_handler (bus, bus_sync_callback, main_loop);
+ gst_object_unref (bus);
+
+ filter_caps = gst_caps_from_string ("video/x-raw-yuv,format=(fourcc)I420");
+ g_object_set (G_OBJECT (camera), "filter-caps", filter_caps, NULL);
+ gst_caps_unref (filter_caps);
+
+ /* force a low framerate here to not timeout the tests because of the
+ * encoders */
+ g_signal_emit_by_name (camera, "set-video-resolution-fps", 320, 240, 5, 1,
+ NULL);
+
+ /* Set some default tags */
+ setter = GST_TAG_SETTER (camera);
+ desc_str = g_strdup_printf ("Created by %s", g_get_real_name ());
+
+ gst_tag_setter_add_tags (setter, GST_TAG_MERGE_REPLACE,
+ GST_TAG_DESCRIPTION, desc_str, NULL);
+ g_free (desc_str);
+
+ if (gst_element_set_state (GST_ELEMENT (camera), GST_STATE_PLAYING) ==
+ GST_STATE_CHANGE_FAILURE) {
+ GST_WARNING ("setting camerabin to PLAYING failed");
+ gst_element_set_state (GST_ELEMENT (camera), GST_STATE_NULL);
+ gst_object_unref (camera);
+ camera = NULL;
+ }
+
+ /* create the taglists */
+ for (i = 0; i < TAGLISTS_COUNT; i++) {
+ taglists[i] = gst_tag_list_new (GST_TAG_ARTIST, "test-artist",
+ GST_TAG_GEO_LOCATION_LONGITUDE, g_random_double_range (-180, 180),
+ GST_TAG_GEO_LOCATION_LATITUDE, g_random_double_range (-90, 90),
+ GST_TAG_GEO_LOCATION_ELEVATION, g_random_double_range (0, 3000), NULL);
+ }
+
+ GST_INFO ("init finished");
+}
+
+static void
+teardown (void)
+{
+ gint i;
+
+ g_source_remove (bus_source);
+
+ if (camera)
+ gst_check_teardown_element (camera);
+
+ for (i = 0; i < TAGLISTS_COUNT; i++) {
+ gst_tag_list_free (taglists[i]);
+ }
+
+ GST_INFO ("done");
+}
+
+static void
+test_camerabin_properties (GstElement * cam)
+{
+ guint flags;
+ gfloat zoom;
+ gboolean mute;
+
+ flags = 0x1f;
+ g_object_set (G_OBJECT (cam), "flags", flags, NULL);
+ g_object_get (G_OBJECT (cam), "flags", &flags, NULL);
+ fail_if (flags != 0x1f, "setting camerabin flags failed");
+
+ zoom = 2.0;
+ g_object_set (G_OBJECT (cam), "zoom", zoom, NULL);
+ g_object_get (G_OBJECT (cam), "zoom", &zoom, NULL);
+ fail_if (zoom != 2.0, "setting camerabin zoom failed");
+ g_object_set (G_OBJECT (cam), "zoom", 1.0f, NULL);
+
+ mute = TRUE;
+ g_object_set (G_OBJECT (cam), "mute", mute, NULL);
+ g_object_get (G_OBJECT (cam), "mute", &mute, NULL);
+ fail_if (mute != TRUE, "setting camerabin mute failed");
+ g_object_set (G_OBJECT (cam), "mute", FALSE, NULL);
+}
+
+static gboolean
+validity_bus_cb (GstBus * bus, GstMessage * message, gpointer data)
+{
+ GMainLoop *loop = (GMainLoop *) data;
+ switch (GST_MESSAGE_TYPE (message)) {
+ case GST_MESSAGE_ERROR:
+ fail_if (TRUE, "validating captured data failed");
+ g_main_loop_quit (loop);
+ break;
+ case GST_MESSAGE_EOS:
+ g_main_loop_quit (loop);
+ GST_DEBUG ("eos");
+ break;
+ case GST_MESSAGE_TAG:{
+ GstTagList *tags = NULL;
+ gst_message_parse_tag (message, &tags);
+ if (validation_taglist) {
+ gst_tag_list_insert (validation_taglist, tags, GST_TAG_MERGE_REPLACE);
+ gst_tag_list_free (tags);
+ } else
+ validation_taglist = tags;
+ break;
+ }
+ default:
+ break;
+ }
+ return TRUE;
+}
+
+static void
+validate_taglist_foreach (const GstTagList * list, const gchar * tag,
+ gpointer user_data)
+{
+ GstTagList *other = GST_TAG_LIST (user_data);
+
+ const GValue *val1 = gst_tag_list_get_value_index (list, tag, 0);
+ const GValue *val2 = gst_tag_list_get_value_index (other, tag, 0);
+
+ fail_if (val1 == NULL);
+ fail_if (val2 == NULL);
+
+ fail_unless (gst_value_can_intersect (val1, val2));
+}
+
+static void
+extract_jpeg_tags (const gchar * filename, gint num)
+{
+ guint source;
+ GstBus *bus;
+ GMainLoop *loop = g_main_loop_new (NULL, FALSE);
+ const gchar *filepath = make_test_file_name (filename, num);
+ gchar *pipeline_str = g_strdup_printf ("filesrc location=%s ! "
+ "jpegparse ! fakesink", filepath);
+ GstElement *pipeline;
+
+ pipeline = gst_parse_launch (pipeline_str, NULL);
+ fail_unless (pipeline != NULL);
+ g_free (pipeline_str);
+
+ bus = gst_pipeline_get_bus (GST_PIPELINE (pipeline));
+ source = gst_bus_add_watch (bus, (GstBusFunc) validity_bus_cb, loop);
+
+ gst_element_set_state (pipeline, GST_STATE_PLAYING);
+ g_main_loop_run (loop);
+ gst_element_set_state (pipeline, GST_STATE_NULL);
+
+ g_main_loop_unref (loop);
+ g_source_remove (source);
+ gst_object_unref (bus);
+ gst_object_unref (pipeline);
+}
+
+/* Validate captured files by playing them with playbin
+ * and checking that no errors occur. */
+static gboolean
+check_file_validity (const gchar * filename, gint num, GstTagList * taglist)
+{
+ guint source;
+ GstBus *bus;
+ GMainLoop *loop = g_main_loop_new (NULL, FALSE);
+ GstElement *playbin = gst_element_factory_make ("playbin2", NULL);
+ GstElement *fakevideo = gst_element_factory_make ("fakesink", NULL);
+ GstElement *fakeaudio = gst_element_factory_make ("fakesink", NULL);
+ gchar *uri = g_strconcat ("file://", make_test_file_name (filename, num),
+ NULL);
+
+ GST_DEBUG ("checking uri: %s", uri);
+ g_object_set (G_OBJECT (playbin), "uri", uri, "video-sink", fakevideo,
+ "audio-sink", fakeaudio, NULL);
+
+ validation_taglist = NULL;
+ bus = gst_pipeline_get_bus (GST_PIPELINE (playbin));
+ source = gst_bus_add_watch (bus, (GstBusFunc) validity_bus_cb, loop);
+
+ gst_element_set_state (playbin, GST_STATE_PLAYING);
+ g_main_loop_run (loop);
+ gst_element_set_state (playbin, GST_STATE_NULL);
+
+ /* special handling for images (jpg) as jpegparse isn't plugged by
+ * default due to its current low rank */
+ if (taglist && strstr (filename, "image")) {
+ extract_jpeg_tags (filename, num);
+ }
+
+ /* check taglist */
+ if (taglist) {
+ fail_if (validation_taglist == NULL);
+
+ GST_DEBUG ("Comparing taglists %" GST_PTR_FORMAT "; with %" GST_PTR_FORMAT,
+ taglist, validation_taglist);
+
+ gst_tag_list_foreach (taglist, validate_taglist_foreach,
+ validation_taglist);
+ }
+ if (validation_taglist)
+ gst_tag_list_free (validation_taglist);
+
+ g_free (uri);
+ g_source_remove (source);
+ gst_object_unref (bus);
+ gst_object_unref (playbin);
+ g_main_loop_unref (loop);
+
+ return TRUE;
+}
+
+static void
+remove_file (const gchar * fn_template, guint num)
+{
+ const gchar *fn;
+
+ fn = make_test_file_name (fn_template, num);
+ GST_INFO ("removing %s", fn);
+ g_unlink (fn);
+}
+
+GST_START_TEST (test_single_image_capture)
+{
+ gboolean ready = FALSE;
+ gboolean idle = FALSE;
+ if (!camera)
+ return;
+
+ /* Test photography iface settings */
+ gst_element_get_state (GST_ELEMENT (camera), NULL, NULL, (2 * GST_SECOND));
+ test_camerabin_properties (camera);
+
+ /* set flags to disable additional elements */
+ g_object_set (camera, "flags", 0, NULL);
+
+ /* set still image mode */
+ g_object_set (camera, "mode", 0,
+ "filename", make_test_file_name (SINGLE_IMAGE_FILENAME, 0), NULL);
+
+ /* don't run viewfinder after capture */
+ g_object_set (camera, "block-after-capture", TRUE, NULL);
+
+ /* check that capturing is possible */
+ g_object_get (camera, "ready-for-capture", &ready, NULL);
+ fail_if (!ready, "not ready for capture");
+
+ /* check that the camera is idle */
+ g_object_get (camera, "idle", &idle, NULL);
+ fail_if (!idle, "camera should be idle");
+
+ GST_INFO ("starting capture");
+ g_signal_emit_by_name (camera, "capture-start", NULL);
+
+ g_object_get (camera, "ready-for-capture", &ready, NULL);
+ fail_if (ready, "ready for capture during capture");
+
+ g_main_loop_run (main_loop);
+
+ g_object_get (camera, "idle", &idle, NULL);
+ fail_if (!idle, "camera should be idle");
+
+ gst_element_set_state (GST_ELEMENT (camera), GST_STATE_NULL);
+
+ check_file_validity (SINGLE_IMAGE_FILENAME, 0, NULL);
+ remove_file (SINGLE_IMAGE_FILENAME, 0);
+}
+
+GST_END_TEST;
+
+GST_START_TEST (test_single_image_capture_with_flags)
+{
+ if (!camera)
+ return;
+
+ /* set flags to enable modifier elements */
+ g_object_set (camera, "flags", 79, NULL);
+
+ /* set still image mode */
+ g_object_set (camera, "mode", 0,
+ "filename", make_test_file_name (SINGLE_IMAGE_WITH_FLAGS_FILENAME, 0),
+ NULL);
+
+ GST_INFO ("starting capture");
+ g_signal_emit_by_name (camera, "capture-start", NULL);
+
+ g_main_loop_run (main_loop);
+ gst_element_set_state (GST_ELEMENT (camera), GST_STATE_NULL);
+
+ check_file_validity (SINGLE_IMAGE_WITH_FLAGS_FILENAME, 0, NULL);
+ remove_file (SINGLE_IMAGE_WITH_FLAGS_FILENAME, 0);
+}
+
+GST_END_TEST;
+
+GST_START_TEST (test_video_recording)
+{
+ GstCaps *preview_caps;
+ gboolean idle = FALSE;
+ preview_caps = gst_caps_from_string ("video/x-raw-rgb,width=320,height=240");
+
+ if (!camera)
+ return;
+
+ /* set flags to disable additional elements */
+ g_object_set (camera, "flags", 0, NULL);
+
+ /* Set video recording mode */
+ g_object_set (camera, "mode", 1,
+ "filename", make_test_file_name (VIDEO_WITH_FLAGS_FILENAME, 0), NULL);
+
+ /* Set preview-caps */
+ g_object_set (camera, "preview-caps", preview_caps, NULL);
+ gst_caps_unref (preview_caps);
+
+ /* check that the camera is idle */
+ g_object_get (camera, "idle", &idle, NULL);
+ fail_if (!idle, "camera should be idle");
+
+ GST_INFO ("starting capture");
+ g_signal_emit_by_name (camera, "capture-start", NULL);
+
+ g_object_get (camera, "idle", &idle, NULL);
+ fail_if (idle, "camera should not be idle");
+
+ /* Record for one seconds */
+ g_usleep (G_USEC_PER_SEC);
+
+ g_signal_emit_by_name (camera, "capture-stop", NULL);
+
+ g_object_get (camera, "idle", &idle, NULL);
+ fail_if (!idle, "camera should be idle");
+
+ /* check if receiving the preview-image message */
+ fail_if (!received_preview_msg,
+ "creating video recording preview image failed");
+
+ gst_element_set_state (GST_ELEMENT (camera), GST_STATE_NULL);
+
+ check_file_validity (VIDEO_WITH_FLAGS_FILENAME, 0, NULL);
+ remove_file (VIDEO_WITH_FLAGS_FILENAME, 0);
+}
+
+GST_END_TEST;
+
+GST_START_TEST (test_video_recording_with_flags)
+{
+ GstCaps *preview_caps;
+ preview_caps = gst_caps_from_string ("video/x-raw-rgb,width=320,height=240");
+
+ if (!camera)
+ return;
+
+ /* set flags to enable modifier elements */
+ g_object_set (camera, "flags", 95, NULL);
+
+ /* Set video recording mode */
+ g_object_set (camera, "mode", 1,
+ "filename", make_test_file_name (VIDEO_FILENAME, 0), NULL);
+
+ /* Set preview-caps */
+ g_object_set (camera, "preview-caps", preview_caps, NULL);
+ gst_caps_unref (preview_caps);
+
+ GST_INFO ("starting capture");
+ g_signal_emit_by_name (camera, "capture-start", NULL);
+ /* Record for one seconds */
+ g_usleep (G_USEC_PER_SEC);
+ g_signal_emit_by_name (camera, "capture-stop", NULL);
+
+ /*check if receiving the preview-image message */
+ fail_if (!received_preview_msg,
+ "creating video recording preview image failed");
+
+ gst_element_set_state (GST_ELEMENT (camera), GST_STATE_NULL);
+
+ check_file_validity (VIDEO_FILENAME, 0, NULL);
+ remove_file (VIDEO_FILENAME, 0);
+}
+
+GST_END_TEST;
+
+GST_START_TEST (test_video_recording_pause)
+{
+ gboolean idle = FALSE;
+ if (!camera)
+ return;
+
+ /* Set video recording mode */
+ g_object_set (camera, "mode", 1,
+ "filename", make_test_file_name (VIDEO_PAUSE_FILENAME, 0), NULL);
+
+ g_object_get (camera, "idle", &idle, NULL);
+ fail_unless (idle, "camera should be idle");
+
+ GST_INFO ("starting capture");
+ g_signal_emit_by_name (camera, "capture-start", NULL);
+
+ g_object_get (camera, "idle", &idle, NULL);
+ fail_if (idle, "camera shouldn't be idle when recording");
+
+ /* Record for one seconds */
+ g_usleep (G_USEC_PER_SEC);
+
+ GST_INFO ("pause capture");
+ g_signal_emit_by_name (camera, "capture-pause", NULL);
+
+ g_object_get (camera, "idle", &idle, NULL);
+ fail_if (idle, "camera shouldn't be idle when recording and paused");
+
+ /* Record for one seconds */
+ g_usleep (G_USEC_PER_SEC);
+
+ GST_INFO ("continue capture");
+ g_signal_emit_by_name (camera, "capture-start", NULL);
+
+ g_object_get (camera, "idle", &idle, NULL);
+ fail_if (idle, "camera shouldn't be idle when recording");
+
+ /* Record for one seconds */
+ g_usleep (G_USEC_PER_SEC);
+ g_signal_emit_by_name (camera, "capture-stop", NULL);
+
+ g_object_get (camera, "idle", &idle, NULL);
+ fail_unless (idle, "camera should be idle after capture-stop");
+
+ gst_element_set_state (GST_ELEMENT (camera), GST_STATE_NULL);
+
+ check_file_validity (VIDEO_PAUSE_FILENAME, 0, NULL);
+ remove_file (VIDEO_PAUSE_FILENAME, 0);
+}
+
+GST_END_TEST;
+
+GST_START_TEST (test_video_recording_no_audio)
+{
+ GstCaps *preview_caps;
+ preview_caps = gst_caps_from_string ("video/x-raw-rgb,width=320,height=240");
+
+ if (!camera)
+ return;
+
+ /* set flags to disable audio elements */
+ g_object_set (camera, "flags", 32, NULL);
+
+ /* Set video recording mode */
+ g_object_set (camera, "mode", 1,
+ "filename", make_test_file_name (VIDEO_NOAUDIO_FILENAME, 0), NULL);
+
+ /* Set preview-caps */
+ g_object_set (camera, "preview-caps", preview_caps, NULL);
+ gst_caps_unref (preview_caps);
+
+ GST_INFO ("starting capture");
+ g_signal_emit_by_name (camera, "capture-start", NULL);
+ /* Record for one seconds */
+ g_usleep (G_USEC_PER_SEC);
+ g_signal_emit_by_name (camera, "capture-stop", NULL);
+
+ /* check if receiving the preview-image message */
+ fail_if (!received_preview_msg,
+ "creating video recording preview image failed");
+
+ gst_element_set_state (GST_ELEMENT (camera), GST_STATE_NULL);
+
+ check_file_validity (VIDEO_NOAUDIO_FILENAME, 0, NULL);
+ remove_file (VIDEO_NOAUDIO_FILENAME, 0);
+}
+
+GST_END_TEST;
+
+GST_START_TEST (test_image_video_cycle)
+{
+ gint i;
+
+ if (!camera)
+ return;
+
+ cycle_count = CYCLE_COUNT_MAX;
+
+ /* set still image mode */
+ g_object_set (camera, "mode", 0,
+ "filename", make_test_file_name (CYCLE_IMAGE_FILENAME, cycle_count),
+ NULL);
+
+ GST_INFO ("starting capture");
+ g_signal_emit_by_name (camera, "capture-start", NULL);
+
+ g_main_loop_run (main_loop);
+ gst_element_set_state (GST_ELEMENT (camera), GST_STATE_NULL);
+
+ /* validate all the files */
+ for (i = 2; i > 0; i--) {
+ check_file_validity (CYCLE_IMAGE_FILENAME, i, NULL);
+ remove_file (CYCLE_IMAGE_FILENAME, i);
+ check_file_validity (CYCLE_VIDEO_FILENAME, i, NULL);
+ remove_file (CYCLE_VIDEO_FILENAME, i);
+ }
+}
+
+GST_END_TEST;
+
+GST_START_TEST (test_image_tags_setting)
+{
+ gint i;
+
+ g_object_set (camera, "flags", 0, NULL);
+ g_object_set (camera, "block-after-capture", TRUE, NULL);
+
+ GST_INFO ("starting capture series");
+
+ for (i = 0; i < SEQUENTIAL_IMAGES_COUNT; i++) {
+ g_object_set (camera, "filename",
+ make_test_file_name (SEQUENTIAL_IMAGES_FILENAME, i), NULL);
+ gst_tag_setter_merge_tags (GST_TAG_SETTER (camera),
+ taglists[i % TAGLISTS_COUNT],
+ gst_tag_setter_get_tag_merge_mode (GST_TAG_SETTER (camera)));
+ g_signal_emit_by_name (camera, "capture-start", NULL);
+ g_main_loop_run (main_loop);
+ }
+ gst_element_set_state (GST_ELEMENT (camera), GST_STATE_NULL);
+
+ for (i = 0; i < SEQUENTIAL_IMAGES_COUNT; i++) {
+ check_file_validity (SEQUENTIAL_IMAGES_FILENAME, i,
+ taglists[i % TAGLISTS_COUNT]);
+ remove_file (SEQUENTIAL_IMAGES_FILENAME, i);
+ }
+}
+
+GST_END_TEST;
+
+static Suite *
+camerabin_suite (void)
+{
+ Suite *s = suite_create ("camerabin");
+ TCase *tc_basic = tcase_create ("general");
+
+ /* Test that basic operations run without errors */
+ suite_add_tcase (s, tc_basic);
+ /* Increase timeout due to video recording */
+ tcase_set_timeout (tc_basic, 20);
+ tcase_add_checked_fixture (tc_basic, setup, teardown);
+ tcase_add_test (tc_basic, test_single_image_capture);
+ tcase_add_test (tc_basic, test_single_image_capture_with_flags);
+ tcase_add_test (tc_basic, test_video_recording);
+ tcase_add_test (tc_basic, test_video_recording_with_flags);
+ tcase_add_test (tc_basic, test_video_recording_pause);
+ tcase_add_test (tc_basic, test_video_recording_no_audio);
+ tcase_add_test (tc_basic, test_image_video_cycle);
+ tcase_add_test (tc_basic, test_image_tags_setting);
+
+ return s;
+}
+
+GST_CHECK_MAIN (camerabin);
diff --git a/tests/check/elements/camerabin2.c b/tests/check/elements/camerabin2.c
new file mode 100644
index 00000000..d8bea462
--- /dev/null
+++ b/tests/check/elements/camerabin2.c
@@ -0,0 +1,1585 @@
+/* GStreamer
+ *
+ * unit test for camerabin2 basic operations
+ * Copyright (C) 2010 Nokia Corporation <multimedia@maemo.org>
+ * Copyright (C) 2010 Thiago Santos <thiago.sousa.santos@collabora.co.uk>
+ *
+ *
+ * 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.
+ */
+
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+#include <unistd.h>
+#include <glib.h>
+#include <glib/gstdio.h>
+#include <gst/gst.h>
+#include <gst/video/video.h>
+#include <gst/check/gstcheck.h>
+#include <gst/basecamerabinsrc/gstbasecamerasrc.h>
+#include <gst/pbutils/encoding-profile.h>
+
+#define IMAGE_FILENAME "image"
+#define VIDEO_FILENAME "video"
+#define CAPTURE_COUNT 3
+#define VIDEO_DURATION 5
+
+#define VIDEO_PAD_SUPPORTED_CAPS "video/x-raw, format=RGB, width=600, height=480"
+#define IMAGE_PAD_SUPPORTED_CAPS "video/x-raw, format=RGB, width=800, height=600"
+
+/* custom test camera src element */
+#define GST_TYPE_TEST_CAMERA_SRC \
+ (gst_test_camera_src_get_type())
+#define GST_TEST_CAMERA_SRC(obj) \
+ (G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_TEST_CAMERA_SRC,GstTestCameraSrc))
+#define GST_TEST_CAMERA_SRC_CLASS(klass) \
+ (G_TYPE_CHECK_CLASS_CAST((klass),GST_TYPE_TEST_CAMERA_SRC,GstTestCameraSrcClass))
+#define GST_IS_TEST_REVERSE_NEGOTIATION_SINK(obj) \
+ (G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_TEST_CAMERA_SRC))
+#define GST_IS_TEST_REVERSE_NEGOTIATION_SINK_CLASS(klass) \
+ (G_TYPE_CHECK_CLASS_TYPE((klass),GST_TYPE_TEST_CAMERA_SRC))
+#define GST_TEST_CAMERA_SRC_CAST(obj) ((GstTestCameraSrc *)obj)
+
+typedef struct _GstTestCameraSrc GstTestCameraSrc;
+typedef struct _GstTestCameraSrcClass GstTestCameraSrcClass;
+struct _GstTestCameraSrc
+{
+ GstBaseCameraSrc element;
+
+ GstPad *vfpad;
+ GstPad *vidpad;
+ GstPad *imgpad;
+
+ GstCameraBinMode mode;
+};
+
+struct _GstTestCameraSrcClass
+{
+ GstBaseCameraSrcClass parent_class;
+};
+
+GType gst_test_camera_src_get_type (void);
+
+#define gst_test_camera_src_parent_class parent_class
+G_DEFINE_TYPE (GstTestCameraSrc, gst_test_camera_src, GST_TYPE_BASE_CAMERA_SRC);
+
+static gboolean
+gst_test_camera_src_set_mode (GstBaseCameraSrc * src, GstCameraBinMode mode)
+{
+ GstTestCameraSrc *self = GST_TEST_CAMERA_SRC (src);
+
+ self->mode = mode;
+ return TRUE;
+}
+
+static gboolean
+gst_test_camera_src_query (GstPad * pad, GstObject * parent, GstQuery * query)
+{
+ GstTestCameraSrc *self = (GstTestCameraSrc *) GST_PAD_PARENT (pad);
+ GstCaps *result = NULL;
+ gboolean ret = FALSE;
+
+ switch (GST_QUERY_TYPE (query)) {
+ case GST_QUERY_CAPS:
+ if (pad == self->vfpad) {
+ result = gst_caps_new_any ();
+ } else if (pad == self->vidpad) {
+ result = gst_caps_from_string (VIDEO_PAD_SUPPORTED_CAPS);
+ } else if (pad == self->imgpad) {
+ result = gst_caps_from_string (IMAGE_PAD_SUPPORTED_CAPS);
+ } else {
+ g_assert_not_reached ();
+ }
+ if (result) {
+ GstCaps *filter;
+
+ gst_query_parse_caps (query, &filter);
+ if (filter) {
+ GstCaps *tmp;
+ tmp = gst_caps_intersect (result, filter);
+ gst_caps_replace (&result, tmp);
+ gst_caps_unref (tmp);
+ }
+ gst_query_set_caps_result (query, result);
+ ret = TRUE;
+ }
+ break;
+ default:
+ break;
+ }
+
+ return ret;
+}
+
+static void
+gst_test_camera_src_class_init (GstTestCameraSrcClass * klass)
+{
+ GstBaseCameraSrcClass *gstbasecamera_class;
+ GstElementClass *gstelement_class = GST_ELEMENT_CLASS (klass);
+
+ gstbasecamera_class = GST_BASE_CAMERA_SRC_CLASS (klass);
+ gstbasecamera_class->set_mode = gst_test_camera_src_set_mode;
+
+ gst_element_class_set_details_simple (gstelement_class,
+ "Test Camera Src",
+ "Camera/Src",
+ "Some test camera src",
+ "Thiago Santos <thiago.sousa.santos@collabora.com>");
+}
+
+static void
+gst_test_camera_src_init (GstTestCameraSrc * self)
+{
+ GstElementClass *gstelement_class = GST_ELEMENT_CLASS (parent_class);
+ GstPadTemplate *template;
+
+ /* create pads */
+ template = gst_element_class_get_pad_template (gstelement_class,
+ GST_BASE_CAMERA_SRC_VIEWFINDER_PAD_NAME);
+ self->vfpad = gst_pad_new_from_template (template,
+ GST_BASE_CAMERA_SRC_VIEWFINDER_PAD_NAME);
+ gst_element_add_pad (GST_ELEMENT_CAST (self), self->vfpad);
+
+ template = gst_element_class_get_pad_template (gstelement_class,
+ GST_BASE_CAMERA_SRC_IMAGE_PAD_NAME);
+ self->imgpad = gst_pad_new_from_template (template,
+ GST_BASE_CAMERA_SRC_IMAGE_PAD_NAME);
+ gst_element_add_pad (GST_ELEMENT_CAST (self), self->imgpad);
+
+ template = gst_element_class_get_pad_template (gstelement_class,
+ GST_BASE_CAMERA_SRC_VIDEO_PAD_NAME);
+ self->vidpad = gst_pad_new_from_template (template,
+ GST_BASE_CAMERA_SRC_VIDEO_PAD_NAME);
+ gst_element_add_pad (GST_ELEMENT_CAST (self), self->vidpad);
+
+ /* add get caps functions */
+ gst_pad_set_query_function (self->vfpad, gst_test_camera_src_query);
+ gst_pad_set_query_function (self->vidpad, gst_test_camera_src_query);
+ gst_pad_set_query_function (self->imgpad, gst_test_camera_src_query);
+}
+
+/* end of custom test camera src element */
+
+
+static GstElement *camera;
+static guint bus_source;
+static GMainLoop *main_loop;
+static gint capture_count = 0;
+guint32 test_id = 0;
+static gchar *image_filename;
+static gchar *video_filename;
+
+static GstBuffer *preview_buffer;
+static gchar *preview_filename;
+static GstCaps *preview_caps;
+static GstTagList *tags_found;
+
+static gboolean
+validity_bus_cb (GstBus * bus, GstMessage * message, gpointer data);
+
+static GstMessage *wait_for_element_message (GstElement * camera,
+ const gchar * name, GstClockTime timeout);
+
+static void
+validate_taglist_foreach (const GstTagList * list, const gchar * tag,
+ gpointer user_data)
+{
+ GstTagList *other = GST_TAG_LIST (user_data);
+
+ const GValue *val1 = gst_tag_list_get_value_index (list, tag, 0);
+ const GValue *val2 = gst_tag_list_get_value_index (other, tag, 0);
+
+ GST_DEBUG ("checking tag '%s'", tag);
+
+ fail_if (val1 == NULL);
+ fail_if (val2 == NULL);
+
+ fail_unless (gst_value_compare (val1, val2) == GST_VALUE_EQUAL);
+}
+
+
+/* helper function for filenames */
+static gchar *
+make_test_file_name (const gchar * base_name, gint num)
+{
+ /* num == -1 means to keep the %d in the resulting string to be used on
+ * multifilesink like location */
+ if (num == -1) {
+ return g_strdup_printf ("%s" G_DIR_SEPARATOR_S
+ "gstcamerabin2test_%s_%u_%%03d.cap", g_get_tmp_dir (), base_name,
+ test_id);
+ } else {
+ return g_strdup_printf ("%s" G_DIR_SEPARATOR_S
+ "gstcamerabin2test_%s_%u_%03d.cap", g_get_tmp_dir (), base_name,
+ test_id, num);
+ }
+}
+
+static const gchar *
+make_const_file_name (const gchar * filename, gint num)
+{
+ static gchar file_name[1000];
+
+ /* num == -1 means to keep the %d in the resulting string to be used on
+ * multifilesink like location */
+ g_snprintf (file_name, 999, filename, num);
+
+ return file_name;
+}
+
+/* configuration */
+
+static gboolean
+capture_bus_cb (GstBus * bus, GstMessage * message, gpointer data)
+{
+ GMainLoop *loop = (GMainLoop *) data;
+ const GstStructure *st;
+
+ switch (GST_MESSAGE_TYPE (message)) {
+ case GST_MESSAGE_ERROR:{
+ GError *err = NULL;
+ gchar *debug = NULL;
+
+ gst_message_parse_error (message, &err, &debug);
+ GST_WARNING ("ERROR: %s [%s]", err->message, debug);
+ g_error_free (err);
+ g_free (debug);
+ /* Write debug graph to file */
+ GST_DEBUG_BIN_TO_DOT_FILE_WITH_TS (GST_BIN (camera),
+ GST_DEBUG_GRAPH_SHOW_ALL, "camerabin.error");
+
+ fail_if (TRUE, "error while capturing");
+ g_main_loop_quit (loop);
+ break;
+ }
+ case GST_MESSAGE_WARNING:{
+ GError *err = NULL;
+ gchar *debug = NULL;
+
+ gst_message_parse_warning (message, &err, &debug);
+ GST_WARNING ("WARNING: %s [%s]", err->message, debug);
+ g_error_free (err);
+ g_free (debug);
+ /* Write debug graph to file */
+ GST_DEBUG_BIN_TO_DOT_FILE_WITH_TS (GST_BIN (camera),
+ GST_DEBUG_GRAPH_SHOW_ALL, "camerabin.warning");
+ break;
+ }
+ case GST_MESSAGE_EOS:
+ GST_DEBUG ("eos");
+ g_main_loop_quit (loop);
+ break;
+ default:
+ st = gst_message_get_structure (message);
+ if (st && gst_structure_has_name (st, "image-done")) {
+ GST_INFO ("image captured");
+ } else if (st && gst_structure_has_name (st,
+ GST_BASE_CAMERA_SRC_PREVIEW_MESSAGE_NAME)) {
+ GstBuffer *buf;
+ const GValue *value;
+
+ value = gst_structure_get_value (st, "buffer");
+ fail_unless (value != NULL);
+ buf = gst_value_get_buffer (value);
+
+ if (preview_buffer)
+ gst_buffer_unref (preview_buffer);
+ preview_buffer = gst_buffer_ref (buf);
+ g_free (preview_filename);
+ preview_filename = g_strdup (gst_structure_get_string (st, "location"));
+ }
+ break;
+ }
+ return TRUE;
+}
+
+static void
+check_preview_image (GstElement * camera, const gchar * filename, gint index)
+{
+ gchar *prev_filename = NULL;
+
+ if (!preview_buffer && camera) {
+ GstMessage *msg = wait_for_element_message (camera,
+ GST_BASE_CAMERA_SRC_PREVIEW_MESSAGE_NAME, GST_CLOCK_TIME_NONE);
+ fail_unless (msg != NULL);
+ gst_message_unref (msg);
+ }
+ fail_unless (preview_buffer != NULL);
+ if (filename) {
+ if (index >= 0) {
+ prev_filename = g_strdup_printf (filename, index);
+ } else {
+ prev_filename = g_strdup (filename);
+ }
+ fail_unless (preview_filename != NULL);
+ fail_unless (strcmp (preview_filename, prev_filename) == 0);
+ }
+ if (preview_caps) {
+ /* TODO porting
+ fail_unless (GST_BUFFER_CAPS (preview_buffer) != NULL);
+ fail_unless (gst_caps_can_intersect (GST_BUFFER_CAPS (preview_buffer),
+ preview_caps));
+ */
+ }
+ g_free (prev_filename);
+}
+
+static void
+extract_jpeg_tags (const gchar * filename, gint num)
+{
+ GstBus *bus;
+ GMainLoop *loop = g_main_loop_new (NULL, FALSE);
+ const gchar *filepath = make_const_file_name (filename, num);
+ gchar *pipeline_str = g_strdup_printf ("filesrc location=%s ! "
+ "jpegparse ! fakesink", filepath);
+ GstElement *pipeline;
+ guint source;
+
+ pipeline = gst_parse_launch (pipeline_str, NULL);
+ fail_unless (pipeline != NULL);
+ g_free (pipeline_str);
+
+ bus = gst_pipeline_get_bus (GST_PIPELINE (pipeline));
+ source = gst_bus_add_watch (bus, (GstBusFunc) validity_bus_cb, loop);
+
+ gst_element_set_state (pipeline, GST_STATE_PLAYING);
+ g_main_loop_run (loop);
+ gst_element_set_state (pipeline, GST_STATE_NULL);
+
+ gst_object_unref (bus);
+ g_source_remove (source);
+ gst_object_unref (pipeline);
+ g_main_loop_unref (loop);
+}
+
+static void
+setup_wrappercamerabinsrc_videotestsrc (void)
+{
+ GstBus *bus;
+ GstElement *vfbin;
+ GstElement *fakevideosink;
+ GstElement *src;
+ GstElement *testsrc;
+ GstElement *audiosrc;
+
+ GST_INFO ("init");
+
+ test_id = g_random_int ();
+ bus_source = 0;
+
+ main_loop = g_main_loop_new (NULL, TRUE);
+
+ camera = gst_check_setup_element ("camerabin2");
+ fakevideosink = gst_element_factory_make ("fakesink", NULL);
+ src = gst_element_factory_make ("wrappercamerabinsrc", NULL);
+ testsrc = gst_element_factory_make ("videotestsrc", NULL);
+ audiosrc = gst_element_factory_make ("audiotestsrc", NULL);
+
+ preview_caps = gst_caps_new_simple ("video/x-raw", "width", G_TYPE_INT,
+ 320, "height", G_TYPE_INT, 240, NULL);
+
+ g_object_set (G_OBJECT (testsrc), "is-live", TRUE, NULL);
+ g_object_set (G_OBJECT (audiosrc), "is-live", TRUE, NULL);
+ g_object_set (G_OBJECT (src), "video-source", testsrc, NULL);
+ g_object_set (G_OBJECT (camera), "camera-source", src, "preview-caps",
+ preview_caps, "post-previews", TRUE, "audio-source", audiosrc, NULL);
+ gst_object_unref (src);
+ gst_object_unref (testsrc);
+ gst_object_unref (audiosrc);
+
+ vfbin = gst_bin_get_by_name (GST_BIN (camera), "vf-bin");
+ g_object_set (G_OBJECT (vfbin), "video-sink", fakevideosink, NULL);
+ gst_object_unref (vfbin);
+ gst_object_unref (fakevideosink);
+
+ bus = gst_pipeline_get_bus (GST_PIPELINE (camera));
+ bus_source = gst_bus_add_watch (bus, (GstBusFunc) capture_bus_cb, main_loop);
+ gst_object_unref (bus);
+
+ tags_found = NULL;
+ capture_count = 0;
+ image_filename = make_test_file_name (IMAGE_FILENAME, -1);
+ video_filename = make_test_file_name (VIDEO_FILENAME, -1);
+
+ GST_INFO ("init finished");
+}
+
+static void
+teardown (void)
+{
+ gst_element_set_state (camera, GST_STATE_NULL);
+
+ if (camera)
+ gst_check_teardown_element (camera);
+ camera = NULL;
+
+ if (bus_source)
+ g_source_remove (bus_source);
+
+ if (main_loop)
+ g_main_loop_unref (main_loop);
+ main_loop = NULL;
+
+ if (preview_caps)
+ gst_caps_unref (preview_caps);
+ preview_caps = NULL;
+
+ if (preview_buffer)
+ gst_buffer_unref (preview_buffer);
+ preview_buffer = NULL;
+
+ g_free (preview_filename);
+ preview_filename = NULL;
+
+ if (tags_found)
+ gst_tag_list_free (tags_found);
+ tags_found = NULL;
+
+ g_free (video_filename);
+ video_filename = NULL;
+
+ g_free (image_filename);
+ image_filename = NULL;
+
+ GST_INFO ("done");
+}
+
+static gboolean
+validity_bus_cb (GstBus * bus, GstMessage * message, gpointer data)
+{
+ GMainLoop *loop = (GMainLoop *) data;
+ switch (GST_MESSAGE_TYPE (message)) {
+ case GST_MESSAGE_ERROR:{
+ GError *err = NULL;
+ gchar *debug = NULL;
+
+ gst_message_parse_error (message, &err, &debug);
+
+ GST_ERROR ("Error: %s : %s", err->message, debug);
+ g_error_free (err);
+ g_free (debug);
+
+ fail_if (TRUE, "validating captured data failed");
+ g_main_loop_quit (loop);
+ }
+ break;
+ case GST_MESSAGE_EOS:
+ g_main_loop_quit (loop);
+ GST_DEBUG ("eos");
+ break;
+ case GST_MESSAGE_TAG:{
+ GstTagList *taglist = NULL;
+
+ gst_message_parse_tag (message, &taglist);
+ if (tags_found) {
+ gst_tag_list_insert (tags_found, taglist, GST_TAG_MERGE_REPLACE);
+ gst_tag_list_free (taglist);
+ } else {
+ tags_found = taglist;
+ }
+ GST_DEBUG ("tags: %" GST_PTR_FORMAT, tags_found);
+ }
+ break;
+ default:
+ break;
+ }
+ return TRUE;
+}
+
+/* checks that tags in @tags_a are in @tags_b */
+static gboolean
+taglist_is_subset (GstTagList * tags_a, GstTagList * tags_b)
+{
+ gst_tag_list_foreach (tags_a, validate_taglist_foreach, tags_b);
+ return TRUE;
+}
+
+/* Validate captured files by playing them with playbin
+ * and checking that no errors occur. */
+#define WITH_AUDIO TRUE
+#define NO_AUDIO FALSE
+static gboolean
+check_file_validity (const gchar * filename, gint num, GstTagList * taglist,
+ gint width, gint height, gboolean has_audio)
+{
+ GstBus *bus;
+ GstPad *pad;
+ GstCaps *caps;
+ gint caps_width, caps_height;
+ GstState state;
+ guint source;
+
+ GMainLoop *loop = g_main_loop_new (NULL, FALSE);
+ GstElement *playbin = gst_element_factory_make ("playbin2", NULL);
+ GstElement *fakevideo = gst_element_factory_make ("fakesink", NULL);
+ GstElement *fakeaudio = gst_element_factory_make ("fakesink", NULL);
+ gchar *uri = g_strconcat ("file://", make_const_file_name (filename, num),
+ NULL);
+
+ GST_DEBUG ("checking uri: %s", uri);
+ g_object_set (G_OBJECT (playbin), "uri", uri, "video-sink", fakevideo,
+ "audio-sink", fakeaudio, NULL);
+
+ bus = gst_pipeline_get_bus (GST_PIPELINE (playbin));
+ source = gst_bus_add_watch (bus, (GstBusFunc) validity_bus_cb, loop);
+
+ gst_element_set_state (playbin, GST_STATE_PAUSED);
+ gst_element_get_state (playbin, &state, NULL, GST_SECOND * 3);
+
+ if (width != 0 && height != 0) {
+ g_signal_emit_by_name (playbin, "get-video-pad", 0, &pad, NULL);
+ g_assert (pad != NULL);
+ caps = gst_pad_get_current_caps (pad);
+
+ g_assert (gst_structure_get_int (gst_caps_get_structure (caps, 0),
+ "width", &caps_width));
+ g_assert (gst_structure_get_int (gst_caps_get_structure (caps, 0),
+ "height", &caps_height));
+
+ g_assert (width == caps_width);
+ g_assert (height == caps_height);
+
+ gst_caps_unref (caps);
+ gst_object_unref (pad);
+ }
+ if (has_audio) {
+ g_signal_emit_by_name (playbin, "get-audio-pad", 0, &pad, NULL);
+ g_assert (pad != NULL);
+ gst_object_unref (pad);
+ }
+
+ gst_element_set_state (playbin, GST_STATE_PLAYING);
+ g_main_loop_run (loop);
+ gst_element_set_state (playbin, GST_STATE_NULL);
+
+ /* special handling for images (jpg) as jpegparse isn't plugged by
+ * default due to its current low rank */
+ if (taglist && strstr (filename, "image")) {
+ extract_jpeg_tags (filename, num);
+ }
+
+ if (taglist) {
+ fail_unless (tags_found != NULL);
+ fail_unless (taglist_is_subset (taglist, tags_found));
+ }
+
+ g_free (uri);
+ g_source_remove (source);
+ gst_object_unref (bus);
+ gst_object_unref (playbin);
+ g_main_loop_unref (loop);
+
+ return TRUE;
+}
+
+static void
+remove_file (const gchar * fn_template, guint num)
+{
+ const gchar *fn;
+
+ fn = make_const_file_name (fn_template, num);
+ GST_INFO ("removing %s", fn);
+ g_unlink (fn);
+}
+
+static GstPadProbeReturn
+filter_buffer_count (GstPad * pad, GstPadProbeInfo * info, gpointer data)
+{
+ gint *counter = data;
+
+ (*counter)++;
+
+ return GST_PAD_PROBE_OK;
+}
+
+static GstMessage *
+wait_for_element_message (GstElement * camera, const gchar * name,
+ GstClockTime timeout)
+{
+ GstBus *bus = gst_pipeline_get_bus (GST_PIPELINE (camera));
+ GstMessage *msg;
+
+ while (1) {
+ msg = gst_bus_timed_pop_filtered (bus, timeout, GST_MESSAGE_ERROR |
+ GST_MESSAGE_EOS | GST_MESSAGE_ELEMENT);
+
+ if (msg) {
+ if (GST_MESSAGE_TYPE (msg) == GST_MESSAGE_ELEMENT) {
+ const GstStructure *st = gst_message_get_structure (msg);
+ if (gst_structure_has_name (st,
+ GST_BASE_CAMERA_SRC_PREVIEW_MESSAGE_NAME)) {
+ GstBuffer *buf;
+ const GValue *value;
+
+ value = gst_structure_get_value (st, "buffer");
+ fail_unless (value != NULL);
+ buf = gst_value_get_buffer (value);
+
+ if (preview_buffer)
+ gst_buffer_unref (preview_buffer);
+ preview_buffer = gst_buffer_ref (buf);
+ g_free (preview_filename);
+ preview_filename =
+ g_strdup (gst_structure_get_string (st, "location"));
+ }
+
+ if (gst_structure_has_name (st, name))
+ break;
+ else
+ gst_message_unref (msg);
+ } else {
+ gst_message_unref (msg);
+ msg = NULL;
+ break;
+ }
+ }
+ }
+
+ gst_object_unref (bus);
+ return msg;
+}
+
+static void
+wait_for_idle_state (void)
+{
+ gboolean idle = FALSE;
+
+ /* not the ideal way, but should be enough for testing */
+ while (idle == FALSE) {
+ g_object_get (camera, "idle", &idle, NULL);
+ if (idle)
+ break;
+
+ GST_LOG ("waiting for idle state..");
+ g_usleep (G_USEC_PER_SEC / 5);
+ }
+ fail_unless (idle);
+}
+
+GST_START_TEST (test_single_image_capture)
+{
+ gboolean idle;
+ GstMessage *msg;
+ if (!camera)
+ return;
+
+ /* set still image mode */
+ g_object_set (camera, "mode", 1, "location", image_filename, NULL);
+
+ if (gst_element_set_state (GST_ELEMENT (camera), GST_STATE_PLAYING) ==
+ GST_STATE_CHANGE_FAILURE) {
+ GST_WARNING ("setting camerabin to PLAYING failed");
+ gst_element_set_state (GST_ELEMENT (camera), GST_STATE_NULL);
+ gst_object_unref (camera);
+ camera = NULL;
+ }
+ GST_INFO ("starting capture");
+ fail_unless (camera != NULL);
+ g_object_get (camera, "idle", &idle, NULL);
+ fail_unless (idle);
+ g_signal_emit_by_name (camera, "start-capture", NULL);
+
+ msg = wait_for_element_message (camera, "image-done", GST_CLOCK_TIME_NONE);
+ fail_unless (msg != NULL);
+ gst_message_unref (msg);
+
+ /* check that we got a preview image */
+ check_preview_image (camera, image_filename, 0);
+
+ wait_for_idle_state ();
+ gst_element_set_state (GST_ELEMENT (camera), GST_STATE_NULL);
+ check_file_validity (image_filename, 0, NULL, 0, 0, NO_AUDIO);
+ remove_file (image_filename, 0);
+}
+
+GST_END_TEST;
+
+
+GST_START_TEST (test_multiple_image_captures)
+{
+ gboolean idle;
+ gint i;
+ gint widths[] = { 800, 640, 1280 };
+ gint heights[] = { 600, 480, 1024 };
+
+ if (!camera)
+ return;
+
+ /* set still image mode */
+ g_object_set (camera, "mode", 1, "location", image_filename, NULL);
+
+ if (gst_element_set_state (GST_ELEMENT (camera), GST_STATE_PLAYING) ==
+ GST_STATE_CHANGE_FAILURE) {
+ GST_WARNING ("setting camerabin to PLAYING failed");
+ gst_element_set_state (GST_ELEMENT (camera), GST_STATE_NULL);
+ gst_object_unref (camera);
+ camera = NULL;
+ }
+ fail_unless (camera != NULL);
+ g_object_get (camera, "idle", &idle, NULL);
+ fail_unless (idle);
+ GST_INFO ("starting capture");
+
+ for (i = 0; i < 3; i++) {
+ GstMessage *msg;
+ GstCaps *caps;
+
+ caps = gst_caps_new_simple ("video/x-raw", "width", G_TYPE_INT,
+ widths[i], "height", G_TYPE_INT, heights[i], NULL);
+
+ g_object_set (camera, "image-capture-caps", caps, NULL);
+ gst_caps_unref (caps);
+
+ g_signal_emit_by_name (camera, "start-capture", NULL);
+
+ msg = wait_for_element_message (camera, "image-done", GST_CLOCK_TIME_NONE);
+ fail_unless (msg != NULL);
+ gst_message_unref (msg);
+
+ check_preview_image (camera, image_filename, i);
+ }
+
+ wait_for_idle_state ();
+ gst_element_set_state (GST_ELEMENT (camera), GST_STATE_NULL);
+ for (i = 0; i < 3; i++) {
+ check_file_validity (image_filename, i, NULL, widths[i], heights[i],
+ NO_AUDIO);
+ remove_file (image_filename, i);
+ }
+}
+
+GST_END_TEST;
+
+GST_START_TEST (test_single_video_recording)
+{
+ GstMessage *msg;
+ gboolean idle;
+ if (!camera)
+ return;
+
+ /* Set video recording mode */
+ g_object_set (camera, "mode", 2, "location", video_filename, NULL);
+
+ if (gst_element_set_state (GST_ELEMENT (camera), GST_STATE_PLAYING) ==
+ GST_STATE_CHANGE_FAILURE) {
+ GST_WARNING ("setting camerabin to PLAYING failed");
+ gst_element_set_state (GST_ELEMENT (camera), GST_STATE_NULL);
+ gst_object_unref (camera);
+ camera = NULL;
+ }
+
+ GST_INFO ("starting capture");
+ fail_unless (camera != NULL);
+ g_object_get (camera, "idle", &idle, NULL);
+ fail_unless (idle);
+ g_signal_emit_by_name (camera, "start-capture", NULL);
+
+ g_object_get (camera, "idle", &idle, NULL);
+ fail_unless (!idle);
+
+ /* Record for one seconds */
+ g_timeout_add_seconds (VIDEO_DURATION, (GSourceFunc) g_main_loop_quit,
+ main_loop);
+ g_main_loop_run (main_loop);
+
+ g_signal_emit_by_name (camera, "stop-capture", NULL);
+
+ check_preview_image (camera, video_filename, 0);
+
+ msg = wait_for_element_message (camera, "video-done", GST_CLOCK_TIME_NONE);
+ fail_unless (msg != NULL);
+ gst_message_unref (msg);
+
+ wait_for_idle_state ();
+ gst_element_set_state (GST_ELEMENT (camera), GST_STATE_NULL);
+
+ check_file_validity (video_filename, 0, NULL, 0, 0, WITH_AUDIO);
+ remove_file (video_filename, 0);
+
+}
+
+GST_END_TEST;
+
+GST_START_TEST (test_multiple_video_recordings)
+{
+ gboolean idle;
+ gint i;
+ gint widths[] = { 800, 640, 1280 };
+ gint heights[] = { 600, 480, 1024 };
+ gint fr[] = { 20, 30, 5 };
+
+ if (!camera)
+ return;
+
+ /* Set video recording mode */
+ g_object_set (camera, "mode", 2, "location", video_filename, NULL);
+
+ if (gst_element_set_state (GST_ELEMENT (camera), GST_STATE_PLAYING) ==
+ GST_STATE_CHANGE_FAILURE) {
+ GST_WARNING ("setting camerabin to PLAYING failed");
+ gst_element_set_state (GST_ELEMENT (camera), GST_STATE_NULL);
+ gst_object_unref (camera);
+ camera = NULL;
+ }
+
+ GST_INFO ("starting capture");
+ fail_unless (camera != NULL);
+ g_object_get (camera, "idle", &idle, NULL);
+ fail_unless (idle);
+ for (i = 0; i < 3; i++) {
+ GstMessage *msg;
+ GstCaps *caps;
+
+ caps = gst_caps_new_simple ("video/x-raw", "width", G_TYPE_INT,
+ widths[i], "height", G_TYPE_INT, heights[i], "framerate",
+ GST_TYPE_FRACTION, fr[i], 1, NULL);
+
+ g_object_set (camera, "video-capture-caps", caps, NULL);
+
+ gst_caps_unref (caps);
+
+ GST_LOG ("starting #%d with caps %" GST_PTR_FORMAT, i, caps);
+ g_signal_emit_by_name (camera, "start-capture", NULL);
+
+ g_object_get (camera, "idle", &idle, NULL);
+ fail_unless (!idle);
+
+ g_timeout_add_seconds (VIDEO_DURATION, (GSourceFunc) g_main_loop_quit,
+ main_loop);
+ g_main_loop_run (main_loop);
+
+ GST_LOG ("stopping run %d", i);
+ g_signal_emit_by_name (camera, "stop-capture", NULL);
+
+ msg = wait_for_element_message (camera, "video-done", GST_CLOCK_TIME_NONE);
+ fail_unless (msg != NULL);
+ gst_message_unref (msg);
+
+ GST_LOG ("video done, checking preview image");
+ check_preview_image (camera, video_filename, i);
+
+ GST_LOG ("waiting for idle state");
+ wait_for_idle_state ();
+ GST_LOG ("finished run %d", i);
+ }
+ gst_element_set_state (GST_ELEMENT (camera), GST_STATE_NULL);
+
+ for (i = 0; i < 3; i++) {
+ check_file_validity (video_filename, i, NULL, widths[i], heights[i],
+ WITH_AUDIO);
+ remove_file (video_filename, i);
+ }
+}
+
+GST_END_TEST;
+
+GST_START_TEST (test_image_video_cycle)
+{
+ gint i;
+
+ if (!camera)
+ return;
+
+ if (gst_element_set_state (GST_ELEMENT (camera), GST_STATE_PLAYING) ==
+ GST_STATE_CHANGE_FAILURE) {
+ GST_WARNING ("setting camerabin to PLAYING failed");
+ gst_element_set_state (GST_ELEMENT (camera), GST_STATE_NULL);
+ gst_object_unref (camera);
+ camera = NULL;
+ }
+
+ GST_INFO ("starting capture");
+ for (i = 0; i < 2; i++) {
+ GstMessage *msg;
+ const gchar *img_filename;
+ const gchar *vid_filename;
+
+ wait_for_idle_state ();
+
+ /* take a picture */
+ img_filename = make_const_file_name (image_filename, i);
+ g_object_set (camera, "mode", 1, NULL);
+ g_object_set (camera, "location", img_filename, NULL);
+ g_signal_emit_by_name (camera, "start-capture", NULL);
+
+ msg = wait_for_element_message (camera, "image-done", GST_CLOCK_TIME_NONE);
+ fail_unless (msg != NULL);
+ gst_message_unref (msg);
+
+ check_preview_image (camera, img_filename, i);
+
+ /* now go to video */
+ vid_filename = make_const_file_name (video_filename, i);
+ g_object_set (camera, "mode", 2, NULL);
+ g_object_set (camera, "location", vid_filename, NULL);
+
+ g_signal_emit_by_name (camera, "start-capture", NULL);
+ g_timeout_add_seconds (VIDEO_DURATION, (GSourceFunc) g_main_loop_quit,
+ main_loop);
+ g_main_loop_run (main_loop);
+ g_signal_emit_by_name (camera, "stop-capture", NULL);
+
+ msg = wait_for_element_message (camera, "video-done", GST_CLOCK_TIME_NONE);
+ fail_unless (msg != NULL);
+ gst_message_unref (msg);
+
+ check_preview_image (camera, vid_filename, i);
+ }
+
+ wait_for_idle_state ();
+ gst_element_set_state (GST_ELEMENT (camera), GST_STATE_NULL);
+
+ /* validate all the files */
+ for (i = 0; i < 2; i++) {
+ check_file_validity (image_filename, i, NULL, 0, 0, NO_AUDIO);
+ remove_file (image_filename, i);
+ check_file_validity (video_filename, i, NULL, 0, 0, WITH_AUDIO);
+ remove_file (video_filename, i);
+ }
+}
+
+GST_END_TEST;
+
+
+GST_START_TEST (test_image_capture_previews)
+{
+ gint i;
+ gint widths[] = { 800, 640, 1280 };
+ gint heights[] = { 600, 480, 1024 };
+
+ if (!camera)
+ return;
+
+ /* set still image mode */
+ g_object_set (camera, "mode", 1, "location", image_filename, NULL);
+
+ if (gst_element_set_state (GST_ELEMENT (camera), GST_STATE_PLAYING) ==
+ GST_STATE_CHANGE_FAILURE) {
+ GST_WARNING ("setting camerabin to PLAYING failed");
+ gst_element_set_state (GST_ELEMENT (camera), GST_STATE_NULL);
+ gst_object_unref (camera);
+ camera = NULL;
+ }
+ fail_unless (camera != NULL);
+ GST_INFO ("starting capture");
+
+ for (i = 0; i < 3; i++) {
+ GstMessage *msg;
+ GstCaps *caps;
+
+ caps = gst_caps_new_simple ("video/x-raw", "width", G_TYPE_INT,
+ widths[i], "height", G_TYPE_INT, heights[i], NULL);
+
+ g_object_set (camera, "preview-caps", caps, NULL);
+ gst_caps_replace (&preview_caps, caps);
+ gst_caps_unref (caps);
+
+ g_signal_emit_by_name (camera, "start-capture", NULL);
+
+ msg = wait_for_element_message (camera, "image-done", GST_CLOCK_TIME_NONE);
+ fail_unless (msg != NULL);
+ gst_message_unref (msg);
+
+ check_preview_image (camera, image_filename, i);
+ remove_file (image_filename, i);
+
+ if (preview_buffer)
+ gst_buffer_unref (preview_buffer);
+ preview_buffer = NULL;
+ gst_caps_replace (&preview_caps, NULL);
+ }
+
+ gst_element_set_state (GST_ELEMENT (camera), GST_STATE_NULL);
+}
+
+GST_END_TEST;
+
+
+GST_START_TEST (test_image_capture_with_tags)
+{
+ gint i;
+ GstTagList *taglists[3];
+
+ if (!camera)
+ return;
+
+ taglists[0] = gst_tag_list_new (GST_TAG_COMMENT, "test1",
+ GST_TAG_GEO_LOCATION_LATITUDE, 36.6, GST_TAG_GEO_LOCATION_LONGITUDE,
+ -12.5,
+ GST_TAG_COPYRIGHT, "My copyright notice",
+ GST_TAG_DEVICE_MANUFACTURER, "MyFavoriteBrand",
+ GST_TAG_DEVICE_MODEL, "123v42.1",
+ GST_TAG_DESCRIPTION, "some description",
+ GST_TAG_APPLICATION_NAME, "camerabin2 test",
+ GST_TAG_GEO_LOCATION_ELEVATION, 300.85, NULL);
+ taglists[1] = gst_tag_list_new (GST_TAG_COMMENT, "test2",
+ GST_TAG_GEO_LOCATION_LATITUDE, 1.6, GST_TAG_GEO_LOCATION_LONGITUDE,
+ 0.0,
+ GST_TAG_COPYRIGHT, "some cp",
+ GST_TAG_DEVICE_MANUFACTURER, "ABRAND",
+ GST_TAG_DEVICE_MODEL, "abcd",
+ GST_TAG_DESCRIPTION, "desc",
+ GST_TAG_APPLICATION_NAME, "another cam test",
+ GST_TAG_GEO_LOCATION_ELEVATION, 10.0, NULL);
+ taglists[2] = gst_tag_list_new (GST_TAG_COMMENT, "test3",
+ GST_TAG_GEO_LOCATION_LATITUDE, 1.3, GST_TAG_GEO_LOCATION_LONGITUDE,
+ -5.0,
+ GST_TAG_COPYRIGHT, "CC",
+ GST_TAG_DEVICE_MANUFACTURER, "Homemade",
+ GST_TAG_DEVICE_MODEL, "xpto",
+ GST_TAG_DESCRIPTION, "another description",
+ GST_TAG_APPLICATION_NAME, "cam2 test",
+ GST_TAG_GEO_LOCATION_ELEVATION, 0.0, NULL);
+
+ /* set still image mode */
+ g_object_set (camera, "mode", 1, "location", image_filename, NULL);
+
+ if (gst_element_set_state (GST_ELEMENT (camera), GST_STATE_PLAYING) ==
+ GST_STATE_CHANGE_FAILURE) {
+ GST_WARNING ("setting camerabin to PLAYING failed");
+ gst_element_set_state (GST_ELEMENT (camera), GST_STATE_NULL);
+ gst_object_unref (camera);
+ camera = NULL;
+ }
+ fail_unless (camera != NULL);
+ GST_INFO ("starting capture");
+
+ for (i = 0; i < 3; i++) {
+ GstMessage *msg;
+ gst_tag_setter_merge_tags (GST_TAG_SETTER (camera), taglists[i],
+ GST_TAG_MERGE_REPLACE);
+
+ g_signal_emit_by_name (camera, "start-capture", NULL);
+
+ msg = wait_for_element_message (camera, "image-done", GST_CLOCK_TIME_NONE);
+ fail_unless (msg != NULL);
+ gst_message_unref (msg);
+ }
+
+ gst_element_set_state (GST_ELEMENT (camera), GST_STATE_NULL);
+
+ for (i = 0; i < 3; i++) {
+ check_file_validity (image_filename, i, taglists[i], 0, 0, NO_AUDIO);
+ gst_tag_list_free (taglists[i]);
+ remove_file (image_filename, i);
+ }
+}
+
+GST_END_TEST;
+
+
+GST_START_TEST (test_video_capture_with_tags)
+{
+ gint i;
+ GstTagList *taglists[3];
+
+ if (!camera)
+ return;
+
+ taglists[0] = gst_tag_list_new (GST_TAG_COMMENT, "test1", NULL);
+ taglists[1] = gst_tag_list_new (GST_TAG_COMMENT, "test2", NULL);
+ taglists[2] = gst_tag_list_new (GST_TAG_COMMENT, "test3", NULL);
+
+ /* set video mode */
+ g_object_set (camera, "mode", 2, "location", video_filename, NULL);
+
+ /* set a profile that has xmp support for more tags being saved */
+ {
+ GstEncodingContainerProfile *profile;
+ GstCaps *caps;
+
+ caps =
+ gst_caps_new_simple ("video/quicktime", "variant", G_TYPE_STRING,
+ "apple", NULL);
+ profile = gst_encoding_container_profile_new ("qt", "jpeg+qt", caps, NULL);
+ gst_caps_unref (caps);
+
+ caps = gst_caps_new_simple ("image/jpeg", NULL, NULL);
+ if (!gst_encoding_container_profile_add_profile (profile,
+ (GstEncodingProfile *) gst_encoding_video_profile_new (caps,
+ NULL, NULL, 1))) {
+ GST_WARNING_OBJECT (camera, "Failed to create encoding profiles");
+ }
+ gst_caps_unref (caps);
+
+ g_object_set (camera, "video-profile", profile, NULL);
+ gst_encoding_profile_unref (profile);
+ }
+
+ if (gst_element_set_state (GST_ELEMENT (camera), GST_STATE_PLAYING) ==
+ GST_STATE_CHANGE_FAILURE) {
+ GST_WARNING ("setting camerabin to PLAYING failed");
+ gst_element_set_state (GST_ELEMENT (camera), GST_STATE_NULL);
+ gst_object_unref (camera);
+ camera = NULL;
+ }
+ fail_unless (camera != NULL);
+ GST_INFO ("starting capture");
+
+ for (i = 0; i < 3; i++) {
+ GstMessage *msg;
+
+ gst_tag_setter_merge_tags (GST_TAG_SETTER (camera), taglists[i],
+ GST_TAG_MERGE_REPLACE);
+
+ g_signal_emit_by_name (camera, "start-capture", NULL);
+
+ g_timeout_add_seconds (3, (GSourceFunc) g_main_loop_quit, main_loop);
+ g_main_loop_run (main_loop);
+
+ g_signal_emit_by_name (camera, "stop-capture", NULL);
+
+ msg = wait_for_element_message (camera, "video-done", GST_CLOCK_TIME_NONE);
+ fail_unless (msg != NULL);
+ gst_message_unref (msg);
+ }
+
+ gst_element_set_state (GST_ELEMENT (camera), GST_STATE_NULL);
+
+ for (i = 0; i < 3; i++) {
+ check_file_validity (video_filename, i, taglists[i], 0, 0, NO_AUDIO);
+ gst_tag_list_free (taglists[i]);
+ remove_file (video_filename, i);
+ }
+}
+
+GST_END_TEST;
+
+
+GST_START_TEST (test_supported_caps)
+{
+ GstCaps *padcaps = NULL;
+ GstCaps *expectedcaps;
+ GstElement *src;
+
+ if (!camera)
+ return;
+
+ src = g_object_new (GST_TYPE_TEST_CAMERA_SRC, NULL);
+ g_object_set (camera, "camera-source", src, NULL);
+ gst_object_unref (src);
+
+ if (gst_element_set_state (GST_ELEMENT (camera), GST_STATE_PLAYING) ==
+ GST_STATE_CHANGE_FAILURE) {
+ GST_WARNING ("setting camerabin to PLAYING failed");
+ gst_element_set_state (GST_ELEMENT (camera), GST_STATE_NULL);
+ gst_object_unref (camera);
+ camera = NULL;
+ }
+ g_assert (camera != NULL);
+
+ expectedcaps = gst_caps_from_string (VIDEO_PAD_SUPPORTED_CAPS);
+ g_object_get (G_OBJECT (camera), "video-capture-supported-caps", &padcaps,
+ NULL);
+ g_assert (expectedcaps != NULL);
+ g_assert (padcaps != NULL);
+ g_assert (gst_caps_is_equal (padcaps, expectedcaps));
+ gst_caps_unref (expectedcaps);
+ gst_caps_unref (padcaps);
+
+ expectedcaps = gst_caps_from_string (IMAGE_PAD_SUPPORTED_CAPS);
+ g_object_get (G_OBJECT (camera), "image-capture-supported-caps", &padcaps,
+ NULL);
+ g_assert (expectedcaps != NULL);
+ g_assert (padcaps != NULL);
+ g_assert (gst_caps_is_equal (padcaps, expectedcaps));
+ gst_caps_unref (expectedcaps);
+ gst_caps_unref (padcaps);
+
+ gst_element_set_state (camera, GST_STATE_NULL);
+}
+
+GST_END_TEST;
+
+
+GST_START_TEST (test_idle_property)
+{
+ GstMessage *msg;
+ gboolean idle;
+ if (!camera)
+ return;
+
+ /* Set video recording mode */
+ g_object_set (camera, "mode", 2, "location", video_filename, NULL);
+
+ if (gst_element_set_state (GST_ELEMENT (camera), GST_STATE_PLAYING) ==
+ GST_STATE_CHANGE_FAILURE) {
+ GST_WARNING ("setting camerabin to PLAYING failed");
+ gst_element_set_state (GST_ELEMENT (camera), GST_STATE_NULL);
+ gst_object_unref (camera);
+ camera = NULL;
+ }
+
+ GST_INFO ("starting capture");
+ fail_unless (camera != NULL);
+ g_object_get (camera, "idle", &idle, NULL);
+ fail_unless (idle);
+ g_signal_emit_by_name (camera, "start-capture", NULL);
+ g_object_get (camera, "idle", &idle, NULL);
+ fail_unless (!idle);
+
+ /* emit a second start-capture that should be ignored */
+ g_signal_emit_by_name (camera, "start-capture", NULL);
+ g_object_get (camera, "idle", &idle, NULL);
+ fail_unless (!idle);
+
+ /* Record for one seconds */
+ g_timeout_add_seconds (VIDEO_DURATION, (GSourceFunc) g_main_loop_quit,
+ main_loop);
+ g_main_loop_run (main_loop);
+
+ g_signal_emit_by_name (camera, "stop-capture", NULL);
+
+ msg = wait_for_element_message (camera, "video-done", GST_CLOCK_TIME_NONE);
+ fail_unless (msg != NULL);
+ gst_message_unref (msg);
+
+ check_preview_image (camera, video_filename, 0);
+
+ wait_for_idle_state ();
+
+ gst_element_set_state (GST_ELEMENT (camera), GST_STATE_NULL);
+
+ check_file_validity (video_filename, 0, NULL, 0, 0, WITH_AUDIO);
+ remove_file (video_filename, 0);
+}
+
+GST_END_TEST;
+
+
+GST_START_TEST (test_image_custom_filter)
+{
+ GstElement *vf_filter;
+ GstElement *image_filter;
+ GstElement *preview_filter;
+ GstPad *pad;
+ gint vf_probe_counter = 0;
+ gint image_probe_counter = 0;
+ gint preview_probe_counter = 0;
+
+ if (!camera)
+ return;
+
+ vf_filter = gst_element_factory_make ("identity", "vf-filter");
+ image_filter = gst_element_factory_make ("identity", "img-filter");
+ preview_filter = gst_element_factory_make ("identity", "preview-filter");
+
+ pad = gst_element_get_static_pad (vf_filter, "src");
+ gst_pad_add_probe (pad, GST_PAD_PROBE_TYPE_BUFFER, filter_buffer_count,
+ &vf_probe_counter, NULL);
+ gst_object_unref (pad);
+
+ pad = gst_element_get_static_pad (image_filter, "src");
+ gst_pad_add_probe (pad, GST_PAD_PROBE_TYPE_BUFFER, filter_buffer_count,
+ &image_probe_counter, NULL);
+ gst_object_unref (pad);
+
+ pad = gst_element_get_static_pad (preview_filter, "src");
+ gst_pad_add_probe (pad, GST_PAD_PROBE_TYPE_BUFFER, filter_buffer_count,
+ &preview_probe_counter, NULL);
+ gst_object_unref (pad);
+
+ /* set still image mode and filters */
+ g_object_set (camera, "mode", 1,
+ "location", image_filename,
+ "viewfinder-filter", vf_filter, "image-filter", image_filter,
+ "preview-filter", preview_filter, NULL);
+
+ gst_object_unref (vf_filter);
+ gst_object_unref (preview_filter);
+ gst_object_unref (image_filter);
+
+ if (gst_element_set_state (GST_ELEMENT (camera), GST_STATE_PLAYING) ==
+ GST_STATE_CHANGE_FAILURE) {
+ GST_WARNING ("setting camerabin to PLAYING failed");
+ gst_element_set_state (GST_ELEMENT (camera), GST_STATE_NULL);
+ gst_object_unref (camera);
+ camera = NULL;
+ }
+ GST_INFO ("starting capture");
+ fail_unless (camera != NULL);
+ g_signal_emit_by_name (camera, "start-capture", NULL);
+
+ g_timeout_add_seconds (3, (GSourceFunc) g_main_loop_quit, main_loop);
+ g_main_loop_run (main_loop);
+
+ /* check that we got a preview image */
+ check_preview_image (camera, image_filename, 0);
+
+ gst_element_set_state (GST_ELEMENT (camera), GST_STATE_NULL);
+ check_file_validity (image_filename, 0, NULL, 0, 0, NO_AUDIO);
+ remove_file (image_filename, 0);
+
+ fail_unless (vf_probe_counter > 0);
+ fail_unless (image_probe_counter == 1);
+ fail_unless (preview_probe_counter == 1);
+}
+
+GST_END_TEST;
+
+
+GST_START_TEST (test_video_custom_filter)
+{
+ GstElement *vf_filter;
+ GstElement *video_filter;
+ GstElement *preview_filter;
+ GstElement *audio_filter;
+ GstPad *pad;
+ gint vf_probe_counter = 0;
+ gint video_probe_counter = 0;
+ gint preview_probe_counter = 0;
+ gint audio_probe_counter = 0;
+
+ if (!camera)
+ return;
+
+ vf_filter = gst_element_factory_make ("identity", "vf-filter");
+ video_filter = gst_element_factory_make ("identity", "video-filter");
+ preview_filter = gst_element_factory_make ("identity", "preview-filter");
+ audio_filter = gst_element_factory_make ("identity", "audio-filter");
+
+ pad = gst_element_get_static_pad (vf_filter, "src");
+ gst_pad_add_probe (pad, GST_PAD_PROBE_TYPE_BUFFER, filter_buffer_count,
+ &vf_probe_counter, NULL);
+ gst_object_unref (pad);
+
+ pad = gst_element_get_static_pad (video_filter, "src");
+ gst_pad_add_probe (pad, GST_PAD_PROBE_TYPE_BUFFER, filter_buffer_count,
+ &video_probe_counter, NULL);
+ gst_object_unref (pad);
+
+ pad = gst_element_get_static_pad (audio_filter, "src");
+ gst_pad_add_probe (pad, GST_PAD_PROBE_TYPE_BUFFER, filter_buffer_count,
+ &audio_probe_counter, NULL);
+ gst_object_unref (pad);
+
+ pad = gst_element_get_static_pad (preview_filter, "src");
+ gst_pad_add_probe (pad, GST_PAD_PROBE_TYPE_BUFFER, filter_buffer_count,
+ &preview_probe_counter, NULL);
+ gst_object_unref (pad);
+
+ /* set still image mode and filters */
+ g_object_set (camera, "mode", 2,
+ "location", video_filename,
+ "viewfinder-filter", vf_filter, "video-filter", video_filter,
+ "preview-filter", preview_filter, "audio-filter", audio_filter, NULL);
+
+ gst_object_unref (vf_filter);
+ gst_object_unref (preview_filter);
+ gst_object_unref (video_filter);
+ gst_object_unref (audio_filter);
+
+ if (gst_element_set_state (GST_ELEMENT (camera), GST_STATE_PLAYING) ==
+ GST_STATE_CHANGE_FAILURE) {
+ GST_WARNING ("setting camerabin to PLAYING failed");
+ gst_element_set_state (GST_ELEMENT (camera), GST_STATE_NULL);
+ gst_object_unref (camera);
+ camera = NULL;
+ }
+ GST_INFO ("starting capture");
+ fail_unless (camera != NULL);
+ g_signal_emit_by_name (camera, "start-capture", NULL);
+
+ g_timeout_add_seconds (VIDEO_DURATION, (GSourceFunc) g_main_loop_quit,
+ main_loop);
+ g_main_loop_run (main_loop);
+ g_signal_emit_by_name (camera, "stop-capture", NULL);
+
+ /* check that we got a preview image */
+ check_preview_image (camera, video_filename, 0);
+
+ gst_element_set_state (GST_ELEMENT (camera), GST_STATE_NULL);
+ check_file_validity (video_filename, 0, NULL, 0, 0, WITH_AUDIO);
+ remove_file (video_filename, 0);
+
+ fail_unless (vf_probe_counter > 0);
+ fail_unless (video_probe_counter > 0);
+ fail_unless (audio_probe_counter > 0);
+ fail_unless (preview_probe_counter == 1);
+}
+
+GST_END_TEST;
+
+#define LOCATION_SWITCHING_FILENAMES_COUNT 5
+
+static gboolean
+image_location_switch_do_capture (gpointer data)
+{
+ gchar **filenames = data;
+ if (capture_count >= LOCATION_SWITCHING_FILENAMES_COUNT) {
+ g_main_loop_quit (main_loop);
+ }
+
+ g_object_set (camera, "location", filenames[capture_count], NULL);
+ g_signal_emit_by_name (camera, "start-capture", NULL);
+ capture_count++;
+ return FALSE;
+}
+
+static void
+image_location_switch_readyforcapture (GObject * obj, GParamSpec * pspec,
+ gpointer user_data)
+{
+ gboolean ready;
+
+ g_object_get (obj, "ready-for-capture", &ready, NULL);
+ if (ready) {
+ g_idle_add (image_location_switch_do_capture, user_data);
+ }
+};
+
+/*
+ * Tests that setting the location and then doing an image
+ * capture will set this capture resulting filename to the
+ * correct location.
+ *
+ * There was a bug in which setting the location, issuing a capture
+ * and then setting a new location would cause this capture to have
+ * the location set after this capture. This test should prevent it
+ * from happening again.
+ */
+GST_START_TEST (test_image_location_switching)
+{
+ gchar *filenames[LOCATION_SWITCHING_FILENAMES_COUNT + 1];
+ gint i;
+ glong notify_id;
+ GstCaps *caps;
+ GstElement *src;
+ GstMessage *msg;
+
+ if (!camera)
+ return;
+
+ g_object_get (camera, "camera-source", &src, NULL);
+
+ for (i = 0; i < LOCATION_SWITCHING_FILENAMES_COUNT; i++) {
+ filenames[i] = make_test_file_name ("image-switching-filename-test", i);
+ }
+ filenames[LOCATION_SWITCHING_FILENAMES_COUNT] = NULL;
+
+ /* set still image mode */
+ g_object_set (camera, "mode", 1, NULL);
+ caps = gst_caps_new_simple ("video/x-raw", "width", G_TYPE_INT,
+ 800, "height", G_TYPE_INT, 600, NULL);
+ g_object_set (camera, "image-capture-caps", caps, NULL);
+ gst_caps_unref (caps);
+
+ if (gst_element_set_state (GST_ELEMENT (camera), GST_STATE_PLAYING) ==
+ GST_STATE_CHANGE_FAILURE) {
+ GST_WARNING ("setting camerabin to PLAYING failed");
+ gst_element_set_state (GST_ELEMENT (camera), GST_STATE_NULL);
+ gst_object_unref (camera);
+ camera = NULL;
+ }
+ fail_unless (camera != NULL);
+ GST_INFO ("starting capture");
+
+ notify_id = g_signal_connect (G_OBJECT (src),
+ "notify::ready-for-capture",
+ G_CALLBACK (image_location_switch_readyforcapture), filenames);
+
+ g_idle_add (image_location_switch_do_capture, filenames);
+ g_main_loop_run (main_loop);
+
+ msg = wait_for_element_message (camera, "image-done", GST_CLOCK_TIME_NONE);
+ fail_unless (msg != NULL);
+ gst_message_unref (msg);
+
+ gst_element_set_state (GST_ELEMENT (camera), GST_STATE_NULL);
+
+ for (i = 0; i < LOCATION_SWITCHING_FILENAMES_COUNT; i++) {
+ GST_INFO ("Checking for file: %s", filenames[i]);
+ fail_unless (g_file_test (filenames[i], G_FILE_TEST_IS_REGULAR));
+ }
+
+ for (i = 0; i < LOCATION_SWITCHING_FILENAMES_COUNT; i++) {
+ g_unlink (filenames[i]);
+ g_free (filenames[i]);
+ }
+ g_signal_handler_disconnect (src, notify_id);
+}
+
+GST_END_TEST;
+
+
+typedef struct _TestCaseDef
+{
+ const gchar *name;
+ gpointer setup_func;
+} TestCaseDef;
+
+TestCaseDef tests[] = {
+ {"wrappercamerabinsrc", setup_wrappercamerabinsrc_videotestsrc}
+};
+
+static Suite *
+camerabin_suite (void)
+{
+ GstElementFactory *jpegenc_factory;
+ Suite *s = suite_create ("camerabin2");
+ gint i;
+ TCase *tc_generic = tcase_create ("generic");
+
+ jpegenc_factory = gst_element_factory_find ("jpegenc");
+ if (jpegenc_factory == NULL) {
+ GST_WARNING ("Skipping camerabin2 tests because jpegenc is missing");
+ goto end;
+ }
+
+ suite_add_tcase (s, tc_generic);
+ tcase_add_checked_fixture (tc_generic, setup_wrappercamerabinsrc_videotestsrc,
+ teardown);
+ tcase_add_test (tc_generic, test_supported_caps);
+
+ for (i = 0; i < G_N_ELEMENTS (tests); i++) {
+ TCase *tc_basic = tcase_create (tests[i].name);
+ suite_add_tcase (s, tc_basic);
+
+ /* Increase timeout due to video recording */
+ tcase_set_timeout (tc_basic, 60);
+ tcase_add_checked_fixture (tc_basic, tests[i].setup_func, teardown);
+
+ tcase_add_test (tc_basic, test_single_image_capture);
+ tcase_add_test (tc_basic, test_single_video_recording);
+ tcase_add_test (tc_basic, test_image_video_cycle);
+ if (gst_plugin_feature_check_version ((GstPluginFeature *) jpegenc_factory,
+ 0, 10, 27))
+ tcase_add_test (tc_basic, test_multiple_image_captures);
+ else
+ GST_WARNING ("Skipping image capture test because -good 0.10.27 is "
+ "needed");
+ tcase_add_test (tc_basic, test_multiple_video_recordings);
+
+ tcase_add_test (tc_basic, test_image_capture_previews);
+ tcase_add_test (tc_basic, test_image_capture_with_tags);
+
+ tcase_add_test (tc_basic, test_video_capture_with_tags);
+
+ tcase_add_test (tc_basic, test_idle_property);
+
+ tcase_add_test (tc_basic, test_image_custom_filter);
+ tcase_add_test (tc_basic, test_video_custom_filter);
+
+ tcase_add_test (tc_basic, test_image_location_switching);
+ }
+
+end:
+ return s;
+}
+
+GST_CHECK_MAIN (camerabin);
diff --git a/tests/check/elements/dataurisrc.c b/tests/check/elements/dataurisrc.c
new file mode 100644
index 00000000..49c9bdbb
--- /dev/null
+++ b/tests/check/elements/dataurisrc.c
@@ -0,0 +1,233 @@
+/* GStreamer unit test for dataurisrc
+ *
+ * Copyright (C) 2010 Tim-Philipp Müller <tim centricular net>
+ *
+ * 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 <unistd.h>
+
+#include <gst/check/gstcheck.h>
+
+/* sine wave encoded in ogg/vorbis, created with:
+ * gst-launch-0.10 audiotestsrc num-buffers=110 ! audioconvert ! \
+ * audio/x-raw,channels=1 ! vorbisenc ! oggmux ! \
+ * filesink location=sine.ogg
+ * and then encoded to base64 */
+const gchar data_uri[] = "data:audio/ogg;base64,"
+ "T2dnUwACAAAAAAAAAACVWbd7AAAAAHgH02kBHgF2b3JiaXMAAAAAAUSsAAAAAAAAgDgBAAAAAAC4"
+ "AU9nZ1MAAAAAAAAAAAAAlVm3ewEAAADrU8FRDkv///////////////+BA3ZvcmJpcx0AAABYaXBo"
+ "Lk9yZyBsaWJWb3JiaXMgSSAyMDA5MDcwOQEAAAAaAAAAREVTQ1JJUFRJT049YXVkaW90ZXN0IHdh"
+ "dmUBBXZvcmJpcyJCQ1YBAEAAACRzGCpGpXMWhBAaQlAZ4xxCzmvsGUJMEYIcMkxbyyVzkCGkoEKI"
+ "WyiB0JBVAABAAACHQXgUhIpBCCGEJT1YkoMnPQghhIg5eBSEaUEIIYQQQgghhBBCCCGERTlokoMn"
+ "QQgdhOMwOAyD5Tj4HIRFOVgQgydB6CCED0K4moOsOQghhCQ1SFCDBjnoHITCLCiKgsQwuBaEBDUo"
+ "jILkMMjUgwtCiJqDSTX4GoRnQXgWhGlBCCGEJEFIkIMGQcgYhEZBWJKDBjm4FITLQagahCo5CB+E"
+ "IDRkFQCQAACgoiiKoigKEBqyCgDIAAAQQFEUx3EcyZEcybEcCwgNWQUAAAEACAAAoEiKpEiO5EiS"
+ "JFmSJVmSJVmS5omqLMuyLMuyLMsyEBqyCgBIAABQUQxFcRQHCA1ZBQBkAAAIoDiKpViKpWiK54iO"
+ "CISGrAIAgAAABAAAEDRDUzxHlETPVFXXtm3btm3btm3btm3btm1blmUZCA1ZBQBAAAAQ0mlmqQaI"
+ "MAMZBkJDVgEACAAAgBGKMMSA0JBVAABAAACAGEoOogmtOd+c46BZDppKsTkdnEi1eZKbirk555xz"
+ "zsnmnDHOOeecopxZDJoJrTnnnMSgWQqaCa0555wnsXnQmiqtOeeccc7pYJwRxjnnnCateZCajbU5"
+ "55wFrWmOmkuxOeecSLl5UptLtTnnnHPOOeecc84555zqxekcnBPOOeecqL25lpvQxTnnnE/G6d6c"
+ "EM4555xzzjnnnHPOOeecIDRkFQAABABAEIaNYdwpCNLnaCBGEWIaMulB9+gwCRqDnELq0ehopJQ6"
+ "CCWVcVJKJwgNWQUAAAIAQAghhRRSSCGFFFJIIYUUYoghhhhyyimnoIJKKqmooowyyyyzzDLLLLPM"
+ "Ouyssw47DDHEEEMrrcRSU2011lhr7jnnmoO0VlprrbVSSimllFIKQkNWAQAgAAAEQgYZZJBRSCGF"
+ "FGKIKaeccgoqqIDQkFUAACAAgAAAAABP8hzRER3RER3RER3RER3R8RzPESVREiVREi3TMjXTU0VV"
+ "dWXXlnVZt31b2IVd933d933d+HVhWJZlWZZlWZZlWZZlWZZlWZYgNGQVAAACAAAghBBCSCGFFFJI"
+ "KcYYc8w56CSUEAgNWQUAAAIACAAAAHAUR3EcyZEcSbIkS9IkzdIsT/M0TxM9URRF0zRV0RVdUTdt"
+ "UTZl0zVdUzZdVVZtV5ZtW7Z125dl2/d93/d93/d93/d93/d9XQdCQ1YBABIAADqSIymSIimS4ziO"
+ "JElAaMgqAEAGAEAAAIriKI7jOJIkSZIlaZJneZaomZrpmZ4qqkBoyCoAABAAQAAAAAAAAIqmeIqp"
+ "eIqoeI7oiJJomZaoqZoryqbsuq7ruq7ruq7ruq7ruq7ruq7ruq7ruq7ruq7ruq7ruq7ruq4LhIas"
+ "AgAkAAB0JEdyJEdSJEVSJEdygNCQVQCADACAAAAcwzEkRXIsy9I0T/M0TxM90RM901NFV3SB0JBV"
+ "AAAgAIAAAAAAAAAMybAUy9EcTRIl1VItVVMt1VJF1VNVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVV"
+ "VVVVVVVVVVVN0zRNEwgNWQkAAAEA0FpzzK2XjkHorJfIKKSg10455qTXzCiCnOcQMWOYx1IxQwzG"
+ "lkGElAVCQ1YEAFEAAIAxyDHEHHLOSeokRc45Kh2lxjlHqaPUUUqxplo7SqW2VGvjnKPUUcoopVpL"
+ "qx2lVGuqsQAAgAAHAIAAC6HQkBUBQBQAAIEMUgophZRizinnkFLKOeYcYoo5p5xjzjkonZTKOSed"
+ "kxIppZxjzinnnJTOSeack9JJKAAAIMABACDAQig0ZEUAECcA4HAcTZM0TRQlTRNFTxRd1xNF1ZU0"
+ "zTQ1UVRVTRRN1VRVWRZNVZYlTTNNTRRVUxNFVRVVU5ZNVbVlzzRt2VRV3RZV1bZlW/Z9V5Z13TNN"
+ "2RZV1bZNVbV1V5Z1XbZt3Zc0zTQ1UVRVTRRV11RV2zZV1bY1UXRdUVVlWVRVWXZdWddVV9Z9TRRV"
+ "1VNN2RVVVZZV2dVlVZZ1X3RV3VZd2ddVWdZ929aFX9Z9wqiqum7Krq6rsqz7si77uu3rlEnTTFMT"
+ "RVXVRFFVTVe1bVN1bVsTRdcVVdWWRVN1ZVWWfV91ZdnXRNF1RVWVZVFVZVmVZV13ZVe3RVXVbVV2"
+ "fd90XV2XdV1YZlv3hdN1dV2VZd9XZVn3ZV3H1nXf90zTtk3X1XXTVXXf1nXlmW3b+EVV1XVVloVf"
+ "lWXf14XheW7dF55RVXXdlF1fV2VZF25fN9q+bjyvbWPbPrKvIwxHvrAsXds2ur5NmHXd6BtD4TeG"
+ "NNO0bdNVdd10XV+Xdd1o67pQVFVdV2XZ91VX9n1b94Xh9n3fGFXX91VZFobVlp1h932l7guVVbaF"
+ "39Z155htXVh+4+j8vjJ0dVto67qxzL6uPLtxdIY+AgAABhwAAAJMKAOFhqwIAOIEABiEnENMQYgU"
+ "gxBCSCmEkFLEGITMOSkZc1JCKamFUlKLGIOQOSYlc05KKKGlUEpLoYTWQimxhVJabK3VmlqLNYTS"
+ "WiiltVBKi6mlGltrNUaMQcick5I5J6WU0loopbXMOSqdg5Q6CCmllFosKcVYOSclg45KByGlkkpM"
+ "JaUYQyqxlZRiLCnF2FpsucWYcyilxZJKbCWlWFtMObYYc44Yg5A5JyVzTkoopbVSUmuVc1I6CCll"
+ "DkoqKcVYSkoxc05KByGlDkJKJaUYU0qxhVJiKynVWEpqscWYc0sx1lBSiyWlGEtKMbYYc26x5dZB"
+ "aC2kEmMoJcYWY66ttRpDKbGVlGIsKdUWY629xZhzKCXGkkqNJaVYW425xhhzTrHlmlqsucXYa225"
+ "9Zpz0Km1WlNMubYYc465BVlz7r2D0FoopcVQSoyttVpbjDmHUmIrKdVYSoq1xZhza7H2UEqMJaVY"
+ "S0o1thhrjjX2mlqrtcWYa2qx5ppz7zHm2FNrNbcYa06x5Vpz7r3m1mMBAAADDgAAASaUgUJDVgIA"
+ "UQAABCFKMQahQYgx56Q0CDHmnJSKMecgpFIx5hyEUjLnIJSSUuYchFJSCqWkklJroZRSUmqtAACA"
+ "AgcAgAAbNCUWByg0ZCUAkAoAYHAcy/I8UTRV2XYsyfNE0TRV1bYdy/I8UTRNVbVty/NE0TRV1XV1"
+ "3fI8UTRVVXVdXfdEUTVV1XVlWfc9UTRVVXVdWfZ901RV1XVlWbaFXzRVV3VdWZZl31hd1XVlWbZ1"
+ "WxhW1XVdWZZtWzeGW9d13feFYTk6t27ruu/7wvE7xwAA8AQHAKACG1ZHOCkaCyw0ZCUAkAEAQBiD"
+ "kEFIIYMQUkghpRBSSgkAABhwAAAIMKEMFBqyEgCIAgAACJFSSimNlFJKKaWRUkoppZQSQgghhBBC"
+ "CCGEEEIIIYQQQgghhBBCCCGEEEIIIYQQQggFAPhPOAD4P9igKbE4QKEhKwGAcAAAwBilmHIMOgkp"
+ "NYw5BqGUlFJqrWGMMQilpNRaS5VzEEpJqbXYYqycg1BSSq3FGmMHIaXWWqyx1po7CCmlFmusOdgc"
+ "Smktxlhzzr33kFJrMdZac++9l9ZirDXn3IMQwrQUY6659uB77ym2WmvNPfgghFCx1Vpz8EEIIYSL"
+ "Mffcg/A9CCFcjDnnHoTwwQdhAAB3gwMARIKNM6wknRWOBhcashIACAkAIBBiijHnnIMQQgiRUow5"
+ "5xyEEEIoJVKKMeecgw5CCCVkjDnnHIQQQiillIwx55yDEEIJpZSSOecchBBCKKWUUjLnoIMQQgml"
+ "lFJK5xyEEEIIpZRSSumggxBCCaWUUkopIYQQQgmllFJKKSWEEEIJpZRSSimlhBBKKKWUUkoppZQQ"
+ "QimllFJKKaWUEkIopZRSSimllJJCKaWUUkoppZRSUiillFJKKaWUUkoJpZRSSimllJRSSQUAABw4"
+ "AAAEGEEnGVUWYaMJFx6AQkNWAgBAAAAUxFZTiZ1BzDFnqSEIMaipQkophjFDyiCmKVMKIYUhc4oh"
+ "AqHFVkvFAAAAEAQACAgJADBAUDADAAwOED4HQSdAcLQBAAhCZIZINCwEhweVABExFQAkJijkAkCF"
+ "xUXaxQV0GeCCLu46EEIQghDE4gAKSMDBCTc88YYn3OAEnaJSBwEAAAAAcAAADwAAxwUQEdEcRobG"
+ "BkeHxwdISAAAAAAAyADABwDAIQJERDSHkaGxwdHh8QESEgAAAAAAAAAAAAQEBAAAAAAAAgAAAAQE"
+ "T2dnUwAAwFIAAAAAAACVWbd7AgAAAPtNZ2oXKxQ4JiYlJSUmJSYmJSUlJiUmJiYmJSWM64s3q+wD"
+ "MAQAnICN1ydV8tWC8lN5Kk/lqTyVp/JUuqu7uqu7KgjDMEwAnO2rVb0qWHw+DQAAAAAAIC5HDwU6"
+ "yj7C62/u4teEkwiA2gAAAAAAAAAAAAAAbL8fuP/EQFh6odjwP2uvvNHgH/d6FLjkcubZXtUAAJ7K"
+ "3qo3ye0WocGOPxVMBwAAAAAAAAAAAAAA8H7XAwAAcm8vpwcAnsreqjfJ7RahwY4/FUwHAAAAAAAA"
+ "AAAAAADw/l0AAIB2r4kzAgCeyt4qNyntFqHBzv0KpgNQAAAAAAAAAAAAAODQowQAgPjtOQoAnsre"
+ "KjfJ/RYF7NyvYDoAAAAAAAAAAAAAAIBf3wMAgL2/NDECAJ7K3qo3Ke0WpcHOrQKmAxAAAAAAAAAA"
+ "AAAAIJoFAACIm3ZUAQCeyt4qN8ntFqnBjj8VTAcAAAAAAAAAAAAAAPDj9wAAgEnDb5MBAJ7K3io3"
+ "ye0WGuz4U8F0AAoAAAAAAAAAAAAAXG8xAQAgv8G5vgCeyt6qN8ntFqHBjj8VTAcAAAAAAAAAAAAA"
+ "APB1FwkAAIPev/QBAJ7K3qo3ye0WGuz4W8B0AAAAAAAAAAAAAAAAX29hAADAwMuzPgIAnsreKjcp"
+ "7RYa7PhTwHQAAgAAAAAAAAAAAACcv6UAAIDcBE+qAJ7K3io3yf0WAez4W8F0AAAAAAAAAAAAAAAA"
+ "P34XAABMFj2SAgCeyt6qNyntFqnBzv0KpgNQAAAAAAAAAAAAACCrSwAAkGUXUwAAnsreKjfJ/RYF"
+ "7PhTwXQAAAAAAAAAAAAAAAC/fhYAYGHvr03cAACeyt4qNyntFhrs+FPAdAACAAAAAAAAAAAAANz3"
+ "OAAAIHrqAhUAnsreqjfJ7RahwY4/FUwHAAAAAAAAAAAAAADw/l0BAEC7xG4ZAACeyt6qN8ntFhrs"
+ "+FvAdAAAAAAAAAAAAAAAAO9vQQIAQP7YG9MBAJ7K3qo3ye0WocGOPxVMBwAAAAAAAAAAAAAA8Ny1"
+ "BACAmsF9ngAAnsreKjfJ7RahwY4/FUwHAAAAAAAAAAAAAADw6+0AAMCi1mdeAACeyt7yNyntFgHs"
+ "3K9gOgABAAAAAAAAAAAAAFpnCgAAMI98WgAAnsre8jfJ7RYN7NyaYDoAAAAAAAAAAAAAAIA/fgMA"
+ "wLKxf1wEAE9nZ1MAAMCqAAAAAAAAlVm3ewMAAAD+9Ox8FiQlJSYmJSUlJSUmJSYlJSUmJiYmJSSe"
+ "yt4qNyntFqHBzv0KpgNQAAAAAAAAAAAAAKB9ZgkAAE6GCACeyt6qN8ntFqnBjj8VTAcAAAAAAAAA"
+ "AAAAAPD1lgEAwODweu8AnsreqjfJ7RYa7PhbwHQAAAAAAAAAAAAAAADPXQoAAKje6sUrAJ7K3qo3"
+ "ye0WocGOPxVMBwAAAAAAAAAAAAAAcN31AACA3K760gIAnsreqjfJ7RahwY4/FUwHAAAAAAAAAAAA"
+ "AADw/l0AAID2OV7SAgCeyt7yNyl1i1Bg5/4E0wEoAAAAAAAAAAAAAHDoQQIAQJxOjwQAnsreKjfJ"
+ "7Ratwc6tAqYDAAAAAAAAAAAAAAD46wcAgMDlal8mAJ7K3io3Ke0WqcHO/QKmAxAAAAAAAAAAAAAA"
+ "oN/DAACAaKfrAACeyt4qN8ntFqnBzv0KpgMAAAAAAAAAAAAAAPjxHQAAMJn8dhoAnsreqjfJ7RYa"
+ "7PhbwHQAAAAAAAAAAAAAAADXW0oAAMj7OMMnAJ7K3qo3ye0WocGOPxVMBwAAAAAAAAAAAAAA8HVX"
+ "CQAAtYu2eQMAnsreqjfJ7RYa7PhbwHQAAAAAAAAAAAAAAABfnwAAAAZN1vcBAJ7K3io3Ke0WocHO"
+ "/QqmAxAAAAAAAAAAAAAA4PzMAwAAzP8cqQIAnsreKjfJ/RYJ7PhTwHQAAAAAAAAAAAAAAAA/fhcA"
+ "AEx+XGYSAJ7K3qo3Ke0WpcHOrQqmA1AAAAAAAAAAAAAAIKtLAACQ841WAACeyt4qN8n9Fgns+FPB"
+ "dAAAAAAAAAAAAAAAAL9+FgAALDa84wEAnsreKjfJ7RaxwY6/FUwHIAAAAAAAAAAAAADA/V0LAACo"
+ "7vGKCgCeyt6qN8ntFqHBjj8VTAcAAAAAAAAAAAAAAPD+XQMAANplf5IRAJ7K3qo3ye0WGuz4W8B0"
+ "AAAAAAAAAAAAAAAA799lAgBAu9mnGQAAnsreKjcp7RYa7PhTwXQACgAAAAAAAAAAAAC83OUEAIDa"
+ "7i8rAACeyt4qN8n9FgHs+FvBdAAAAAAAAAAAAAAAAL9+BgAALNa/7Q4Ansreqjcp7Rapwc79CqYD"
+ "EAAAAAAAAAAAAAAgmgUAAIj5x6gAT2dnUwAAwAIBAAAAAACVWbd7BAAAAFDbxx4WJSUmJiYlJSUl"
+ "JiUmJSUlJSUlJiUmJZ7K3io3yf0WBezcr2A6AAAAAAAAAAAAAACAH78DAAA2flSWLwCeyt4qNynt"
+ "Fhrs+FPAdAAKAAAAAAAAAAAAALTPLAEAwPnmCAUAnsreqjfJ7RapwY4/FUwHAAAAAAAAAAAAAADw"
+ "9ZYBAMCg6Xo+AgCeyt6qN8ntFhrs+FvAdAAAAAAAAAAAAAAAAF93KQAAoHrhht4BAJ7K3qo3ye0W"
+ "ocGOPxVMBwAAAAAAAAAAAAAAcL3FAACAnA8zUwEAnsreKjfJ7RYa7PhTwHQAAAAAAAAAAAAAAAA/"
+ "PhkAAEymvJMWAJ7K3vI3Ke0WAezcr2A6AAUAAAAAAAAAAAAADj1IAACI5x0vAQCeyt4qN8n9Fg3s"
+ "3CpgOgAAAAAAAAAAAAAAgL9+AAAI7K317QAAnsreKjcp7Rahwc79CqYDEAAAAAAAAAAAAACg3+MA"
+ "AIAobSQBAJ7K3qo3ye0WqcGOPxVMBwAAAAAAAAAAAAAA8P5JAQBA+2yvaQAAnsreqjfJ7RYa7Phb"
+ "wHQAAAAAAAAAAAAAAADXW5AAAJDfzWAaAJ7K3qo3ye0WocGOPxVMBwAAAAAAAAAAAAAA8NxVAgBA"
+ "7TavXgAAnsreqjfJ7RahwY4/FUwHAAAAAAAAAAAAAADw9QkAAGBwWIM3AJ7K3vI3KXWLUGDn/gTT"
+ "AQgAAAAAAAAAAAAA0DpTAACAWUZ6AQCeyt4qN8ntFq3Bzq0CpgMAAAAAAAAAAAAAAPjjtwAALCfy"
+ "Y8UAnsre8jcp7RYB7NyvYDoABQAAAAAAAAAAAADaPU0AAHCOeIYEAJ7K3io3ye0WqcHO/QqmAwAA"
+ "AAAAAAAAAAAA+PX2AABgUftTrwCeyt6qN8ntFhrs+FvAdAAAAAAAAAAAAAAAAM9dDgAAqBrY7xkA"
+ "nsreqjfJ7RahwY4/FUwHAAAAAAAAAAAAAADwftcDAAByx9yUHgCeyt6qN8ntFhrs+FvAdAAAAAAA"
+ "AAAAAAAAAO/fJQAAaJfcNSMAnsreKjcp7Rahwc79CqYDUAAAAAAAAAAAAADgpUcJAADxk+crAACe"
+ "yt4qN8n9Fgns+FPAdAAAAAAAAAAAAAAAAL9+BgAALP7S1BAAT2dnUwAAwFoBAAAAAACVWbd7BQAA"
+ "ABLEbSgWJSUmJiYlJSUlJSYmJiYlJSUlJSYlJZ7K3lo3Kf0WbcDOrQqmAxAAAAAAAAAAAAAAIKof"
+ "AAAgmhXTAACeyt4qN8n9Fgns+FPAdAAAAAAAAAAAAAAAAD9+BwAATJ7eWzIAnsreKjfJ7RaxwY6/"
+ "BUwHoAAAAAAAAAAAAADAzVtMAADIj/+UAgCeyt6qN8ntFqHBjj8VTAcAAAAAAAAAAAAAAPD1iRIA"
+ "AAZeX/ABAJ7K3qo3ye0WGuz4W8B0AAAAAAAAAAAAAAAAX2cZAAAw6O0LHwEAnsreKjfJ7RYa7PhT"
+ "wXQAAgAAAAAAAAAAAABcbykAACC3/nlJAJ7K3io3yf0WAez4U8F0AAAAAAAAAAAAAAAAP34vAACY"
+ "dPsqBQCeyt6qNyntFqXBzq0CpgNQAAAAAAAAAAAAACCrSwAAkDfupAAAnsreKjfJ/RYF7NyvYDoA"
+ "AAAAAAAAAAAAAIBfPwEAgL2/NnUBAJ7K3io3Ke0WGuz4U8B0AAIAAAAAAAAAAAAA9HscAAAQvTNb"
+ "BQCeyt6qN8ntFqnBjj8VTAcAAAAAAAAAAAAAAPD+SQEAQLvnvAwAAJ7K3qo3ye0WGuz4W8B0AAAA"
+ "AAAAAAAAAAAA729BAgBA/p0l6QAAnsreqjfJ7RahwY4/FUwHAAAAAAAAAAAAAADw3LUEAIBai6M9"
+ "AQCeyt6qN8ntFqHBjj8FTAcAAAAAAAAAAAAAAPDr7QAAwOLZvXkBAJ7K3vI3Ke0WAezcr2A6AAEA"
+ "AAAAAAAAAAAAWmcKAAAwmy4gAACeyt4qN8ntFq3Bzq0KpgMAAAAAAAAAAAAAAPjjFwAAy8Yf7gEA"
+ "nsreKjcp7Rahwc79CqYDUAAAAAAAAAAAAACgfWYJAABOmg4BAJ7K3qo3ye0WqcGOPxVMBwAAAAAA"
+ "AAAAAAAA8PX2AABgcENGrwCeyt6qN8ntFhrs+FvAdAAAAAAAAAAAAAAAAM9dDgAAqK6f0SsAnsre"
+ "qjfJ7RahwY4/FUwHAAAAAAAAAAAAAABw3fUAAIDck43SAgCeyt6qN8ntFqHBjj8VTAcAAAAAAAAA"
+ "AAAAAPD+XQAAgPZO7fQAnsreKjcp7Rapwc79CqYDUAAAAAAAAAAAAADg0KMEAIB4XVMAAE9nZ1MA"
+ "AMCyAQAAAAAAlVm3ewYAAADDE4GEFiUkJSUmJSYlJSYlJiYmJiQlJSUlJiaeyt4qN8ntFqXBzv0K"
+ "pgMAAAAAAAAAAAAAAPj1PQAA2PtTwgQAnsre8jcp7RYB7NyfYDoAAQAAAAAAAAAAAAD6TQEAAOLr"
+ "jwUAnsreKjfJ7Rapwc79CqYDAAAAAAAAAAAAAAD48R0AADCp/OETAJ7K3qo3ye0WGuz4W8B0AAAA"
+ "AAAAAAAAAAAA11tKAADIZzylAwCeyt6qN8ntFqHBjj8VTAcAAAAAAAAAAAAAAPB1VwkAAEPzP+kN"
+ "AJ7K3qo3ye0WGuz4W8B0AAAAAAAAAAAAAAAAX28hAAAY+LzBBwCeyt4qNyntFqHBzv0KpgMQAAAA"
+ "AAAAAAAAAOD8zAMAAMzb/qMCAJ7K3io3yf0WCez4U8B0AAAAAAAAAAAAAAAAP34XAABMPpBLAgCe"
+ "yt7aN6nzFmXCzv0CpgNQAAAAAAAAAAAAACCrlwAAIL2kaAEAnsreKjfJ/RYF7PhTwXQAAAAAAAAA"
+ "AAAAAAC/fhYAYGHvK6M8AACeyt4qN8ntFhrs+FPAdAACAAAAAAAAAAAAANzftQAAgOqC/6sAnsre"
+ "qjfJ7RahwY4/FUwHAAAAAAAAAAAAAADw/l0DAADaeh7ICACeyt6qN8ntFhrs+FvAdAAAAAAAAAAA"
+ "AAAAAO9vngAA0B7vmekAAJ7K3qo3ye0WocGOPxVMBwAAAAAAAAAAAAAA8Ny1BACAWt+vaAEAnsre"
+ "KjfJ7RahwY4/FUwHAAAAAAAAAAAAAADw67sDAIBF3989AQCeyt7yNyntFgHs3K9gOgABAAAAAAAA"
+ "AAAAAKIRAAAgvnymAACeyt7yN8ntFgXs3C9gOgAAAAAAAAAAAAAAgD9+AwAANpqv+gEAnsreKjcp"
+ "7RYa7PhTwHQACgAAAAAAAAAAAAC0zywBAMC5cJgAAJ7K3qo3ye0WqcGOPxVMBwAAAAAAAAAAAAAA"
+ "8PWWAQDAYK0R7wCeyt6qN8ntFhrs+FvAdAAAAAAAAAAAAAAAAF93KQAAoPpNq1cAnsreqjfJ7Rah"
+ "wY4/FUwHAAAAAAAAAAAAAABwvcUAAIBcX6VTAQCeyt6qN8ntFqHBjj8FTAcAAAAAAAAAAAAAAPDj"
+ "uwAAAJM3TJgWAE9nZ1MAAMC2AQAAAAAAlVm3ewcAAAChMbyhATK+ur7krvf7iNcT84QFpAwAAAAA"
+ "AAAAAAAAAEAnELfPda81yNy2bdpbCkUt8amvXMHuAE9nZ1MABAC4AQAAAAAAlVm3ewgAAAA8WkRh"
+ "AWZeiL1v7LSgX1wHDrB3NhI3k3sSnaKJAAAAAAAAQOJJS94nzV+3/3r/2Ho5ub5tHN70XSuPfdZZ"
+ "C/9eZOtqZc5Zfl8wP5ZenOT3hbWPpZeE6jzjkdY3f+GXCblaF41qKouT/N7UyQA=";
+
+GST_START_TEST (test_playbin2)
+{
+ GstElement *playbin, *sink;
+ int loops = 2;
+
+ playbin = gst_element_factory_make ("playbin", NULL);
+ sink = gst_element_factory_make ("fakesink", NULL);
+
+ if (playbin == NULL || sink == NULL) {
+ GST_WARNING ("skipping test, no playbin or fakesink element(s)");
+ return;
+ }
+
+ g_object_set (playbin, "uri", data_uri, "audio-sink", sink, NULL);
+
+ do {
+ GstMessage *msg;
+
+ /* not checking return val on purpose, should always get an error on bus */
+ gst_element_set_state (playbin, GST_STATE_PLAYING);
+
+ msg = gst_bus_timed_pop_filtered (GST_ELEMENT_BUS (playbin),
+ GST_CLOCK_TIME_NONE, GST_MESSAGE_EOS | GST_MESSAGE_ERROR);
+
+ GST_INFO ("message: %" GST_PTR_FORMAT, msg);
+ if (GST_MESSAGE_TYPE (msg) == GST_MESSAGE_ERROR) {
+ GError *err = NULL;
+
+ gst_message_parse_error (msg, &err, NULL);
+ fail_unless (err->code == GST_CORE_ERROR_MISSING_PLUGIN ||
+ err->code == GST_STREAM_ERROR_CODEC_NOT_FOUND,
+ "Got unexpected error: %s", err->message);
+ g_error_free (err);
+ }
+
+ gst_message_unref (msg);
+ gst_element_set_state (playbin, GST_STATE_NULL);
+
+ --loops;
+ GST_INFO ("done, %d rounds left", loops);
+ } while (loops > 0);
+
+ gst_element_set_state (playbin, GST_STATE_NULL);
+ gst_object_unref (playbin);
+}
+
+GST_END_TEST;
+
+static Suite *
+dataurisrc_suite (void)
+{
+ Suite *s = suite_create ("dataurisrc");
+ TCase *tc_chain = tcase_create ("general");
+
+ suite_add_tcase (s, tc_chain);
+
+ tcase_add_test (tc_chain, test_playbin2);
+
+ return s;
+}
+
+GST_CHECK_MAIN (dataurisrc);
diff --git a/tests/check/elements/faac.c b/tests/check/elements/faac.c
new file mode 100644
index 00000000..b82c58d1
--- /dev/null
+++ b/tests/check/elements/faac.c
@@ -0,0 +1,260 @@
+/* GStreamer
+ *
+ * unit test for faac
+ *
+ * Copyright (C) <2009> Mark Nauwelaerts <mnauw@users.sf.net>
+ *
+ * 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 <unistd.h>
+
+#include <gst/check/gstcheck.h>
+#include <gst/audio/audio.h>
+
+/* For ease of programming we use globals to keep refs for our floating
+ * src and sink pads we create; otherwise we always have to do get_pad,
+ * get_peer, and then remove references in every test function */
+static GstPad *mysrcpad, *mysinkpad;
+
+#define AUDIO_CAPS_STRING "audio/x-raw, " \
+ "format = (string) " GST_AUDIO_NE (S16) ", "\
+ "layout = (string) interleaved, " \
+ "rate = (int) 48000, " \
+ "channels = (int) 2, " \
+ "channel-mask = (bitmask) 3"
+
+#define AAC_RAW_CAPS_STRING "audio/mpeg, " \
+ "mpegversion = (int) 4, " \
+ "rate = (int) 48000, " \
+ "channels = (int) 2, " \
+ "stream-format = \"raw\"," \
+ "base-profile = \"lc\""
+
+#define AAC_ADTS_CAPS_STRING "audio/mpeg, " \
+ "mpegversion = (int) 4, " \
+ "rate = (int) 48000, " \
+ "channels = (int) 2, " \
+ "stream-format = \"adts\"," \
+ "base-profile = \"lc\""
+
+static GstStaticPadTemplate sinktemplate_adts = GST_STATIC_PAD_TEMPLATE ("sink",
+ GST_PAD_SINK,
+ GST_PAD_ALWAYS,
+ GST_STATIC_CAPS (AAC_ADTS_CAPS_STRING));
+
+static GstStaticPadTemplate sinktemplate_raw = GST_STATIC_PAD_TEMPLATE ("sink",
+ GST_PAD_SINK,
+ GST_PAD_ALWAYS,
+ GST_STATIC_CAPS (AAC_RAW_CAPS_STRING));
+
+static GstStaticPadTemplate srctemplate = GST_STATIC_PAD_TEMPLATE ("src",
+ GST_PAD_SRC,
+ GST_PAD_ALWAYS,
+ GST_STATIC_CAPS (AUDIO_CAPS_STRING));
+
+
+static GstElement *
+setup_faac (gboolean adts)
+{
+ GstElement *faac;
+
+ GST_DEBUG ("setup_faac");
+ faac = gst_check_setup_element ("faac");
+ mysrcpad = gst_check_setup_src_pad (faac, &srctemplate);
+
+ if (adts)
+ mysinkpad = gst_check_setup_sink_pad (faac, &sinktemplate_adts);
+ else
+ mysinkpad = gst_check_setup_sink_pad (faac, &sinktemplate_raw);
+
+ gst_pad_set_active (mysrcpad, TRUE);
+ gst_pad_set_active (mysinkpad, TRUE);
+
+ return faac;
+}
+
+static void
+cleanup_faac (GstElement * faac)
+{
+ GST_DEBUG ("cleanup_faac");
+ gst_element_set_state (faac, GST_STATE_NULL);
+
+ gst_pad_set_active (mysrcpad, FALSE);
+ gst_pad_set_active (mysinkpad, FALSE);
+ gst_check_teardown_src_pad (faac);
+ gst_check_teardown_sink_pad (faac);
+ gst_check_teardown_element (faac);
+}
+
+static void
+do_test (gboolean adts)
+{
+ GstElement *faac;
+ GstBuffer *inbuffer, *outbuffer;
+ GstCaps *caps;
+ gint i, num_buffers;
+ const gint nbuffers = 10;
+
+ faac = setup_faac (adts);
+ fail_unless (gst_element_set_state (faac,
+ GST_STATE_PLAYING) == GST_STATE_CHANGE_SUCCESS,
+ "could not set to playing");
+
+ /* corresponds to audio buffer mentioned in the caps */
+ inbuffer = gst_buffer_new_and_alloc (1024 * nbuffers * 2 * 2);
+ /* makes valgrind's memcheck happier */
+ gst_buffer_memset (inbuffer, 0, 0, 1024 * nbuffers * 2 * 2);
+ caps = gst_caps_from_string (AUDIO_CAPS_STRING);
+ gst_pad_set_caps (mysrcpad, caps);
+ gst_caps_unref (caps);
+ GST_BUFFER_TIMESTAMP (inbuffer) = 0;
+ ASSERT_BUFFER_REFCOUNT (inbuffer, "inbuffer", 1);
+ fail_unless (gst_pad_push (mysrcpad, inbuffer) == GST_FLOW_OK);
+
+ /* send eos to have all flushed if needed */
+ fail_unless (gst_pad_push_event (mysrcpad, gst_event_new_eos ()) == TRUE);
+
+ num_buffers = g_list_length (buffers);
+ fail_unless_equals_int (num_buffers, nbuffers + 1);
+
+ /* clean up buffers */
+ for (i = 0; i < num_buffers; ++i) {
+ gint header = 0, id;
+ GstMapInfo map;
+ gsize size;
+ guint8 *data;
+
+ outbuffer = GST_BUFFER (buffers->data);
+ fail_if (outbuffer == NULL);
+
+ gst_buffer_map (outbuffer, &map, GST_MAP_READ);
+ data = map.data;
+ size = map.size;
+
+ if (adts) {
+ gboolean protection;
+ gint k;
+
+ fail_if (size < 7);
+ protection = !(data[1] & 0x1);
+ /* expect only 1 raw data block */
+ k = (data[6] & 0x3) + 1;
+ fail_if (k != 1);
+
+ header = 7;
+ if (protection)
+ header += (k - 1) * 2 + 2;
+
+ /* check header */
+ k = GST_READ_UINT16_BE (data) & 0xFFF6;
+ /* sync */
+ fail_unless (k == 0xFFF0);
+ k = data[2];
+ /* profile */
+ fail_unless ((k >> 6) == 0x1);
+ /* rate */
+ fail_unless (((k >> 2) & 0xF) == 0x3);
+ /* channels */
+ fail_unless ((k & 0x1) == 0);
+ k = data[3];
+ fail_unless ((k >> 6) == 0x2);
+ } else {
+ GstCaps *caps;
+ GstStructure *s;
+ const GValue *value;
+ GstBuffer *buf;
+ gint k;
+ GstMapInfo cmap;
+
+ caps = gst_pad_get_current_caps (mysinkpad);
+ fail_if (caps == NULL);
+ s = gst_caps_get_structure (caps, 0);
+ fail_if (s == NULL);
+ value = gst_structure_get_value (s, "codec_data");
+ fail_if (value == NULL);
+ buf = gst_value_get_buffer (value);
+ fail_if (buf == NULL);
+ gst_buffer_map (buf, &cmap, GST_MAP_READ);
+ fail_if (cmap.size < 2);
+ k = GST_READ_UINT16_BE (cmap.data);
+ gst_buffer_unmap (buf, &cmap);
+ /* profile, rate, channels */
+ fail_unless ((k & 0xFFF8) == ((0x02 << 11) | (0x3 << 7) | (0x02 << 3)));
+ gst_caps_unref (caps);
+ }
+
+ fail_if (size <= header);
+ id = data[header] & (0x7 << 5);
+ /* allow all but ID_END or ID_LFE */
+ fail_if (id == 7 || id == 3);
+ gst_buffer_unmap (outbuffer, &map);
+
+ buffers = g_list_remove (buffers, outbuffer);
+
+ ASSERT_BUFFER_REFCOUNT (outbuffer, "outbuffer", 1);
+ gst_buffer_unref (outbuffer);
+ outbuffer = NULL;
+ }
+
+ cleanup_faac (faac);
+ g_list_free (buffers);
+ buffers = NULL;
+}
+
+GST_START_TEST (test_adts)
+{
+ do_test (TRUE);
+}
+
+GST_END_TEST;
+
+GST_START_TEST (test_raw)
+{
+ do_test (FALSE);
+}
+
+GST_END_TEST;
+
+static Suite *
+faac_suite (void)
+{
+ Suite *s = suite_create ("faac");
+ TCase *tc_chain = tcase_create ("general");
+
+ suite_add_tcase (s, tc_chain);
+ tcase_add_test (tc_chain, test_adts);
+ tcase_add_test (tc_chain, test_raw);
+
+ return s;
+}
+
+int
+main (int argc, char **argv)
+{
+ int nf;
+
+ Suite *s = faac_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/faad.c b/tests/check/elements/faad.c
new file mode 100644
index 00000000..a97b8735
--- /dev/null
+++ b/tests/check/elements/faad.c
@@ -0,0 +1,221 @@
+/* GStreamer
+ *
+ * unit test for faad
+ *
+ * Copyright (C) <2009> Mark Nauwelaerts <mnauw@users.sf.net>
+ *
+ * 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 <unistd.h>
+
+#include <gst/check/gstcheck.h>
+#include <gst/audio/audio.h>
+
+/* For ease of programming we use globals to keep refs for our floating
+ * src and sink pads we create; otherwise we always have to do get_pad,
+ * get_peer, and then remove references in every test function */
+static GstPad *mysrcpad, *mysinkpad;
+
+#define AUDIO_CAPS_STRING "audio/x-raw, " \
+ "format = (string) " GST_AUDIO_NE (S16) ", " \
+ "rate = (int) 48000, " \
+ "channels = (int) 2, " \
+ "channel-mask = (bitmask) 3"
+
+#define AAC_CAPS_STRING "audio/mpeg, " \
+ "mpegversion = (int) 4, " \
+ "rate = (int) 48000, " \
+ "channels = (int) 2, " \
+ "framed = (boolean) true "
+
+static GstStaticPadTemplate sinktemplate = GST_STATIC_PAD_TEMPLATE ("sink",
+ GST_PAD_SINK,
+ GST_PAD_ALWAYS,
+ GST_STATIC_CAPS (AUDIO_CAPS_STRING));
+
+static GstStaticPadTemplate srctemplate = GST_STATIC_PAD_TEMPLATE ("src",
+ GST_PAD_SRC,
+ GST_PAD_ALWAYS,
+ GST_STATIC_CAPS (AAC_CAPS_STRING));
+
+
+static GstElement *
+setup_faad (void)
+{
+ GstElement *faad;
+
+ GST_DEBUG ("setup_faad");
+ faad = gst_check_setup_element ("faad");
+ mysrcpad = gst_check_setup_src_pad (faad, &srctemplate);
+ mysinkpad = gst_check_setup_sink_pad (faad, &sinktemplate);
+ gst_pad_set_active (mysrcpad, TRUE);
+ gst_pad_set_active (mysinkpad, TRUE);
+
+ return faad;
+}
+
+static void
+cleanup_faad (GstElement * faad)
+{
+ GST_DEBUG ("cleanup_faad");
+ gst_element_set_state (faad, GST_STATE_NULL);
+
+ gst_pad_set_active (mysrcpad, FALSE);
+ gst_pad_set_active (mysinkpad, FALSE);
+ gst_check_teardown_src_pad (faad);
+ gst_check_teardown_sink_pad (faad);
+ gst_check_teardown_element (faad);
+}
+
+static void
+do_test (GstBuffer * inbuffer, GstCaps * caps)
+{
+ GstElement *faad;
+ GstBuffer *outbuffer;
+ gint i, num_buffers;
+ const gint nbuffers = 2;
+
+ faad = setup_faad ();
+ fail_unless (gst_element_set_state (faad,
+ GST_STATE_PLAYING) == GST_STATE_CHANGE_SUCCESS,
+ "could not set to playing");
+
+ GST_BUFFER_TIMESTAMP (inbuffer) = 0;
+ ASSERT_BUFFER_REFCOUNT (inbuffer, "inbuffer", 1);
+
+ gst_pad_set_caps (mysrcpad, caps);
+ /* need to push twice to get faad output */
+ gst_buffer_ref (inbuffer);
+ fail_unless (gst_pad_push (mysrcpad, inbuffer) == GST_FLOW_OK);
+ fail_unless (gst_pad_push (mysrcpad, inbuffer) == GST_FLOW_OK);
+
+ /* send eos to have all flushed if needed */
+ fail_unless (gst_pad_push_event (mysrcpad, gst_event_new_eos ()) == TRUE);
+
+ num_buffers = g_list_length (buffers);
+ fail_unless (num_buffers >= nbuffers - 1);
+
+ /* clean up buffers */
+ for (i = 0; i < num_buffers; ++i) {
+ gint size;
+
+ outbuffer = GST_BUFFER (buffers->data);
+ fail_if (outbuffer == NULL);
+
+ size = gst_buffer_get_size (outbuffer);
+
+ /* 2 16-bit channels */
+ fail_unless (size == 1024 * 2 * 2);
+
+ buffers = g_list_remove (buffers, outbuffer);
+
+ ASSERT_BUFFER_REFCOUNT (outbuffer, "outbuffer", 1);
+ gst_buffer_unref (outbuffer);
+ outbuffer = NULL;
+ }
+
+ cleanup_faad (faad);
+ g_list_free (buffers);
+ buffers = NULL;
+}
+
+static guint8 raw_data_block[] = {
+ 0x21, 0x1b, 0x80, 0x00, 0x7d, 0xe0, 0x00, 0x3e, 0xf1, 0xe7
+};
+
+static guint8 adts_header[] = {
+ 0xff, 0xf8, 0x4c, 0x80, 0x02, 0x7f, 0xfc, 0x04, 0x40
+};
+
+static guint8 codec_data[] = {
+ 0x11, 0x90
+};
+
+GST_START_TEST (test_adts)
+{
+ gint size;
+ GstBuffer *buf, *header_buf;
+ GstCaps *caps;
+
+ size = sizeof (adts_header);
+ header_buf = gst_buffer_new_and_alloc (size);
+ gst_buffer_fill (header_buf, 0, adts_header, size);
+
+ size = sizeof (raw_data_block);
+ buf = gst_buffer_new_and_alloc (size);
+ gst_buffer_fill (buf, 0, raw_data_block, size);
+
+ buf = gst_buffer_append (header_buf, buf);
+ caps = gst_caps_from_string (AAC_CAPS_STRING);
+ do_test (buf, caps);
+ gst_caps_unref (caps);
+}
+
+GST_END_TEST;
+
+GST_START_TEST (test_raw)
+{
+ gint size;
+ GstBuffer *buf, *codec_buf;
+ GstCaps *caps;
+
+ size = sizeof (codec_data);
+ codec_buf = gst_buffer_new_and_alloc (size);
+ gst_buffer_fill (codec_buf, 0, codec_data, size);
+
+ size = sizeof (raw_data_block);
+ buf = gst_buffer_new_and_alloc (size);
+ gst_buffer_fill (buf, 0, raw_data_block, size);
+ caps = gst_caps_from_string (AAC_CAPS_STRING);
+ gst_caps_set_simple (caps, "codec_data", GST_TYPE_BUFFER, codec_buf, NULL);
+ gst_buffer_unref (codec_buf);
+
+ do_test (buf, caps);
+ gst_caps_unref (caps);
+}
+
+GST_END_TEST;
+
+static Suite *
+faad_suite (void)
+{
+ Suite *s = suite_create ("faad");
+ TCase *tc_chain = tcase_create ("general");
+
+ suite_add_tcase (s, tc_chain);
+ tcase_add_test (tc_chain, test_adts);
+ tcase_add_test (tc_chain, test_raw);
+
+ return s;
+}
+
+int
+main (int argc, char **argv)
+{
+ int nf;
+
+ Suite *s = faad_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/h263parse.c b/tests/check/elements/h263parse.c
new file mode 100644
index 00000000..4c23c619
--- /dev/null
+++ b/tests/check/elements/h263parse.c
@@ -0,0 +1,175 @@
+/*
+ * GStreamer
+ *
+ * unit test for h263parse
+ *
+ * Copyright (C) 2011 Nokia Corporation. All rights reserved.
+ *
+ * Contact: Stefan Kost <stefan.kost@nokia.com>
+ *
+ * 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>
+#include "parser.h"
+
+#define SRC_CAPS_TMPL "video/x-h263, framed=(boolean)false"
+#define SINK_CAPS_TMPL "video/x-h263, framed=(boolean)true"
+
+GstStaticPadTemplate sinktemplate = GST_STATIC_PAD_TEMPLATE ("sink",
+ GST_PAD_SINK,
+ GST_PAD_ALWAYS,
+ GST_STATIC_CAPS (SINK_CAPS_TMPL)
+ );
+
+GstStaticPadTemplate srctemplate = GST_STATIC_PAD_TEMPLATE ("src",
+ GST_PAD_SRC,
+ GST_PAD_ALWAYS,
+ GST_STATIC_CAPS (SRC_CAPS_TMPL)
+ );
+
+/* some data */
+
+#if 0
+static guint8 h263_iframe[] = {
+ /* keyframes all around */
+ 0x00, 0x00, 0x80, 0x02, 0x1c, 0x88, 0x01, 0x00,
+ 0x11, 0xe0, 0x44, 0xc4, 0x04, 0x04, 0x04, 0x3f,
+ 0xff, 0xe6, 0x20, 0x20, 0x20, 0x21, 0xff, 0xff,
+ 0x31, 0x01, 0x01, 0x01, 0x0f, 0xff, 0xf9, 0x88,
+ 0x08, 0x08, 0x08, 0x7f, 0xff, 0x80
+};
+#endif
+
+static guint8 h263_iframe[] = {
+ /* keyframes all around */
+ /* actually, this is a truncated keyframe,
+ * but don't tell anyone or try this at home */
+ 0x00, 0x00, 0x80, 0x02, 0x0c, 0x04, 0x26, 0x20,
+ 0x20, 0x20, 0x21, 0xff, 0xff, 0x31, 0x01, 0x01,
+ 0x01, 0x0f, 0xff, 0xf9, 0x88, 0x08, 0x08, 0x08,
+ 0x7f, 0xff, 0xcc, 0x40, 0x40, 0x40, 0x43, 0xff,
+ 0xfe, 0x62, 0x02, 0x02, 0x02, 0x1f, 0xff, 0xf3,
+ 0x10, 0x10, 0x10, 0x10, 0xff, 0xff, 0x98, 0x80,
+ 0x80, 0x80, 0x87, 0xff, 0xfc, 0xc4, 0x04, 0x04,
+ 0x04, 0x3f, 0xff, 0xe6, 0x20, 0x20, 0x20, 0x21,
+ 0xff, 0xff, 0x31, 0x01, 0x01, 0x01, 0x0f, 0xff,
+ 0xf9, 0x88, 0x08, 0x08, 0x08, 0x7f, 0xff, 0xcc,
+ 0x40, 0x40, 0x40, 0x43, 0xff, 0xfe, 0x62, 0x02,
+ 0x02, 0x02, 0x1f, 0xff, 0xf3, 0x10, 0x10, 0x10,
+ 0x10, 0xff, 0xff, 0x98, 0x80, 0x80, 0x80, 0x87,
+ 0xff, 0xfc, 0xc4, 0x04, 0x04, 0x04, 0x3f, 0xff,
+ 0xe6, 0x20, 0x20, 0x20, 0x21, 0xff, 0xff, 0x31,
+ 0x01, 0x01, 0x01, 0x0f, 0xff, 0xf9, 0x88, 0x08
+};
+
+GST_START_TEST (test_parse_normal)
+{
+ gst_parser_test_normal (h263_iframe, sizeof (h263_iframe));
+}
+
+GST_END_TEST;
+
+
+GST_START_TEST (test_parse_drain_single)
+{
+ gst_parser_test_drain_single (h263_iframe, sizeof (h263_iframe));
+}
+
+GST_END_TEST;
+
+
+GST_START_TEST (test_parse_split)
+{
+ gst_parser_test_split (h263_iframe, sizeof (h263_iframe));
+}
+
+GST_END_TEST;
+
+
+#define structure_get_int(s,f) \
+ (g_value_get_int(gst_structure_get_value(s,f)))
+#define fail_unless_structure_field_int_equals(s,field,num) \
+ fail_unless_equals_int (structure_get_int(s,field), num)
+
+GST_START_TEST (test_parse_detect_stream)
+{
+ GstCaps *caps;
+ GstStructure *s;
+
+ caps = gst_parser_test_get_output_caps (h263_iframe, sizeof (h263_iframe),
+ NULL);
+ fail_unless (caps != NULL);
+
+ /* Check that the negotiated caps are as expected */
+ /* When codec_data is present, parser assumes that data is version 4 */
+ GST_LOG ("mpegvideo output caps: %" GST_PTR_FORMAT, caps);
+ s = gst_caps_get_structure (caps, 0);
+ fail_unless (gst_structure_has_name (s, "video/x-h263"));
+ fail_unless_structure_field_int_equals (s, "width", 352);
+ fail_unless_structure_field_int_equals (s, "height", 288);
+
+ gst_caps_unref (caps);
+}
+
+GST_END_TEST;
+
+
+static Suite *
+h263parse_suite (void)
+{
+ Suite *s = suite_create ("h263parse");
+ TCase *tc_chain = tcase_create ("general");
+
+ suite_add_tcase (s, tc_chain);
+ tcase_add_test (tc_chain, test_parse_normal);
+ tcase_add_test (tc_chain, test_parse_drain_single);
+ tcase_add_test (tc_chain, test_parse_split);
+ tcase_add_test (tc_chain, test_parse_detect_stream);
+
+ return s;
+}
+
+
+/*
+ * TODO:
+ * - Both push- and pull-modes need to be tested
+ * * Pull-mode & EOS
+ */
+
+int
+main (int argc, char **argv)
+{
+ int nf;
+
+ Suite *s = h263parse_suite ();
+ SRunner *sr = srunner_create (s);
+
+ gst_check_init (&argc, &argv);
+
+ /* init test context */
+ ctx_factory = "h263parse";
+ ctx_sink_template = &sinktemplate;
+ ctx_src_template = &srctemplate;
+ /* no timing info to parse */
+ ctx_no_metadata = TRUE;
+
+ srunner_run_all (sr, CK_NORMAL);
+ nf = srunner_ntests_failed (sr);
+ srunner_free (sr);
+
+ return nf;
+}
diff --git a/tests/check/elements/h264parse.c b/tests/check/elements/h264parse.c
new file mode 100644
index 00000000..8a767248
--- /dev/null
+++ b/tests/check/elements/h264parse.c
@@ -0,0 +1,402 @@
+/*
+ * GStreamer
+ *
+ * unit test for h264parse
+ *
+ * Copyright (C) 2011 Nokia Corporation. All rights reserved.
+ *
+ * Contact: Stefan Kost <stefan.kost@nokia.com>
+ *
+ * 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>
+#include "parser.h"
+
+#define SRC_CAPS_TMPL "video/x-h264, parsed=(boolean)false"
+#define SINK_CAPS_TMPL "video/x-h264, parsed=(boolean)true"
+
+GstStaticPadTemplate sinktemplate_bs_nal = GST_STATIC_PAD_TEMPLATE ("sink",
+ GST_PAD_SINK,
+ GST_PAD_ALWAYS,
+ GST_STATIC_CAPS (SINK_CAPS_TMPL
+ ", stream-format = (string) byte-stream, alignment = (string) nal")
+ );
+
+GstStaticPadTemplate sinktemplate_avc_au = GST_STATIC_PAD_TEMPLATE ("sink",
+ GST_PAD_SINK,
+ GST_PAD_ALWAYS,
+ GST_STATIC_CAPS (SINK_CAPS_TMPL
+ ", stream-format = (string) avc, alignment = (string) au")
+ );
+
+GstStaticPadTemplate srctemplate = GST_STATIC_PAD_TEMPLATE ("src",
+ GST_PAD_SRC,
+ GST_PAD_ALWAYS,
+ GST_STATIC_CAPS (SRC_CAPS_TMPL)
+ );
+
+/* some data */
+
+/* SPS */
+static guint8 h264_sps[] = {
+ 0x00, 0x00, 0x00, 0x01, 0x67, 0x4d, 0x40, 0x15,
+ 0xec, 0xa4, 0xbf, 0x2e, 0x02, 0x20, 0x00, 0x00,
+ 0x03, 0x00, 0x2e, 0xe6, 0xb2, 0x80, 0x01, 0xe2,
+ 0xc5, 0xb2, 0xc0
+};
+
+/* PPS */
+static guint8 h264_pps[] = {
+ 0x00, 0x00, 0x00, 0x01, 0x68, 0xeb, 0xec, 0xb2
+};
+
+/* combines to this codec-data */
+static guint8 h264_codec_data[] = {
+ 0x01, 0x4d, 0x40, 0x15, 0xff, 0xe1, 0x00, 0x17,
+ 0x67, 0x4d, 0x40, 0x15, 0xec, 0xa4, 0xbf, 0x2e,
+ 0x02, 0x20, 0x00, 0x00, 0x03, 0x00, 0x2e, 0xe6,
+ 0xb2, 0x80, 0x01, 0xe2, 0xc5, 0xb2, 0xc0, 0x01,
+ 0x00, 0x04, 0x68, 0xeb, 0xec, 0xb2
+};
+
+/* keyframes all around */
+static guint8 h264_idrframe[] = {
+ 0x00, 0x00, 0x00, 0x01, 0x65, 0x88, 0x84, 0x00,
+ 0x10, 0xff, 0xfe, 0xf6, 0xf0, 0xfe, 0x05, 0x36,
+ 0x56, 0x04, 0x50, 0x96, 0x7b, 0x3f, 0x53, 0xe1
+};
+
+/* truncated nal */
+static guint8 garbage_frame[] = {
+ 0x00, 0x00, 0x00, 0x01, 0x05
+};
+
+/* context to tweak tests */
+static const gchar *ctx_suite;
+static gboolean ctx_codec_data;
+
+static gboolean
+verify_buffer (buffer_verify_data_s * vdata, GstBuffer * buffer)
+{
+ if (vdata->discard) {
+ /* check separate header NALs */
+ gint i = vdata->buffer_counter;
+
+ fail_unless (i <= 1);
+ fail_unless (gst_buffer_get_size (buffer) == ctx_headers[i].size);
+ fail_unless (gst_buffer_memcmp (buffer, 0, ctx_headers[i].data,
+ gst_buffer_get_size (buffer)) == 0);
+ } else {
+ GstMapInfo map;
+
+ gst_buffer_map (buffer, &map, GST_MAP_READ);
+ fail_unless (map.size > 4);
+ /* only need to check avc output case */
+ if (GST_READ_UINT32_BE (map.data) == 0x01) {
+ gst_buffer_unmap (buffer, &map);
+ return FALSE;
+ }
+ /* header is merged in initial frame */
+ if (vdata->buffer_counter == 0) {
+ guint8 *data = map.data;
+
+ fail_unless (map.size == vdata->data_to_verify_size +
+ ctx_headers[0].size + ctx_headers[1].size);
+ fail_unless (GST_READ_UINT32_BE (data) == ctx_headers[0].size - 4);
+ fail_unless (memcmp (data + 4, ctx_headers[0].data + 4,
+ ctx_headers[0].size - 4) == 0);
+ data += ctx_headers[0].size;
+ fail_unless (GST_READ_UINT32_BE (data) == ctx_headers[1].size - 4);
+ fail_unless (memcmp (data + 4, ctx_headers[1].data + 4,
+ ctx_headers[1].size - 4) == 0);
+ data += ctx_headers[1].size;
+ fail_unless (GST_READ_UINT32_BE (data) == vdata->data_to_verify_size - 4);
+ fail_unless (memcmp (data + 4, vdata->data_to_verify + 4,
+ vdata->data_to_verify_size - 4) == 0);
+ } else {
+ fail_unless (GST_READ_UINT32_BE (map.data) == map.size - 4);
+ fail_unless (map.size == vdata->data_to_verify_size);
+ fail_unless (memcmp (map.data + 4, vdata->data_to_verify + 4,
+ map.size - 4) == 0);
+ }
+ gst_buffer_unmap (buffer, &map);
+ return TRUE;
+ }
+
+ return FALSE;
+}
+
+GST_START_TEST (test_parse_normal)
+{
+ gst_parser_test_normal (h264_idrframe, sizeof (h264_idrframe));
+}
+
+GST_END_TEST;
+
+
+GST_START_TEST (test_parse_drain_single)
+{
+ gst_parser_test_drain_single (h264_idrframe, sizeof (h264_idrframe));
+}
+
+GST_END_TEST;
+
+
+GST_START_TEST (test_parse_drain_garbage)
+{
+ gst_parser_test_drain_garbage (h264_idrframe, sizeof (h264_idrframe),
+ garbage_frame, sizeof (garbage_frame));
+}
+
+GST_END_TEST
+GST_START_TEST (test_parse_split)
+{
+ gst_parser_test_split (h264_idrframe, sizeof (h264_idrframe));
+}
+
+GST_END_TEST;
+
+
+GST_START_TEST (test_parse_skip_garbage)
+{
+ gst_parser_test_skip_garbage (h264_idrframe, sizeof (h264_idrframe),
+ garbage_frame, sizeof (garbage_frame));
+}
+
+GST_END_TEST;
+
+#define structure_get_int(s,f) \
+ (g_value_get_int(gst_structure_get_value(s,f)))
+#define fail_unless_structure_field_int_equals(s,field,num) \
+ fail_unless_equals_int (structure_get_int(s,field), num)
+
+
+GST_START_TEST (test_parse_detect_stream)
+{
+ GstCaps *caps;
+ GstStructure *s;
+ GstBuffer *buf;
+ const GValue *val;
+
+ /* parser does not really care that mpeg1 and mpeg2 frame data
+ * should be a bit different */
+ caps = gst_parser_test_get_output_caps (h264_idrframe, sizeof (h264_idrframe),
+ NULL);
+ fail_unless (caps != NULL);
+
+ /* Check that the negotiated caps are as expected */
+ /* When codec_data is present, parser assumes that data is version 4 */
+ GST_LOG ("h264 output caps: %" GST_PTR_FORMAT, caps);
+ s = gst_caps_get_structure (caps, 0);
+ fail_unless (gst_structure_has_name (s, "video/x-h264"));
+ fail_unless_structure_field_int_equals (s, "width", 32);
+ fail_unless_structure_field_int_equals (s, "height", 24);
+
+ if (ctx_codec_data) {
+ fail_unless (gst_structure_has_field (s, "codec_data"));
+
+ /* check codec-data in more detail */
+ val = gst_structure_get_value (s, "codec_data");
+ fail_unless (val != NULL);
+ buf = gst_value_get_buffer (val);
+ fail_unless (buf != NULL);
+ fail_unless (gst_buffer_get_size (buf) == sizeof (h264_codec_data));
+ fail_unless (gst_buffer_memcmp (buf, 0, h264_codec_data,
+ gst_buffer_get_size (buf)) == 0);
+ }
+
+ gst_caps_unref (caps);
+}
+
+GST_END_TEST;
+
+
+static Suite *
+h264parse_suite (void)
+{
+ Suite *s = suite_create (ctx_suite);
+ TCase *tc_chain = tcase_create ("general");
+
+ suite_add_tcase (s, tc_chain);
+ tcase_add_test (tc_chain, test_parse_normal);
+ tcase_add_test (tc_chain, test_parse_drain_single);
+ tcase_add_test (tc_chain, test_parse_drain_garbage);
+ tcase_add_test (tc_chain, test_parse_split);
+ tcase_add_test (tc_chain, test_parse_skip_garbage);
+ tcase_add_test (tc_chain, test_parse_detect_stream);
+
+ return s;
+}
+
+static gboolean
+verify_buffer_packetized (buffer_verify_data_s * vdata, GstBuffer * buffer)
+{
+ GstMapInfo map;
+
+ gst_buffer_map (buffer, &map, GST_MAP_READ);
+
+ fail_unless (map.size > 4);
+ fail_unless (GST_READ_UINT32_BE (map.data) == 0x01);
+ if (vdata->discard) {
+ /* check separate header NALs */
+ guint8 *data;
+ gint size;
+
+ if (vdata->buffer_counter == 0) {
+ data = h264_sps;
+ size = sizeof (h264_sps);
+ } else {
+ data = h264_pps;
+ size = sizeof (h264_pps);
+ }
+
+ fail_unless (map.size == size);
+ fail_unless (memcmp (map.data + 4, data + 4, size - 4) == 0);
+ } else {
+ fail_unless (map.size == vdata->data_to_verify_size);
+ fail_unless (memcmp (map.data + 4,
+ vdata->data_to_verify + 4, map.size - 4) == 0);
+ }
+ gst_buffer_unmap (buffer, &map);
+
+ return TRUE;
+}
+
+GST_START_TEST (test_parse_packetized)
+{
+ guint8 *frame;
+ GstCaps *caps;
+ GstBuffer *cdata;
+ GstStructure *s;
+ gchar *desc;
+
+ /* make AVC frame */
+ frame = g_malloc (sizeof (h264_idrframe));
+ GST_WRITE_UINT32_BE (frame, sizeof (h264_idrframe) - 4);
+ memcpy (frame + 4, h264_idrframe + 4, sizeof (h264_idrframe) - 4);
+
+ /* some caps messing */
+ caps = gst_caps_from_string (SRC_CAPS_TMPL);
+ cdata =
+ gst_buffer_new_wrapped_full (GST_MEMORY_FLAG_READONLY, h264_codec_data,
+ sizeof (h264_codec_data), 0, sizeof (h264_codec_data), NULL, NULL);
+ gst_caps_set_simple (caps, "codec_data", GST_TYPE_BUFFER, cdata, NULL);
+ gst_buffer_unref (cdata);
+ desc = gst_caps_to_string (caps);
+ gst_caps_unref (caps);
+
+ caps = gst_parser_test_get_output_caps (frame, sizeof (h264_idrframe), desc);
+ g_free (desc);
+ g_free (frame);
+
+ /* minor caps checks */
+ GST_LOG ("h264 output caps: %" GST_PTR_FORMAT, caps);
+ s = gst_caps_get_structure (caps, 0);
+ fail_unless (gst_structure_has_name (s, "video/x-h264"));
+ fail_unless_structure_field_int_equals (s, "width", 32);
+ fail_unless_structure_field_int_equals (s, "height", 24);
+
+ gst_caps_unref (caps);
+}
+
+GST_END_TEST;
+
+static Suite *
+h264parse_packetized_suite (void)
+{
+ Suite *s = suite_create (ctx_suite);
+ TCase *tc_chain = tcase_create ("general");
+
+ suite_add_tcase (s, tc_chain);
+ tcase_add_test (tc_chain, test_parse_packetized);
+
+ return s;
+}
+
+
+/*
+ * TODO:
+ * - Both push- and pull-modes need to be tested
+ * * Pull-mode & EOS
+ */
+
+int
+main (int argc, char **argv)
+{
+ int nf = 0;
+
+ Suite *s;
+ SRunner *sr;
+
+ gst_check_init (&argc, &argv);
+
+ /* globabl init test context */
+ ctx_factory = "h264parse";
+ ctx_sink_template = &sinktemplate_bs_nal;
+ ctx_src_template = &srctemplate;
+ ctx_headers[0].data = h264_sps;
+ ctx_headers[0].size = sizeof (h264_sps);
+ ctx_headers[1].data = h264_pps;
+ ctx_headers[1].size = sizeof (h264_pps);
+ ctx_verify_buffer = verify_buffer;
+ /* discard initial sps/pps buffers */
+ ctx_discard = 2;
+ /* no timing info to parse */
+ ctx_no_metadata = TRUE;
+ ctx_codec_data = FALSE;
+
+ ctx_suite = "h264parse_to_bs_nal";
+ s = h264parse_suite ();
+ sr = srunner_create (s);
+ srunner_run_all (sr, CK_NORMAL);
+ nf += srunner_ntests_failed (sr);
+ srunner_free (sr);
+
+ /* setup and tweak to handle avc au output */
+ ctx_suite = "h264parse_to_avc_au";
+ ctx_sink_template = &sinktemplate_avc_au;
+ ctx_discard = 0;
+ ctx_codec_data = TRUE;
+
+ s = h264parse_suite ();
+ sr = srunner_create (s);
+ srunner_run_all (sr, CK_NORMAL);
+ nf += srunner_ntests_failed (sr);
+ srunner_free (sr);
+
+ /* setup and tweak to handle avc packetized input */
+ ctx_suite = "h264parse_packetized";
+ /* turn into separate byte stream NALs */
+ ctx_sink_template = &sinktemplate_bs_nal;
+ /* and ignore inserted codec-data NALs */
+ ctx_discard = 2;
+ /* no more config headers */
+ ctx_headers[0].data = NULL;
+ ctx_headers[1].data = NULL;
+ ctx_headers[0].size = 0;
+ ctx_headers[1].size = 0;
+ /* and need adapter buffer check */
+ ctx_verify_buffer = verify_buffer_packetized;
+
+ s = h264parse_packetized_suite ();
+ sr = srunner_create (s);
+ srunner_run_all (sr, CK_NORMAL);
+ nf += srunner_ntests_failed (sr);
+ srunner_free (sr);
+
+ return nf;
+}
diff --git a/tests/check/elements/id3mux.c b/tests/check/elements/id3mux.c
new file mode 100644
index 00000000..b494c2ea
--- /dev/null
+++ b/tests/check/elements/id3mux.c
@@ -0,0 +1,557 @@
+/* GStreamer
+ *
+ * unit test for the id3tag element
+ *
+ * Copyright (C) 2006 Tim-Philipp Müller <tim centricular net>
+ *
+ * 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>
+
+#include <gst/gst.h>
+#include <string.h>
+
+#define TEST_ARTIST "Ar T\303\255st"
+#define TEST_TITLE "M\303\274llermilch!"
+#define TEST_ALBUM "Boom"
+#define TEST_DATE g_date_new_dmy(1,1,2006)
+#define TEST_TRACK_NUMBER 7
+#define TEST_TRACK_COUNT 19
+#define TEST_VOLUME_NUMBER 2
+#define TEST_VOLUME_COUNT 3
+#define TEST_TRACK_GAIN 1.45
+#define TEST_ALBUM_GAIN 0.78
+#define TEST_TRACK_PEAK 0.83
+#define TEST_ALBUM_PEAK 0.18
+#define TEST_BPM 113.0
+
+/* for dummy mp3 frame sized MP3_FRAME_SIZE bytes,
+ * start: ff fb b0 44 00 00 08 00 00 4b 00 00 00 00 00 00 */
+static const guint8 mp3_dummyhdr[] = { 0xff, 0xfb, 0xb0, 0x44, 0x00, 0x00,
+ 0x08, 0x00, 0x4b, 0x00, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00
+};
+
+#define MP3_FRAME_SIZE 626
+
+/* the peak and gain values are stored pretty roughly, so check that they're
+ * within 2% of the expected value.
+ */
+#define fail_unless_sorta_equals_float(a, b) \
+G_STMT_START { \
+ double first = a; \
+ double second = b; \
+ fail_unless(fabs (first - second) < (0.02 * fabs (first)), \
+ "'" #a "' (%g) is not equal to '" #b "' (%g)", first, second); \
+} G_STMT_END;
+
+
+static GstTagList *
+test_taglib_id3mux_create_tags (guint32 mask)
+{
+ GstTagList *tags;
+
+ tags = gst_tag_list_new_empty ();
+
+ if (mask & (1 << 0)) {
+ gst_tag_list_add (tags, GST_TAG_MERGE_KEEP,
+ GST_TAG_ARTIST, TEST_ARTIST, NULL);
+ }
+ if (mask & (1 << 1)) {
+ gst_tag_list_add (tags, GST_TAG_MERGE_KEEP,
+ GST_TAG_TITLE, TEST_TITLE, NULL);
+ }
+ if (mask & (1 << 2)) {
+ gst_tag_list_add (tags, GST_TAG_MERGE_KEEP,
+ GST_TAG_ALBUM, TEST_ALBUM, NULL);
+ }
+ if (mask & (1 << 3)) {
+ GDate *date;
+
+ date = TEST_DATE;
+ gst_tag_list_add (tags, GST_TAG_MERGE_KEEP, GST_TAG_DATE, date, NULL);
+ g_date_free (date);
+ }
+ if (mask & (1 << 4)) {
+ gst_tag_list_add (tags, GST_TAG_MERGE_KEEP,
+ GST_TAG_TRACK_NUMBER, TEST_TRACK_NUMBER, NULL);
+ }
+ if (mask & (1 << 5)) {
+ gst_tag_list_add (tags, GST_TAG_MERGE_KEEP,
+ GST_TAG_TRACK_COUNT, TEST_TRACK_COUNT, NULL);
+ }
+ if (mask & (1 << 6)) {
+ gst_tag_list_add (tags, GST_TAG_MERGE_KEEP,
+ GST_TAG_ALBUM_VOLUME_NUMBER, TEST_VOLUME_NUMBER, NULL);
+ }
+ if (mask & (1 << 7)) {
+ gst_tag_list_add (tags, GST_TAG_MERGE_KEEP,
+ GST_TAG_ALBUM_VOLUME_COUNT, TEST_VOLUME_COUNT, NULL);
+ }
+ if (mask & (1 << 8)) {
+ gst_tag_list_add (tags, GST_TAG_MERGE_KEEP,
+ GST_TAG_TRACK_GAIN, TEST_TRACK_GAIN, NULL);
+ }
+ if (mask & (1 << 9)) {
+ gst_tag_list_add (tags, GST_TAG_MERGE_KEEP,
+ GST_TAG_ALBUM_GAIN, TEST_ALBUM_GAIN, NULL);
+ }
+ if (mask & (1 << 10)) {
+ gst_tag_list_add (tags, GST_TAG_MERGE_KEEP,
+ GST_TAG_TRACK_PEAK, TEST_TRACK_PEAK, NULL);
+ }
+ if (mask & (1 << 11)) {
+ gst_tag_list_add (tags, GST_TAG_MERGE_KEEP,
+ GST_TAG_ALBUM_PEAK, TEST_ALBUM_PEAK, NULL);
+ }
+ if (mask & (1 << 12)) {
+ gst_tag_list_add (tags, GST_TAG_MERGE_KEEP,
+ GST_TAG_BEATS_PER_MINUTE, TEST_BPM, NULL);
+ }
+ if (mask & (1 << 13)) {
+ }
+ return tags;
+}
+
+static gboolean
+utf_string_in_buf (GstBuffer * buf, const gchar * s, int v2version)
+{
+ gint i, len;
+ gchar *free_str = NULL;
+ GstMapInfo map;
+
+ if (v2version == 3) {
+ free_str = g_convert (s, -1, "UTF-16LE", "UTF-8", NULL, NULL, NULL);
+ s = free_str;
+ }
+
+ len = strlen (s);
+ gst_buffer_map (buf, &map, GST_MAP_READ);
+ for (i = 0; i < (map.size - len); ++i) {
+ if (memcmp (map.data + i, s, len) == 0) {
+ gst_buffer_unmap (buf, &map);
+ g_free (free_str);
+ return TRUE;
+ }
+ }
+ gst_buffer_unmap (buf, &map);
+
+ g_free (free_str);
+ return FALSE;
+}
+
+static void
+test_taglib_id3mux_check_tag_buffer (GstBuffer * buf, guint32 mask,
+ int v2version)
+{
+ /* make sure our UTF-8 string hasn't been put into the tag as ISO-8859-1 */
+ if (mask & (1 << 0)) {
+ fail_unless (utf_string_in_buf (buf, TEST_ARTIST, v2version));
+ }
+ /* make sure our UTF-8 string hasn't been put into the tag as ISO-8859-1 */
+ if (mask & (1 << 1)) {
+ fail_unless (utf_string_in_buf (buf, TEST_TITLE, v2version));
+ }
+ /* make sure our UTF-8 string hasn't been put into the tag as ISO-8859-1 */
+ if (mask & (1 << 2)) {
+ fail_unless (utf_string_in_buf (buf, TEST_ALBUM, v2version));
+ }
+}
+
+static void
+test_taglib_id3mux_check_tags (GstTagList * tags, guint32 mask, int v2version)
+{
+ if (mask & (1 << 0)) {
+ gchar *s = NULL;
+
+ fail_unless (gst_tag_list_get_string (tags, GST_TAG_ARTIST, &s));
+ fail_unless (g_str_equal (s, TEST_ARTIST));
+ g_free (s);
+ }
+ if (mask & (1 << 1)) {
+ gchar *s = NULL;
+
+ fail_unless (gst_tag_list_get_string (tags, GST_TAG_TITLE, &s));
+ fail_unless (g_str_equal (s, TEST_TITLE));
+ g_free (s);
+ }
+ if (mask & (1 << 2)) {
+ gchar *s = NULL;
+
+ fail_unless (gst_tag_list_get_string (tags, GST_TAG_ALBUM, &s));
+ fail_unless (g_str_equal (s, TEST_ALBUM));
+ g_free (s);
+ }
+ if (mask & (1 << 3)) {
+ GDate *shouldbe, *date = NULL;
+
+ shouldbe = TEST_DATE;
+ fail_unless (gst_tag_list_get_date (tags, GST_TAG_DATE, &date));
+ fail_unless (g_date_compare (shouldbe, date) == 0);
+ g_date_free (shouldbe);
+ g_date_free (date);
+ }
+ if (mask & (1 << 4)) {
+ guint num;
+
+ fail_unless (gst_tag_list_get_uint (tags, GST_TAG_TRACK_NUMBER, &num));
+ fail_unless (num == TEST_TRACK_NUMBER);
+ }
+ if (mask & (1 << 5)) {
+ guint count;
+
+ fail_unless (gst_tag_list_get_uint (tags, GST_TAG_TRACK_COUNT, &count));
+ fail_unless (count == TEST_TRACK_COUNT);
+ }
+ if (mask & (1 << 6)) {
+ guint num;
+
+ fail_unless (gst_tag_list_get_uint (tags, GST_TAG_ALBUM_VOLUME_NUMBER,
+ &num));
+ fail_unless (num == TEST_VOLUME_NUMBER);
+ }
+ if (mask & (1 << 7)) {
+ guint count;
+
+ fail_unless (gst_tag_list_get_uint (tags, GST_TAG_ALBUM_VOLUME_COUNT,
+ &count));
+ fail_unless (count == TEST_VOLUME_COUNT);
+ }
+ if (mask & (1 << 8)) {
+ gdouble gain;
+
+ if (v2version == 4) {
+ fail_unless (gst_tag_list_get_double (tags, GST_TAG_TRACK_GAIN, &gain));
+ fail_unless_sorta_equals_float (gain, TEST_TRACK_GAIN);
+ }
+ }
+ if (mask & (1 << 9)) {
+ gdouble gain;
+
+ if (v2version == 4) {
+ fail_unless (gst_tag_list_get_double (tags, GST_TAG_ALBUM_GAIN, &gain));
+ fail_unless_sorta_equals_float (gain, TEST_ALBUM_GAIN);
+ }
+ }
+ if (mask & (1 << 10)) {
+ gdouble peak;
+
+ if (v2version == 4) {
+ fail_unless (gst_tag_list_get_double (tags, GST_TAG_TRACK_PEAK, &peak));
+ fail_unless_sorta_equals_float (peak, TEST_TRACK_PEAK);
+ }
+ }
+ if (mask & (1 << 11)) {
+ gdouble peak;
+
+ if (v2version == 4) {
+ fail_unless (gst_tag_list_get_double (tags, GST_TAG_ALBUM_PEAK, &peak));
+ fail_unless_sorta_equals_float (peak, TEST_ALBUM_PEAK);
+ }
+ }
+ if (mask & (1 << 12)) {
+ gdouble bpm;
+
+ fail_unless (gst_tag_list_get_double (tags, GST_TAG_BEATS_PER_MINUTE,
+ &bpm));
+ fail_unless_sorta_equals_float (bpm, TEST_BPM);
+ }
+ if (mask & (1 << 13)) {
+ }
+}
+
+static void
+fill_mp3_buffer (GstElement * fakesrc, GstBuffer * buf, GstPad * pad,
+ guint64 * p_offset)
+{
+ fail_unless (gst_buffer_get_size (buf) == MP3_FRAME_SIZE);
+
+ GST_LOG ("filling buffer with fake mp3 data, offset = %" G_GUINT64_FORMAT,
+ *p_offset);
+
+ gst_buffer_fill (buf, 0, mp3_dummyhdr, sizeof (mp3_dummyhdr));
+
+#if 0
+ /* can't use gst_buffer_set_caps() here because the metadata isn't writable
+ * because of the extra refcounts taken by the signal emission mechanism;
+ * we know it's fine to use GST_BUFFER_CAPS() here though */
+ GST_BUFFER_CAPS (buf) = gst_caps_new_simple ("audio/mpeg", "mpegversion",
+ G_TYPE_INT, 1, "layer", G_TYPE_INT, 3, NULL);
+#endif
+
+ GST_BUFFER_OFFSET (buf) = *p_offset;
+ *p_offset += gst_buffer_get_size (buf);
+}
+
+static void
+got_buffer (GstElement * fakesink, GstBuffer * buf, GstPad * pad,
+ GstBuffer ** p_buf)
+{
+ GstMapInfo map;
+ gint64 off;
+ guint size;
+
+ off = GST_BUFFER_OFFSET (buf);
+ gst_buffer_map (buf, &map, GST_MAP_READ);
+ size = map.size;
+
+ GST_LOG ("got buffer, size=%u, offset=%" G_GINT64_FORMAT, size, off);
+
+ fail_unless (GST_BUFFER_OFFSET_IS_VALID (buf));
+
+ if (*p_buf == NULL || (off + size) > gst_buffer_get_size (*p_buf)) {
+ GstBuffer *newbuf;
+
+ /* not very elegant, but who cares */
+ newbuf = gst_buffer_new_and_alloc (off + size);
+ if (*p_buf) {
+ GstMapInfo pmap;
+
+ gst_buffer_map (*p_buf, &pmap, GST_MAP_READ);
+ gst_buffer_fill (newbuf, 0, pmap.data, pmap.size);
+ gst_buffer_unmap (*p_buf, &pmap);
+ }
+ gst_buffer_fill (newbuf, off, map.data, size);
+
+ if (*p_buf)
+ gst_buffer_unref (*p_buf);
+ *p_buf = newbuf;
+ } else {
+ gst_buffer_fill (*p_buf, off, map.data, size);
+ }
+ gst_buffer_unmap (buf, &map);
+}
+
+static void
+test_taglib_id3mux_check_output_buffer (GstBuffer * buf)
+{
+ GstMapInfo map;
+ guint off;
+
+ gst_buffer_map (buf, &map, GST_MAP_READ);
+
+ g_assert (map.size % MP3_FRAME_SIZE == 0);
+
+ for (off = 0; off < map.size; off += MP3_FRAME_SIZE) {
+ fail_unless (memcmp (map.data + off, mp3_dummyhdr,
+ sizeof (mp3_dummyhdr)) == 0);
+ }
+ gst_buffer_unmap (buf, &map);
+}
+
+static void
+identity_cb (GstElement * identity, GstBuffer * buf, GstBuffer ** p_tagbuf)
+{
+ if (*p_tagbuf == NULL) {
+ *p_tagbuf = gst_buffer_ref (buf);
+ }
+}
+
+static void
+test_taglib_id3mux_with_tags (GstTagList * tags, guint32 mask, int v2version)
+{
+ GstMessage *msg;
+ GstTagList *tags_read = NULL;
+ GstElement *pipeline, *id3mux, *id3demux, *fakesrc, *identity, *fakesink;
+ GstBus *bus;
+ guint64 offset;
+ GstBuffer *outbuf = NULL;
+ GstBuffer *tagbuf = NULL;
+ GstStateChangeReturn state_result;
+
+ pipeline = gst_pipeline_new ("pipeline");
+ g_assert (pipeline != NULL);
+
+ fakesrc = gst_element_factory_make ("fakesrc", "fakesrc");
+ g_assert (fakesrc != NULL);
+
+ id3mux = gst_element_factory_make ("id3mux", "id3mux");
+ g_assert (id3mux != NULL);
+ g_object_set (id3mux, "v2-version", v2version, NULL);
+
+ identity = gst_element_factory_make ("identity", "identity");
+ g_assert (identity != NULL);
+
+ id3demux = gst_element_factory_make ("id3demux", "id3demux");
+ g_assert (id3demux != NULL);
+
+ fakesink = gst_element_factory_make ("fakesink", "fakesink");
+ g_assert (fakesink != NULL);
+
+ /* set up sink */
+ outbuf = NULL;
+ g_object_set (fakesink, "signal-handoffs", TRUE, NULL);
+ g_signal_connect (fakesink, "handoff", G_CALLBACK (got_buffer), &outbuf);
+
+ gst_bin_add (GST_BIN (pipeline), fakesrc);
+ gst_bin_add (GST_BIN (pipeline), id3mux);
+ gst_bin_add (GST_BIN (pipeline), identity);
+ gst_bin_add (GST_BIN (pipeline), id3demux);
+ gst_bin_add (GST_BIN (pipeline), fakesink);
+
+ gst_tag_setter_merge_tags (GST_TAG_SETTER (id3mux), tags,
+ GST_TAG_MERGE_APPEND);
+
+ gst_element_link_many (fakesrc, id3mux, identity, id3demux, fakesink, NULL);
+
+ /* set up source */
+ g_object_set (fakesrc, "signal-handoffs", TRUE, "can-activate-pull", FALSE,
+ "filltype", 2, "sizetype", 2, "sizemax", MP3_FRAME_SIZE,
+ "num-buffers", 16, NULL);
+
+ offset = 0;
+ g_signal_connect (fakesrc, "handoff", G_CALLBACK (fill_mp3_buffer), &offset);
+
+ /* set up identity to catch tag buffer */
+ g_signal_connect (identity, "handoff", G_CALLBACK (identity_cb), &tagbuf);
+
+ GST_LOG ("setting and getting state ...");
+ gst_element_set_state (pipeline, GST_STATE_PLAYING);
+ state_result = gst_element_get_state (pipeline, NULL, NULL, -1);
+ fail_unless (state_result == GST_STATE_CHANGE_SUCCESS,
+ "Unexpected result from get_state(). Expected success, got %d",
+ state_result);
+
+ bus = gst_pipeline_get_bus (GST_PIPELINE (pipeline));
+
+ GST_LOG ("Waiting for tag ...");
+ msg =
+ gst_bus_poll (bus, GST_MESSAGE_TAG | GST_MESSAGE_EOS | GST_MESSAGE_ERROR,
+ -1);
+ if (GST_MESSAGE_TYPE (msg) == GST_MESSAGE_ERROR) {
+ GError *err;
+ gchar *dbg;
+
+ gst_message_parse_error (msg, &err, &dbg);
+ g_printerr ("ERROR from element %s: %s\n%s\n",
+ GST_OBJECT_NAME (msg->src), err->message, GST_STR_NULL (dbg));
+ g_error_free (err);
+ g_free (dbg);
+ } else if (GST_MESSAGE_TYPE (msg) == GST_MESSAGE_EOS) {
+ g_printerr ("EOS message, but were waiting for TAGS!\n");
+ }
+ fail_unless (msg->type == GST_MESSAGE_TAG);
+
+ gst_message_parse_tag (msg, &tags_read);
+ gst_message_unref (msg);
+
+ GST_LOG ("Got tags: %" GST_PTR_FORMAT, tags_read);
+ test_taglib_id3mux_check_tags (tags_read, mask, v2version);
+ gst_tag_list_free (tags_read);
+
+ fail_unless (tagbuf != NULL);
+ test_taglib_id3mux_check_tag_buffer (tagbuf, mask, v2version);
+ gst_buffer_unref (tagbuf);
+
+ GST_LOG ("Waiting for EOS ...");
+ msg = gst_bus_poll (bus, GST_MESSAGE_EOS | GST_MESSAGE_ERROR, -1);
+ if (GST_MESSAGE_TYPE (msg) == GST_MESSAGE_ERROR) {
+ GError *err;
+ gchar *dbg;
+
+ gst_message_parse_error (msg, &err, &dbg);
+ g_printerr ("ERROR from element %s: %s\n%s\n",
+ GST_OBJECT_NAME (msg->src), err->message, GST_STR_NULL (dbg));
+ g_error_free (err);
+ g_free (dbg);
+ }
+ fail_unless (msg->type == GST_MESSAGE_EOS);
+ gst_message_unref (msg);
+
+ gst_object_unref (bus);
+
+ GST_LOG ("Got EOS, shutting down ...");
+ gst_element_set_state (pipeline, GST_STATE_NULL);
+ gst_object_unref (pipeline);
+
+ test_taglib_id3mux_check_output_buffer (outbuf);
+ gst_buffer_unref (outbuf);
+
+ GST_LOG ("Done");
+}
+
+static void
+run_id3mux_test (int v2version)
+{
+ GstTagList *tags;
+ gint i;
+
+ g_random_set_seed (247166295);
+
+ /* internal consistency check */
+ tags = test_taglib_id3mux_create_tags (0xFFFFFFFF);
+ test_taglib_id3mux_check_tags (tags, 0xFFFFFFFF, v2version);
+ gst_tag_list_free (tags);
+
+ /* now the real tests */
+ for (i = 0; i < 50; ++i) {
+ guint32 mask;
+
+ mask = g_random_int ();
+ GST_LOG ("tag mask = %08x (i=%d)", mask, i);
+
+ if (mask == 0)
+ continue;
+
+ /* create tags */
+ tags = test_taglib_id3mux_create_tags (mask);
+ GST_LOG ("tags for mask %08x = %" GST_PTR_FORMAT, mask, tags);
+
+ /* double-check for internal consistency */
+ test_taglib_id3mux_check_tags (tags, mask, v2version);
+
+ /* test with pipeline */
+ test_taglib_id3mux_with_tags (tags, mask, v2version);
+
+ /* free tags */
+ gst_tag_list_free (tags);
+ }
+}
+
+GST_START_TEST (test_id3mux_v2_3)
+{
+ run_id3mux_test (3);
+}
+
+GST_END_TEST;
+
+GST_START_TEST (test_id3mux_v2_4)
+{
+ run_id3mux_test (4);
+}
+
+GST_END_TEST;
+
+static Suite *
+id3mux_suite (void)
+{
+ Suite *s = suite_create ("id3mux");
+ TCase *tc_chain = tcase_create ("general");
+
+ suite_add_tcase (s, tc_chain);
+
+ if (gst_registry_check_feature_version (gst_registry_get (), "id3demux",
+ GST_VERSION_MAJOR, GST_VERSION_MINOR, 0)) {
+ tcase_add_test (tc_chain, test_id3mux_v2_3);
+ tcase_add_test (tc_chain, test_id3mux_v2_4);
+ } else {
+ GST_WARNING ("id3demux element not available, skipping tests");
+ }
+
+ return s;
+}
+
+GST_CHECK_MAIN (id3mux);
diff --git a/tests/check/elements/jifmux.c b/tests/check/elements/jifmux.c
new file mode 100644
index 00000000..680e0122
--- /dev/null
+++ b/tests/check/elements/jifmux.c
@@ -0,0 +1,1239 @@
+/* GStreamer
+ *
+ * unit test for jifmux
+ *
+ * Copyright (C) <2010> Thiago Santos <thiago.sousa.santos@collabora.co.uk>
+ *
+ * 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.
+ */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <stdio.h>
+#include <unistd.h>
+
+#include <glib/gstdio.h>
+
+#include <gst/check/gstcheck.h>
+#include <gst/tag/tag.h>
+
+#include <libexif/exif-data.h>
+#include <libexif/exif-loader.h>
+
+typedef struct
+{
+ gboolean result;
+ const GstTagList *taglist;
+ gint map_index;
+} ExifTagCheckData;
+
+/* taken from the exif helper lib in -base */
+/* Exif tag types */
+#define EXIF_TYPE_BYTE 1
+#define EXIF_TYPE_ASCII 2
+#define EXIF_TYPE_SHORT 3
+#define EXIF_TYPE_LONG 4
+#define EXIF_TYPE_RATIONAL 5
+#define EXIF_TYPE_UNDEFINED 7
+#define EXIF_TYPE_SLONG 9
+#define EXIF_TYPE_SRATIONAL 10
+
+typedef struct _GstExifTagMatch GstExifTagMatch;
+typedef void (*CompareFunc) (ExifEntry * entry, ExifTagCheckData * testdata);
+
+struct _GstExifTagMatch
+{
+ const gchar *gst_tag;
+ guint16 exif_tag;
+ guint16 exif_type;
+ CompareFunc compare_func;
+};
+
+/* compare funcs */
+
+/* Copied over from gst-libs/gst/tag/gsttagedittingprivate.c from -base */
+static gint
+__exif_tag_image_orientation_to_exif_value (const gchar * str)
+{
+ if (str == NULL)
+ goto end;
+
+ if (strcmp (str, "rotate-0") == 0)
+ return 1;
+ else if (strcmp (str, "flip-rotate-0") == 0)
+ return 2;
+ else if (strcmp (str, "rotate-180") == 0)
+ return 3;
+ else if (strcmp (str, "flip-rotate-180") == 0)
+ return 4;
+ else if (strcmp (str, "flip-rotate-270") == 0)
+ return 5;
+ else if (strcmp (str, "rotate-90") == 0)
+ return 6;
+ else if (strcmp (str, "flip-rotate-90") == 0)
+ return 7;
+ else if (strcmp (str, "rotate-270") == 0)
+ return 8;
+
+end:
+ GST_WARNING ("Invalid image orientation tag: %s", str);
+ return -1;
+}
+
+static gint
+__exif_tag_capture_exposure_program_to_exif_value (const gchar * str)
+{
+ if (str == NULL)
+ goto end;
+
+ if (strcmp (str, "undefined") == 0)
+ return 0;
+ else if (strcmp (str, "manual") == 0)
+ return 1;
+ else if (strcmp (str, "normal") == 0)
+ return 2;
+ else if (strcmp (str, "aperture-priority") == 0)
+ return 3;
+ else if (strcmp (str, "shutter-priority") == 0)
+ return 4;
+ else if (strcmp (str, "creative") == 0)
+ return 5;
+ else if (strcmp (str, "action") == 0)
+ return 6;
+ else if (strcmp (str, "portrait") == 0)
+ return 7;
+ else if (strcmp (str, "landscape") == 0)
+ return 8;
+
+end:
+ GST_WARNING ("Invalid capture exposure program tag: %s", str);
+ return -1;
+}
+
+static gint
+__exif_tag_capture_exposure_mode_to_exif_value (const gchar * str)
+{
+ if (str == NULL)
+ goto end;
+
+ if (strcmp (str, "auto-exposure") == 0)
+ return 0;
+ else if (strcmp (str, "manual-exposure") == 0)
+ return 1;
+ else if (strcmp (str, "auto-bracket") == 0)
+ return 2;
+
+end:
+ GST_WARNING ("Invalid capture exposure mode tag: %s", str);
+ return -1;
+}
+
+static gint
+__exif_tag_capture_scene_capture_type_to_exif_value (const gchar * str)
+{
+ if (str == NULL)
+ goto end;
+
+ if (strcmp (str, "standard") == 0)
+ return 0;
+ else if (strcmp (str, "landscape") == 0)
+ return 1;
+ else if (strcmp (str, "portrait") == 0)
+ return 2;
+ else if (strcmp (str, "night-scene") == 0)
+ return 3;
+
+end:
+ GST_WARNING ("Invalid capture scene capture type: %s", str);
+ return -1;
+}
+
+static gint
+__exif_tag_capture_gain_adjustment_to_exif_value (const gchar * str)
+{
+ if (str == NULL)
+ goto end;
+
+ if (strcmp (str, "none") == 0)
+ return 0;
+ else if (strcmp (str, "low-gain-up") == 0)
+ return 1;
+ else if (strcmp (str, "high-gain-up") == 0)
+ return 2;
+ else if (strcmp (str, "low-gain-down") == 0)
+ return 3;
+ else if (strcmp (str, "high-gain-down") == 0)
+ return 4;
+
+end:
+ GST_WARNING ("Invalid capture gain adjustment type: %s", str);
+ return -1;
+}
+
+static gint
+__exif_tag_capture_white_balance_to_exif_value (const gchar * str)
+{
+ if (str == NULL)
+ goto end;
+
+ if (strcmp (str, "auto") == 0)
+ return 0;
+ else /* everything else is just manual */
+ return 1;
+
+end:
+ GST_WARNING ("Invalid white balance: %s", str);
+ return -1;
+}
+
+static gint
+__exif_tag_capture_contrast_to_exif_value (const gchar * str)
+{
+ if (str == NULL)
+ goto end;
+
+ if (strcmp (str, "normal") == 0)
+ return 0;
+ else if (strcmp (str, "soft") == 0)
+ return 1;
+ else if (strcmp (str, "hard") == 0)
+ return 2;
+
+end:
+ GST_WARNING ("Invalid contrast type: %s", str);
+ return -1;
+}
+
+static gint
+__exif_tag_capture_sharpness_to_exif_value (const gchar * str)
+{
+ if (str == NULL)
+ goto end;
+
+ if (strcmp (str, "normal") == 0)
+ return 0;
+ else if (strcmp (str, "soft") == 0)
+ return 1;
+ else if (strcmp (str, "hard") == 0)
+ return 2;
+
+end:
+ GST_WARNING ("Invalid sharpness type: %s", str);
+ return -1;
+}
+
+static gint
+__exif_tag_capture_saturation_to_exif_value (const gchar * str)
+{
+ if (str == NULL)
+ goto end;
+
+ if (strcmp (str, "normal") == 0)
+ return 0;
+ else if (strcmp (str, "low-saturation") == 0)
+ return 1;
+ else if (strcmp (str, "high-saturation") == 0)
+ return 2;
+
+end:
+ GST_WARNING ("Invalid saturation type: %s", str);
+ return -1;
+}
+
+static gint
+__exif_tag_capture_metering_mode_to_exif_value (const gchar * str)
+{
+ if (str == NULL)
+ goto end;
+
+ if (strcmp (str, "unknown") == 0)
+ return 0;
+ else if (strcmp (str, "average") == 0)
+ return 1;
+ else if (strcmp (str, "center-weighted-average") == 0)
+ return 2;
+ else if (strcmp (str, "spot") == 0)
+ return 3;
+ else if (strcmp (str, "multi-spot") == 0)
+ return 4;
+ else if (strcmp (str, "pattern") == 0)
+ return 5;
+ else if (strcmp (str, "partial") == 0)
+ return 6;
+ else if (strcmp (str, "other") == 0)
+ return 255;
+
+end:
+ GST_WARNING ("Invalid metering mode type: %s", str);
+ return -1;
+}
+
+static gint
+__exif_tag_capture_source_to_exif_value (const gchar * str)
+{
+ if (str == NULL)
+ goto end;
+
+ if (strcmp (str, "dsc") == 0)
+ return 3;
+ else if (strcmp (str, "other") == 0)
+ return 0;
+ else if (strcmp (str, "transparent-scanner") == 0)
+ return 1;
+ else if (strcmp (str, "reflex-scanner") == 0)
+ return 2;
+
+end:
+ GST_WARNING ("Invalid capturing source type: %s", str);
+ return -1;
+}
+
+#define GST_COMPARE_GST_STRING_TAG_TO_EXIF_SHORT_FUNC(gst_tag,name) \
+static void \
+compare_ ## name (ExifEntry * entry, ExifTagCheckData * testdata) \
+{ \
+ gchar *str_tag = NULL; \
+ gint exif_value = -1; \
+ gint value = -1; \
+ \
+ if (!gst_tag_list_get_string_index (testdata->taglist, \
+ gst_tag, 0, &str_tag)) { \
+ /* fail the test if we can't get the tag */ \
+ GST_WARNING ("Failed to get %s from taglist", gst_tag); \
+ fail (); \
+ } \
+ \
+ value = __exif_tag_ ## name ## _to_exif_value (str_tag); \
+ \
+ if (value == -1) { \
+ GST_WARNING ("Invalid %s tag value: %s", gst_tag, str_tag); \
+ fail (); \
+ } \
+ \
+ if (entry->format == EXIF_TYPE_SHORT) \
+ exif_value = (gint) exif_get_short (entry->data, \
+ exif_data_get_byte_order (entry->parent->parent)); \
+ else if (entry->format == EXIF_TYPE_UNDEFINED) \
+ exif_value = (gint) entry->data[0]; \
+ \
+ if (value != exif_value) { \
+ GST_WARNING ("Gstreamer tag value (%d) is different from libexif (%d)", \
+ value, exif_value); \
+ fail (); \
+ } \
+ \
+ testdata->result = TRUE; \
+ \
+ g_free (str_tag); \
+}
+
+GST_COMPARE_GST_STRING_TAG_TO_EXIF_SHORT_FUNC (GST_TAG_IMAGE_ORIENTATION,
+ image_orientation);
+GST_COMPARE_GST_STRING_TAG_TO_EXIF_SHORT_FUNC
+ (GST_TAG_CAPTURING_EXPOSURE_PROGRAM, capture_exposure_program);
+GST_COMPARE_GST_STRING_TAG_TO_EXIF_SHORT_FUNC (GST_TAG_CAPTURING_EXPOSURE_MODE,
+ capture_exposure_mode);
+GST_COMPARE_GST_STRING_TAG_TO_EXIF_SHORT_FUNC (GST_TAG_CAPTURING_WHITE_BALANCE,
+ capture_white_balance);
+GST_COMPARE_GST_STRING_TAG_TO_EXIF_SHORT_FUNC (GST_TAG_CAPTURING_CONTRAST,
+ capture_contrast);
+GST_COMPARE_GST_STRING_TAG_TO_EXIF_SHORT_FUNC
+ (GST_TAG_CAPTURING_GAIN_ADJUSTMENT, capture_gain_adjustment);
+GST_COMPARE_GST_STRING_TAG_TO_EXIF_SHORT_FUNC (GST_TAG_CAPTURING_SATURATION,
+ capture_saturation);
+GST_COMPARE_GST_STRING_TAG_TO_EXIF_SHORT_FUNC
+ (GST_TAG_CAPTURING_SHARPNESS, capture_sharpness);
+GST_COMPARE_GST_STRING_TAG_TO_EXIF_SHORT_FUNC
+ (GST_TAG_CAPTURING_SCENE_CAPTURE_TYPE, capture_scene_capture_type);
+GST_COMPARE_GST_STRING_TAG_TO_EXIF_SHORT_FUNC
+ (GST_TAG_CAPTURING_METERING_MODE, capture_metering_mode);
+GST_COMPARE_GST_STRING_TAG_TO_EXIF_SHORT_FUNC
+ (GST_TAG_CAPTURING_SOURCE, capture_source);
+
+static void
+compare_date_time (ExifEntry * entry, ExifTagCheckData * testdata)
+{
+ gint year = 0, month = 1, day = 1, hour = 0, minute = 0, second = 0;
+ GstDateTime *exif_datetime;
+ GstDateTime *datetime;
+ const gchar *str;
+
+ if (!gst_tag_list_get_date_time_index (testdata->taglist, GST_TAG_DATE_TIME,
+ 0, &datetime)) {
+ GST_WARNING ("Failed to get datetime from taglist");
+ return;
+ }
+
+ str = (gchar *) entry->data;
+
+ sscanf (str, "%04d:%02d:%02d %02d:%02d:%02d", &year, &month, &day,
+ &hour, &minute, &second);
+ exif_datetime = gst_date_time_new_local_time (year, month, day, hour, minute,
+ second);
+ fail_if (exif_datetime == NULL);
+
+ fail_unless (gst_date_time_get_year (datetime) ==
+ gst_date_time_get_year (exif_datetime)
+ && gst_date_time_get_month (datetime) ==
+ gst_date_time_get_month (exif_datetime)
+ && gst_date_time_get_day (datetime) ==
+ gst_date_time_get_day (exif_datetime)
+ && gst_date_time_get_hour (datetime) ==
+ gst_date_time_get_hour (exif_datetime)
+ && gst_date_time_get_minute (datetime) ==
+ gst_date_time_get_minute (exif_datetime)
+ && gst_date_time_get_second (datetime) ==
+ gst_date_time_get_second (exif_datetime));
+
+ gst_date_time_unref (exif_datetime);
+ gst_date_time_unref (datetime);
+
+ testdata->result = TRUE;
+}
+
+static void
+compare_shutter_speed (ExifEntry * entry, ExifTagCheckData * testdata)
+{
+ gdouble gst_num, exif_num;
+ ExifSRational rational;
+ GValue exif_value = { 0 };
+ const GValue *gst_value = NULL;
+
+ gst_value = gst_tag_list_get_value_index (testdata->taglist,
+ GST_TAG_CAPTURING_SHUTTER_SPEED, 0);
+ if (gst_value == NULL) {
+ GST_WARNING ("Failed to get shutter-speed from taglist");
+ return;
+ }
+
+ rational = exif_get_srational (entry->data,
+ exif_data_get_byte_order (entry->parent->parent));
+
+ g_value_init (&exif_value, GST_TYPE_FRACTION);
+ gst_value_set_fraction (&exif_value, rational.numerator,
+ rational.denominator);
+ gst_util_fraction_to_double (gst_value_get_fraction_numerator (&exif_value),
+ gst_value_get_fraction_denominator (&exif_value), &exif_num);
+ g_value_unset (&exif_value);
+
+ gst_util_fraction_to_double (gst_value_get_fraction_numerator (gst_value),
+ gst_value_get_fraction_denominator (gst_value), &gst_num);
+
+ exif_num = pow (2, -exif_num);
+
+ GST_LOG ("Shutter speed in gst=%lf and in exif=%lf", gst_num, exif_num);
+ fail_unless (ABS (gst_num - exif_num) < 0.001);
+ testdata->result = TRUE;
+}
+
+static void
+compare_aperture_value (ExifEntry * entry, ExifTagCheckData * testdata)
+{
+ gdouble gst_value, exif_value;
+ ExifSRational rational;
+ GValue value = { 0 };
+
+ if (!gst_tag_list_get_double_index (testdata->taglist,
+ GST_TAG_CAPTURING_FOCAL_RATIO, 0, &gst_value)) {
+ GST_WARNING ("Failed to get focal ratio from taglist");
+ return;
+ }
+
+ rational = exif_get_srational (entry->data,
+ exif_data_get_byte_order (entry->parent->parent));
+
+ g_value_init (&value, GST_TYPE_FRACTION);
+ gst_value_set_fraction (&value, rational.numerator, rational.denominator);
+ gst_util_fraction_to_double (gst_value_get_fraction_numerator (&value),
+ gst_value_get_fraction_denominator (&value), &exif_value);
+ g_value_unset (&value);
+
+ exif_value = pow (2, exif_value / 2);
+
+ GST_LOG ("Aperture value in gst=%lf and in exif=%lf", gst_value, exif_value);
+ fail_unless (ABS (gst_value - exif_value) < 0.001);
+ testdata->result = TRUE;
+}
+
+static void
+compare_flash (ExifEntry * entry, ExifTagCheckData * testdata)
+{
+ guint16 flags;
+ gboolean flash_fired;
+ const gchar *flash_mode;
+
+ flags = (gint) exif_get_short (entry->data,
+ exif_data_get_byte_order (entry->parent->parent));
+
+ if (!gst_tag_list_get_boolean_index (testdata->taglist,
+ GST_TAG_CAPTURING_FLASH_FIRED, 0, &flash_fired)) {
+ GST_WARNING ("Failed to get %s tag", GST_TAG_CAPTURING_FLASH_FIRED);
+ return;
+ }
+ if (!gst_tag_list_peek_string_index (testdata->taglist,
+ GST_TAG_CAPTURING_FLASH_MODE, 0, &flash_mode)) {
+ GST_WARNING ("Failed to get %s tag", GST_TAG_CAPTURING_FLASH_MODE);
+ return;
+ }
+
+ if (flash_fired)
+ fail_unless ((flags & 1) == 1);
+ else
+ fail_unless ((flags & 1) == 0);
+
+ if (strcmp (flash_mode, "auto") == 0) {
+ fail_unless (((flags >> 3) & 0x3) == 3);
+ } else if (strcmp (flash_mode, "always") == 0) {
+ fail_unless (((flags >> 3) & 0x3) == 1);
+ } else if (strcmp (flash_mode, "never") == 0) {
+ fail_unless (((flags >> 3) & 0x3) == 2);
+ } else {
+ fail ();
+ }
+ testdata->result = TRUE;
+}
+
+static void
+compare_geo_elevation (ExifEntry * entry, ExifTagCheckData * testdata)
+{
+ gdouble altitude = 0, gst_value;
+ ExifRational rational;
+
+ fail_unless (gst_tag_list_get_double_index (testdata->taglist,
+ GST_TAG_GEO_LOCATION_ELEVATION, 0, &gst_value));
+
+ fail_unless (entry->components == 1);
+
+ rational = exif_get_rational (entry->data,
+ exif_data_get_byte_order (entry->parent->parent));
+ gst_util_fraction_to_double (rational.numerator, rational.denominator,
+ &altitude);
+
+ gst_value = ABS (gst_value);
+ fail_unless (ABS (gst_value - altitude) < 0.001);
+ testdata->result = TRUE;
+}
+
+static void
+compare_geo_elevation_ref (ExifEntry * entry, ExifTagCheckData * testdata)
+{
+ gdouble gst_value;
+
+ fail_unless (gst_tag_list_get_double_index (testdata->taglist,
+ GST_TAG_GEO_LOCATION_ELEVATION, 0, &gst_value));
+
+ fail_unless (entry->components == 1);
+
+ if (gst_value >= 0) {
+ fail_unless (entry->data[0] == 0);
+ } else {
+ fail_unless (entry->data[0] == 1);
+ }
+ testdata->result = TRUE;
+}
+
+static void
+compare_speed (ExifEntry * entry, ExifTagCheckData * testdata)
+{
+ gdouble speed = 0, gst_value;
+ ExifRational rational;
+
+ fail_unless (gst_tag_list_get_double_index (testdata->taglist,
+ GST_TAG_GEO_LOCATION_MOVEMENT_SPEED, 0, &gst_value));
+
+ fail_unless (entry->components == 1);
+
+ rational = exif_get_rational (entry->data,
+ exif_data_get_byte_order (entry->parent->parent));
+ gst_util_fraction_to_double (rational.numerator, rational.denominator,
+ &speed);
+
+ speed = speed / 3.6;
+
+ fail_unless (ABS (gst_value - speed) < 0.001);
+ testdata->result = TRUE;
+}
+
+static void
+compare_speed_ref (ExifEntry * entry, ExifTagCheckData * testdata)
+{
+ fail_unless (entry->components == 2);
+ fail_unless (entry->data[0] == 'K');
+ testdata->result = TRUE;
+}
+
+static void
+compare_geo_coordinate (ExifEntry * entry, ExifTagCheckData * testdata);
+
+static void
+compare_geo_coordinate_ref (ExifEntry * entry, ExifTagCheckData * testdata);
+
+static void
+compare_geo_direction (ExifEntry * entry, ExifTagCheckData * testdata);
+
+static void
+compare_geo_direction_ref (ExifEntry * entry, ExifTagCheckData * testdata);
+
+static const GstExifTagMatch tag_map[] = {
+ {GST_TAG_DESCRIPTION, EXIF_TAG_IMAGE_DESCRIPTION, EXIF_TYPE_ASCII,
+ NULL},
+ {GST_TAG_DEVICE_MANUFACTURER, EXIF_TAG_MAKE, EXIF_TYPE_ASCII,
+ NULL},
+ {GST_TAG_DEVICE_MODEL, EXIF_TAG_MODEL, EXIF_TYPE_ASCII, NULL},
+ {GST_TAG_IMAGE_ORIENTATION, EXIF_TAG_ORIENTATION, EXIF_TYPE_SHORT,
+ compare_image_orientation},
+ {GST_TAG_IMAGE_HORIZONTAL_PPI, EXIF_TAG_X_RESOLUTION, EXIF_TYPE_RATIONAL,
+ NULL},
+ {GST_TAG_IMAGE_VERTICAL_PPI, EXIF_TAG_Y_RESOLUTION, EXIF_TYPE_RATIONAL, NULL},
+ {GST_TAG_APPLICATION_NAME, EXIF_TAG_SOFTWARE, EXIF_TYPE_ASCII,
+ NULL},
+ {GST_TAG_DATE_TIME, EXIF_TAG_DATE_TIME, EXIF_TYPE_ASCII,
+ compare_date_time},
+ {GST_TAG_ARTIST, EXIF_TAG_ARTIST, EXIF_TYPE_ASCII, NULL},
+ {GST_TAG_COPYRIGHT, EXIF_TAG_COPYRIGHT, EXIF_TYPE_ASCII, NULL},
+ {GST_TAG_CAPTURING_SHUTTER_SPEED, EXIF_TAG_EXPOSURE_TIME,
+ EXIF_TYPE_RATIONAL, NULL},
+ {GST_TAG_CAPTURING_FOCAL_RATIO, EXIF_TAG_FNUMBER, EXIF_TYPE_RATIONAL,
+ NULL},
+ {GST_TAG_CAPTURING_EXPOSURE_PROGRAM, EXIF_TAG_EXPOSURE_PROGRAM,
+ EXIF_TYPE_SHORT, compare_capture_exposure_program},
+
+ /* This is called PhotographicSensitivity in 2.3 */
+ {GST_TAG_CAPTURING_ISO_SPEED, EXIF_TAG_ISO_SPEED_RATINGS,
+ EXIF_TYPE_SHORT, NULL},
+
+ {GST_TAG_CAPTURING_SHUTTER_SPEED, EXIF_TAG_SHUTTER_SPEED_VALUE,
+ EXIF_TYPE_SRATIONAL, compare_shutter_speed},
+ {GST_TAG_CAPTURING_FOCAL_RATIO, EXIF_TAG_APERTURE_VALUE, EXIF_TYPE_RATIONAL,
+ compare_aperture_value},
+ {GST_TAG_CAPTURING_EXPOSURE_COMPENSATION, EXIF_TAG_EXPOSURE_BIAS_VALUE,
+ EXIF_TYPE_SRATIONAL},
+ {GST_TAG_CAPTURING_FLASH_FIRED, EXIF_TAG_FLASH, EXIF_TYPE_SHORT,
+ compare_flash},
+ {GST_TAG_CAPTURING_FLASH_MODE, EXIF_TAG_FLASH, EXIF_TYPE_SHORT,
+ compare_flash},
+ {GST_TAG_CAPTURING_FOCAL_LENGTH, EXIF_TAG_FOCAL_LENGTH, EXIF_TYPE_RATIONAL,
+ NULL},
+ {GST_TAG_APPLICATION_DATA, EXIF_TAG_MAKER_NOTE, EXIF_TYPE_UNDEFINED, NULL},
+ {GST_TAG_CAPTURING_EXPOSURE_MODE, EXIF_TAG_EXPOSURE_MODE, EXIF_TYPE_SHORT,
+ compare_capture_exposure_mode},
+ {GST_TAG_CAPTURING_WHITE_BALANCE, EXIF_TAG_WHITE_BALANCE, EXIF_TYPE_SHORT,
+ compare_capture_white_balance},
+ {GST_TAG_CAPTURING_DIGITAL_ZOOM_RATIO, EXIF_TAG_DIGITAL_ZOOM_RATIO,
+ EXIF_TYPE_RATIONAL, NULL},
+ {GST_TAG_CAPTURING_SCENE_CAPTURE_TYPE, EXIF_TAG_SCENE_CAPTURE_TYPE,
+ EXIF_TYPE_SHORT, compare_capture_scene_capture_type},
+ {GST_TAG_CAPTURING_GAIN_ADJUSTMENT, EXIF_TAG_GAIN_CONTROL,
+ EXIF_TYPE_SHORT, compare_capture_gain_adjustment},
+ {GST_TAG_CAPTURING_CONTRAST, EXIF_TAG_CONTRAST, EXIF_TYPE_SHORT,
+ compare_capture_contrast},
+ {GST_TAG_CAPTURING_SATURATION, EXIF_TAG_SATURATION, EXIF_TYPE_SHORT,
+ compare_capture_saturation},
+ {GST_TAG_CAPTURING_SHARPNESS, EXIF_TAG_SHARPNESS, EXIF_TYPE_SHORT,
+ compare_capture_sharpness},
+ {GST_TAG_CAPTURING_METERING_MODE, EXIF_TAG_METERING_MODE, EXIF_TYPE_SHORT,
+ compare_capture_metering_mode},
+ {GST_TAG_CAPTURING_SOURCE, EXIF_TAG_FILE_SOURCE, EXIF_TYPE_UNDEFINED,
+ compare_capture_source},
+
+ /* gps tags */
+ {GST_TAG_GEO_LOCATION_LATITUDE, EXIF_TAG_GPS_LATITUDE, EXIF_TYPE_RATIONAL,
+ compare_geo_coordinate},
+ {GST_TAG_GEO_LOCATION_LATITUDE, EXIF_TAG_GPS_LATITUDE_REF, EXIF_TYPE_ASCII,
+ compare_geo_coordinate_ref},
+ {GST_TAG_GEO_LOCATION_LONGITUDE, EXIF_TAG_GPS_LONGITUDE, EXIF_TYPE_RATIONAL,
+ compare_geo_coordinate},
+ {GST_TAG_GEO_LOCATION_LONGITUDE, EXIF_TAG_GPS_LONGITUDE_REF, EXIF_TYPE_ASCII,
+ compare_geo_coordinate_ref},
+ {GST_TAG_GEO_LOCATION_ELEVATION, EXIF_TAG_GPS_ALTITUDE, EXIF_TYPE_RATIONAL,
+ compare_geo_elevation},
+ {GST_TAG_GEO_LOCATION_ELEVATION, EXIF_TAG_GPS_ALTITUDE_REF, EXIF_TYPE_BYTE,
+ compare_geo_elevation_ref},
+ {GST_TAG_GEO_LOCATION_MOVEMENT_SPEED, EXIF_TAG_GPS_SPEED, EXIF_TYPE_RATIONAL,
+ compare_speed},
+ {GST_TAG_GEO_LOCATION_MOVEMENT_SPEED, EXIF_TAG_GPS_SPEED_REF, EXIF_TYPE_ASCII,
+ compare_speed_ref},
+ {GST_TAG_GEO_LOCATION_MOVEMENT_DIRECTION, EXIF_TAG_GPS_TRACK,
+ EXIF_TYPE_RATIONAL, compare_geo_direction},
+ {GST_TAG_GEO_LOCATION_MOVEMENT_DIRECTION, EXIF_TAG_GPS_TRACK_REF,
+ EXIF_TYPE_ASCII, compare_geo_direction_ref},
+ {GST_TAG_GEO_LOCATION_CAPTURE_DIRECTION, EXIF_TAG_GPS_IMG_DIRECTION,
+ EXIF_TYPE_RATIONAL, compare_geo_direction},
+ {GST_TAG_GEO_LOCATION_CAPTURE_DIRECTION, EXIF_TAG_GPS_IMG_DIRECTION_REF,
+ EXIF_TYPE_ASCII, compare_geo_direction_ref}
+
+/*
+ * libexif doesn't have these tags
+ * {GST_TAG_CAPTURING_ISO_SPEED, EXIF_TAG_ISO_SPEED, EXIF_TYPE_LONG, NULL},
+ * {GST_TAG_CAPTURING_ISO_SPEED, EXIF_TAG_SENSITIVITY_TYPE,
+ * EXIF_TYPE_SHORT, compare_sensitivity_type},
+ */
+};
+
+static void
+compare_geo_coordinate (ExifEntry * entry, ExifTagCheckData * testdata)
+{
+ gdouble coordinate = 0, aux, gst_value;
+ ExifRational rational;
+
+ fail_unless (gst_tag_list_get_double_index (testdata->taglist,
+ tag_map[testdata->map_index].gst_tag, 0, &gst_value));
+
+ fail_unless (entry->components == 3);
+
+ rational = exif_get_rational (entry->data,
+ exif_data_get_byte_order (entry->parent->parent));
+ gst_util_fraction_to_double (rational.numerator, rational.denominator, &aux);
+ coordinate += aux;
+
+ rational = exif_get_rational (entry->data + 8,
+ exif_data_get_byte_order (entry->parent->parent));
+ gst_util_fraction_to_double (rational.numerator, rational.denominator, &aux);
+ coordinate += aux / 60.0;
+
+ rational = exif_get_rational (entry->data + 16,
+ exif_data_get_byte_order (entry->parent->parent));
+ gst_util_fraction_to_double (rational.numerator, rational.denominator, &aux);
+ coordinate += aux / 3600.0;
+
+ gst_value = ABS (gst_value);
+ fail_unless (ABS (gst_value - coordinate) < 0.001);
+ testdata->result = TRUE;
+}
+
+static void
+compare_geo_coordinate_ref (ExifEntry * entry, ExifTagCheckData * testdata)
+{
+ gdouble gst_value;
+ const gchar *tag;
+
+ tag = tag_map[testdata->map_index].gst_tag;
+
+ fail_unless (gst_tag_list_get_double_index (testdata->taglist, tag, 0,
+ &gst_value));
+
+ fail_unless (entry->components == 2);
+
+ if (strcmp (tag, GST_TAG_GEO_LOCATION_LATITUDE) == 0) {
+ if (gst_value >= 0) {
+ fail_unless (entry->data[0] == 'N');
+ } else {
+ fail_unless (entry->data[0] == 'S');
+ }
+ } else {
+ if (gst_value >= 0) {
+ fail_unless (entry->data[0] == 'E');
+ } else {
+ fail_unless (entry->data[0] == 'W');
+ }
+ }
+ testdata->result = TRUE;
+}
+
+static void
+compare_geo_direction (ExifEntry * entry, ExifTagCheckData * testdata)
+{
+ gdouble direction = 0, gst_value;
+ ExifRational rational;
+
+ fail_unless (gst_tag_list_get_double_index (testdata->taglist,
+ tag_map[testdata->map_index].gst_tag, 0, &gst_value));
+
+ fail_unless (entry->components == 1);
+
+ rational = exif_get_rational (entry->data,
+ exif_data_get_byte_order (entry->parent->parent));
+ gst_util_fraction_to_double (rational.numerator, rational.denominator,
+ &direction);
+
+ fail_unless (ABS (gst_value - direction) < 0.001);
+ testdata->result = TRUE;
+}
+
+static void
+compare_geo_direction_ref (ExifEntry * entry, ExifTagCheckData * testdata)
+{
+ fail_unless (entry->components == 2);
+ fail_unless (entry->data[0] == 'T');
+ testdata->result = TRUE;
+}
+
+static void
+check_content (ExifContent * content, void *user_data)
+{
+ ExifTagCheckData *test_data = (ExifTagCheckData *) user_data;
+ guint16 tagindex;
+ ExifEntry *entry;
+ GType gst_tag_type;
+
+ tagindex = test_data->map_index;
+ gst_tag_type = gst_tag_get_type (tag_map[tagindex].gst_tag);
+
+ GST_DEBUG ("Got tagindex %u for gsttag %s with type %s", tagindex,
+ tag_map[tagindex].gst_tag, g_type_name (gst_tag_type));
+
+ /* search for the entry */
+ entry = exif_content_get_entry (content, tag_map[tagindex].exif_tag);
+ GST_DEBUG ("Entry found at %p", entry);
+ if (entry == NULL)
+ return;
+
+ fail_unless (entry->format == tag_map[tagindex].exif_type);
+
+ if (tag_map[tagindex].compare_func) {
+ tag_map[tagindex].compare_func (entry, test_data);
+ return;
+ }
+
+ switch (entry->format) {
+ case EXIF_TYPE_ASCII:{
+ const gchar *str;
+ gchar *taglist_str;
+
+ str = (gchar *) entry->data;
+ fail_unless (gst_tag_list_get_string (test_data->taglist,
+ tag_map[tagindex].gst_tag, &taglist_str));
+
+ fail_unless (strcmp (str, taglist_str) == 0);
+ test_data->result = TRUE;
+ g_free (taglist_str);
+ }
+ break;
+ case EXIF_TYPE_SRATIONAL:
+ case EXIF_TYPE_RATIONAL:{
+ GValue exif_value = { 0 };
+
+ g_value_init (&exif_value, GST_TYPE_FRACTION);
+ if (entry->format == EXIF_TYPE_RATIONAL) {
+ ExifRational exif_rational = exif_get_rational (entry->data,
+ exif_data_get_byte_order (entry->parent->parent));
+
+ gst_value_set_fraction (&exif_value, exif_rational.numerator,
+ exif_rational.denominator);
+ } else {
+ ExifSRational exif_rational = exif_get_srational (entry->data,
+ exif_data_get_byte_order (entry->parent->parent));
+
+ gst_value_set_fraction (&exif_value, exif_rational.numerator,
+ exif_rational.denominator);
+ }
+
+ if (gst_tag_type == GST_TYPE_FRACTION) {
+ const GValue *value = gst_tag_list_get_value_index (test_data->taglist,
+ tag_map[tagindex].gst_tag, 0);
+
+ fail_unless (value != NULL);
+ fail_unless (G_VALUE_TYPE (value) == GST_TYPE_FRACTION);
+
+ fail_unless (gst_value_get_fraction_numerator (value) ==
+ gst_value_get_fraction_numerator (&exif_value) &&
+ gst_value_get_fraction_denominator (value) ==
+ gst_value_get_fraction_denominator (&exif_value));
+
+ test_data->result = TRUE;
+ } else if (gst_tag_type == G_TYPE_DOUBLE) {
+ gdouble gst_num;
+ gdouble exif_num;
+
+ gst_util_fraction_to_double (gst_value_get_fraction_numerator
+ (&exif_value), gst_value_get_fraction_denominator (&exif_value),
+ &exif_num);
+
+ fail_unless (gst_tag_list_get_double_index (test_data->taglist,
+ tag_map[tagindex].gst_tag, 0, &gst_num));
+
+ fail_unless (gst_num == exif_num);
+ test_data->result = TRUE;
+ } else {
+ GST_WARNING ("Unhandled type for rational tag(%X): %s",
+ entry->tag, g_type_name (gst_tag_type));
+ }
+ g_value_unset (&exif_value);
+ }
+ break;
+ case EXIF_TYPE_SHORT:
+ case EXIF_TYPE_LONG:{
+ gint gst_num;
+ gint exif_num = -1;
+
+ if (entry->format == EXIF_TYPE_LONG) {
+ exif_num = (gint) exif_get_long (entry->data,
+ exif_data_get_byte_order (entry->parent->parent));
+ } else if (entry->format == EXIF_TYPE_SHORT) {
+ exif_num = (gint) exif_get_short (entry->data,
+ exif_data_get_byte_order (entry->parent->parent));
+ }
+
+ fail_unless (gst_tag_list_get_int_index (test_data->taglist,
+ tag_map[tagindex].gst_tag, 0, &gst_num));
+
+ fail_unless (exif_num == gst_num);
+ test_data->result = TRUE;
+ }
+ break;
+ case EXIF_TYPE_UNDEFINED:{
+ GstMapInfo map;
+ GstBuffer *buf;
+ gint i;
+
+ if (!gst_tag_list_get_buffer_index (test_data->taglist,
+ tag_map[tagindex].gst_tag, 0, &buf)) {
+ return;
+ }
+
+ gst_buffer_map (buf, &map, GST_MAP_READ);
+ fail_unless (entry->size, map.size);
+ for (i = 0; i < map.size; i++) {
+ fail_unless (map.data[i] == (guint8) entry->data[i]);
+ }
+ gst_buffer_unmap (buf, &map);
+
+ test_data->result = TRUE;
+ gst_buffer_unref (buf);
+ }
+ break;
+ default:
+ fail ();
+ }
+}
+
+/*
+ * Iterates over the exif data searching for the mapping pointed by index
+ */
+static void
+libexif_check_tag_exists (const GstTagList * taglist, gint index, gpointer data)
+{
+ ExifData *exif_data = (ExifData *) data;
+ ExifTagCheckData test_data;
+
+ test_data.result = FALSE;
+ test_data.taglist = taglist;
+ test_data.map_index = index;
+
+ exif_data_foreach_content (exif_data, check_content, &test_data);
+
+ fail_unless (test_data.result);
+}
+
+static void
+generate_jif_file_with_tags_from_taglist (GstTagList * taglist,
+ const gchar * filepath)
+{
+ GstElement *pipeline;
+ GstBus *bus;
+ GstMessage *msg;
+ gchar *launchline;
+ GstElement *jifmux;
+ GstTagSetter *setter;
+
+ launchline = g_strdup_printf ("videotestsrc num-buffers=1 ! jpegenc ! "
+ "jifmux name=jifmux0 ! filesink location=%s", filepath);
+
+ pipeline = gst_parse_launch (launchline, NULL);
+ fail_unless (pipeline != NULL);
+ g_free (launchline);
+
+ jifmux = gst_bin_get_by_name (GST_BIN (pipeline), "jifmux0");
+ fail_unless (jifmux != NULL);
+ setter = GST_TAG_SETTER (jifmux);
+ gst_tag_setter_merge_tags (setter, taglist, GST_TAG_MERGE_REPLACE);
+ gst_object_unref (jifmux);
+
+ bus = gst_pipeline_get_bus (GST_PIPELINE (pipeline));
+
+ fail_if (gst_element_set_state (pipeline, GST_STATE_PLAYING) ==
+ GST_STATE_CHANGE_FAILURE);
+
+ msg = gst_bus_timed_pop_filtered (bus, GST_SECOND * 10, GST_MESSAGE_EOS |
+ GST_MESSAGE_ERROR);
+ fail_if (!msg);
+ fail_if (GST_MESSAGE_TYPE (msg) == GST_MESSAGE_ERROR);
+
+ gst_message_unref (msg);
+ gst_object_unref (bus);
+ gst_element_set_state (pipeline, GST_STATE_NULL);
+ gst_object_unref (pipeline);
+}
+
+static void
+generate_jif_file_with_tags (const gchar * tags, const gchar * filepath)
+{
+ GstTagList *taglist;
+
+ taglist = gst_tag_list_new_from_string (tags);
+ generate_jif_file_with_tags_from_taglist (taglist, filepath);
+
+ gst_tag_list_free (taglist);
+}
+
+static void
+libexif_check_tags_from_taglist (GstTagList * taglist, const gchar * filepath)
+{
+ ExifData *exif_data;
+ gint i;
+
+ fail_unless (taglist != NULL);
+ exif_data = exif_data_new_from_file (filepath);
+
+ /* iterate over our tag mapping */
+ for (i = 0; i < G_N_ELEMENTS (tag_map); i++) {
+ if (gst_structure_has_field ((GstStructure *) taglist, tag_map[i].gst_tag)) {
+ /* we have added this field to the taglist, check if it was writen in
+ * exif */
+ libexif_check_tag_exists (taglist, i, exif_data);
+ }
+ }
+
+ exif_data_unref (exif_data);
+}
+
+static void
+libexif_check_tags (const gchar * tags, const gchar * filepath)
+{
+ GstTagList *taglist;
+
+ taglist = gst_tag_list_new_from_string (tags);
+ fail_unless (taglist != NULL);
+
+ libexif_check_tags_from_taglist (taglist, filepath);
+
+ gst_tag_list_free (taglist);
+}
+
+GST_START_TEST (test_jifmux_tags)
+{
+ gchar *tmpfile;
+ gchar *tmp;
+ GstTagList *taglist;
+ GstDateTime *datetime;
+ GstBuffer *buffer;
+ GstMapInfo map;
+ gint i;
+
+ gst_tag_register_musicbrainz_tags ();
+
+ tmp = g_strdup_printf ("%s%d", "gst-check-xmp-test-", g_random_int ());
+ tmpfile = g_build_filename (g_get_tmp_dir (), tmp, NULL);
+ g_free (tmp);
+
+ datetime = gst_date_time_new_local_time (2000, 10, 5, 8, 45, 13);
+ buffer = gst_buffer_new_and_alloc (100);
+ gst_buffer_map (buffer, &map, GST_MAP_WRITE);
+ for (i = 0; i < 100; i++) {
+ map.data[i] = i;
+ }
+ gst_buffer_unmap (buffer, &map);
+
+ taglist = gst_tag_list_new (GST_TAG_ARTIST, "some artist",
+ GST_TAG_COPYRIGHT, "My copyright notice",
+ GST_TAG_DEVICE_MANUFACTURER, "MyFavoriteBrand",
+ GST_TAG_DEVICE_MODEL, "123v42.1",
+ GST_TAG_DESCRIPTION, "some description",
+ GST_TAG_APPLICATION_NAME, "jifmux-test v1.2b",
+ GST_TAG_CAPTURING_SHUTTER_SPEED, 1, 30,
+ GST_TAG_CAPTURING_FOCAL_RATIO, 2.0,
+ GST_TAG_CAPTURING_ISO_SPEED, 800, GST_TAG_DATE_TIME, datetime,
+ GST_TAG_CAPTURING_FOCAL_LENGTH, 22.5,
+ GST_TAG_CAPTURING_DIGITAL_ZOOM_RATIO, 5.25,
+ GST_TAG_CAPTURING_EXPOSURE_COMPENSATION, -2.5,
+ GST_TAG_APPLICATION_DATA, buffer,
+ GST_TAG_CAPTURING_FLASH_FIRED, TRUE,
+ GST_TAG_CAPTURING_FLASH_MODE, "auto",
+ GST_TAG_CAPTURING_SOURCE, "dsc",
+ GST_TAG_CAPTURING_METERING_MODE, "multi-spot",
+ GST_TAG_CAPTURING_SHARPNESS, "normal",
+ GST_TAG_CAPTURING_SATURATION, "normal",
+ GST_TAG_CAPTURING_CONTRAST, "normal",
+ GST_TAG_GEO_LOCATION_LATITUDE, -32.375,
+ GST_TAG_GEO_LOCATION_LONGITUDE, 76.0125,
+ GST_TAG_GEO_LOCATION_ELEVATION, 300.85,
+ GST_TAG_GEO_LOCATION_MOVEMENT_SPEED, 3.6,
+ GST_TAG_GEO_LOCATION_MOVEMENT_DIRECTION, 35.4,
+ GST_TAG_GEO_LOCATION_CAPTURE_DIRECTION, 12.345,
+ GST_TAG_IMAGE_HORIZONTAL_PPI, 300.0,
+ GST_TAG_IMAGE_VERTICAL_PPI, 96.0, NULL);
+ gst_date_time_unref (datetime);
+ gst_buffer_unref (buffer);
+ generate_jif_file_with_tags_from_taglist (taglist, tmpfile);
+ libexif_check_tags_from_taglist (taglist, tmpfile);
+ gst_tag_list_free (taglist);
+
+#define IMAGE_ORIENTATION_TAG(t) "taglist," GST_TAG_IMAGE_ORIENTATION "=" t
+ generate_jif_file_with_tags (IMAGE_ORIENTATION_TAG ("rotate-0"), tmpfile);
+ libexif_check_tags (IMAGE_ORIENTATION_TAG ("rotate-0"), tmpfile);
+ generate_jif_file_with_tags (IMAGE_ORIENTATION_TAG ("flip-rotate-0"),
+ tmpfile);
+ libexif_check_tags (IMAGE_ORIENTATION_TAG ("flip-rotate-0"), tmpfile);
+ generate_jif_file_with_tags (IMAGE_ORIENTATION_TAG ("rotate-180"), tmpfile);
+ libexif_check_tags (IMAGE_ORIENTATION_TAG ("rotate-180"), tmpfile);
+ generate_jif_file_with_tags (IMAGE_ORIENTATION_TAG ("flip-rotate-180"),
+ tmpfile);
+ libexif_check_tags (IMAGE_ORIENTATION_TAG ("flip-rotate-180"), tmpfile);
+ generate_jif_file_with_tags (IMAGE_ORIENTATION_TAG
+ ("flip-rotate-270"), tmpfile);
+ libexif_check_tags (IMAGE_ORIENTATION_TAG ("flip-rotate-270"), tmpfile);
+ generate_jif_file_with_tags (IMAGE_ORIENTATION_TAG ("rotate-90"), tmpfile);
+ libexif_check_tags (IMAGE_ORIENTATION_TAG ("rotate-90"), tmpfile);
+ generate_jif_file_with_tags (IMAGE_ORIENTATION_TAG
+ ("flip-rotate-90"), tmpfile);
+ libexif_check_tags (IMAGE_ORIENTATION_TAG ("flip-rotate-90"), tmpfile);
+ generate_jif_file_with_tags (IMAGE_ORIENTATION_TAG ("rotate-270"), tmpfile);
+ libexif_check_tags (IMAGE_ORIENTATION_TAG ("rotate-270"), tmpfile);
+
+#define EXPOSURE_PROGRAM_TAG(t) "taglist," GST_TAG_CAPTURING_EXPOSURE_PROGRAM \
+ "=" t
+ generate_jif_file_with_tags (EXPOSURE_PROGRAM_TAG ("undefined"), tmpfile);
+ libexif_check_tags (EXPOSURE_PROGRAM_TAG ("undefined"), tmpfile);
+ generate_jif_file_with_tags (EXPOSURE_PROGRAM_TAG ("manual"), tmpfile);
+ libexif_check_tags (EXPOSURE_PROGRAM_TAG ("manual"), tmpfile);
+ generate_jif_file_with_tags (EXPOSURE_PROGRAM_TAG ("normal"), tmpfile);
+ libexif_check_tags (EXPOSURE_PROGRAM_TAG ("normal"), tmpfile);
+ generate_jif_file_with_tags (EXPOSURE_PROGRAM_TAG ("aperture-priority"),
+ tmpfile);
+ libexif_check_tags (EXPOSURE_PROGRAM_TAG ("aperture-priority"), tmpfile);
+ generate_jif_file_with_tags (EXPOSURE_PROGRAM_TAG ("shutter-priority"),
+ tmpfile);
+ libexif_check_tags (EXPOSURE_PROGRAM_TAG ("shutter-priority"), tmpfile);
+ generate_jif_file_with_tags (EXPOSURE_PROGRAM_TAG ("creative"), tmpfile);
+ libexif_check_tags (EXPOSURE_PROGRAM_TAG ("creative"), tmpfile);
+ generate_jif_file_with_tags (EXPOSURE_PROGRAM_TAG ("action"), tmpfile);
+ libexif_check_tags (EXPOSURE_PROGRAM_TAG ("action"), tmpfile);
+ generate_jif_file_with_tags (EXPOSURE_PROGRAM_TAG ("portrait"), tmpfile);
+ libexif_check_tags (EXPOSURE_PROGRAM_TAG ("portrait"), tmpfile);
+ generate_jif_file_with_tags (EXPOSURE_PROGRAM_TAG ("landscape"), tmpfile);
+ libexif_check_tags (EXPOSURE_PROGRAM_TAG ("landscape"), tmpfile);
+
+#define EXPOSURE_MODE_TAG(t) "taglist," GST_TAG_CAPTURING_EXPOSURE_MODE "=" t
+ generate_jif_file_with_tags (EXPOSURE_MODE_TAG ("auto-exposure"), tmpfile);
+ libexif_check_tags (EXPOSURE_MODE_TAG ("auto-exposure"), tmpfile);
+ generate_jif_file_with_tags (EXPOSURE_MODE_TAG ("manual-exposure"), tmpfile);
+ libexif_check_tags (EXPOSURE_MODE_TAG ("manual-exposure"), tmpfile);
+ generate_jif_file_with_tags (EXPOSURE_MODE_TAG ("auto-bracket"), tmpfile);
+ libexif_check_tags (EXPOSURE_MODE_TAG ("auto-bracket"), tmpfile);
+
+#define SCENE_CAPTURE_TYPE_TAG(t) "taglist," GST_TAG_CAPTURING_SCENE_CAPTURE_TYPE\
+ "=" t
+ generate_jif_file_with_tags (SCENE_CAPTURE_TYPE_TAG ("standard"), tmpfile);
+ libexif_check_tags (SCENE_CAPTURE_TYPE_TAG ("standard"), tmpfile);
+ generate_jif_file_with_tags (SCENE_CAPTURE_TYPE_TAG ("landscape"), tmpfile);
+ libexif_check_tags (SCENE_CAPTURE_TYPE_TAG ("landscape"), tmpfile);
+ generate_jif_file_with_tags (SCENE_CAPTURE_TYPE_TAG ("portrait"), tmpfile);
+ libexif_check_tags (SCENE_CAPTURE_TYPE_TAG ("portrait"), tmpfile);
+ generate_jif_file_with_tags (SCENE_CAPTURE_TYPE_TAG ("night-scene"), tmpfile);
+ libexif_check_tags (SCENE_CAPTURE_TYPE_TAG ("night-scene"), tmpfile);
+
+#define WHITE_BALANCE_TAG(t) "taglist," GST_TAG_CAPTURING_WHITE_BALANCE "=" t
+ generate_jif_file_with_tags (WHITE_BALANCE_TAG ("auto"), tmpfile);
+ libexif_check_tags (WHITE_BALANCE_TAG ("auto"), tmpfile);
+ generate_jif_file_with_tags (WHITE_BALANCE_TAG ("manual"), tmpfile);
+ libexif_check_tags (WHITE_BALANCE_TAG ("manual"), tmpfile);
+
+#define GAIN_ADJUSTMENT_TAG(t) "taglist," GST_TAG_CAPTURING_GAIN_ADJUSTMENT "=" t
+ generate_jif_file_with_tags (GAIN_ADJUSTMENT_TAG ("none"), tmpfile);
+ libexif_check_tags (GAIN_ADJUSTMENT_TAG ("none"), tmpfile);
+ generate_jif_file_with_tags (GAIN_ADJUSTMENT_TAG ("high-gain-up"), tmpfile);
+ libexif_check_tags (GAIN_ADJUSTMENT_TAG ("high-gain-up"), tmpfile);
+ generate_jif_file_with_tags (GAIN_ADJUSTMENT_TAG ("low-gain-up"), tmpfile);
+ libexif_check_tags (GAIN_ADJUSTMENT_TAG ("low-gain-up"), tmpfile);
+ generate_jif_file_with_tags (GAIN_ADJUSTMENT_TAG ("high-gain-down"), tmpfile);
+ libexif_check_tags (GAIN_ADJUSTMENT_TAG ("high-gain-down"), tmpfile);
+ generate_jif_file_with_tags (GAIN_ADJUSTMENT_TAG ("low-gain-down"), tmpfile);
+ libexif_check_tags (GAIN_ADJUSTMENT_TAG ("low-gain-down"), tmpfile);
+
+#define CONTRAST_TAG(t) "taglist," GST_TAG_CAPTURING_CONTRAST "=" t
+ generate_jif_file_with_tags (CONTRAST_TAG ("normal"), tmpfile);
+ libexif_check_tags (CONTRAST_TAG ("normal"), tmpfile);
+ generate_jif_file_with_tags (CONTRAST_TAG ("soft"), tmpfile);
+ libexif_check_tags (CONTRAST_TAG ("soft"), tmpfile);
+ generate_jif_file_with_tags (CONTRAST_TAG ("hard"), tmpfile);
+ libexif_check_tags (CONTRAST_TAG ("hard"), tmpfile);
+
+#define SATURATION_TAG(t) "taglist," GST_TAG_CAPTURING_SATURATION "=" t
+ generate_jif_file_with_tags (SATURATION_TAG ("normal"), tmpfile);
+ libexif_check_tags (SATURATION_TAG ("normal"), tmpfile);
+ generate_jif_file_with_tags (SATURATION_TAG ("low-saturation"), tmpfile);
+ libexif_check_tags (SATURATION_TAG ("low-saturation"), tmpfile);
+ generate_jif_file_with_tags (SATURATION_TAG ("high-saturation"), tmpfile);
+ libexif_check_tags (SATURATION_TAG ("high-saturation"), tmpfile);
+
+#define SHARPNESS_TAG(t) "taglist," GST_TAG_CAPTURING_SHARPNESS "=" t
+ generate_jif_file_with_tags (SHARPNESS_TAG ("normal"), tmpfile);
+ libexif_check_tags (SHARPNESS_TAG ("normal"), tmpfile);
+ generate_jif_file_with_tags (SHARPNESS_TAG ("soft"), tmpfile);
+ libexif_check_tags (SHARPNESS_TAG ("soft"), tmpfile);
+ generate_jif_file_with_tags (SHARPNESS_TAG ("hard"), tmpfile);
+ libexif_check_tags (SHARPNESS_TAG ("hard"), tmpfile);
+
+#define METERING_MODE_TAG(t) "taglist," GST_TAG_CAPTURING_METERING_MODE "=" t
+ generate_jif_file_with_tags (METERING_MODE_TAG ("unknown"), tmpfile);
+ libexif_check_tags (METERING_MODE_TAG ("unknown"), tmpfile);
+ generate_jif_file_with_tags (METERING_MODE_TAG ("average"), tmpfile);
+ libexif_check_tags (METERING_MODE_TAG ("average"), tmpfile);
+ generate_jif_file_with_tags (METERING_MODE_TAG ("center-weighted-average"),
+ tmpfile);
+ libexif_check_tags (METERING_MODE_TAG ("center-weighted-average"), tmpfile);
+ generate_jif_file_with_tags (METERING_MODE_TAG ("spot"), tmpfile);
+ libexif_check_tags (METERING_MODE_TAG ("spot"), tmpfile);
+ generate_jif_file_with_tags (METERING_MODE_TAG ("multi-spot"), tmpfile);
+ libexif_check_tags (METERING_MODE_TAG ("multi-spot"), tmpfile);
+ generate_jif_file_with_tags (METERING_MODE_TAG ("pattern"), tmpfile);
+ libexif_check_tags (METERING_MODE_TAG ("pattern"), tmpfile);
+ generate_jif_file_with_tags (METERING_MODE_TAG ("partial"), tmpfile);
+ libexif_check_tags (METERING_MODE_TAG ("partial"), tmpfile);
+ generate_jif_file_with_tags (METERING_MODE_TAG ("other"), tmpfile);
+ libexif_check_tags (METERING_MODE_TAG ("other"), tmpfile);
+
+#define FILE_SOURCE_TAG(t) "taglist," GST_TAG_CAPTURING_SOURCE "=" t
+ generate_jif_file_with_tags (FILE_SOURCE_TAG ("dsc"), tmpfile);
+ libexif_check_tags (FILE_SOURCE_TAG ("dsc"), tmpfile);
+ generate_jif_file_with_tags (FILE_SOURCE_TAG ("other"), tmpfile);
+ libexif_check_tags (FILE_SOURCE_TAG ("other"), tmpfile);
+ generate_jif_file_with_tags (FILE_SOURCE_TAG ("reflex-scanner"), tmpfile);
+ libexif_check_tags (FILE_SOURCE_TAG ("reflex-scanner"), tmpfile);
+ generate_jif_file_with_tags (FILE_SOURCE_TAG ("transparent-scanner"),
+ tmpfile);
+ libexif_check_tags (FILE_SOURCE_TAG ("transparent-scanner"), tmpfile);
+
+ g_unlink (tmpfile);
+ g_free (tmpfile);
+}
+
+GST_END_TEST;
+
+#define HAVE_ELEMENT(name) \
+ gst_registry_check_feature_version (gst_registry_get (), name,\
+ GST_VERSION_MAJOR, GST_VERSION_MINOR, 0)
+
+static Suite *
+jifmux_suite (void)
+{
+ Suite *s = suite_create ("jifmux");
+ TCase *tc_chain = tcase_create ("general");
+
+ if (HAVE_ELEMENT ("taginject") && HAVE_ELEMENT ("jpegenc")) {
+ tcase_add_test (tc_chain, test_jifmux_tags);
+ } else {
+ GST_WARNING ("jpegenc or taginject element not available, skipping tests");
+ }
+
+ suite_add_tcase (s, tc_chain);
+
+ return s;
+}
+
+GST_CHECK_MAIN (jifmux);
diff --git a/tests/check/elements/jpegparse.c b/tests/check/elements/jpegparse.c
new file mode 100644
index 00000000..fa8c63ac
--- /dev/null
+++ b/tests/check/elements/jpegparse.c
@@ -0,0 +1,402 @@
+/* GStreamer
+ *
+ * unit test for jpegparse
+ *
+ * Copyright (C) <2009> Arnout Vandecappelle (Essensium/Mind) <arnout@mind.be>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser 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 <unistd.h>
+
+#include <gst/check/gstcheck.h>
+
+/* This test doesn't use actual JPEG data, but some fake data that we know
+ will trigger certain paths in jpegparse. */
+
+guint8 test_data_garbage[] = { 0x00, 0x01, 0xff, 0x32, 0x00, 0xff };
+guint8 test_data_short_frame[] = { 0xff, 0xd8, 0xff, 0xd9 };
+
+guint8 test_data_normal_frame[] = { 0xff, 0xd8, 0xff, 0x12, 0x00, 0x03, 0x33,
+ 0xff, 0xd9
+};
+
+guint8 test_data_entropy[] = { 0xff, 0xd8, 0xff, 0xda, 0x00, 0x04, 0x22, 0x33,
+ 0x44, 0xff, 0x00, 0x55, 0xff, 0x04, 0x00, 0x04, 0x22, 0x33, 0xff, 0xd9
+};
+guint8 test_data_ff[] = { 0xff, 0xff };
+
+guint8 test_data_extra_ff[] = { 0xff, 0xd8, 0xff, 0xff, 0xff, 0x12, 0x00, 0x03,
+ 0x33, 0xff, 0xff, 0xff, 0xd9
+};
+
+guint8 test_data_soi[] = { 0xff, 0xd8 };
+
+guint8 test_data_app1_exif[] = {
+ 0xff, 0xe1,
+ 0x00, 0xd2, /* length = 210 */
+ 0x45, 0x78, 0x69, 0x66, 0x00, /* Exif */
+ 0x00,
+ 0x49, 0x49,
+ 0x2a, 0x00,
+ 0x08,
+ 0x00, 0x00, 0x00,
+ 0x09, /* number of entries */
+ 0x00,
+ 0x0e, 0x01, /* tag 0x10e */
+ 0x02, 0x00, /* type 2 */
+ 0x0b, 0x00, /* count 11 */
+ 0x00, 0x00,
+ 0x7a, /* offset 122 (0x7a) */
+ 0x00, 0x00, 0x00,
+ 0x0f, 0x01, /* tag 0x10f */
+ 0x02, 0x00, /* type 2 */
+ 0x06, 0x00, /* count 6 */
+ 0x00, 0x00,
+ 0x85, /* offset 133 (0x85) */
+ 0x00, 0x00, 0x00,
+ 0x10, 0x01, /* tag 0x110 */
+ 0x02, 0x00, /* type 2 */
+ 0x05, 0x00, /* count 5 */
+ 0x00, 0x00,
+ 0x8b, /* offset 139 (0x8b) */
+ 0x00, 0x00, 0x00,
+ 0x12, 0x01, /* tag 0x112 */
+ 0x03, 0x00, /* type 3 */
+ 0x01, 0x00, /* count 1 */
+ 0x00, 0x00,
+ 0x01, 0x00, 0x30, 0x2c, /* offset (0x2c300001) */
+ 0x1a, 0x01, /* tag 0x11a */
+ 0x05, 0x00, /* type 5 */
+ 0x01, 0x00, /* count 1 */
+ 0x00, 0x00,
+ 0x90, /* offset 144 (0x90) */
+ 0x00, 0x00, 0x00,
+ 0x1b, 0x01, /* tag 0x11b */
+ 0x05, 0x00, /* type 5 */
+ 0x01, 0x00, /* count 1 */
+ 0x00, 0x00,
+ 0x98, /* offset 152 (0x98) */
+ 0x00, 0x00, 0x00,
+ 0x28, 0x01, /* tag 0x128 */
+ 0x03, 0x00, /* type 3 */
+ 0x01, 0x00, /* count 1 */
+ 0x00, 0x00,
+ 0x02, 0x00, 0x31, 0x2f, /* offset (0x2f310002) */
+ 0x31, 0x01, /* tag 0x131 */
+ 0x02, 0x00, /* type 2 */
+ 0x08, 0x00, /* count 8 */
+ 0x00, 0x00,
+ 0xa0, /* offset 160 (0xa0) */
+ 0x00, 0x00, 0x00,
+ 0x32, 0x01, /* tag 0x132 */
+ 0x02, 0x00, /* type 2 */
+ 0x14, 0x00, /* count 20 */
+ 0x00, 0x00,
+ 0xa8, /* offset 168 (0xa8) */
+ 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00,
+ 0x00,
+ /* string */
+ /* 122: */ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x00,
+ /* string (NIKON) */
+ /* 133: */ 0x4e, 0x49, 0x4b, 0x4f, 0x4e, 0x00,
+ /* string (E800) */
+ /* 139: */ 0x45, 0x38, 0x30, 0x30, 0x00,
+ /* 144: */ 0x00, 0x00, 0x80, 0x25, /* / */ 0x00, 0x00, 0x20, 0x00,
+ /* 152: */ 0x00, 0x00, 0x80, 0x25, /* / */ 0x00, 0x00, 0x20, 0x00,
+ /* string (v984-75) */
+ /* 160: */ 0x76, 0x39, 0x38, 0x34, 0x2d, 0x37, 0x35, 0x00,
+ /* string (2001:08:18 21:44:21) */
+ /* 168: */ 0x32, 0x30, 0x30, 0x31, 0x3a, 0x30, 0x38, 0x3a,
+ 0x31, 0x38, 0x20, 0x32, 0x31, 0x3a, 0x34, 0x34,
+ 0x3a, 0x32, 0x31, 0x00,
+
+ 0x1e, 0x21, 0x1f, 0x1e, 0x21, 0x1c, 0x20, 0x21, 0x22, 0x24, 0x24, 0x27,
+ 0x22, 0x20,
+};
+
+guint8 test_data_comment[] = {
+ 0xff, 0xfe,
+ 0x00, 0x08, /* size */
+ /* xxxxx */
+ 0x78, 0x78, 0x78, 0x78, 0x78, 0x00,
+};
+
+guint8 test_data_sof0[] = {
+ 0xff, 0xc0,
+ 0x00, 0x11, /* size */
+ 0x08, /* precision */
+ 0x00, 0x3c, /* width */
+ 0x00, 0x50, /* height */
+ 0x03, /* number of components */
+ 0x01, 0x22, 0x00, /* component 1 */
+ 0x02, 0x11, 0x01, /* component 2 */
+ 0x03, 0x11, 0x01, /* component 3 */
+};
+
+guint8 test_data_eoi[] = { 0xff, 0xd9 };
+
+static GList *
+_make_buffers_in (GList * buffer_in, guint8 * test_data, gsize test_data_size)
+{
+ GstBuffer *buffer;
+ gsize i;
+
+ for (i = 0; i < test_data_size; i++) {
+ buffer =
+ gst_buffer_new_wrapped_full (GST_MEMORY_FLAG_READONLY, test_data + i, 1,
+ 0, 1, NULL, NULL);
+ buffer_in = g_list_append (buffer_in, buffer);
+ }
+ return buffer_in;
+}
+
+#define make_buffers_in(buffer_in, test_data) \
+ _make_buffers_in(buffer_in, test_data, sizeof(test_data))
+
+static GList *
+_make_buffers_out (GList * buffer_out, guint8 * test_data, gsize test_data_size)
+{
+ GstBuffer *buffer;
+
+ buffer =
+ gst_buffer_new_wrapped_full (GST_MEMORY_FLAG_READONLY, test_data,
+ test_data_size, 0, test_data_size, NULL, NULL);
+ buffer_out = g_list_append (buffer_out, buffer);
+
+ return buffer_out;
+}
+
+#define make_buffers_out(buffer_out, test_data) \
+ _make_buffers_out(buffer_out, test_data, sizeof(test_data))
+
+GST_START_TEST (test_parse_single_byte)
+{
+ GList *buffer_in = NULL, *buffer_out = NULL;
+ GstCaps *caps_in, *caps_out;
+
+ caps_in = gst_caps_new_simple ("image/jpeg", "parsed", G_TYPE_BOOLEAN, FALSE,
+ NULL);
+ caps_out = gst_caps_new_simple ("image/jpeg", "parsed", G_TYPE_BOOLEAN, TRUE,
+ "framerate", GST_TYPE_FRACTION, 1, 1, NULL);
+
+ /* Push the data byte by byte, injecting some garbage. */
+ buffer_in = make_buffers_in (buffer_in, test_data_garbage);
+ buffer_in = make_buffers_in (buffer_in, test_data_short_frame);
+ buffer_in = make_buffers_in (buffer_in, test_data_garbage);
+ buffer_in = make_buffers_in (buffer_in, test_data_normal_frame);
+ buffer_in = make_buffers_in (buffer_in, test_data_ff);
+ buffer_in = make_buffers_in (buffer_in, test_data_entropy);
+ buffer_in = make_buffers_in (buffer_in, test_data_extra_ff);
+
+ buffer_out = make_buffers_out (buffer_out, test_data_short_frame);
+ buffer_out = make_buffers_out (buffer_out, test_data_normal_frame);
+ buffer_out = make_buffers_out (buffer_out, test_data_entropy);
+ buffer_out = make_buffers_out (buffer_out, test_data_extra_ff);
+ gst_check_element_push_buffer_list ("jpegparse", buffer_in, caps_in,
+ buffer_out, caps_out, GST_FLOW_OK);
+
+ gst_caps_unref (caps_in);
+ gst_caps_unref (caps_out);
+}
+
+GST_END_TEST;
+
+
+
+GST_START_TEST (test_parse_all_in_one_buf)
+{
+ GList *buffer_in = NULL, *buffer_out = NULL;
+ GstBuffer *buffer = NULL;
+ gsize total_size = 0;
+ gsize offset = 0;
+ GstCaps *caps_in, *caps_out;
+
+ /* Push the data in a single buffer, injecting some garbage. */
+ total_size += sizeof (test_data_garbage);
+ total_size += sizeof (test_data_short_frame);
+ total_size += sizeof (test_data_garbage);
+ total_size += sizeof (test_data_normal_frame);
+ total_size += sizeof (test_data_ff);
+ total_size += sizeof (test_data_entropy);
+ total_size += sizeof (test_data_extra_ff);
+ buffer = gst_buffer_new_and_alloc (total_size);
+ gst_buffer_fill (buffer, offset, test_data_garbage,
+ sizeof (test_data_garbage));
+ offset += sizeof (test_data_garbage);
+ gst_buffer_fill (buffer, offset, test_data_short_frame,
+ sizeof (test_data_short_frame));
+ offset += sizeof (test_data_short_frame);
+ gst_buffer_fill (buffer, offset, test_data_garbage,
+ sizeof (test_data_garbage));
+ offset += sizeof (test_data_garbage);
+ gst_buffer_fill (buffer, offset, test_data_normal_frame,
+ sizeof (test_data_normal_frame));
+ offset += sizeof (test_data_normal_frame);
+ gst_buffer_fill (buffer, offset, test_data_ff, sizeof (test_data_ff));
+ offset += sizeof (test_data_ff);
+ gst_buffer_fill (buffer, offset, test_data_entropy,
+ sizeof (test_data_entropy));
+ offset += sizeof (test_data_entropy);
+ gst_buffer_fill (buffer, offset, test_data_extra_ff,
+ sizeof (test_data_extra_ff));
+ offset += sizeof (test_data_extra_ff);
+
+ caps_in = gst_caps_new_simple ("image/jpeg", "parsed",
+ G_TYPE_BOOLEAN, FALSE, NULL);
+ GST_LOG ("Pushing single buffer of %u bytes.", (guint) total_size);
+ buffer_in = g_list_append (buffer_in, buffer);
+
+ caps_out = gst_caps_new_simple ("image/jpeg", "parsed", G_TYPE_BOOLEAN, TRUE,
+ "framerate", GST_TYPE_FRACTION, 1, 1, NULL);
+ buffer_out = make_buffers_out (buffer_out, test_data_short_frame);
+ buffer_out = make_buffers_out (buffer_out, test_data_normal_frame);
+ buffer_out = make_buffers_out (buffer_out, test_data_entropy);
+ buffer_out = make_buffers_out (buffer_out, test_data_extra_ff);
+
+ gst_check_element_push_buffer_list ("jpegparse", buffer_in, caps_in,
+ buffer_out, caps_out, GST_FLOW_OK);
+
+ gst_caps_unref (caps_in);
+ gst_caps_unref (caps_out);
+}
+
+GST_END_TEST;
+
+static inline GstBuffer *
+make_my_input_buffer (guint8 * test_data_header, gsize test_data_size)
+{
+ GstBuffer *buffer;
+ gsize total_size = 0, offset = 0;
+
+ total_size += sizeof (test_data_soi);
+ total_size += test_data_size;
+ total_size += sizeof (test_data_sof0);
+ total_size += sizeof (test_data_eoi);
+
+ buffer = gst_buffer_new_and_alloc (total_size);
+
+ gst_buffer_fill (buffer, offset, test_data_soi, sizeof (test_data_soi));
+ offset += sizeof (test_data_soi);
+ gst_buffer_fill (buffer, offset, test_data_header, test_data_size);
+ offset += test_data_size;
+ gst_buffer_fill (buffer, offset, test_data_sof0, sizeof (test_data_sof0));
+ offset += sizeof (test_data_sof0);
+ gst_buffer_fill (buffer, offset, test_data_eoi, sizeof (test_data_eoi));
+ offset += sizeof (test_data_eoi);
+
+ return buffer;
+}
+
+static inline GstBuffer *
+make_my_output_buffer (GstBuffer * buffer_in)
+{
+ GstBuffer *buffer;
+ GstMapInfo map;
+
+ buffer = gst_buffer_new ();
+ gst_buffer_map (buffer_in, &map, GST_MAP_READ);
+ gst_buffer_fill (buffer, 0, map.data, map.size);
+ gst_buffer_unmap (buffer_in, &map);
+
+ return buffer;
+}
+
+
+GST_START_TEST (test_parse_app1_exif)
+{
+ GstBuffer *buffer_in, *buffer_out;
+ GstCaps *caps_in, *caps_out;
+
+ caps_in = gst_caps_new_simple ("image/jpeg", "parsed",
+ G_TYPE_BOOLEAN, FALSE, NULL);
+
+ caps_out = gst_caps_new_simple ("image/jpeg", "parsed", G_TYPE_BOOLEAN, TRUE,
+ "framerate", GST_TYPE_FRACTION, 1, 1, "format", G_TYPE_STRING,
+ "I420", "interlaced", G_TYPE_BOOLEAN, FALSE,
+ "width", G_TYPE_INT, 80, "height", G_TYPE_INT, 60, NULL);
+
+ buffer_in = make_my_input_buffer (test_data_app1_exif,
+ sizeof (test_data_app1_exif));
+ buffer_out = make_my_output_buffer (buffer_in);
+
+ gst_check_element_push_buffer ("jpegparse", buffer_in, caps_in, buffer_out,
+ caps_out);
+
+ gst_caps_unref (caps_in);
+ gst_caps_unref (caps_out);
+}
+
+GST_END_TEST;
+
+GST_START_TEST (test_parse_comment)
+{
+ GstBuffer *buffer_in, *buffer_out;
+ GstCaps *caps_in, *caps_out;
+
+ caps_in = gst_caps_new_simple ("image/jpeg", "parsed",
+ G_TYPE_BOOLEAN, FALSE, NULL);
+
+ caps_out = gst_caps_new_simple ("image/jpeg", "parsed", G_TYPE_BOOLEAN, TRUE,
+ "framerate", GST_TYPE_FRACTION, 1, 1, "format", G_TYPE_STRING,
+ "I420", "interlaced", G_TYPE_BOOLEAN, FALSE,
+ "width", G_TYPE_INT, 80, "height", G_TYPE_INT, 60, NULL);
+
+ buffer_in = make_my_input_buffer (test_data_comment,
+ sizeof (test_data_comment));
+ buffer_out = make_my_output_buffer (buffer_in);
+
+ gst_check_element_push_buffer ("jpegparse", buffer_in, caps_in, buffer_out,
+ caps_out);
+
+ gst_caps_unref (caps_in);
+ gst_caps_unref (caps_out);
+}
+
+GST_END_TEST;
+
+static Suite *
+jpegparse_suite (void)
+{
+ Suite *s = suite_create ("jpegparse");
+ TCase *tc_chain = tcase_create ("jpegparse");
+
+ suite_add_tcase (s, tc_chain);
+ tcase_add_test (tc_chain, test_parse_single_byte);
+ tcase_add_test (tc_chain, test_parse_all_in_one_buf);
+ tcase_add_test (tc_chain, test_parse_app1_exif);
+ tcase_add_test (tc_chain, test_parse_comment);
+
+ return s;
+}
+
+int
+main (int argc, char **argv)
+{
+ int nf;
+
+ Suite *s = jpegparse_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/kate.c b/tests/check/elements/kate.c
new file mode 100644
index 00000000..d1d9218b
--- /dev/null
+++ b/tests/check/elements/kate.c
@@ -0,0 +1,858 @@
+/* GStreamer
+ *
+ * unit test for kate
+ *
+ * Copyright (C) <2007> Stefan Kost <ensonic@users.sf.net>
+ * Copyright (C) <2008> ogg.k.ogg.k <ogg.k.ogg.k@googlemail.com>
+ *
+ * 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 <unistd.h>
+
+#include <gst/check/gstcheck.h>
+#include <gst/base/gsttypefindhelper.h>
+
+
+static const guint8 kate_header_0x80[64] = {
+ 0x80, 0x6b, 0x61, 0x74, 0x65, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x09, 0x00, 0x00, 0x00, 0x20, /* .kate...... ... */
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe8, 0x03, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, /* ................ */
+ 0x65, 0x6e, 0x5f, 0x47, 0x42, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* en_GB........... */
+ 0x6e, 0x6f, 0x6e, 0x65, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* none............ */
+};
+
+static const guint8 kate_header_0x81[53] = {
+ 0x81, 0x6b, 0x61, 0x74, 0x65, 0x00, 0x00, 0x00, 0x00, 0x15, 0x00, 0x00, 0x00, 0x6c, 0x69, 0x62, /* .kate........lib */
+ 0x6b, 0x61, 0x74, 0x65, 0x20, 0x30, 0x2e, 0x31, 0x2e, 0x30, 0x20, 0x28, 0x54, 0x69, 0x67, 0x65, /* kate 0.1.0 (Tige */
+ 0x72, 0x29, 0x01, 0x00, 0x00, 0x00, 0x0b, 0x00, 0x00, 0x00, 0x54, 0x49, 0x54, 0x4c, 0x45, 0x3d, /* r)........TITLE= */
+ 0x54, 0x69, 0x67, 0x65, 0x72, /* Tiger */
+};
+
+static const guint8 kate_header_0x8x[10] = {
+ 0x80, 0x6b, 0x61, 0x74, 0x65, 0x00, 0x00, 0x00, 0x00
+};
+
+static const guint8 kate_header_0x88[11] = {
+ 0x88, 0x6b, 0x61, 0x74, 0x65, 0x00, 0x00, 0x00, 0x00, 0x00
+};
+
+static const guint8 kate_header_0x00[45] = {
+ 0x00, 0xe8, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xd0, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, /* ................ */
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0e, 0x00, 0x00, 0x00, 0x70, 0x6c, 0x61, /* .............pla */
+ 0x69, 0x6e, 0x20, 0x6f, 0x6c, 0x64, 0x20, 0x74, 0x65, 0x78, 0x74, 0x08, 0x00 /* in old text.. */
+};
+
+static const guint8 kate_header_0x01[1] = {
+ 0x01
+};
+
+static const guint8 kate_header_0x7f[1] = {
+ 0x7f
+};
+
+static const unsigned char kate_spu[] = {
+ 0x00, 0x1b, /* size */
+ 0x00, 0x06, /* commands at offset 6 */
+ 0x45, /* first line data - 2 pixels of colors 0 and 1 */
+ 0x76, /* first line data - 2 pixels of colors 3 and 2 */
+ 0x00, 0x00, /* timestamp */
+ 0x00, 0x06, /* link to next command sequence - points back to the current one to mark no more */
+ 0x06, 0x00, 0x04, 0x00, 0x05, /* pointers to data */
+ 0x05, 0x00, 0x30, 0x04, 0x00, 0x10, 0x02, /* area: 3x1 -> 4x2 */
+ 0x04, 0x0f, 0xff, /* alpha: color 0 transparent, all others opaque */
+ 0x01, /* show */
+ 0xff /* end */
+};
+
+/* A lot of these taken from the vorbisdec test */
+
+/* For ease of programming we use globals to keep refs for our floating
+ * src and sink pads we create; otherwise we always have to do get_pad,
+ * get_peer, and then remove references in every test function */
+static GstPad *mydecsrcpad, *mydecsinkpad;
+static GstPad *myencsrcpad, *myencsinkpad;
+static GstPad *myparsesrcpad, *myparsesinkpad;
+static GstPad *mytagsrcpad, *mytagsinkpad;
+
+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_ANY);
+
+static GstElement *
+setup_katedec (void)
+{
+ GstElement *katedec;
+
+ GST_DEBUG ("setup_katedec");
+ katedec = gst_check_setup_element ("katedec");
+ mydecsrcpad = gst_check_setup_src_pad (katedec, &srctemplate, NULL);
+ mydecsinkpad = gst_check_setup_sink_pad (katedec, &sinktemplate, NULL);
+ gst_pad_set_active (mydecsrcpad, TRUE);
+ gst_pad_set_active (mydecsinkpad, TRUE);
+
+ return katedec;
+}
+
+static void
+cleanup_katedec (GstElement * katedec)
+{
+ GST_DEBUG ("cleanup_katedec");
+ gst_element_set_state (katedec, GST_STATE_NULL);
+
+ gst_pad_set_active (mydecsrcpad, FALSE);
+ gst_pad_set_active (mydecsinkpad, FALSE);
+ gst_check_teardown_src_pad (katedec);
+ gst_check_teardown_sink_pad (katedec);
+ gst_check_teardown_element (katedec);
+}
+
+static GstElement *
+setup_kateenc (void)
+{
+ GstElement *kateenc;
+
+ GST_DEBUG ("setup_kateenc");
+ kateenc = gst_check_setup_element ("kateenc");
+ myencsrcpad = gst_check_setup_src_pad (kateenc, &srctemplate, NULL);
+ myencsinkpad = gst_check_setup_sink_pad (kateenc, &sinktemplate, NULL);
+ gst_pad_set_active (myencsrcpad, TRUE);
+ gst_pad_set_active (myencsinkpad, TRUE);
+
+ return kateenc;
+}
+
+static void
+cleanup_kateenc (GstElement * kateenc)
+{
+ GST_DEBUG ("cleanup_kateenc");
+ gst_element_set_state (kateenc, GST_STATE_NULL);
+
+ gst_pad_set_active (myencsrcpad, FALSE);
+ gst_pad_set_active (myencsinkpad, FALSE);
+ gst_check_teardown_src_pad (kateenc);
+ gst_check_teardown_sink_pad (kateenc);
+ gst_check_teardown_element (kateenc);
+}
+
+static GstElement *
+setup_kateparse (void)
+{
+ GstElement *kateparse;
+
+ GST_DEBUG ("setup_kateparse");
+ kateparse = gst_check_setup_element ("kateparse");
+ myparsesrcpad = gst_check_setup_src_pad (kateparse, &srctemplate, NULL);
+ myparsesinkpad = gst_check_setup_sink_pad (kateparse, &sinktemplate, NULL);
+ gst_pad_set_active (myparsesrcpad, TRUE);
+ gst_pad_set_active (myparsesinkpad, TRUE);
+
+ return kateparse;
+}
+
+static void
+cleanup_kateparse (GstElement * kateparse)
+{
+ GST_DEBUG ("cleanup_kateparse");
+ gst_element_set_state (kateparse, GST_STATE_NULL);
+
+ gst_pad_set_active (myparsesrcpad, FALSE);
+ gst_pad_set_active (myparsesinkpad, FALSE);
+ gst_check_teardown_src_pad (kateparse);
+ gst_check_teardown_sink_pad (kateparse);
+ gst_check_teardown_element (kateparse);
+}
+
+static GstElement *
+setup_katetag (void)
+{
+ GstElement *katetag;
+
+ GST_DEBUG ("setup_katetag");
+ katetag = gst_check_setup_element ("katetag");
+ mytagsrcpad = gst_check_setup_src_pad (katetag, &srctemplate, NULL);
+ mytagsinkpad = gst_check_setup_sink_pad (katetag, &sinktemplate, NULL);
+ gst_pad_set_active (mytagsrcpad, TRUE);
+ gst_pad_set_active (mytagsinkpad, TRUE);
+
+ return katetag;
+}
+
+static void
+cleanup_katetag (GstElement * katetag)
+{
+ GST_DEBUG ("cleanup_katetag");
+ gst_element_set_state (katetag, GST_STATE_NULL);
+
+ gst_pad_set_active (mytagsrcpad, FALSE);
+ gst_pad_set_active (mytagsinkpad, FALSE);
+ gst_check_teardown_src_pad (katetag);
+ gst_check_teardown_sink_pad (katetag);
+ gst_check_teardown_element (katetag);
+}
+
+static void
+check_buffers (guint expected, gboolean headers_in_caps)
+{
+ GstBuffer *outbuffer;
+ guint i, num_buffers;
+ const int num_headers = 9;
+ unsigned char packet_type;
+
+ /* check buffers are the type we expect */
+ num_buffers = g_list_length (buffers);
+ fail_unless (num_buffers >= num_headers + expected); /* at least 9 headers, plus a variable number of data packets */
+ for (i = 0; i < num_buffers; ++i) {
+ outbuffer = GST_BUFFER (buffers->data);
+ fail_if (outbuffer == NULL);
+ fail_if (GST_BUFFER_SIZE (outbuffer) == 0);
+
+ if (i < num_headers) {
+ /* different headers packets */
+ packet_type = (0x80 | i);
+ fail_unless (GST_BUFFER_DATA (outbuffer)[0] == packet_type);
+ /* headers could be in caps, so would have an extra ref */
+ } else if (i == num_buffers - 1) {
+ /* eos data packet */
+ packet_type = 0x7f;
+ fail_unless (GST_BUFFER_DATA (outbuffer)[0] == packet_type);
+ } else {
+ /* data packet */
+ packet_type = 0;
+ fail_unless (GST_BUFFER_DATA (outbuffer)[0] >= 0
+ && GST_BUFFER_DATA (outbuffer)[0] < 0x7f);
+ }
+
+ buffers = g_list_remove (buffers, outbuffer);
+
+ ASSERT_BUFFER_REFCOUNT (outbuffer, "outbuffer", 1);
+ gst_buffer_unref (outbuffer);
+ outbuffer = NULL;
+ }
+}
+
+GST_START_TEST (test_kate_typefind)
+{
+ GstTypeFindProbability prob;
+ const gchar *type;
+ GstBuffer *buf;
+ GstCaps *caps = NULL;
+
+ buf = gst_buffer_new ();
+ GST_BUFFER_DATA (buf) = (guint8 *) kate_header_0x80;
+ GST_BUFFER_SIZE (buf) = sizeof (kate_header_0x80);
+ GST_BUFFER_OFFSET (buf) = 0;
+
+ caps = gst_type_find_helper_for_buffer (NULL, buf, &prob);
+ fail_unless (caps != NULL);
+ GST_LOG ("Found type: %" GST_PTR_FORMAT, caps);
+
+ type = gst_structure_get_name (gst_caps_get_structure (caps, 0));
+ fail_unless_equals_string (type, "application/x-kate");
+ fail_unless (prob > GST_TYPE_FIND_MINIMUM && prob <= GST_TYPE_FIND_MAXIMUM);
+
+ gst_buffer_unref (buf);
+ gst_caps_unref (caps);
+}
+
+GST_END_TEST;
+
+GST_START_TEST (test_kate_empty_identification_header)
+{
+ GstElement *katedec;
+ GstBuffer *inbuffer;
+ GstBus *bus;
+
+ katedec = setup_katedec ();
+ bus = gst_bus_new ();
+
+ fail_unless (gst_element_set_state (katedec,
+ GST_STATE_PLAYING) == GST_STATE_CHANGE_SUCCESS,
+ "could not set to playing");
+
+ inbuffer = gst_buffer_new_and_alloc (0);
+ ASSERT_BUFFER_REFCOUNT (inbuffer, "inbuffer", 1);
+
+ /* set a bus here so we avoid getting state change messages */
+ gst_element_set_bus (katedec, bus);
+
+ fail_unless_equals_int (gst_pad_push (mydecsrcpad, inbuffer), GST_FLOW_ERROR);
+ /* ... but it ends up being collected on the global buffer list */
+ fail_unless_equals_int (g_list_length (buffers), 0);
+
+ gst_element_set_bus (katedec, NULL);
+
+ /* cleanup */
+ gst_object_unref (GST_OBJECT (bus));
+ cleanup_katedec (katedec);
+}
+
+GST_END_TEST;
+
+/* FIXME: also tests comment header */
+GST_START_TEST (test_kate_identification_header)
+{
+ GstElement *katedec;
+ GstBuffer *inbuffer;
+ GstBus *bus;
+ GstMessage *message;
+ GstTagList *tag_list;
+ gchar *language;
+ gchar *title;
+
+ katedec = setup_katedec ();
+ fail_unless (gst_element_set_state (katedec,
+ GST_STATE_PLAYING) == GST_STATE_CHANGE_SUCCESS,
+ "could not set to playing");
+ bus = gst_bus_new ();
+
+ inbuffer = gst_buffer_new_and_alloc (sizeof (kate_header_0x80));
+ memcpy (GST_BUFFER_DATA (inbuffer), kate_header_0x80,
+ sizeof (kate_header_0x80));
+ ASSERT_BUFFER_REFCOUNT (inbuffer, "inbuffer", 1);
+ gst_buffer_ref (inbuffer);
+
+ gst_element_set_bus (katedec, bus);
+ /* pushing gives away my reference ... */
+ fail_unless (gst_pad_push (mydecsrcpad, inbuffer) == GST_FLOW_OK);
+ /* ... and nothing ends up on the global buffer list */
+ ASSERT_BUFFER_REFCOUNT (inbuffer, "inbuffer", 1);
+ gst_buffer_unref (inbuffer);
+ fail_unless (g_list_length (buffers) == 0);
+
+ inbuffer = gst_buffer_new_and_alloc (sizeof (kate_header_0x81));
+ memcpy (GST_BUFFER_DATA (inbuffer), kate_header_0x81,
+ sizeof (kate_header_0x81));
+ ASSERT_BUFFER_REFCOUNT (inbuffer, "inbuffer", 1);
+ gst_buffer_ref (inbuffer);
+
+ /* pushing gives away my reference ... */
+ fail_unless (gst_pad_push (mydecsrcpad, inbuffer) == GST_FLOW_OK);
+ /* ... and nothing ends up on the global buffer list */
+ ASSERT_BUFFER_REFCOUNT (inbuffer, "inbuffer", 1);
+ gst_buffer_unref (inbuffer);
+ fail_unless (g_list_length (buffers) == 0);
+ /* there's a tag message waiting */
+ fail_if ((message = gst_bus_pop (bus)) == NULL);
+ gst_message_parse_tag (message, &tag_list);
+ fail_unless_equals_int (gst_tag_list_get_tag_size (tag_list,
+ GST_TAG_LANGUAGE_CODE), 1);
+ fail_unless (gst_tag_list_get_string (tag_list, GST_TAG_LANGUAGE_CODE,
+ &language));
+ fail_unless_equals_string (language, "en");
+ g_free (language);
+ fail_unless_equals_int (gst_tag_list_get_tag_size (tag_list, "title"), 1);
+ fail_unless (gst_tag_list_get_string (tag_list, GST_TAG_TITLE, &title));
+ fail_unless_equals_string (title, "Tiger");
+ g_free (title);
+ gst_tag_list_free (tag_list);
+ gst_message_unref (message);
+
+ /* cleanup */
+ gst_bus_set_flushing (bus, TRUE);
+ gst_element_set_bus (katedec, NULL);
+ gst_object_unref (GST_OBJECT (bus));
+ cleanup_katedec (katedec);
+}
+
+GST_END_TEST;
+
+GST_START_TEST (test_kate_encode_nothing)
+{
+ GstElement *kateenc;
+
+ kateenc = setup_kateenc ();
+ fail_unless (gst_element_set_state (kateenc,
+ GST_STATE_PLAYING) == GST_STATE_CHANGE_SUCCESS,
+ "could not set to playing");
+
+ fail_unless (gst_pad_push_event (myencsrcpad, gst_event_new_eos ()) == TRUE);
+
+ fail_unless (gst_element_set_state (kateenc,
+ GST_STATE_READY) == GST_STATE_CHANGE_SUCCESS,
+ "could not set to ready");
+
+ /* cleanup */
+ cleanup_kateenc (kateenc);
+}
+
+GST_END_TEST;
+
+GST_START_TEST (test_kate_encode_empty)
+{
+ GstElement *kateenc;
+ GstBuffer *inbuffer;
+ GstBus *bus;
+ GstCaps *caps;
+
+ kateenc = setup_kateenc ();
+ fail_unless (gst_element_set_state (kateenc,
+ GST_STATE_PLAYING) == GST_STATE_CHANGE_SUCCESS,
+ "could not set to playing");
+ bus = gst_bus_new ();
+
+ inbuffer = gst_buffer_new_and_alloc (0);
+ GST_BUFFER_TIMESTAMP (inbuffer) = GST_BUFFER_OFFSET (inbuffer) =
+ 1 * GST_SECOND;
+ GST_BUFFER_DURATION (inbuffer) = 5 * GST_SECOND;
+ ASSERT_BUFFER_REFCOUNT (inbuffer, "inbuffer", 1);
+
+ caps = gst_caps_from_string ("text/plain");
+ fail_unless (caps != NULL);
+ gst_buffer_set_caps (inbuffer, caps);
+ gst_caps_unref (caps);
+
+ gst_element_set_bus (kateenc, bus);
+ /* pushing gives away my reference ... */
+ fail_unless (gst_pad_push (myencsrcpad, inbuffer) == GST_FLOW_ERROR);
+
+ fail_unless (gst_pad_push_event (myencsrcpad, gst_event_new_eos ()) == TRUE);
+
+ fail_unless (gst_element_set_state (kateenc,
+ GST_STATE_READY) == GST_STATE_CHANGE_SUCCESS,
+ "could not set to ready");
+
+ gst_element_set_bus (kateenc, NULL);
+
+ /* cleanup */
+ gst_object_unref (GST_OBJECT (bus));
+ cleanup_kateenc (kateenc);
+}
+
+GST_END_TEST;
+
+GST_START_TEST (test_kate_encode_simple)
+{
+ GstElement *kateenc;
+ GstBuffer *inbuffer;
+ GstBus *bus;
+ const gchar *test_string = "";
+ GstCaps *caps;
+
+ kateenc = setup_kateenc ();
+ g_object_set (kateenc, "category", "subtitles", NULL);
+
+ fail_unless (gst_element_set_state (kateenc,
+ GST_STATE_PLAYING) == GST_STATE_CHANGE_SUCCESS,
+ "could not set to playing");
+ bus = gst_bus_new ();
+
+ inbuffer = gst_buffer_new_and_alloc (strlen (test_string) + 1);
+ memcpy (GST_BUFFER_DATA (inbuffer), test_string, strlen (test_string) + 1);
+ GST_BUFFER_TIMESTAMP (inbuffer) = GST_BUFFER_OFFSET (inbuffer) =
+ 1 * GST_SECOND;
+ GST_BUFFER_DURATION (inbuffer) = 5 * GST_SECOND;
+ ASSERT_BUFFER_REFCOUNT (inbuffer, "inbuffer", 1);
+
+ caps = gst_caps_from_string ("text/plain");
+ fail_unless (caps != NULL);
+ gst_buffer_set_caps (inbuffer, caps);
+ gst_caps_unref (caps);
+ gst_buffer_ref (inbuffer);
+
+ gst_element_set_bus (kateenc, bus);
+ /* pushing gives away my reference ... */
+ fail_unless (gst_pad_push (myencsrcpad, inbuffer) == GST_FLOW_OK);
+ /* ... and nothing ends up on the global buffer list */
+ ASSERT_BUFFER_REFCOUNT (inbuffer, "inbuffer", 1);
+ gst_buffer_unref (inbuffer);
+ fail_unless (gst_pad_push_event (myencsrcpad, gst_event_new_eos ()) == TRUE);
+
+ fail_unless (gst_element_set_state (kateenc,
+ GST_STATE_READY) == GST_STATE_CHANGE_SUCCESS,
+ "could not set to ready");
+
+ /* at least one data packet and one EOS packet should have been emitted */
+ check_buffers (1 + 1, FALSE);
+
+ /* cleanup */
+ gst_bus_set_flushing (bus, TRUE);
+ gst_element_set_bus (kateenc, NULL);
+ gst_object_unref (GST_OBJECT (bus));
+ cleanup_kateenc (kateenc);
+ g_list_free (buffers);
+}
+
+GST_END_TEST;
+
+GST_START_TEST (test_kate_encode_spu)
+{
+ GstElement *kateenc;
+ GstBuffer *inbuffer;
+ GstBus *bus;
+ GstCaps *caps;
+
+ kateenc = setup_kateenc ();
+ g_object_set (kateenc, "category", "spu-subtitles", NULL);
+
+ fail_unless (gst_element_set_state (kateenc,
+ GST_STATE_PLAYING) == GST_STATE_CHANGE_SUCCESS,
+ "could not set to playing");
+ bus = gst_bus_new ();
+
+ inbuffer = gst_buffer_new_and_alloc (sizeof (kate_spu));
+ memcpy (GST_BUFFER_DATA (inbuffer), kate_spu, sizeof (kate_spu));
+ GST_BUFFER_TIMESTAMP (inbuffer) = GST_BUFFER_OFFSET (inbuffer) =
+ 1 * GST_SECOND;
+ GST_BUFFER_DURATION (inbuffer) = 5 * GST_SECOND;
+ ASSERT_BUFFER_REFCOUNT (inbuffer, "inbuffer", 1);
+
+ caps = gst_caps_from_string ("video/x-dvd-subpicture");
+ fail_unless (caps != NULL);
+ gst_buffer_set_caps (inbuffer, caps);
+ gst_caps_unref (caps);
+ gst_buffer_ref (inbuffer);
+
+ gst_element_set_bus (kateenc, bus);
+ /* pushing gives away my reference ... */
+ fail_unless_equals_int (gst_pad_push (myencsrcpad, inbuffer), GST_FLOW_OK);
+ /* ... and nothing ends up on the global buffer list */
+ ASSERT_BUFFER_REFCOUNT (inbuffer, "inbuffer", 1);
+ gst_buffer_unref (inbuffer);
+ fail_unless (gst_pad_push_event (myencsrcpad, gst_event_new_eos ()) == TRUE);
+
+ fail_unless (gst_element_set_state (kateenc,
+ GST_STATE_READY) == GST_STATE_CHANGE_SUCCESS,
+ "could not set to ready");
+
+ /* at least one data packet and one EOS packet should have been emitted */
+ check_buffers (2, FALSE);
+
+ /* cleanup */
+ gst_bus_set_flushing (bus, TRUE);
+ gst_element_set_bus (kateenc, NULL);
+ gst_object_unref (GST_OBJECT (bus));
+ cleanup_kateenc (kateenc);
+ g_list_free (buffers);
+}
+
+GST_END_TEST;
+
+GST_START_TEST (test_kate_encode_keepalives)
+{
+ GstElement *kateenc;
+ GstBus *bus;
+ guint i, round;
+ enum
+ { n_keepalives = 1000 };
+ static const struct
+ {
+ gdouble keepalive_min_time;
+ gint packets;
+ } cfg[3] = {
+ {
+ 0.5, n_keepalives}, {
+ 2.0, n_keepalives / 2}, {
+ 5.0, n_keepalives / 5},};
+
+ for (round = 0; round < 3; ++round) {
+ kateenc = setup_kateenc ();
+ /* doesn't matter here, since we never send a packet */
+ g_object_set (kateenc, "category", "subtitles", NULL);
+ fail_unless (gst_element_set_state (kateenc,
+ GST_STATE_PLAYING) == GST_STATE_CHANGE_SUCCESS,
+ "could not set to playing");
+ bus = gst_bus_new ();
+
+ gst_element_set_bus (kateenc, bus);
+
+ g_object_set (kateenc, "keepalive-min-time", cfg[round].keepalive_min_time,
+ NULL);
+
+ /* the second one here should not emit a keepalive since the time since last packet
+ is less than the keepalive delay */
+ for (i = 1; i <= n_keepalives; ++i) {
+ gint64 t = i * GST_SECOND;
+ fail_unless (gst_pad_push_event (myencsrcpad,
+ gst_event_new_new_segment (TRUE, 1.0, GST_FORMAT_TIME, t, -1,
+ 0)) == TRUE);
+ }
+
+ fail_unless (gst_pad_push_event (myencsrcpad,
+ gst_event_new_eos ()) == TRUE);
+
+ fail_unless (gst_element_set_state (kateenc,
+ GST_STATE_READY) == GST_STATE_CHANGE_SUCCESS,
+ "could not set to ready");
+
+ /* at least a number data packet and an EOS packet should have been emitted */
+ check_buffers (cfg[round].packets + 1, FALSE);
+
+ /* cleanup */
+ gst_bus_set_flushing (bus, TRUE);
+ gst_element_set_bus (kateenc, NULL);
+ gst_object_unref (GST_OBJECT (bus));
+ cleanup_kateenc (kateenc);
+ g_list_free (buffers);
+ }
+}
+
+GST_END_TEST;
+
+static void
+test_kate_send_headers (GstPad * pad)
+{
+ GstBuffer *inbuffer;
+ GstCaps *caps;
+ int i;
+
+ caps = gst_caps_new_simple ("subtitle/x-kate", NULL);
+
+ /* push headers */
+ inbuffer = gst_buffer_new ();
+ gst_buffer_set_caps (inbuffer, caps);
+ GST_BUFFER_DATA (inbuffer) = (guint8 *) kate_header_0x80;
+ GST_BUFFER_SIZE (inbuffer) = sizeof (kate_header_0x80);
+ GST_BUFFER_OFFSET (inbuffer) = GST_BUFFER_OFFSET_END (inbuffer) = 0;
+ fail_unless_equals_int (gst_pad_push (pad, inbuffer), GST_FLOW_OK);
+
+ inbuffer = gst_buffer_new ();
+ gst_buffer_set_caps (inbuffer, caps);
+ GST_BUFFER_DATA (inbuffer) = (guint8 *) kate_header_0x81;
+ GST_BUFFER_SIZE (inbuffer) = sizeof (kate_header_0x81);
+ GST_BUFFER_OFFSET (inbuffer) = GST_BUFFER_OFFSET_END (inbuffer) = 0;
+ fail_unless_equals_int (gst_pad_push (pad, inbuffer), GST_FLOW_OK);
+
+ for (i = 2; i < 8; ++i) {
+ inbuffer = gst_buffer_new_and_alloc (sizeof (kate_header_0x8x));
+ gst_buffer_set_caps (inbuffer, caps);
+ memcpy (GST_BUFFER_DATA (inbuffer), (guint8 *) kate_header_0x8x,
+ sizeof (kate_header_0x8x));
+ GST_BUFFER_DATA (inbuffer)[0] = 0x80 | i;
+ GST_BUFFER_OFFSET (inbuffer) = GST_BUFFER_OFFSET_END (inbuffer) = 0;
+ fail_unless_equals_int (gst_pad_push (pad, inbuffer), GST_FLOW_OK);
+ }
+
+ inbuffer = gst_buffer_new ();
+ gst_buffer_set_caps (inbuffer, caps);
+ GST_BUFFER_DATA (inbuffer) = (guint8 *) kate_header_0x88;
+ GST_BUFFER_SIZE (inbuffer) = sizeof (kate_header_0x88);
+ GST_BUFFER_OFFSET (inbuffer) = GST_BUFFER_OFFSET_END (inbuffer) = 0;
+ fail_unless_equals_int (gst_pad_push (pad, inbuffer), GST_FLOW_OK);
+
+ gst_caps_unref (caps);
+}
+
+GST_START_TEST (test_kate_parse)
+{
+ GstElement *kateparse;
+ GstBuffer *inbuffer;
+ GstBus *bus;
+
+ kateparse = setup_kateparse ();
+ fail_unless (gst_element_set_state (kateparse,
+ GST_STATE_PLAYING) == GST_STATE_CHANGE_SUCCESS,
+ "could not set to playing");
+ bus = gst_bus_new ();
+
+ gst_element_set_bus (kateparse, bus);
+
+ test_kate_send_headers (myparsesrcpad);
+
+ /* push a text packet */
+ inbuffer = gst_buffer_new ();
+ GST_BUFFER_DATA (inbuffer) = (guint8 *) kate_header_0x00;
+ GST_BUFFER_SIZE (inbuffer) = sizeof (kate_header_0x00);
+ GST_BUFFER_TIMESTAMP (inbuffer) = GST_BUFFER_OFFSET (inbuffer) =
+ 1 * GST_SECOND;
+ GST_BUFFER_DURATION (inbuffer) = 5 * GST_SECOND;
+ GST_BUFFER_OFFSET_END (inbuffer) = (GST_BUFFER_TIMESTAMP (inbuffer) << 32); /* granpos */
+ fail_unless_equals_int (gst_pad_push (myparsesrcpad, inbuffer), GST_FLOW_OK);
+
+ /* push a eos packet */
+ inbuffer = gst_buffer_new ();
+ GST_BUFFER_DATA (inbuffer) = (guint8 *) kate_header_0x7f;
+ GST_BUFFER_SIZE (inbuffer) = sizeof (kate_header_0x7f);
+ GST_BUFFER_TIMESTAMP (inbuffer) = GST_BUFFER_OFFSET (inbuffer) =
+ 6 * GST_SECOND;
+ GST_BUFFER_DURATION (inbuffer) = 0;
+ GST_BUFFER_OFFSET_END (inbuffer) = (GST_BUFFER_TIMESTAMP (inbuffer) << 32); /* granpos */
+ fail_unless_equals_int (gst_pad_push (myparsesrcpad, inbuffer), GST_FLOW_OK);
+
+ /* signal eos */
+ fail_unless (gst_pad_push_event (myparsesrcpad,
+ gst_event_new_eos ()) == TRUE);
+
+ fail_unless (gst_element_set_state (kateparse,
+ GST_STATE_READY) == GST_STATE_CHANGE_SUCCESS,
+ "could not set to ready");
+
+ /* at least one data packet and one EOS packet should have been emitted */
+ check_buffers (2, TRUE);
+
+ /* cleanup */
+ gst_bus_set_flushing (bus, TRUE);
+ gst_element_set_bus (kateparse, NULL);
+ gst_object_unref (GST_OBJECT (bus));
+ cleanup_kateparse (kateparse);
+ g_list_free (buffers);
+}
+
+GST_END_TEST;
+
+GST_START_TEST (test_kate_tag_passthrough)
+{
+ GstElement *katetag;
+ GstBus *bus;
+ GstBuffer *outbuffer;
+ GList *list;
+
+ katetag = setup_katetag ();
+ fail_unless (gst_element_set_state (katetag,
+ GST_STATE_PLAYING) == GST_STATE_CHANGE_SUCCESS,
+ "could not set to playing");
+ bus = gst_bus_new ();
+
+ gst_element_set_bus (katetag, bus);
+
+ test_kate_send_headers (mytagsrcpad);
+
+ /* signal eos */
+ fail_unless (gst_pad_push_event (mytagsrcpad, gst_event_new_eos ()) == TRUE);
+
+ fail_unless (gst_element_set_state (katetag,
+ GST_STATE_READY) == GST_STATE_CHANGE_SUCCESS,
+ "could not set to ready");
+
+ /* get the first buffer and check language/category */
+ fail_unless (g_list_length (buffers) >= 2); /* ID header, Vorbis comments header */
+ outbuffer = GST_BUFFER (buffers->data);
+ fail_if (outbuffer == NULL);
+
+ /* check identification header is unchanged */
+ list = g_list_nth (buffers, 0);
+ fail_unless (list != NULL);
+ outbuffer = list->data;
+ fail_unless_equals_int (GST_BUFFER_SIZE (outbuffer),
+ sizeof (kate_header_0x80));
+ fail_unless_equals_int (memcmp (GST_BUFFER_DATA (outbuffer), kate_header_0x80,
+ sizeof (kate_header_0x80)), 0);
+
+ /* check comment header is unchanged */
+ list = g_list_nth (buffers, 1);
+ fail_unless (list != NULL);
+ outbuffer = list->data;
+ fail_unless_equals_int (GST_BUFFER_SIZE (outbuffer),
+ sizeof (kate_header_0x81));
+ fail_unless_equals_int (memcmp (GST_BUFFER_DATA (outbuffer), kate_header_0x81,
+ sizeof (kate_header_0x81)), 0);
+
+ /* all headers should have been emitted, but no particular packets */
+ check_buffers (0, TRUE);
+
+ /* cleanup */
+ gst_bus_set_flushing (bus, TRUE);
+ gst_element_set_bus (katetag, NULL);
+ gst_object_unref (GST_OBJECT (bus));
+ cleanup_katetag (katetag);
+ g_list_free (buffers);
+}
+
+GST_END_TEST;
+
+GST_START_TEST (test_kate_tag)
+{
+ GstElement *katetag;
+ GstBus *bus;
+ GstBuffer *outbuffer;
+
+ katetag = setup_katetag ();
+ fail_unless (gst_element_set_state (katetag,
+ GST_STATE_PLAYING) == GST_STATE_CHANGE_SUCCESS,
+ "could not set to playing");
+ bus = gst_bus_new ();
+
+ gst_element_set_bus (katetag, bus);
+
+ g_object_set (katetag, "language", "cy", NULL);
+ g_object_set (katetag, "category", "subtitles", NULL);
+
+ test_kate_send_headers (mytagsrcpad);
+
+ /* signal eos */
+ fail_unless (gst_pad_push_event (mytagsrcpad, gst_event_new_eos ()) == TRUE);
+
+ fail_unless (gst_element_set_state (katetag,
+ GST_STATE_READY) == GST_STATE_CHANGE_SUCCESS,
+ "could not set to ready");
+
+ /* get the first buffer and check language/category */
+ fail_unless (g_list_length (buffers) >= 1);
+ outbuffer = GST_BUFFER (buffers->data);
+ fail_if (outbuffer == NULL);
+ fail_if (GST_BUFFER_SIZE (outbuffer) != 64);
+ fail_if (strcmp ((const char *) GST_BUFFER_DATA (outbuffer) + 32, "cy"));
+ fail_if (strcmp ((const char *) GST_BUFFER_DATA (outbuffer) + 48,
+ "subtitles"));
+
+ /* all headers should have been emitted, but no particular packets */
+ check_buffers (0, TRUE);
+
+ /* cleanup */
+ gst_bus_set_flushing (bus, TRUE);
+ gst_element_set_bus (katetag, NULL);
+ gst_object_unref (GST_OBJECT (bus));
+ cleanup_katetag (katetag);
+ g_list_free (buffers);
+}
+
+GST_END_TEST;
+
+static Suite *
+kate_suite (void)
+{
+ Suite *s = suite_create ("kate");
+ TCase *tc_chain = tcase_create ("general");
+
+ suite_add_tcase (s, tc_chain);
+
+#define X if (0)
+ tcase_add_test (tc_chain, test_kate_typefind);
+ tcase_add_test (tc_chain, test_kate_empty_identification_header);
+ tcase_add_test (tc_chain, test_kate_identification_header);
+ tcase_add_test (tc_chain, test_kate_encode_nothing);
+ tcase_add_test (tc_chain, test_kate_encode_empty);
+ tcase_add_test (tc_chain, test_kate_encode_simple);
+ tcase_add_test (tc_chain, test_kate_encode_spu);
+ tcase_add_test (tc_chain, test_kate_encode_keepalives);
+ tcase_add_test (tc_chain, test_kate_parse);
+ tcase_add_test (tc_chain, test_kate_tag_passthrough);
+ tcase_add_test (tc_chain, test_kate_tag);
+#undef X
+
+ return s;
+}
+
+int
+main (int argc, char **argv)
+{
+ int nf;
+
+ Suite *s = kate_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/legacyresample.c b/tests/check/elements/legacyresample.c
new file mode 100644
index 00000000..3c1bda3d
--- /dev/null
+++ b/tests/check/elements/legacyresample.c
@@ -0,0 +1,574 @@
+/* GStreamer
+ *
+ * unit test for legacyresample
+ *
+ * Copyright (C) <2005> Thomas Vander Stichele <thomas at apestaart dot org>
+ * Copyright (C) <2006> Tim-Philipp Müller <tim at centricular net>
+ *
+ * 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 <unistd.h>
+
+#include <gst/check/gstcheck.h>
+#include <gst/audio/audio.h>
+
+/* For ease of programming we use globals to keep refs for our floating
+ * src and sink pads we create; otherwise we always have to do get_pad,
+ * get_peer, and then remove references in every test function */
+static GstPad *mysrcpad, *mysinkpad;
+
+
+#define RESAMPLE_CAPS_TEMPLATE_STRING \
+ "audio/x-raw, " \
+ "format = (string) " GST_AUDIO_NE (S16) ", " \
+ "channels = (int) [ 1, MAX ], " \
+ "rate = (int) [ 1, MAX ]"
+
+static GstStaticPadTemplate sinktemplate = GST_STATIC_PAD_TEMPLATE ("sink",
+ GST_PAD_SINK,
+ GST_PAD_ALWAYS,
+ GST_STATIC_CAPS (RESAMPLE_CAPS_TEMPLATE_STRING)
+ );
+static GstStaticPadTemplate srctemplate = GST_STATIC_PAD_TEMPLATE ("src",
+ GST_PAD_SRC,
+ GST_PAD_ALWAYS,
+ GST_STATIC_CAPS (RESAMPLE_CAPS_TEMPLATE_STRING)
+ );
+
+static GstElement *
+setup_legacyresample (int channels, int inrate, int outrate)
+{
+ GstElement *legacyresample;
+ GstCaps *caps;
+ GstStructure *structure;
+
+ GST_DEBUG ("setup_legacyresample");
+ legacyresample = gst_check_setup_element ("legacyresample");
+
+ caps = gst_caps_from_string (RESAMPLE_CAPS_TEMPLATE_STRING);
+ structure = gst_caps_get_structure (caps, 0);
+ gst_structure_set (structure, "channels", G_TYPE_INT, channels,
+ "rate", G_TYPE_INT, inrate, NULL);
+ fail_unless (gst_caps_is_fixed (caps));
+
+ fail_unless (gst_element_set_state (legacyresample,
+ GST_STATE_PAUSED) == GST_STATE_CHANGE_SUCCESS,
+ "could not set to paused");
+
+ mysrcpad = gst_check_setup_src_pad (legacyresample, &srctemplate);
+ gst_pad_set_active (mysrcpad, TRUE);
+ fail_unless (gst_pad_set_caps (mysrcpad, caps));
+ gst_caps_unref (caps);
+
+ caps = gst_caps_from_string (RESAMPLE_CAPS_TEMPLATE_STRING);
+ structure = gst_caps_get_structure (caps, 0);
+ gst_structure_set (structure, "channels", G_TYPE_INT, channels,
+ "rate", G_TYPE_INT, outrate, NULL);
+ fail_unless (gst_caps_is_fixed (caps));
+
+ mysinkpad = gst_check_setup_sink_pad (legacyresample, &sinktemplate);
+ gst_pad_set_active (mysinkpad, TRUE);
+ /* this installs a getcaps func that will always return the caps we set
+ * later */
+ fail_unless (gst_pad_set_caps (mysinkpad, caps));
+ gst_pad_use_fixed_caps (mysinkpad);
+ gst_caps_unref (caps);
+
+ return legacyresample;
+}
+
+static void
+cleanup_legacyresample (GstElement * legacyresample)
+{
+ GST_DEBUG ("cleanup_legacyresample");
+
+ fail_unless (gst_element_set_state (legacyresample,
+ GST_STATE_NULL) == GST_STATE_CHANGE_SUCCESS, "could not set to NULL");
+
+ gst_pad_set_active (mysrcpad, FALSE);
+ gst_pad_set_active (mysinkpad, FALSE);
+ gst_check_teardown_src_pad (legacyresample);
+ gst_check_teardown_sink_pad (legacyresample);
+ gst_check_teardown_element (legacyresample);
+}
+
+static void
+fail_unless_perfect_stream (void)
+{
+ guint64 timestamp = 0L, duration = 0L;
+ guint64 offset = 0L, offset_end = 0L;
+
+ GList *l;
+ GstBuffer *buffer;
+
+ for (l = buffers; l; l = l->next) {
+ buffer = GST_BUFFER (l->data);
+ ASSERT_BUFFER_REFCOUNT (buffer, "buffer", 1);
+ GST_DEBUG ("buffer timestamp %" G_GUINT64_FORMAT ", duration %"
+ G_GUINT64_FORMAT " offset %" G_GUINT64_FORMAT " offset_end %"
+ G_GUINT64_FORMAT,
+ GST_BUFFER_TIMESTAMP (buffer),
+ GST_BUFFER_DURATION (buffer),
+ GST_BUFFER_OFFSET (buffer), GST_BUFFER_OFFSET_END (buffer));
+
+ fail_unless_equals_uint64 (timestamp, GST_BUFFER_TIMESTAMP (buffer));
+ fail_unless_equals_uint64 (offset, GST_BUFFER_OFFSET (buffer));
+ duration = GST_BUFFER_DURATION (buffer);
+ offset_end = GST_BUFFER_OFFSET_END (buffer);
+
+ timestamp += duration;
+ offset = offset_end;
+ gst_buffer_unref (buffer);
+ }
+ g_list_free (buffers);
+ buffers = NULL;
+}
+
+/* this tests that the output is a perfect stream if the input is */
+static void
+test_perfect_stream_instance (int inrate, int outrate, int samples,
+ int numbuffers)
+{
+ GstElement *legacyresample;
+ GstBuffer *inbuffer, *outbuffer;
+ GstCaps *caps;
+ guint64 offset = 0;
+
+ int i, j;
+ gint16 *p;
+
+ legacyresample = setup_legacyresample (2, inrate, outrate);
+ caps = gst_pad_get_current_caps (mysrcpad);
+ fail_unless (gst_caps_is_fixed (caps));
+
+ fail_unless (gst_element_set_state (legacyresample,
+ GST_STATE_PLAYING) == GST_STATE_CHANGE_SUCCESS,
+ "could not set to playing");
+
+ for (j = 1; j <= numbuffers; ++j) {
+ GstMapInfo map;
+
+ inbuffer = gst_buffer_new_and_alloc (samples * 4);
+ GST_BUFFER_DURATION (inbuffer) = samples * GST_SECOND / inrate;
+ GST_BUFFER_TIMESTAMP (inbuffer) = GST_BUFFER_DURATION (inbuffer) * (j - 1);
+ GST_BUFFER_OFFSET (inbuffer) = offset;
+ offset += samples;
+ GST_BUFFER_OFFSET_END (inbuffer) = offset;
+
+ gst_buffer_map (inbuffer, &map, GST_MAP_WRITE);
+ p = (gint16 *) map.data;
+
+ /* create a 16 bit signed ramp */
+ for (i = 0; i < samples; ++i) {
+ *p = -32767 + i * (65535 / samples);
+ ++p;
+ *p = -32767 + i * (65535 / samples);
+ ++p;
+ }
+ gst_buffer_unmap (inbuffer, &map);
+
+ /* pushing gives away my reference ... */
+ fail_unless (gst_pad_push (mysrcpad, inbuffer) == GST_FLOW_OK);
+ /* ... but it ends up being collected on the global buffer list */
+ fail_unless_equals_int (g_list_length (buffers), j);
+ }
+
+ /* FIXME: we should make legacyresample handle eos by flushing out the last
+ * samples, which will give us one more, small, buffer */
+ fail_if ((outbuffer = (GstBuffer *) buffers->data) == NULL);
+ ASSERT_BUFFER_REFCOUNT (outbuffer, "outbuffer", 1);
+
+ fail_unless_perfect_stream ();
+
+ /* cleanup */
+ gst_caps_unref (caps);
+ cleanup_legacyresample (legacyresample);
+}
+
+
+/* make sure that outgoing buffers are contiguous in timestamp/duration and
+ * offset/offsetend
+ */
+GST_START_TEST (test_perfect_stream)
+{
+ /* integral scalings */
+ test_perfect_stream_instance (48000, 24000, 500, 20);
+ test_perfect_stream_instance (48000, 12000, 500, 20);
+ test_perfect_stream_instance (12000, 24000, 500, 20);
+ test_perfect_stream_instance (12000, 48000, 500, 20);
+
+ /* non-integral scalings */
+ test_perfect_stream_instance (44100, 8000, 500, 20);
+ test_perfect_stream_instance (8000, 44100, 500, 20);
+
+ /* wacky scalings */
+ test_perfect_stream_instance (12345, 54321, 500, 20);
+ test_perfect_stream_instance (101, 99, 500, 20);
+}
+
+GST_END_TEST;
+
+/* this tests that the output is a correct discontinuous stream
+ * if the input is; ie input drops in time come out the same way */
+static void
+test_discont_stream_instance (int inrate, int outrate, int samples,
+ int numbuffers)
+{
+ GstElement *legacyresample;
+ GstBuffer *inbuffer, *outbuffer;
+ GstCaps *caps;
+ GstClockTime ints;
+
+ int i, j;
+ gint16 *p;
+
+ GST_DEBUG ("inrate:%d outrate:%d samples:%d numbuffers:%d",
+ inrate, outrate, samples, numbuffers);
+
+ legacyresample = setup_legacyresample (2, inrate, outrate);
+ caps = gst_pad_get_current_caps (mysrcpad);
+ fail_unless (gst_caps_is_fixed (caps));
+
+ fail_unless (gst_element_set_state (legacyresample,
+ GST_STATE_PLAYING) == GST_STATE_CHANGE_SUCCESS,
+ "could not set to playing");
+
+ for (j = 1; j <= numbuffers; ++j) {
+ GstMapInfo map;
+
+ inbuffer = gst_buffer_new_and_alloc (samples * 4);
+ GST_BUFFER_DURATION (inbuffer) = samples * GST_SECOND / inrate;
+ /* "drop" half the buffers */
+ ints = GST_BUFFER_DURATION (inbuffer) * 2 * (j - 1);
+ GST_BUFFER_TIMESTAMP (inbuffer) = ints;
+ GST_BUFFER_OFFSET (inbuffer) = (j - 1) * 2 * samples;
+ GST_BUFFER_OFFSET_END (inbuffer) = j * 2 * samples + samples;
+
+ gst_buffer_map (inbuffer, &map, GST_MAP_WRITE);
+ p = (gint16 *) map.data;
+
+ /* create a 16 bit signed ramp */
+ for (i = 0; i < samples; ++i) {
+ *p = -32767 + i * (65535 / samples);
+ ++p;
+ *p = -32767 + i * (65535 / samples);
+ ++p;
+ }
+ gst_buffer_unmap (inbuffer, &map);
+
+ GST_DEBUG ("Sending Buffer time:%" G_GUINT64_FORMAT " duration:%"
+ G_GINT64_FORMAT " discont:%d offset:%" G_GUINT64_FORMAT " offset_end:%"
+ G_GUINT64_FORMAT, GST_BUFFER_TIMESTAMP (inbuffer),
+ GST_BUFFER_DURATION (inbuffer), GST_BUFFER_IS_DISCONT (inbuffer),
+ GST_BUFFER_OFFSET (inbuffer), GST_BUFFER_OFFSET_END (inbuffer));
+ /* pushing gives away my reference ... */
+ fail_unless (gst_pad_push (mysrcpad, inbuffer) == GST_FLOW_OK);
+
+ /* check if the timestamp of the pushed buffer matches the incoming one */
+ outbuffer = g_list_nth_data (buffers, g_list_length (buffers) - 1);
+ fail_if (outbuffer == NULL);
+ fail_unless_equals_uint64 (ints, GST_BUFFER_TIMESTAMP (outbuffer));
+ GST_DEBUG ("Got Buffer time:%" G_GUINT64_FORMAT " duration:%"
+ G_GINT64_FORMAT " discont:%d offset:%" G_GUINT64_FORMAT " offset_end:%"
+ G_GUINT64_FORMAT, GST_BUFFER_TIMESTAMP (outbuffer),
+ GST_BUFFER_DURATION (outbuffer), GST_BUFFER_IS_DISCONT (outbuffer),
+ GST_BUFFER_OFFSET (outbuffer), GST_BUFFER_OFFSET_END (outbuffer));
+ if (j > 1) {
+ fail_unless (GST_BUFFER_IS_DISCONT (outbuffer),
+ "expected discont for buffer #%d", j);
+ }
+ }
+
+ /* cleanup */
+ gst_caps_unref (caps);
+ cleanup_legacyresample (legacyresample);
+}
+
+GST_START_TEST (test_discont_stream)
+{
+ /* integral scalings */
+ test_discont_stream_instance (48000, 24000, 500, 20);
+ test_discont_stream_instance (48000, 12000, 500, 20);
+ test_discont_stream_instance (12000, 24000, 500, 20);
+ test_discont_stream_instance (12000, 48000, 500, 20);
+
+ /* non-integral scalings */
+ test_discont_stream_instance (44100, 8000, 500, 20);
+ test_discont_stream_instance (8000, 44100, 500, 20);
+
+ /* wacky scalings */
+ test_discont_stream_instance (12345, 54321, 500, 20);
+ test_discont_stream_instance (101, 99, 500, 20);
+}
+
+GST_END_TEST;
+
+
+
+GST_START_TEST (test_reuse)
+{
+ GstElement *legacyresample;
+ GstEvent *newseg;
+ GstBuffer *inbuffer;
+ GstCaps *caps;
+ GstSegment seg;
+
+ legacyresample = setup_legacyresample (1, 9343, 48000);
+ caps = gst_pad_get_current_caps (mysrcpad);
+ fail_unless (gst_caps_is_fixed (caps));
+
+ fail_unless (gst_element_set_state (legacyresample,
+ GST_STATE_PLAYING) == GST_STATE_CHANGE_SUCCESS,
+ "could not set to playing");
+
+ gst_segment_init (&seg, GST_FORMAT_TIME);
+ newseg = gst_event_new_segment (&seg);
+ fail_unless (gst_pad_push_event (mysrcpad, newseg) != FALSE);
+
+ inbuffer = gst_buffer_new_and_alloc (9343 * 4);
+ gst_buffer_memset (inbuffer, 0, 0, -1);
+ GST_BUFFER_DURATION (inbuffer) = GST_SECOND;
+ GST_BUFFER_TIMESTAMP (inbuffer) = 0;
+ GST_BUFFER_OFFSET (inbuffer) = 0;
+
+ /* pushing gives away my reference ... */
+ fail_unless (gst_pad_push (mysrcpad, inbuffer) == GST_FLOW_OK);
+
+ /* ... but it ends up being collected on the global buffer list */
+ fail_unless_equals_int (g_list_length (buffers), 1);
+
+ /* now reset and try again ... */
+ fail_unless (gst_element_set_state (legacyresample,
+ GST_STATE_NULL) == GST_STATE_CHANGE_SUCCESS, "could not set to NULL");
+
+ fail_unless (gst_element_set_state (legacyresample,
+ GST_STATE_PLAYING) == GST_STATE_CHANGE_SUCCESS,
+ "could not set to playing");
+
+ gst_segment_init (&seg, GST_FORMAT_TIME);
+ newseg = gst_event_new_segment (&seg);
+ fail_unless (gst_pad_push_event (mysrcpad, newseg) != FALSE);
+
+ inbuffer = gst_buffer_new_and_alloc (9343 * 4);
+ gst_buffer_memset (inbuffer, 0, 0, -1);
+ GST_BUFFER_DURATION (inbuffer) = GST_SECOND;
+ GST_BUFFER_TIMESTAMP (inbuffer) = 0;
+ GST_BUFFER_OFFSET (inbuffer) = 0;
+
+ fail_unless (gst_pad_push (mysrcpad, inbuffer) == GST_FLOW_OK);
+
+ /* ... it also ends up being collected on the global buffer list. If we
+ * now have more than 2 buffers, then legacyresample probably didn't clean
+ * up its internal buffer properly and tried to push the remaining samples
+ * when it got the second NEWSEGMENT event */
+ fail_unless_equals_int (g_list_length (buffers), 2);
+
+ cleanup_legacyresample (legacyresample);
+ gst_caps_unref (caps);
+}
+
+GST_END_TEST;
+
+GST_START_TEST (test_shutdown)
+{
+ GstElement *pipeline, *src, *cf1, *ar, *cf2, *sink;
+ GstCaps *caps;
+ guint i;
+
+ /* create pipeline, force legacyresample to actually resample */
+ pipeline = gst_pipeline_new (NULL);
+
+ src = gst_check_setup_element ("audiotestsrc");
+ cf1 = gst_check_setup_element ("capsfilter");
+ ar = gst_check_setup_element ("legacyresample");
+ cf2 = gst_check_setup_element ("capsfilter");
+ g_object_set (cf2, "name", "capsfilter2", NULL);
+ sink = gst_check_setup_element ("fakesink");
+
+ caps =
+ gst_caps_new_simple ("audio/x-raw-int", "rate", G_TYPE_INT, 11025, NULL);
+ g_object_set (cf1, "caps", caps, NULL);
+ gst_caps_unref (caps);
+
+ caps =
+ gst_caps_new_simple ("audio/x-raw-int", "rate", G_TYPE_INT, 48000, NULL);
+ g_object_set (cf2, "caps", caps, NULL);
+ gst_caps_unref (caps);
+
+ /* don't want to sync against the clock, the more throughput the better */
+ g_object_set (src, "is-live", FALSE, NULL);
+ g_object_set (sink, "sync", FALSE, NULL);
+
+ gst_bin_add_many (GST_BIN (pipeline), src, cf1, ar, cf2, sink, NULL);
+ fail_if (!gst_element_link_many (src, cf1, ar, cf2, sink, NULL));
+
+ /* now, wait until pipeline is running and then shut it down again; repeat */
+ for (i = 0; i < 20; ++i) {
+ gst_element_set_state (pipeline, GST_STATE_PAUSED);
+ gst_element_get_state (pipeline, NULL, NULL, -1);
+ gst_element_set_state (pipeline, GST_STATE_PLAYING);
+ g_usleep (100);
+ gst_element_set_state (pipeline, GST_STATE_NULL);
+ }
+
+ gst_object_unref (pipeline);
+}
+
+GST_END_TEST;
+
+#if 0
+static GstFlowReturn
+live_switch_alloc_only_48000 (GstPad * pad, guint64 offset,
+ guint size, GstCaps * caps, GstBuffer ** buf)
+{
+ GstStructure *structure;
+ gint rate;
+ gint channels;
+ GstCaps *desired;
+
+ structure = gst_caps_get_structure (caps, 0);
+ fail_unless (gst_structure_get_int (structure, "rate", &rate));
+ fail_unless (gst_structure_get_int (structure, "channels", &channels));
+
+ if (rate < 48000)
+ return GST_FLOW_NOT_NEGOTIATED;
+
+ desired = gst_caps_copy (caps);
+ gst_caps_set_simple (desired, "rate", G_TYPE_INT, 48000, NULL);
+
+ *buf = gst_buffer_new_and_alloc (channels * 48000);
+ gst_buffer_set_caps (*buf, desired);
+ gst_caps_unref (desired);
+
+ return GST_FLOW_OK;
+}
+
+static GstCaps *
+live_switch_get_sink_caps (GstPad * pad)
+{
+ GstCaps *result;
+
+ result = gst_caps_copy (GST_PAD_CAPS (pad));
+
+ gst_caps_set_simple (result,
+ "rate", GST_TYPE_INT_RANGE, 48000, G_MAXINT, NULL);
+
+ return result;
+}
+
+static void
+live_switch_push (int rate, GstCaps * caps)
+{
+ GstBuffer *inbuffer;
+ GstCaps *desired;
+ GList *l;
+
+ desired = gst_caps_copy (caps);
+ gst_caps_set_simple (desired, "rate", G_TYPE_INT, rate, NULL);
+
+ fail_unless (gst_pad_alloc_buffer_and_set_caps (mysrcpad,
+ GST_BUFFER_OFFSET_NONE, rate * 4, desired, &inbuffer) == GST_FLOW_OK);
+
+ /* When the basetransform hits the non-configured case it always
+ * returns a buffer with exactly the same caps as we requested so the actual
+ * renegotiation (if needed) will be done in the _chain*/
+ fail_unless (inbuffer != NULL);
+ fail_unless (gst_caps_is_equal (desired, GST_BUFFER_CAPS (inbuffer)));
+
+ gst_buffer_memset (inbuffer, 0, 0, -1);
+ GST_BUFFER_DURATION (inbuffer) = GST_SECOND;
+ GST_BUFFER_TIMESTAMP (inbuffer) = 0;
+ GST_BUFFER_OFFSET (inbuffer) = 0;
+
+ /* pushing gives away my reference ... */
+ fail_unless (gst_pad_push (mysrcpad, inbuffer) == GST_FLOW_OK);
+
+ /* ... but it ends up being collected on the global buffer list */
+ fail_unless_equals_int (g_list_length (buffers), 1);
+
+ for (l = buffers; l; l = l->next) {
+ GstBuffer *buffer = GST_BUFFER (l->data);
+
+ gst_buffer_unref (buffer);
+ }
+
+ g_list_free (buffers);
+ buffers = NULL;
+
+ gst_caps_unref (desired);
+}
+
+GST_START_TEST (test_live_switch)
+{
+ GstElement *legacyresample;
+ GstEvent *newseg;
+ GstCaps *caps;
+
+ legacyresample = setup_legacyresample (4, 48000, 48000);
+
+ /* Let the sinkpad act like something that can only handle things of
+ * rate 48000- and can only allocate buffers for that rate, but if someone
+ * tries to get a buffer with a rate higher then 48000 tries to renegotiate
+ * */
+ gst_pad_set_bufferalloc_function (mysinkpad, live_switch_alloc_only_48000);
+ gst_pad_set_getcaps_function (mysinkpad, live_switch_get_sink_caps);
+
+ caps = gst_pad_get_negotiated_caps (mysrcpad);
+ fail_unless (gst_caps_is_fixed (caps));
+
+ fail_unless (gst_element_set_state (legacyresample,
+ GST_STATE_PLAYING) == GST_STATE_CHANGE_SUCCESS,
+ "could not set to playing");
+
+ newseg = gst_event_new_new_segment (FALSE, 1.0, GST_FORMAT_TIME, 0, -1, 0);
+ fail_unless (gst_pad_push_event (mysrcpad, newseg) != FALSE);
+
+ /* downstream can provide the requested rate, a buffer alloc will be passed
+ * on */
+ live_switch_push (48000, caps);
+
+ /* Downstream can never accept this rate, buffer alloc isn't passed on */
+ live_switch_push (40000, caps);
+
+ /* Downstream can provide the requested rate but will re-negotiate */
+ live_switch_push (50000, caps);
+
+ cleanup_legacyresample (legacyresample);
+ gst_caps_unref (caps);
+}
+
+GST_END_TEST
+#endif
+static Suite *
+legacyresample_suite (void)
+{
+ Suite *s = suite_create ("legacyresample");
+ TCase *tc_chain = tcase_create ("general");
+
+ suite_add_tcase (s, tc_chain);
+ tcase_add_test (tc_chain, test_perfect_stream);
+ tcase_add_test (tc_chain, test_discont_stream);
+ tcase_add_test (tc_chain, test_reuse);
+ tcase_add_test (tc_chain, test_shutdown);
+#if 0
+ tcase_add_test (tc_chain, test_live_switch);
+#endif
+
+ return s;
+}
+
+GST_CHECK_MAIN (legacyresample);
diff --git a/tests/check/elements/logoinsert.c b/tests/check/elements/logoinsert.c
new file mode 100644
index 00000000..08f19d2a
--- /dev/null
+++ b/tests/check/elements/logoinsert.c
@@ -0,0 +1,252 @@
+/* GStreamer
+ *
+ * unit test for logoinsert
+ *
+ * Copyright (C) 2011 David Schleef <ds@schleef.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>
+#include <string.h>
+
+static guint8 image_data[];
+/* sizeof on a forward declaration? not so fast */
+#define SIZEOF_IMAGE_DATA 1428
+
+typedef struct
+{
+ GMainLoop *loop;
+ gboolean eos;
+} OnMessageUserData;
+
+static void
+on_message_cb (GstBus * bus, GstMessage * message, gpointer user_data)
+{
+ OnMessageUserData *d = user_data;
+
+ switch (GST_MESSAGE_TYPE (message)) {
+ case GST_MESSAGE_ERROR:
+ case GST_MESSAGE_WARNING:
+ g_assert_not_reached ();
+ break;
+ case GST_MESSAGE_EOS:
+ g_main_loop_quit (d->loop);
+ d->eos = TRUE;
+ break;
+ default:
+ break;
+ }
+}
+
+static void
+run_test (const gchar * pipeline_string)
+{
+ GstElement *pipeline;
+ GstBus *bus;
+ GMainLoop *loop;
+ OnMessageUserData omud = { NULL, };
+ GstStateChangeReturn ret;
+ GstElement *e;
+ GstBuffer *buffer;
+
+ GST_DEBUG ("Testing pipeline '%s'", pipeline_string);
+
+ pipeline = gst_parse_launch (pipeline_string, NULL);
+ fail_unless (pipeline != NULL);
+ g_object_set (G_OBJECT (pipeline), "async-handling", TRUE, NULL);
+
+ e = gst_bin_get_by_name (GST_BIN (pipeline), "e");
+ fail_unless (e != NULL);
+ buffer = gst_buffer_new ();
+ GST_BUFFER_DATA (buffer) = image_data;
+ GST_BUFFER_SIZE (buffer) = SIZEOF_IMAGE_DATA;
+ g_object_set (e, "data", buffer, NULL);
+ g_object_unref (e);
+
+ loop = g_main_loop_new (NULL, FALSE);
+
+ bus = gst_element_get_bus (pipeline);
+ fail_unless (bus != NULL);
+ gst_bus_add_signal_watch (bus);
+
+ omud.loop = loop;
+ omud.eos = FALSE;
+
+ g_signal_connect (bus, "message", (GCallback) on_message_cb, &omud);
+
+ gst_object_unref (bus);
+
+ ret = gst_element_set_state (pipeline, GST_STATE_PLAYING);
+ fail_unless (ret == GST_STATE_CHANGE_SUCCESS
+ || ret == GST_STATE_CHANGE_ASYNC);
+
+ g_main_loop_run (loop);
+
+ fail_unless (gst_element_set_state (pipeline,
+ GST_STATE_NULL) == GST_STATE_CHANGE_SUCCESS);
+
+ fail_unless (omud.eos == TRUE);
+
+ gst_object_unref (pipeline);
+ g_main_loop_unref (loop);
+}
+
+GST_START_TEST (test_logoinsert)
+{
+
+ run_test ("videotestsrc num-buffers=250 ! coglogoinsert name=e ! fakesink");
+}
+
+GST_END_TEST;
+
+static Suite *
+logoinsert_suite (void)
+{
+ Suite *s = suite_create ("logoinsert");
+ TCase *tc_chain = tcase_create ("general");
+
+ suite_add_tcase (s, tc_chain);
+ tcase_set_timeout (tc_chain, 180);
+
+ tcase_add_test (tc_chain, test_logoinsert);
+
+ return s;
+}
+
+GST_CHECK_MAIN (logoinsert);
+
+static guint8 image_data[] = {
+ 0x89, 0x50, 0x4e, 0x47, 0x0d, 0x0a, 0x1a, 0x0a, 0x00, 0x00, 0x00, 0x0d, 0x49,
+ 0x48, 0x44, 0x52, 0x00, 0x00, 0x00, 0x64, 0x00, 0x00, 0x00, 0x64, 0x08,
+ 0x06, 0x00, 0x00, 0x00, 0x70, 0xe2, 0x95, 0x54, 0x00, 0x00, 0x00, 0x01,
+ 0x73, 0x52, 0x47, 0x42, 0x00, 0xae, 0xce, 0x1c, 0xe9, 0x00, 0x00, 0x00,
+ 0x06, 0x62, 0x4b, 0x47, 0x44, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0xa0,
+ 0xbd, 0xa7, 0x93, 0x00, 0x00, 0x00, 0x09, 0x70, 0x48, 0x59, 0x73, 0x00,
+ 0x00, 0x0b, 0x13, 0x00, 0x00, 0x0b, 0x13, 0x01, 0x00, 0x9a, 0x9c, 0x18,
+ 0x00, 0x00, 0x00, 0x07, 0x74, 0x49, 0x4d, 0x45, 0x07, 0xdb, 0x03, 0x12,
+ 0x01, 0x3b, 0x19, 0x50, 0x86, 0x8e, 0x47, 0x00, 0x00, 0x00, 0x19, 0x74,
+ 0x45, 0x58, 0x74, 0x43, 0x6f, 0x6d, 0x6d, 0x65, 0x6e, 0x74, 0x00, 0x43,
+ 0x72, 0x65, 0x61, 0x74, 0x65, 0x64, 0x20, 0x77, 0x69, 0x74, 0x68, 0x20,
+ 0x47, 0x49, 0x4d, 0x50, 0x57, 0x81, 0x0e, 0x17, 0x00, 0x00, 0x04, 0xef,
+ 0x49, 0x44, 0x41, 0x54, 0x78, 0xda, 0xed, 0x9d, 0xcf, 0x6b, 0x1d, 0x55,
+ 0x14, 0xc7, 0x3f, 0xf7, 0xa1, 0x89, 0x81, 0x16, 0xa3, 0x82, 0x9a, 0x57,
+ 0xc4, 0x59, 0x68, 0x05, 0x05, 0x13, 0x28, 0x08, 0xba, 0x49, 0x16, 0xa2,
+ 0xb8, 0x90, 0x06, 0xd4, 0x45, 0x75, 0x61, 0x17, 0xfe, 0x07, 0xe2, 0xca,
+ 0x85, 0x8a, 0x9b, 0x82, 0x14, 0x04, 0x37, 0x5d, 0x5a, 0xfc, 0x51, 0x10,
+ 0xd4, 0xd6, 0xba, 0x69, 0x11, 0xac, 0x22, 0x55, 0xb0, 0xd1, 0x44, 0xd0,
+ 0x62, 0x57, 0x53, 0x82, 0x81, 0x46, 0x6b, 0x5f, 0xd3, 0x17, 0x34, 0x21,
+ 0xf5, 0xb8, 0x98, 0x33, 0xed, 0x04, 0x5e, 0x9a, 0xbe, 0xf7, 0x66, 0xee,
+ 0xdc, 0x99, 0x39, 0x5f, 0xb8, 0x0c, 0x59, 0xcd, 0xdc, 0xf3, 0xc9, 0xf7,
+ 0xdc, 0x3b, 0x77, 0xde, 0x3d, 0xd7, 0x89, 0x08, 0xa6, 0x70, 0xd4, 0xb2,
+ 0x10, 0x18, 0x10, 0x93, 0x01, 0x31, 0x20, 0x26, 0x03, 0x62, 0x40, 0x4c,
+ 0x06, 0xa4, 0xfe, 0xba, 0xa5, 0xea, 0x1d, 0x70, 0xce, 0x8d, 0x03, 0xd9,
+ 0x96, 0x55, 0x27, 0x6d, 0x22, 0xd2, 0xa9, 0x44, 0x7f, 0x42, 0x7f, 0x31,
+ 0x74, 0xce, 0x8d, 0x00, 0x6d, 0x20, 0xbd, 0x02, 0xec, 0x00, 0x1e, 0x00,
+ 0x22, 0x60, 0xa7, 0xfe, 0x3d, 0x72, 0x23, 0x20, 0x40, 0x0c, 0x2c, 0x00,
+ 0xf3, 0x21, 0xc3, 0x09, 0x12, 0x88, 0x42, 0xd8, 0x0d, 0x3c, 0xa1, 0x41,
+ 0x9f, 0xd0, 0xc0, 0xdf, 0xaf, 0xc1, 0xcf, 0xb6, 0x9b, 0x75, 0x79, 0x07,
+ 0x98, 0xd7, 0xb6, 0xa0, 0xd7, 0x38, 0x34, 0x38, 0xc1, 0x00, 0x51, 0x08,
+ 0x51, 0x06, 0xc4, 0x6e, 0xe0, 0xf1, 0x8c, 0x2b, 0xf2, 0xd4, 0x45, 0x60,
+ 0x11, 0x38, 0x03, 0x7c, 0x01, 0xcc, 0x89, 0xc8, 0x92, 0x01, 0xb9, 0x0e,
+ 0x63, 0x07, 0xf0, 0x34, 0xf0, 0x9c, 0x82, 0xd8, 0xe3, 0xe9, 0xd6, 0x1b,
+ 0x40, 0x17, 0xb8, 0x04, 0x9c, 0x03, 0x3e, 0x07, 0x8e, 0x97, 0x09, 0xa7,
+ 0x54, 0x20, 0x99, 0xd4, 0xf4, 0x14, 0xf0, 0xa2, 0x47, 0x10, 0xbd, 0x74,
+ 0x55, 0x9d, 0xb3, 0x0c, 0x7c, 0x0f, 0x1c, 0x2f, 0xc3, 0x39, 0xa5, 0x01,
+ 0xc9, 0xb8, 0x62, 0x5f, 0x81, 0xa9, 0x69, 0x50, 0x75, 0x15, 0xce, 0x29,
+ 0xe0, 0x3d, 0x11, 0x99, 0xab, 0x35, 0x10, 0x85, 0xf1, 0x2c, 0xf0, 0x6a,
+ 0xc9, 0xae, 0xd8, 0x4e, 0xab, 0x3a, 0xce, 0x1c, 0xf1, 0x96, 0xca, 0x44,
+ 0xc4, 0x6b, 0xd3, 0x99, 0xd1, 0x3e, 0xed, 0xa8, 0x54, 0xa0, 0x6d, 0x00,
+ 0x7f, 0x01, 0x1f, 0x03, 0x7b, 0x0a, 0x8f, 0x4f, 0x49, 0x30, 0x7e, 0xae,
+ 0x08, 0x8c, 0x6c, 0x5b, 0x07, 0x7e, 0xd0, 0xe7, 0x1f, 0xaf, 0x3c, 0x10,
+ 0x7d, 0x71, 0x9b, 0x06, 0x7e, 0xa9, 0x20, 0x8c, 0xb4, 0x5d, 0xd5, 0xe9,
+ 0xf2, 0x41, 0x20, 0xaa, 0x3a, 0x90, 0x87, 0x74, 0xce, 0x2f, 0x35, 0x68,
+ 0x5d, 0xe0, 0x23, 0x60, 0x26, 0x6f, 0xb7, 0x78, 0x19, 0xd4, 0x9d, 0x73,
+ 0x0f, 0x03, 0xaf, 0xeb, 0x7b, 0xc6, 0x68, 0x4d, 0xd6, 0x01, 0xd7, 0x80,
+ 0x9f, 0x80, 0x4f, 0x80, 0xa3, 0x22, 0x12, 0x57, 0x62, 0x71, 0xd1, 0x39,
+ 0xf7, 0x20, 0xf0, 0x1a, 0xf0, 0xbc, 0xa6, 0xad, 0xba, 0x68, 0x54, 0xa7,
+ 0xeb, 0x13, 0xc0, 0xb8, 0x73, 0xee, 0xfd, 0x3c, 0xa0, 0xb4, 0x0a, 0x86,
+ 0x11, 0x01, 0xaf, 0x00, 0xb3, 0x35, 0x83, 0x91, 0x55, 0x04, 0xbc, 0x0c,
+ 0xec, 0xd7, 0xfe, 0x86, 0x09, 0x44, 0x1f, 0x6e, 0x3f, 0xf0, 0x52, 0x8f,
+ 0x55, 0x58, 0x83, 0xe2, 0x13, 0x88, 0x7e, 0xa3, 0x98, 0x55, 0x20, 0xbb,
+ 0x68, 0x86, 0x52, 0x28, 0xb3, 0xda, 0xff, 0xa0, 0x1c, 0x32, 0x05, 0xec,
+ 0x25, 0x59, 0x2e, 0x6f, 0x92, 0x22, 0xed, 0xf7, 0x54, 0x30, 0x40, 0xd4,
+ 0xb2, 0x43, 0x3d, 0x54, 0xc5, 0x35, 0x05, 0xec, 0x1d, 0x34, 0x75, 0xb5,
+ 0x72, 0x86, 0x91, 0xa6, 0xaa, 0xd9, 0x06, 0x8c, 0x1b, 0x5b, 0xe9, 0x5a,
+ 0x0c, 0x06, 0x49, 0x5d, 0xad, 0x02, 0x2c, 0x3b, 0xad, 0xd7, 0x26, 0x6b,
+ 0xe0, 0x38, 0xb4, 0x0a, 0xb0, 0xeb, 0x14, 0xa6, 0x81, 0x63, 0x91, 0x1b,
+ 0x10, 0xb5, 0xe7, 0xa4, 0xb9, 0x63, 0x93, 0x4b, 0x26, 0xfb, 0x4d, 0x5b,
+ 0x2d, 0x73, 0x47, 0x58, 0x2e, 0xc9, 0x13, 0xc8, 0xa4, 0x01, 0xe9, 0x09,
+ 0x64, 0xd2, 0x3b, 0x10, 0xb5, 0x65, 0xd4, 0xe0, 0x99, 0xd5, 0x8d, 0x66,
+ 0x5c, 0x51, 0x3f, 0x69, 0xab, 0x95, 0xe3, 0x8d, 0xdb, 0x16, 0xff, 0x2d,
+ 0x63, 0x53, 0x0a, 0x90, 0x7b, 0x2d, 0xf6, 0x61, 0x01, 0xd9, 0x65, 0xb1,
+ 0x0f, 0x07, 0xc8, 0x5d, 0xc0, 0x98, 0xc5, 0x7e, 0x78, 0xe5, 0x05, 0xe4,
+ 0x11, 0xe0, 0x76, 0x0b, 0x67, 0x38, 0x40, 0xee, 0x33, 0x87, 0x04, 0x02,
+ 0xc4, 0x39, 0xd7, 0x06, 0xee, 0xc0, 0x36, 0xff, 0x6c, 0xa5, 0x74, 0x3b,
+ 0x84, 0x37, 0x87, 0x8c, 0x90, 0xfc, 0x12, 0xc3, 0x14, 0x08, 0x90, 0x36,
+ 0x70, 0xa7, 0xc5, 0x3d, 0x2c, 0x87, 0x58, 0xba, 0xea, 0xad, 0x35, 0xe0,
+ 0x42, 0x3f, 0x9b, 0x82, 0x2c, 0x90, 0xc5, 0xea, 0x1f, 0xe0, 0xdf, 0x32,
+ 0x66, 0x59, 0xa6, 0xde, 0x1a, 0x03, 0x6e, 0x33, 0x20, 0xe1, 0x68, 0x14,
+ 0xb8, 0xc7, 0xf7, 0xe2, 0xe2, 0x52, 0x3f, 0x83, 0x56, 0x03, 0xe5, 0x7d,
+ 0xe9, 0x64, 0x9d, 0x64, 0x0f, 0x85, 0x29, 0x10, 0x20, 0x4b, 0x3a, 0x78,
+ 0x99, 0x42, 0x00, 0x22, 0x22, 0xeb, 0x24, 0x1b, 0x25, 0xd7, 0x2c, 0xf6,
+ 0xc3, 0x2b, 0xaf, 0x41, 0xfd, 0x57, 0x60, 0xc5, 0xc2, 0x19, 0x0e, 0x90,
+ 0x45, 0x4b, 0x5b, 0x61, 0x01, 0xd9, 0x00, 0x2e, 0x5b, 0x38, 0x7b, 0xca,
+ 0xfb, 0xd2, 0x49, 0x3a, 0xb0, 0x9f, 0xb7, 0xd8, 0x87, 0x03, 0x64, 0x1d,
+ 0xf8, 0xdb, 0x62, 0x1f, 0x96, 0x43, 0xfe, 0xb0, 0xd8, 0xf7, 0x84, 0x11,
+ 0x7b, 0x5f, 0x5c, 0xd4, 0xa9, 0x6f, 0xac, 0x60, 0x4c, 0xd7, 0x95, 0x96,
+ 0x82, 0xf2, 0x3e, 0xa8, 0x03, 0x9c, 0x26, 0x29, 0xda, 0x62, 0xda, 0x0c,
+ 0x64, 0xbe, 0x2c, 0x20, 0xe7, 0xb4, 0x99, 0x12, 0xc5, 0xc0, 0x42, 0xbf,
+ 0x05, 0xd2, 0x72, 0x03, 0xa2, 0x69, 0xeb, 0x34, 0x30, 0x67, 0x2c, 0x06,
+ 0x73, 0x47, 0xde, 0x0e, 0x31, 0x97, 0x6c, 0x76, 0xc7, 0x37, 0x7a, 0x2d,
+ 0x15, 0x48, 0x0c, 0x7c, 0xda, 0x70, 0x97, 0x74, 0x80, 0xa3, 0x24, 0xd5,
+ 0x1d, 0xfa, 0xfe, 0x2c, 0x91, 0x6b, 0x25, 0x07, 0x11, 0x59, 0x77, 0xce,
+ 0x9d, 0x20, 0xd9, 0x7d, 0x3b, 0x41, 0x33, 0x7f, 0x80, 0x3d, 0x0f, 0x1c,
+ 0x1b, 0xb4, 0xaa, 0x43, 0xee, 0x5f, 0x0c, 0x45, 0xa4, 0x0b, 0x9c, 0x6c,
+ 0xe8, 0x8c, 0x2b, 0x06, 0x8e, 0x0d, 0x32, 0x76, 0x14, 0x06, 0x24, 0x33,
+ 0x96, 0x1c, 0x69, 0x58, 0xea, 0x5a, 0x04, 0x0e, 0x0f, 0x9a, 0xaa, 0x0a,
+ 0x05, 0xa2, 0x33, 0xae, 0x13, 0x24, 0x75, 0xa5, 0x9a, 0x00, 0xe5, 0x4f,
+ 0xe0, 0x03, 0x60, 0xf8, 0x02, 0x34, 0x9e, 0x2a, 0xc8, 0x55, 0xb9, 0x68,
+ 0xd9, 0x76, 0xed, 0x12, 0xf0, 0x0e, 0x39, 0x15, 0x34, 0xf3, 0x59, 0xd6,
+ 0xef, 0xf7, 0x1a, 0xc2, 0xb8, 0x08, 0xbc, 0x4d, 0x8e, 0xd5, 0xe5, 0x7c,
+ 0xd6, 0x5a, 0x9c, 0x06, 0x7e, 0xac, 0x11, 0x8c, 0x55, 0xe0, 0x2d, 0xa0,
+ 0x5d, 0xe5, 0x9a, 0x8b, 0x8f, 0x01, 0x67, 0x6b, 0x00, 0xe3, 0x0a, 0xf0,
+ 0x2e, 0x70, 0x77, 0xa5, 0xab, 0x92, 0x2a, 0x98, 0x67, 0xa8, 0x66, 0x55,
+ 0xd2, 0x6c, 0x9a, 0x3a, 0x50, 0x04, 0x8c, 0x52, 0x80, 0x28, 0x94, 0x27,
+ 0x81, 0xef, 0x2a, 0x08, 0xe3, 0x02, 0xf0, 0x66, 0x51, 0x30, 0xbc, 0x15,
+ 0xc1, 0xec, 0x25, 0xe7, 0xdc, 0x0c, 0xf0, 0x06, 0x49, 0x65, 0xcf, 0xd0,
+ 0xb5, 0xaa, 0x30, 0x0e, 0x03, 0x87, 0x44, 0x64, 0xb9, 0xa8, 0x1b, 0x95,
+ 0x76, 0xc2, 0x8e, 0x88, 0x9c, 0x72, 0xce, 0xa5, 0x6f, 0xb7, 0x33, 0x84,
+ 0x5b, 0x23, 0x65, 0x19, 0xf8, 0x5a, 0x61, 0x7c, 0x2b, 0x22, 0xab, 0x85,
+ 0xfe, 0xa3, 0x96, 0x7d, 0x5c, 0x85, 0x16, 0xfa, 0x9a, 0x26, 0x29, 0x07,
+ 0x38, 0x13, 0x18, 0x88, 0x15, 0x7d, 0xe1, 0x2b, 0xd4, 0x15, 0x41, 0x38,
+ 0x24, 0xe3, 0x94, 0x18, 0x88, 0x9d, 0x73, 0xe7, 0xd5, 0x2d, 0x51, 0x89,
+ 0x60, 0xd2, 0xd4, 0xb4, 0x02, 0x7c, 0xa6, 0x4b, 0xe8, 0x73, 0x45, 0xbb,
+ 0x22, 0x28, 0x87, 0xf4, 0x70, 0x4b, 0xea, 0x98, 0xc8, 0x43, 0x2a, 0xfb,
+ 0x4f, 0x67, 0x4d, 0x1d, 0x85, 0xf1, 0x1b, 0xf0, 0xa1, 0x8f, 0xd4, 0x54,
+ 0x09, 0x20, 0x5b, 0xa4, 0xb2, 0x14, 0xd2, 0xad, 0xc0, 0xa3, 0x24, 0x45,
+ 0x0a, 0x86, 0x5d, 0xd6, 0xbf, 0x0c, 0x7c, 0xa5, 0xab, 0x07, 0x27, 0x15,
+ 0xc6, 0xd9, 0xb2, 0x20, 0x54, 0x02, 0x48, 0x0f, 0x38, 0x64, 0xdc, 0x32,
+ 0x46, 0x72, 0x4e, 0xd5, 0x0b, 0x24, 0x35, 0xe5, 0x6f, 0x46, 0x57, 0x80,
+ 0x2f, 0x81, 0x83, 0x3e, 0x0f, 0x68, 0xa9, 0x25, 0x90, 0x6d, 0x60, 0xed,
+ 0x24, 0x39, 0x14, 0x26, 0xbd, 0x66, 0xd5, 0x25, 0x39, 0xa7, 0xa4, 0x2b,
+ 0x22, 0x67, 0x2a, 0xd1, 0x1f, 0x3b, 0xe0, 0x3e, 0x2c, 0xd9, 0x1e, 0x43,
+ 0x03, 0x62, 0x32, 0x20, 0x06, 0xc4, 0x64, 0x40, 0x0c, 0x88, 0xc9, 0x80,
+ 0x18, 0x10, 0x93, 0x01, 0x31, 0x20, 0x26, 0x03, 0x62, 0x32, 0x20, 0x06,
+ 0xc4, 0x64, 0x40, 0x0c, 0x88, 0xc9, 0x80, 0x18, 0x10, 0x93, 0x01, 0x69,
+ 0xb2, 0xfe, 0x07, 0xb0, 0x6d, 0xc6, 0x8c, 0x41, 0x92, 0x78, 0x97, 0x00,
+ 0x00, 0x00, 0x00, 0x49, 0x45, 0x4e, 0x44, 0xae, 0x42, 0x60, 0x82
+};
diff --git a/tests/check/elements/mpeg2enc.c b/tests/check/elements/mpeg2enc.c
new file mode 100644
index 00000000..41dc7e07
--- /dev/null
+++ b/tests/check/elements/mpeg2enc.c
@@ -0,0 +1,208 @@
+/* GStreamer
+ *
+ * unit test for mpeg2enc
+ *
+ * Copyright (C) <2006> Mark Nauwelaerts <manauw@skynet.be>
+ *
+ * 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 <unistd.h>
+
+#include <gst/check/gstcheck.h>
+
+/* For ease of programming we use globals to keep refs for our floating
+ * src and sink pads we create; otherwise we always have to do get_pad,
+ * get_peer, and then remove references in every test function */
+static GstPad *mysrcpad, *mysinkpad;
+
+#define VIDEO_CAPS_STRING "video/x-raw, " \
+ "format = (string) I420, " \
+ "width = (int) 384, " \
+ "height = (int) 288, " \
+ "framerate = (fraction) 25/1"
+
+#define MPEG_CAPS_STRING "video/mpeg, " \
+ "mpegversion = (int) { 1, 2 }, " \
+ "systemstream = (bool) false, " \
+ "height = (int) 288, " \
+ "framerate = (fraction) 25/1"
+
+static GstStaticPadTemplate sinktemplate = GST_STATIC_PAD_TEMPLATE ("sink",
+ GST_PAD_SINK,
+ GST_PAD_ALWAYS,
+ GST_STATIC_CAPS (MPEG_CAPS_STRING));
+
+static GstStaticPadTemplate srctemplate = GST_STATIC_PAD_TEMPLATE ("src",
+ GST_PAD_SRC,
+ GST_PAD_ALWAYS,
+ GST_STATIC_CAPS (VIDEO_CAPS_STRING));
+
+
+/* some global vars, makes it easy as for the ones above */
+static GMutex *mpeg2enc_mutex;
+static GCond *mpeg2enc_cond;
+static gboolean arrived_eos;
+
+static gboolean
+test_sink_event (GstPad * pad, GstObject * parent, GstEvent * event)
+{
+
+ switch (GST_EVENT_TYPE (event)) {
+ case GST_EVENT_EOS:
+ g_mutex_lock (mpeg2enc_mutex);
+ arrived_eos = TRUE;
+ g_cond_signal (mpeg2enc_cond);
+ g_mutex_unlock (mpeg2enc_mutex);
+ break;
+ default:
+ break;
+ }
+
+ return gst_pad_event_default (pad, parent, event);
+}
+
+static GstElement *
+setup_mpeg2enc (void)
+{
+ GstElement *mpeg2enc;
+
+ GST_DEBUG ("setup_mpeg2enc");
+ mpeg2enc = gst_check_setup_element ("mpeg2enc");
+ mysrcpad = gst_check_setup_src_pad (mpeg2enc, &srctemplate);
+ mysinkpad = gst_check_setup_sink_pad (mpeg2enc, &sinktemplate);
+ gst_pad_set_active (mysrcpad, TRUE);
+ gst_pad_set_active (mysinkpad, TRUE);
+
+ /* need to know when we are eos */
+ gst_pad_set_event_function (mysinkpad, test_sink_event);
+
+ /* and notify the test run */
+ mpeg2enc_mutex = g_mutex_new ();
+ mpeg2enc_cond = g_cond_new ();
+
+ return mpeg2enc;
+}
+
+static void
+cleanup_mpeg2enc (GstElement * mpeg2enc)
+{
+ GST_DEBUG ("cleanup_mpeg2enc");
+ gst_element_set_state (mpeg2enc, GST_STATE_NULL);
+
+ gst_pad_set_active (mysrcpad, FALSE);
+ gst_pad_set_active (mysinkpad, FALSE);
+ gst_check_teardown_src_pad (mpeg2enc);
+ gst_check_teardown_sink_pad (mpeg2enc);
+ gst_check_teardown_element (mpeg2enc);
+
+ g_mutex_free (mpeg2enc_mutex);
+ g_cond_free (mpeg2enc_cond);
+}
+
+GST_START_TEST (test_video_pad)
+{
+ GstElement *mpeg2enc;
+ GstBuffer *inbuffer, *outbuffer;
+ GstCaps *caps;
+ int i, num_buffers;
+ guint8 data0[] = { 0x00, 0x00, 0x01, 0xb3 };
+
+
+ mpeg2enc = setup_mpeg2enc ();
+ fail_unless (gst_element_set_state (mpeg2enc,
+ GST_STATE_PLAYING) == GST_STATE_CHANGE_SUCCESS,
+ "could not set to playing");
+
+ /* corresponds to I420 buffer for the size mentioned in the caps */
+ inbuffer = gst_buffer_new_and_alloc (384 * 288 * 3 / 2);
+ /* makes valgrind's memcheck happier */
+ gst_buffer_memset (inbuffer, 0, 0, -1);
+ caps = gst_caps_from_string (VIDEO_CAPS_STRING);
+ gst_pad_set_caps (mysrcpad, caps);
+ gst_caps_unref (caps);
+ GST_BUFFER_TIMESTAMP (inbuffer) = 0;
+ ASSERT_BUFFER_REFCOUNT (inbuffer, "inbuffer", 1);
+ fail_unless (gst_pad_push (mysrcpad, inbuffer) == GST_FLOW_OK);
+
+ /* need to force eos and state change to make sure the encoding task ends */
+ fail_unless (gst_pad_push_event (mysrcpad, gst_event_new_eos ()) == TRUE);
+ /* need to wait a bit to make sure mpeg2enc task digested all this */
+ g_mutex_lock (mpeg2enc_mutex);
+ while (!arrived_eos)
+ g_cond_wait (mpeg2enc_cond, mpeg2enc_mutex);
+ g_mutex_unlock (mpeg2enc_mutex);
+
+ num_buffers = g_list_length (buffers);
+ /* well, we do not really know much with mpeg, but at least something ... */
+ fail_unless (num_buffers >= 1);
+
+ /* clean up buffers */
+ for (i = 0; i < num_buffers; ++i) {
+ outbuffer = GST_BUFFER (buffers->data);
+ fail_if (outbuffer == NULL);
+
+ switch (i) {
+ case 0:
+ fail_unless (gst_buffer_get_size (outbuffer) >= sizeof (data0));
+ fail_unless (gst_buffer_memcmp (outbuffer, 0, data0,
+ sizeof (data0)) == 0);
+ break;
+ default:
+ break;
+ }
+ buffers = g_list_remove (buffers, outbuffer);
+
+ ASSERT_BUFFER_REFCOUNT (outbuffer, "outbuffer", 1);
+ gst_buffer_unref (outbuffer);
+ outbuffer = NULL;
+ }
+
+ cleanup_mpeg2enc (mpeg2enc);
+ g_list_free (buffers);
+ buffers = NULL;
+}
+
+GST_END_TEST;
+
+static Suite *
+mpeg2enc_suite (void)
+{
+ Suite *s = suite_create ("mpeg2enc");
+ TCase *tc_chain = tcase_create ("general");
+
+ suite_add_tcase (s, tc_chain);
+ tcase_add_test (tc_chain, test_video_pad);
+
+ return s;
+}
+
+int
+main (int argc, char **argv)
+{
+ int nf;
+
+ Suite *s = mpeg2enc_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/mpeg4videoparse.c b/tests/check/elements/mpeg4videoparse.c
new file mode 100644
index 00000000..ccddf7f3
--- /dev/null
+++ b/tests/check/elements/mpeg4videoparse.c
@@ -0,0 +1,200 @@
+/*
+ * GStreamer
+ *
+ * unit test for mpeg4videoparse
+ *
+ * Copyright (C) 2011 Nokia Corporation. All rights reserved.
+ *
+ * Contact: Stefan Kost <stefan.kost@nokia.com>
+ *
+ * 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>
+#include "parser.h"
+
+#define SRC_CAPS_TMPL "video/mpeg, framed=(boolean)false"
+#define SINK_CAPS_TMPL "video/mpeg, framed=(boolean)true"
+
+GstStaticPadTemplate sinktemplate = GST_STATIC_PAD_TEMPLATE ("sink",
+ GST_PAD_SINK,
+ GST_PAD_ALWAYS,
+ GST_STATIC_CAPS (SINK_CAPS_TMPL)
+ );
+
+GstStaticPadTemplate srctemplate = GST_STATIC_PAD_TEMPLATE ("src",
+ GST_PAD_SRC,
+ GST_PAD_ALWAYS,
+ GST_STATIC_CAPS (SRC_CAPS_TMPL)
+ );
+
+/* some data */
+
+/* codec data; VOS up to and including GOP */
+static guint8 mpeg4_config[] = {
+ 0x00, 0x00, 0x01, 0xb0, 0x01, 0x00, 0x00, 0x01,
+ 0xb5, 0x89, 0x13, 0x00, 0x00, 0x01, 0x00, 0x00,
+ 0x00, 0x01, 0x20, 0x00, 0xc4, 0x8d, 0x88, 0x00,
+ 0xf5, 0x01, 0x04, 0x03, 0x14, 0x63, 0x00, 0x00,
+ 0x01, 0xb3, 0x00, 0x10, 0x07
+};
+
+/* keyframes all around */
+static guint8 mpeg4_iframe[] = {
+ 0x00, 0x00, 0x01, 0xb6, 0x10, 0x60, 0x91, 0x82,
+ 0x3d, 0xb7, 0xf1, 0xb6, 0xdf, 0xc6, 0xdb, 0x7f,
+ 0x1b, 0x6d, 0xfb
+};
+
+static gboolean
+verify_buffer (buffer_verify_data_s * vdata, GstBuffer * buffer)
+{
+ GstMapInfo map;
+
+ gst_buffer_map (buffer, &map, GST_MAP_READ);
+
+ /* header is merged in initial frame */
+ if (vdata->buffer_counter == 0) {
+ /* the whole sequence header is included */
+ fail_unless (map.size == ctx_headers[0].size + vdata->data_to_verify_size);
+ fail_unless (memcmp (map.data, ctx_headers[0].data,
+ ctx_headers[0].size) == 0);
+ fail_unless (memcmp (map.data + ctx_headers[0].size,
+ vdata->data_to_verify, vdata->data_to_verify_size) == 0);
+ gst_buffer_unmap (buffer, &map);
+ return TRUE;
+ }
+ gst_buffer_unmap (buffer, &map);
+
+ return FALSE;
+}
+
+GST_START_TEST (test_parse_normal)
+{
+ gst_parser_test_normal (mpeg4_iframe, sizeof (mpeg4_iframe));
+}
+
+GST_END_TEST;
+
+
+GST_START_TEST (test_parse_drain_single)
+{
+ gst_parser_test_drain_single (mpeg4_iframe, sizeof (mpeg4_iframe));
+}
+
+GST_END_TEST;
+
+
+GST_START_TEST (test_parse_split)
+{
+ gst_parser_test_split (mpeg4_iframe, sizeof (mpeg4_iframe));
+}
+
+GST_END_TEST;
+
+
+#define structure_get_int(s,f) \
+ (g_value_get_int(gst_structure_get_value(s,f)))
+#define fail_unless_structure_field_int_equals(s,field,num) \
+ fail_unless_equals_int (structure_get_int(s,field), num)
+
+GST_START_TEST (test_parse_detect_stream)
+{
+ GstCaps *caps;
+ GstStructure *s;
+ GstBuffer *buf;
+ const GValue *val;
+ GstMapInfo map;
+
+ caps = gst_parser_test_get_output_caps (mpeg4_iframe, sizeof (mpeg4_iframe),
+ NULL);
+ fail_unless (caps != NULL);
+
+ /* Check that the negotiated caps are as expected */
+ /* When codec_data is present, parser assumes that data is version 4 */
+ GST_LOG ("mpeg4video output caps: %" GST_PTR_FORMAT, caps);
+ s = gst_caps_get_structure (caps, 0);
+ fail_unless (gst_structure_has_name (s, "video/mpeg"));
+ fail_unless_structure_field_int_equals (s, "mpegversion", 4);
+ fail_unless_structure_field_int_equals (s, "width", 32);
+ fail_unless_structure_field_int_equals (s, "height", 24);
+ fail_unless (gst_structure_has_field (s, "codec_data"));
+
+ /* check codec-data in more detail */
+ val = gst_structure_get_value (s, "codec_data");
+ fail_unless (val != NULL);
+ buf = gst_value_get_buffer (val);
+ fail_unless (buf != NULL);
+ /* codec-data == config header - GOP */
+ gst_buffer_map (buf, &map, GST_MAP_READ);
+ fail_unless (map.size == sizeof (mpeg4_config) - 7);
+ fail_unless (memcmp (map.data, mpeg4_config, map.size) == 0);
+ gst_buffer_unmap (buf, &map);
+
+ gst_caps_unref (caps);
+}
+
+GST_END_TEST;
+
+
+static Suite *
+mpeg4videoparse_suite (void)
+{
+ Suite *s = suite_create ("mpeg4videoparse");
+ TCase *tc_chain = tcase_create ("general");
+
+ suite_add_tcase (s, tc_chain);
+ tcase_add_test (tc_chain, test_parse_normal);
+ tcase_add_test (tc_chain, test_parse_drain_single);
+ tcase_add_test (tc_chain, test_parse_split);
+ tcase_add_test (tc_chain, test_parse_detect_stream);
+
+ return s;
+}
+
+
+/*
+ * TODO:
+ * - Both push- and pull-modes need to be tested
+ * * Pull-mode & EOS
+ */
+
+int
+main (int argc, char **argv)
+{
+ int nf;
+
+ Suite *s = mpeg4videoparse_suite ();
+ SRunner *sr = srunner_create (s);
+
+ gst_check_init (&argc, &argv);
+
+ /* init test context */
+ ctx_factory = "mpeg4videoparse";
+ ctx_sink_template = &sinktemplate;
+ ctx_src_template = &srctemplate;
+ ctx_headers[0].data = mpeg4_config;
+ ctx_headers[0].size = sizeof (mpeg4_config);
+ ctx_verify_buffer = verify_buffer;
+ /* no timing info to parse */
+ ctx_no_metadata = TRUE;
+
+ srunner_run_all (sr, CK_NORMAL);
+ nf = srunner_ntests_failed (sr);
+ srunner_free (sr);
+
+ return nf;
+}
diff --git a/tests/check/elements/mpegtsmux.c b/tests/check/elements/mpegtsmux.c
new file mode 100644
index 00000000..a95cee1a
--- /dev/null
+++ b/tests/check/elements/mpegtsmux.c
@@ -0,0 +1,323 @@
+/* GStreamer
+ *
+ * Copyright (C) 2011 Alessandro Decina <alessandro.d@gmail.com>
+ *
+ * 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>
+#include <string.h>
+#include <gst/video/video.h>
+
+static GstStaticPadTemplate sink_template = GST_STATIC_PAD_TEMPLATE ("sink",
+ GST_PAD_SINK,
+ GST_PAD_ALWAYS,
+ GST_STATIC_CAPS_ANY);
+
+static GstStaticPadTemplate video_src_template = GST_STATIC_PAD_TEMPLATE ("src",
+ GST_PAD_SRC,
+ GST_PAD_ALWAYS,
+ GST_STATIC_CAPS ("video/x-h264")
+ );
+
+static GstStaticPadTemplate audio_src_template = GST_STATIC_PAD_TEMPLATE ("src",
+ GST_PAD_SRC,
+ GST_PAD_ALWAYS,
+ GST_STATIC_CAPS ("audio/mpeg")
+ );
+
+typedef struct _TestData
+{
+ GstEvent *sink_event;
+ GstEvent *src_event1;
+ GstEvent *src_event2;
+ gint src_events;
+} TestData;
+
+typedef struct _ThreadData
+{
+ GstPad *pad;
+ GstBuffer *buffer;
+ GstFlowReturn flow_return;
+ GThread *thread;
+} ThreadData;
+
+static gboolean
+src_event (GstPad * pad, GstObject * parent, GstEvent * event)
+{
+ TestData *data = (TestData *) gst_pad_get_element_private (pad);
+
+ if (event->type == GST_EVENT_CUSTOM_UPSTREAM) {
+ data->src_events += 1;
+ if (data->src_event1 != NULL)
+ data->src_event2 = event;
+ else
+ data->src_event1 = event;
+ }
+
+ return TRUE;
+}
+
+static gboolean
+sink_event (GstPad * pad, GstObject * parent, GstEvent * event)
+{
+ TestData *data = (TestData *) gst_pad_get_element_private (pad);
+
+ if (event->type == GST_EVENT_CUSTOM_DOWNSTREAM)
+ data->sink_event = event;
+
+ return TRUE;
+}
+
+static void
+link_sinks (GstElement * mpegtsmux,
+ GstPad ** src1, GstPad ** src2, GstPad ** src3, TestData * test_data)
+{
+ GstPad *mux_sink1, *mux_sink2, *mux_sink3;
+ GstCaps *caps;
+
+ /* link 3 sink pads, 2 video 1 audio */
+ *src1 = gst_pad_new_from_static_template (&video_src_template, "src1");
+ gst_pad_set_active (*src1, TRUE);
+ gst_pad_set_element_private (*src1, test_data);
+ gst_pad_set_event_function (*src1, src_event);
+ mux_sink1 = gst_element_get_request_pad (mpegtsmux, "sink_1");
+ fail_unless (gst_pad_link (*src1, mux_sink1) == GST_PAD_LINK_OK);
+
+ *src2 = gst_pad_new_from_static_template (&video_src_template, "src2");
+ gst_pad_set_active (*src2, TRUE);
+ gst_pad_set_element_private (*src2, test_data);
+ gst_pad_set_event_function (*src2, src_event);
+ mux_sink2 = gst_element_get_request_pad (mpegtsmux, "sink_2");
+ fail_unless (gst_pad_link (*src2, mux_sink2) == GST_PAD_LINK_OK);
+
+ *src3 = gst_pad_new_from_static_template (&audio_src_template, "src3");
+ gst_pad_set_active (*src3, TRUE);
+ gst_pad_set_element_private (*src3, test_data);
+ gst_pad_set_event_function (*src3, src_event);
+ mux_sink3 = gst_element_get_request_pad (mpegtsmux, "sink_3");
+ fail_unless (gst_pad_link (*src3, mux_sink3) == GST_PAD_LINK_OK);
+
+ caps = gst_caps_new_empty_simple ("video/x-h264");
+ gst_pad_set_caps (mux_sink1, caps);
+ gst_pad_set_caps (mux_sink2, caps);
+ gst_caps_unref (caps);
+ caps = gst_caps_new_simple ("audio/mpeg", "mpegversion", G_TYPE_INT, 4, NULL);
+ gst_pad_set_caps (mux_sink3, caps);
+ gst_caps_unref (caps);
+
+ gst_object_unref (mux_sink1);
+ gst_object_unref (mux_sink2);
+ gst_object_unref (mux_sink3);
+}
+
+static void
+link_src (GstElement * mpegtsmux, GstPad ** sink, TestData * test_data)
+{
+ GstPad *mux_src;
+
+ mux_src = gst_element_get_static_pad (mpegtsmux, "src");
+ *sink = gst_pad_new_from_static_template (&sink_template, "sink");
+ gst_pad_set_active (*sink, TRUE);
+ gst_pad_set_event_function (*sink, sink_event);
+ gst_pad_set_element_private (*sink, test_data);
+ fail_unless (gst_pad_link (mux_src, *sink) == GST_PAD_LINK_OK);
+
+ gst_object_unref (mux_src);
+}
+
+static gpointer
+pad_push_thread (gpointer user_data)
+{
+ ThreadData *data = (ThreadData *) user_data;
+
+ data->flow_return = gst_pad_push (data->pad, data->buffer);
+
+ return NULL;
+}
+
+static ThreadData *
+pad_push (GstPad * pad, GstBuffer * buffer, GstClockTime timestamp)
+{
+ ThreadData *data;
+
+ data = g_new0 (ThreadData, 1);
+ data->pad = pad;
+ data->buffer = buffer;
+ GST_BUFFER_TIMESTAMP (buffer) = timestamp;
+ data->thread = g_thread_create (pad_push_thread, data, TRUE, NULL);
+
+ return data;
+}
+
+GST_START_TEST (test_force_key_unit_event_downstream)
+{
+ GstElement *mpegtsmux;
+ GstPad *sink;
+ GstPad *src1;
+ GstPad *src2;
+ GstPad *src3;
+ GstEvent *sink_event;
+ GstClockTime timestamp, stream_time, running_time;
+ gboolean all_headers = TRUE;
+ gint count = 0;
+ ThreadData *thread_data_1, *thread_data_2, *thread_data_3, *thread_data_4;
+ TestData test_data = { 0, };
+
+ mpegtsmux = gst_check_setup_element ("mpegtsmux");
+ gst_element_set_state (mpegtsmux, GST_STATE_PLAYING);
+
+ link_src (mpegtsmux, &sink, &test_data);
+ link_sinks (mpegtsmux, &src1, &src2, &src3, &test_data);
+
+ /* hack: make sure collectpads builds collect->data */
+ gst_pad_push_event (src1, gst_event_new_flush_start ());
+ gst_pad_push_event (src1, gst_event_new_flush_stop (FALSE));
+
+ /* send a force-key-unit event with running_time=2s */
+ timestamp = stream_time = running_time = 2 * GST_SECOND;
+ sink_event = gst_video_event_new_downstream_force_key_unit (timestamp,
+ stream_time, running_time, all_headers, count);
+
+ fail_unless (gst_pad_push_event (src1, sink_event));
+ fail_unless (test_data.sink_event == NULL);
+
+ /* push 4 buffers, make sure mpegtsmux handles the force-key-unit event when
+ * the buffer with the requested running time is collected */
+ thread_data_1 = pad_push (src1, gst_buffer_new (), 1 * GST_SECOND);
+ thread_data_2 = pad_push (src2, gst_buffer_new (), 2 * GST_SECOND);
+ thread_data_3 = pad_push (src3, gst_buffer_new (), 3 * GST_SECOND);
+
+ g_thread_join (thread_data_1->thread);
+ fail_unless (test_data.sink_event == NULL);
+
+ /* push again on src1 so that the buffer on src2 is collected */
+ thread_data_4 = pad_push (src1, gst_buffer_new (), 4 * GST_SECOND);
+
+ g_thread_join (thread_data_2->thread);
+ fail_unless (test_data.sink_event != NULL);
+
+ gst_element_set_state (mpegtsmux, GST_STATE_NULL);
+
+ g_thread_join (thread_data_3->thread);
+ g_thread_join (thread_data_4->thread);
+
+ g_free (thread_data_1);
+ g_free (thread_data_2);
+ g_free (thread_data_3);
+ g_free (thread_data_4);
+ gst_object_unref (src1);
+ gst_object_unref (src2);
+ gst_object_unref (src3);
+ gst_object_unref (sink);
+ gst_object_unref (mpegtsmux);
+}
+
+GST_END_TEST;
+
+GST_START_TEST (test_force_key_unit_event_upstream)
+{
+ GstElement *mpegtsmux;
+ GstPad *sink;
+ GstPad *src1;
+ GstPad *src2;
+ GstPad *src3;
+ GstEvent *event;
+ GstClockTime timestamp, stream_time, running_time;
+ gboolean all_headers = TRUE;
+ gint count = 0;
+ TestData test_data = { 0, };
+ ThreadData *thread_data_1, *thread_data_2, *thread_data_3, *thread_data_4;
+
+ mpegtsmux = gst_check_setup_element ("mpegtsmux");
+ gst_element_set_state (mpegtsmux, GST_STATE_PLAYING);
+
+ link_src (mpegtsmux, &sink, &test_data);
+ link_sinks (mpegtsmux, &src1, &src2, &src3, &test_data);
+
+ /* hack: make sure collectpads builds collect->data */
+ gst_pad_push_event (src1, gst_event_new_flush_start ());
+ gst_pad_push_event (src1, gst_event_new_flush_stop (FALSE));
+
+ /* send an upstream force-key-unit event with running_time=2s */
+ timestamp = stream_time = running_time = 2 * GST_SECOND;
+ event =
+ gst_video_event_new_upstream_force_key_unit (running_time, TRUE, count);
+ fail_unless (gst_pad_push_event (sink, event));
+
+ fail_unless (test_data.sink_event == NULL);
+ fail_unless_equals_int (test_data.src_events, 3);
+
+ /* send downstream events with unrelated seqnums */
+ event = gst_video_event_new_downstream_force_key_unit (timestamp,
+ stream_time, running_time, all_headers, count);
+ fail_unless (gst_pad_push_event (src1, event));
+ event = gst_video_event_new_downstream_force_key_unit (timestamp,
+ stream_time, running_time, all_headers, count);
+ fail_unless (gst_pad_push_event (src2, event));
+
+ /* events should be skipped */
+ fail_unless (test_data.sink_event == NULL);
+
+ /* push 4 buffers, make sure mpegtsmux handles the force-key-unit event when
+ * the buffer with the requested running time is collected */
+ thread_data_1 = pad_push (src1, gst_buffer_new (), 1 * GST_SECOND);
+ thread_data_2 = pad_push (src2, gst_buffer_new (), 2 * GST_SECOND);
+ thread_data_3 = pad_push (src3, gst_buffer_new (), 3 * GST_SECOND);
+
+ g_thread_join (thread_data_1->thread);
+ fail_unless (test_data.sink_event == NULL);
+
+ /* push again on src1 so that the buffer on src2 is collected */
+ thread_data_4 = pad_push (src1, gst_buffer_new (), 4 * GST_SECOND);
+
+ g_thread_join (thread_data_2->thread);
+ fail_unless (test_data.sink_event != NULL);
+
+ gst_element_set_state (mpegtsmux, GST_STATE_NULL);
+
+ g_thread_join (thread_data_3->thread);
+ g_thread_join (thread_data_4->thread);
+
+ g_free (thread_data_1);
+ g_free (thread_data_2);
+ g_free (thread_data_3);
+ g_free (thread_data_4);
+
+ gst_object_unref (src1);
+ gst_object_unref (src2);
+ gst_object_unref (src3);
+ gst_object_unref (sink);
+ gst_object_unref (mpegtsmux);
+}
+
+GST_END_TEST;
+
+static Suite *
+mpegtsmux_suite (void)
+{
+ Suite *s = suite_create ("mpegtsmux");
+ TCase *tc_chain = tcase_create ("general");
+
+ suite_add_tcase (s, tc_chain);
+
+ tcase_add_test (tc_chain, test_force_key_unit_event_downstream);
+ tcase_add_test (tc_chain, test_force_key_unit_event_upstream);
+
+ return s;
+}
+
+GST_CHECK_MAIN (mpegtsmux);
diff --git a/tests/check/elements/mpegvideoparse.c b/tests/check/elements/mpegvideoparse.c
new file mode 100644
index 00000000..fd7a170c
--- /dev/null
+++ b/tests/check/elements/mpegvideoparse.c
@@ -0,0 +1,275 @@
+/*
+ * GStreamer
+ *
+ * unit test for mpegvideoparse
+ *
+ * Copyright (C) 2011 Nokia Corporation. All rights reserved.
+ *
+ * Contact: Stefan Kost <stefan.kost@nokia.com>
+ *
+ * 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>
+#include "parser.h"
+
+#define SRC_CAPS_TMPL "video/mpeg, framed=(boolean)false"
+#define SINK_CAPS_TMPL "video/mpeg, framed=(boolean)true"
+
+GstStaticPadTemplate sinktemplate = GST_STATIC_PAD_TEMPLATE ("sink",
+ GST_PAD_SINK,
+ GST_PAD_ALWAYS,
+ GST_STATIC_CAPS (SINK_CAPS_TMPL)
+ );
+
+GstStaticPadTemplate srctemplate = GST_STATIC_PAD_TEMPLATE ("src",
+ GST_PAD_SRC,
+ GST_PAD_ALWAYS,
+ GST_STATIC_CAPS (SRC_CAPS_TMPL)
+ );
+
+/* some data */
+
+/* actually seq + gop */
+static guint8 mpeg2_seq[] = {
+ 0x00, 0x00, 0x01, 0xb3, 0x02, 0x00, 0x18, 0x15,
+ 0xff, 0xff, 0xe0, 0x28, 0x00, 0x00, 0x01, 0xb5,
+ 0x14, 0x8a, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00,
+ 0x01, 0xb8, 0x00, 0x08, 0x00, 0x00
+};
+
+/* actually seq + gop */
+static guint8 mpeg1_seq[] = {
+ 0x00, 0x00, 0x01, 0xb3, 0x02, 0x00, 0x18, 0x15,
+ 0xff, 0xff, 0xe0, 0x28, 0x00, 0x00, 0x01, 0xb8,
+ 0x00, 0x08, 00, 00
+};
+
+/* keyframes all around */
+static guint8 mpeg2_iframe[] = {
+ 0x00, 0x00, 0x01, 0x00, 0x00, 0x0f, 0xff, 0xf8,
+ 0x00, 0x00, 0x01, 0xb5, 0x8f, 0xff, 0xf3, 0x41,
+ 0x80, 0x00, 0x00, 0x01, 0x01, 0x23, 0xf8, 0x7d,
+ 0x29, 0x48, 0x8b, 0x94, 0xa5, 0x22, 0x20, 0x00,
+ 0x00, 0x01, 0x02, 0x23, 0xf8, 0x7d, 0x29, 0x48,
+ 0x8b, 0x94, 0xa5, 0x22, 0x20
+};
+
+static gboolean
+verify_buffer (buffer_verify_data_s * vdata, GstBuffer * buffer)
+{
+ GstMapInfo map;
+
+ gst_buffer_map (buffer, &map, GST_MAP_READ);
+
+ /* check initial header special case, otherwise delegate to default */
+ if (vdata->discard) {
+ /* header is separate */
+ fail_unless (map.size == ctx_headers[0].size - 8);
+ fail_unless (memcmp (map.data, ctx_headers[0].data, map.size) == 0);
+ } else {
+ /* header is merged in initial frame */
+ if (vdata->buffer_counter == 0) {
+ fail_unless (map.size > 4);
+ if (GST_READ_UINT32_BE (map.data) == 0x1b3) {
+ /* the whole sequence header is included */
+ fail_unless (map.size ==
+ ctx_headers[0].size + vdata->data_to_verify_size);
+ fail_unless (memcmp (map.data, ctx_headers[0].data,
+ ctx_headers[0].size) == 0);
+ fail_unless (memcmp (map.data + ctx_headers[0].size,
+ vdata->data_to_verify, vdata->data_to_verify_size) == 0);
+ } else {
+ /* sequence was separate, only gop here */
+ fail_unless (map.size == 8 + vdata->data_to_verify_size);
+ fail_unless (memcmp (map.data,
+ ctx_headers[0].data + ctx_headers[0].size - 8, 8) == 0);
+ fail_unless (memcmp (map.data + 8,
+ vdata->data_to_verify, vdata->data_to_verify_size) == 0);
+ }
+ gst_buffer_unmap (buffer, &map);
+ return TRUE;
+ }
+ }
+ gst_buffer_unmap (buffer, &map);
+
+ return FALSE;
+}
+
+#define GOP_SPLIT "gop-split"
+
+static GstElement *
+setup_element (const gchar * desc)
+{
+ GstElement *element;
+
+ if (strcmp (desc, GOP_SPLIT) == 0) {
+ element = gst_check_setup_element ("mpegvideoparse");
+ g_object_set (G_OBJECT (element), "gop-split", TRUE, NULL);
+ } else {
+ element = gst_check_setup_element ("mpegvideoparse");
+ }
+
+ return element;
+}
+
+GST_START_TEST (test_parse_normal)
+{
+ gst_parser_test_normal (mpeg2_iframe, sizeof (mpeg2_iframe));
+}
+
+GST_END_TEST;
+
+
+GST_START_TEST (test_parse_drain_single)
+{
+ gst_parser_test_drain_single (mpeg2_iframe, sizeof (mpeg2_iframe));
+}
+
+GST_END_TEST;
+
+
+GST_START_TEST (test_parse_split)
+{
+ gst_parser_test_split (mpeg2_iframe, sizeof (mpeg2_iframe));
+}
+
+GST_END_TEST;
+
+
+#define structure_get_int(s,f) \
+ (g_value_get_int(gst_structure_get_value(s,f)))
+#define fail_unless_structure_field_int_equals(s,field,num) \
+ fail_unless_equals_int (structure_get_int(s,field), num)
+
+static void
+mpeg_video_parse_check_caps (guint version, guint8 * seq, gint size)
+{
+ GstCaps *caps;
+ GstStructure *s;
+ GstBuffer *buf;
+ const GValue *val;
+ GstMapInfo map;
+
+ ctx_headers[0].data = seq;
+ ctx_headers[0].size = size;
+ /* parser does not really care that mpeg1 and mpeg2 frame data
+ * should be a bit different */
+ caps = gst_parser_test_get_output_caps (mpeg2_iframe, sizeof (mpeg2_iframe),
+ NULL);
+ fail_unless (caps != NULL);
+
+ /* Check that the negotiated caps are as expected */
+ /* When codec_data is present, parser assumes that data is version 4 */
+ GST_LOG ("mpegvideo output caps: %" GST_PTR_FORMAT, caps);
+ s = gst_caps_get_structure (caps, 0);
+ fail_unless (gst_structure_has_name (s, "video/mpeg"));
+ fail_unless_structure_field_int_equals (s, "mpegversion", version);
+ fail_unless_structure_field_int_equals (s, "width", 32);
+ fail_unless_structure_field_int_equals (s, "height", 24);
+ fail_unless (gst_structure_has_field (s, "codec_data"));
+
+ /* check codec-data in more detail */
+ val = gst_structure_get_value (s, "codec_data");
+ fail_unless (val != NULL);
+ buf = gst_value_get_buffer (val);
+ fail_unless (buf != NULL);
+ gst_buffer_map (buf, &map, GST_MAP_READ);
+ /* codec-data = header - GOP */
+ assert_equals_int (map.size, size - 8);
+ fail_unless (memcmp (map.data, seq + 4, map.size) == 0);
+ gst_buffer_unmap (buf, &map);
+
+ gst_caps_unref (caps);
+}
+
+GST_START_TEST (test_parse_detect_stream_mpeg2)
+{
+ mpeg_video_parse_check_caps (2, mpeg2_seq, sizeof (mpeg2_seq));
+}
+
+GST_END_TEST;
+
+
+GST_START_TEST (test_parse_detect_stream_mpeg1)
+{
+ mpeg_video_parse_check_caps (1, mpeg1_seq, sizeof (mpeg1_seq));
+}
+
+GST_END_TEST;
+
+
+GST_START_TEST (test_parse_gop_split)
+{
+ ctx_factory = GOP_SPLIT;
+ ctx_discard = 1;
+ gst_parser_test_normal (mpeg2_iframe, sizeof (mpeg2_iframe));
+ ctx_factory = "mpegvideoparse";
+ ctx_discard = 0;
+}
+
+GST_END_TEST;
+
+
+static Suite *
+mpegvideoparse_suite (void)
+{
+ Suite *s = suite_create ("mpegvideoparse");
+ TCase *tc_chain = tcase_create ("general");
+
+ suite_add_tcase (s, tc_chain);
+ tcase_add_test (tc_chain, test_parse_normal);
+ tcase_add_test (tc_chain, test_parse_drain_single);
+ tcase_add_test (tc_chain, test_parse_split);
+ tcase_add_test (tc_chain, test_parse_detect_stream_mpeg1);
+ tcase_add_test (tc_chain, test_parse_detect_stream_mpeg2);
+ tcase_add_test (tc_chain, test_parse_gop_split);
+
+ return s;
+}
+
+
+/*
+ * TODO:
+ * - Both push- and pull-modes need to be tested
+ * * Pull-mode & EOS
+ */
+
+int
+main (int argc, char **argv)
+{
+ int nf;
+
+ Suite *s = mpegvideoparse_suite ();
+ SRunner *sr = srunner_create (s);
+
+ gst_check_init (&argc, &argv);
+
+ /* init test context */
+ ctx_factory = "mpegvideoparse";
+ ctx_sink_template = &sinktemplate;
+ ctx_src_template = &srctemplate;
+ ctx_headers[0].data = mpeg2_seq;
+ ctx_headers[0].size = sizeof (mpeg2_seq);
+ ctx_verify_buffer = verify_buffer;
+ ctx_setup = setup_element;
+
+ srunner_run_all (sr, CK_NORMAL);
+ nf = srunner_ntests_failed (sr);
+ srunner_free (sr);
+
+ return nf;
+}
diff --git a/tests/check/elements/mplex.c b/tests/check/elements/mplex.c
new file mode 100644
index 00000000..13a2c277
--- /dev/null
+++ b/tests/check/elements/mplex.c
@@ -0,0 +1,314 @@
+/* GStreamer
+ *
+ * unit test for mplex
+ *
+ * Copyright (C) <2008> Mark Nauwelaerts <mnauw@users.sourceforge.net>
+ *
+ * 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 <unistd.h>
+
+#include <gst/check/gstcheck.h>
+
+/* For ease of programming we use globals to keep refs for our floating
+ * src and sink pads we create; otherwise we always have to do get_pad,
+ * get_peer, and then remove references in every test function */
+static GstPad *mysrcpad, *mysinkpad;
+
+#define AUDIO_CAPS_STRING "audio/mpeg, " \
+ "mpegversion = (int) 1, " \
+ "layer = (int) 2, " \
+ "rate = (int) 48000, " \
+ "channels = (int) 1, " \
+ "framerate = (fraction) 25/1"
+
+#define MPEG_CAPS_STRING "video/mpeg, " \
+ "systemstream = (bool) true"
+
+static GstStaticPadTemplate sinktemplate = GST_STATIC_PAD_TEMPLATE ("sink",
+ GST_PAD_SINK,
+ GST_PAD_ALWAYS,
+ GST_STATIC_CAPS (MPEG_CAPS_STRING));
+
+static GstStaticPadTemplate srctemplate = GST_STATIC_PAD_TEMPLATE ("src",
+ GST_PAD_SRC,
+ GST_PAD_ALWAYS,
+ GST_STATIC_CAPS (AUDIO_CAPS_STRING));
+
+
+/* some global vars, makes it easy as for the ones above */
+static GMutex *mplex_mutex;
+static GCond *mplex_cond;
+static gboolean arrived_eos;
+
+/* another easy hack, some mp2 audio data that should please mplex
+ * perhaps less would also do, but anyway ...
+ */
+/* begin binary data: */
+guint8 mp2_data[] = /* 384 */
+{
+ 0xFF, 0xFD, 0x84, 0xC4, 0x75, 0x56, 0x46, 0x54, 0x54, 0x5B, 0x2E, 0xB0,
+ 0x80, 0x00, 0x00, 0xAB, 0xAA, 0xAE, 0x8A, 0xAC, 0xB4, 0xD7, 0x9D, 0xB6,
+ 0xDB, 0x5D, 0xB3, 0xDB, 0x8C, 0xF5, 0xCF, 0x8D, 0x38, 0xD2, 0xFB, 0xF3,
+ 0x66, 0x59, 0x6C, 0x62, 0x49, 0x16, 0x59, 0x65, 0xAC, 0xE8, 0x8C, 0x6F,
+ 0x18, 0x48, 0x6B, 0x96, 0xD0, 0xD2, 0x68, 0xA6, 0xC5, 0x42, 0x45, 0xA1,
+ 0x28, 0x42, 0xBC, 0xA3, 0x99, 0x39, 0x53, 0x20, 0xBA, 0x4A, 0x56, 0x30,
+ 0xC5, 0x81, 0xE6, 0x16, 0x6B, 0x77, 0x67, 0x24, 0x29, 0xA9, 0x11, 0x7E,
+ 0xA9, 0xA8, 0x41, 0xE1, 0x11, 0x48, 0x79, 0xB1, 0xC2, 0x30, 0x39, 0x2D,
+ 0x40, 0x9A, 0xEC, 0x12, 0x65, 0xC5, 0xDD, 0x68, 0x8D, 0x6A, 0xF4, 0x63,
+ 0x02, 0xAE, 0xE5, 0x1B, 0xAA, 0xA3, 0x87, 0x1B, 0xDE, 0xB8, 0x6B, 0x7A,
+ 0x9B, 0xAF, 0xF7, 0x1A, 0x39, 0x33, 0x9A, 0x17, 0x56, 0x64, 0x0D, 0xDC,
+ 0xE2, 0x15, 0xEF, 0x93, 0x24, 0x9A, 0x8E, 0x59, 0x49, 0x7D, 0x45, 0x68,
+ 0x2D, 0x9F, 0x85, 0x71, 0xA8, 0x99, 0xC4, 0x6D, 0x26, 0x46, 0x40, 0xBA,
+ 0x9A, 0xD6, 0x3D, 0xCF, 0x45, 0xB2, 0xC6, 0xF3, 0x16, 0x21, 0x8B, 0xA8,
+ 0xD5, 0x59, 0x78, 0x87, 0xB7, 0x42, 0x9A, 0x65, 0x59, 0x9A, 0x99, 0x58,
+ 0x71, 0x26, 0x20, 0x33, 0x76, 0xEE, 0x96, 0x70, 0xF2, 0xBC, 0xB3, 0x7D,
+ 0x6B, 0x35, 0x48, 0x37, 0x59, 0x21, 0xC4, 0x87, 0x8A, 0xD8, 0x05, 0x36,
+ 0xA5, 0x1A, 0x5C, 0x0A, 0x4F, 0x4B, 0x39, 0x40, 0x39, 0x9A, 0x17, 0xD9,
+ 0xAD, 0x21, 0xBE, 0x64, 0xB4, 0x6B, 0x13, 0x03, 0x20, 0x95, 0xDA, 0x18,
+ 0x89, 0x88, 0xB5, 0x44, 0xE2, 0x5D, 0x4F, 0x12, 0x19, 0xC4, 0x1A, 0x1A,
+ 0x07, 0x07, 0x91, 0xA8, 0x4C, 0x66, 0xB4, 0x81, 0x33, 0xDE, 0xDB, 0xD6,
+ 0x24, 0x17, 0xD2, 0x9A, 0x4E, 0xC9, 0x88, 0xAB, 0x44, 0xAA, 0x25, 0x4A,
+ 0x79, 0xA9, 0x39, 0x39, 0x0D, 0x2D, 0x20, 0x76, 0x68, 0x5F, 0x65, 0x25,
+ 0xCF, 0x29, 0x27, 0x67, 0xB3, 0x68, 0x6C, 0xE5, 0xDC, 0xA5, 0x79, 0xC9,
+ 0xAB, 0x46, 0x9D, 0x21, 0x35, 0x82, 0x98, 0xBA, 0x0E, 0x26, 0x39, 0x20,
+ 0xAE, 0x1B, 0x92, 0x3D, 0xF7, 0x9F, 0x29, 0xB5, 0xF3, 0xB6, 0x38, 0x68,
+ 0x65, 0x99, 0xAD, 0xD8, 0x98, 0x56, 0x5A, 0x61, 0x8D, 0xCB, 0x4A, 0x29,
+ 0x43, 0x0E, 0x2D, 0x33, 0x40, 0x6A, 0xB7, 0x5F, 0x49, 0xC9, 0x81, 0xE4,
+ 0x0D, 0x6F, 0x15, 0x58, 0x1B, 0x9E, 0x74, 0x20, 0x5D, 0x97, 0x5B, 0x5A,
+ 0xDF, 0x92, 0x2D, 0x5A, 0x98, 0xCE, 0x50, 0x20, 0x1A, 0x33, 0x6A, 0x67,
+ 0xE2, 0x18, 0x94, 0xA4, 0x70, 0x8F, 0x5F, 0x11, 0x85, 0xB0, 0xE5, 0xD8,
+ 0xD4, 0xAA, 0x86, 0xAE, 0x1C, 0x0D, 0xA1, 0x6B, 0x21, 0xB9, 0xC2, 0x17
+};
+
+/* end binary data. size = 384 bytes */
+
+static gboolean
+test_sink_event (GstPad * pad, GstObject * parent, GstEvent * event)
+{
+
+ switch (GST_EVENT_TYPE (event)) {
+ case GST_EVENT_EOS:
+ g_mutex_lock (mplex_mutex);
+ arrived_eos = TRUE;
+ g_cond_signal (mplex_cond);
+ g_mutex_unlock (mplex_mutex);
+ break;
+ default:
+ break;
+ }
+
+ return gst_pad_event_default (pad, parent, event);
+}
+
+/* setup and teardown needs some special handling for muxer */
+static GstPad *
+setup_src_pad (GstElement * element,
+ GstStaticPadTemplate * template, GstCaps * caps, const gchar * sinkname)
+{
+ GstPad *srcpad, *sinkpad;
+
+ GST_DEBUG_OBJECT (element, "setting up sending pad");
+ /* sending pad */
+ srcpad = gst_pad_new_from_static_template (template, "src");
+ fail_if (srcpad == NULL, "Could not create a srcpad");
+ ASSERT_OBJECT_REFCOUNT (srcpad, "srcpad", 1);
+
+ sinkpad = gst_element_get_request_pad (element, sinkname);
+ fail_if (sinkpad == NULL, "Could not get sink pad from %s",
+ GST_ELEMENT_NAME (element));
+ /* references are owned by: 1) us, 2) mplex, 3) mplex list */
+ ASSERT_OBJECT_REFCOUNT (sinkpad, "sinkpad", 3);
+ if (caps)
+ fail_unless (gst_pad_set_caps (srcpad, caps));
+ fail_unless (gst_pad_link (srcpad, sinkpad) == GST_PAD_LINK_OK,
+ "Could not link source and %s sink pads", GST_ELEMENT_NAME (element));
+ gst_object_unref (sinkpad); /* because we got it higher up */
+
+ /* references are owned by: 1) mplex, 2) mplex list */
+ ASSERT_OBJECT_REFCOUNT (sinkpad, "sinkpad", 2);
+
+ return srcpad;
+}
+
+static void
+teardown_src_pad (GstElement * element, const gchar * sinkname)
+{
+ GstPad *srcpad, *sinkpad;
+ gchar *padname;
+
+ /* clean up floating src pad */
+ padname = g_strdup (sinkname);
+ memcpy (strchr (padname, '%'), "0", 2);
+ sinkpad = gst_element_get_static_pad (element, padname);
+ g_free (padname);
+ /* pad refs held by 1) mplex 2) mplex list and 3) us (through _get) */
+ ASSERT_OBJECT_REFCOUNT (sinkpad, "sinkpad", 3);
+ srcpad = gst_pad_get_peer (sinkpad);
+
+ gst_pad_unlink (srcpad, sinkpad);
+
+ /* after unlinking, pad refs still held by
+ * 1) mplex and 2) mplex list and 3) us (through _get) */
+ ASSERT_OBJECT_REFCOUNT (sinkpad, "sinkpad", 3);
+ gst_object_unref (sinkpad);
+ /* one more ref is held by element itself */
+
+ /* pad refs held by both creator and this function (through _get_peer) */
+ ASSERT_OBJECT_REFCOUNT (srcpad, "srcpad", 2);
+ gst_object_unref (srcpad);
+ gst_object_unref (srcpad);
+
+}
+
+static GstElement *
+setup_mplex (void)
+{
+ GstElement *mplex;
+
+ GST_DEBUG ("setup_mplex");
+ mplex = gst_check_setup_element ("mplex");
+ mysrcpad = setup_src_pad (mplex, &srctemplate, NULL, "audio_%u");
+ mysinkpad = gst_check_setup_sink_pad (mplex, &sinktemplate);
+ gst_pad_set_active (mysrcpad, TRUE);
+ gst_pad_set_active (mysinkpad, TRUE);
+
+ /* need to know when we are eos */
+ gst_pad_set_event_function (mysinkpad, test_sink_event);
+
+ /* and notify the test run */
+ mplex_mutex = g_mutex_new ();
+ mplex_cond = g_cond_new ();
+
+ return mplex;
+}
+
+static void
+cleanup_mplex (GstElement * mplex)
+{
+ GST_DEBUG ("cleanup_mplex");
+ gst_element_set_state (mplex, GST_STATE_NULL);
+
+ gst_pad_set_active (mysrcpad, FALSE);
+ gst_pad_set_active (mysinkpad, FALSE);
+ teardown_src_pad (mplex, "audio_%u");
+ gst_check_teardown_sink_pad (mplex);
+ gst_check_teardown_element (mplex);
+
+ g_mutex_free (mplex_mutex);
+ g_cond_free (mplex_cond);
+
+ gst_deinit ();
+}
+
+GST_START_TEST (test_audio_pad)
+{
+ GstElement *mplex;
+ GstBuffer *inbuffer, *outbuffer;
+ GstCaps *caps;
+ int i, num_buffers;
+
+ /* PES pack_start_code */
+ guint8 data0[] = { 0x00, 0x00, 0x01, 0xba };
+ /* MPEG_program_end_code */
+ guint8 data1[] = { 0x00, 0x00, 0x01, 0xb9 };
+
+ mplex = setup_mplex ();
+ fail_unless (gst_element_set_state (mplex,
+ GST_STATE_PLAYING) == GST_STATE_CHANGE_SUCCESS,
+ "could not set to playing");
+
+ /* corresponds to I420 buffer for the size mentioned in the caps */
+ inbuffer = gst_buffer_new_and_alloc (sizeof (mp2_data));
+ gst_buffer_fill (inbuffer, 0, mp2_data, sizeof (mp2_data));
+ caps = gst_caps_from_string (AUDIO_CAPS_STRING);
+ gst_pad_set_caps (mysrcpad, caps);
+ gst_caps_unref (caps);
+ GST_BUFFER_TIMESTAMP (inbuffer) = 0;
+ ASSERT_BUFFER_REFCOUNT (inbuffer, "inbuffer", 1);
+ fail_unless (gst_pad_push (mysrcpad, inbuffer) == GST_FLOW_OK);
+
+ /* need to force eos and state change to make sure the encoding task ends */
+ fail_unless (gst_pad_push_event (mysrcpad, gst_event_new_eos ()) == TRUE);
+ /* need to wait a bit to make sure mplex task digested all this */
+ g_mutex_lock (mplex_mutex);
+ while (!arrived_eos)
+ g_cond_wait (mplex_cond, mplex_mutex);
+ g_mutex_unlock (mplex_mutex);
+
+ num_buffers = g_list_length (buffers);
+ /* well, we do not really know much with mplex, but at least something ... */
+ fail_unless (num_buffers >= 1);
+
+ /* clean up buffers */
+ for (i = 0; i < num_buffers; ++i) {
+ outbuffer = GST_BUFFER (buffers->data);
+ fail_if (outbuffer == NULL);
+
+ if (i == 0) {
+ fail_unless (gst_buffer_get_size (outbuffer) >= sizeof (data0));
+ fail_unless (gst_buffer_memcmp (outbuffer, 0, data0,
+ sizeof (data0)) == 0);
+ }
+ if (i == num_buffers - 1) {
+ fail_unless (gst_buffer_get_size (outbuffer) >= sizeof (data1));
+ fail_unless (gst_buffer_memcmp (outbuffer,
+ gst_buffer_get_size (outbuffer) - sizeof (data1), data1,
+ sizeof (data1)) == 0);
+ }
+ buffers = g_list_remove (buffers, outbuffer);
+
+ ASSERT_BUFFER_REFCOUNT (outbuffer, "outbuffer", 1);
+ gst_buffer_unref (outbuffer);
+ outbuffer = NULL;
+ }
+
+ cleanup_mplex (mplex);
+ g_list_free (buffers);
+ buffers = NULL;
+}
+
+GST_END_TEST;
+
+static Suite *
+mplex_suite (void)
+{
+ Suite *s = suite_create ("mplex");
+ TCase *tc_chain = tcase_create ("general");
+
+ suite_add_tcase (s, tc_chain);
+ tcase_add_test (tc_chain, test_audio_pad);
+
+ return s;
+}
+
+int
+main (int argc, char **argv)
+{
+ int nf;
+
+ Suite *s = mplex_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/mxfdemux.c b/tests/check/elements/mxfdemux.c
new file mode 100644
index 00000000..d84ae32a
--- /dev/null
+++ b/tests/check/elements/mxfdemux.c
@@ -0,0 +1,280 @@
+/* GStreamer
+ *
+ * unit test for mxfdemux
+ *
+ * Copyright (C) <2008> Sebastian Dröge <sebastian.droege@collabora.co.uk>
+ *
+ * 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>
+#include <string.h>
+#include "mxfdemux.h"
+
+static GstPad *mysrcpad, *mysinkpad;
+static GMainLoop *loop = NULL;
+static gboolean have_eos = FALSE;
+static gboolean have_data = FALSE;
+
+static GstStaticPadTemplate mysrctemplate =
+GST_STATIC_PAD_TEMPLATE ("src", GST_PAD_SRC, GST_PAD_ALWAYS,
+ GST_STATIC_CAPS ("application/mxf"));
+
+static GstStaticPadTemplate mysinktemplate =
+GST_STATIC_PAD_TEMPLATE ("sink", GST_PAD_SINK, GST_PAD_ALWAYS,
+ GST_STATIC_CAPS_ANY);
+
+static void
+_pad_added (GstElement * element, GstPad * pad, gpointer user_data)
+{
+ gchar *name = gst_pad_get_name (pad);
+
+ fail_unless_equals_string (name, "track_2");
+ fail_unless (gst_pad_link (pad, mysinkpad) == GST_PAD_LINK_OK);
+
+ g_free (name);
+}
+
+static void
+_sink_check_caps (GstPad * pad, GstCaps * caps)
+{
+ GstCaps *tcaps = gst_caps_new_simple ("audio/x-raw",
+ "rate", G_TYPE_INT, 11025,
+ "channels", G_TYPE_INT, 1,
+ "format", G_TYPE_STRING, "U8",
+ "layout", G_TYPE_STRING, "interleaved",
+ NULL);
+
+ fail_unless (gst_caps_is_always_compatible (caps, tcaps));
+ gst_caps_unref (tcaps);
+}
+
+static GstFlowReturn
+_sink_chain (GstPad * pad, GstObject * parent, GstBuffer * buffer)
+{
+ fail_unless_equals_int (gst_buffer_get_size (buffer), sizeof (mxf_essence));
+ fail_unless (gst_buffer_memcmp (buffer, 0, mxf_essence,
+ sizeof (mxf_essence)) == 0);
+
+ fail_unless (GST_BUFFER_TIMESTAMP (buffer) == 0);
+ fail_unless (GST_BUFFER_DURATION (buffer) == 200 * GST_MSECOND);
+
+ gst_buffer_unref (buffer);
+
+ have_data = TRUE;
+ return GST_FLOW_OK;
+}
+
+static gboolean
+_sink_event (GstPad * pad, GstObject * parent, GstEvent * event)
+{
+ switch (GST_EVENT_TYPE (event)) {
+ case GST_EVENT_EOS:
+ if (loop) {
+ while (!g_main_loop_is_running (loop));
+ }
+
+ have_eos = TRUE;
+ if (loop)
+ g_main_loop_quit (loop);
+ break;
+ case GST_EVENT_CAPS:
+ {
+ GstCaps *caps;
+
+ gst_event_parse_caps (event, &caps);
+ _sink_check_caps (pad, caps);
+ break;
+ }
+ default:
+ break;
+ }
+
+ gst_event_unref (event);
+
+ return TRUE;
+}
+
+static GstPad *
+_create_sink_pad (void)
+{
+ mysinkpad = gst_pad_new_from_static_template (&mysinktemplate, "sink");
+
+ gst_pad_set_chain_function (mysinkpad, _sink_chain);
+ gst_pad_set_event_function (mysinkpad, _sink_event);
+
+ return mysinkpad;
+}
+
+static GstPad *
+_create_src_pad_push (void)
+{
+ mysrcpad = gst_pad_new_from_static_template (&mysrctemplate, "src");
+
+ return mysrcpad;
+}
+
+static GstFlowReturn
+_src_getrange (GstPad * pad, GstObject * parent, guint64 offset, guint length,
+ GstBuffer ** buffer)
+{
+ if (offset + length > sizeof (mxf_file))
+ return GST_FLOW_EOS;
+
+ *buffer = gst_buffer_new_wrapped_full (GST_MEMORY_FLAG_READONLY,
+ (guint8 *) (mxf_file + offset), length, 0, length, NULL, NULL);
+
+ return GST_FLOW_OK;
+}
+
+static gboolean
+_src_query (GstPad * pad, GstObject * parent, GstQuery * query)
+{
+ GstFormat fmt;
+
+ if (GST_QUERY_TYPE (query) != GST_QUERY_DURATION)
+ return FALSE;
+
+ gst_query_parse_duration (query, &fmt, NULL);
+
+ if (fmt != GST_FORMAT_BYTES)
+ return FALSE;
+
+ gst_query_set_duration (query, fmt, sizeof (mxf_file));
+
+ return TRUE;
+}
+
+static GstPad *
+_create_src_pad_pull (void)
+{
+ mysrcpad = gst_pad_new_from_static_template (&mysrctemplate, "src");
+ gst_pad_set_getrange_function (mysrcpad, _src_getrange);
+ gst_pad_set_query_function (mysrcpad, _src_query);
+
+ return mysrcpad;
+}
+
+GST_START_TEST (test_pull)
+{
+ GstElement *mxfdemux;
+ GstPad *sinkpad;
+
+ have_eos = FALSE;
+ have_data = FALSE;
+ loop = g_main_loop_new (NULL, FALSE);
+
+ mxfdemux = gst_element_factory_make ("mxfdemux", NULL);
+ fail_unless (mxfdemux != NULL);
+ g_signal_connect (mxfdemux, "pad-added", G_CALLBACK (_pad_added), NULL);
+ sinkpad = gst_element_get_static_pad (mxfdemux, "sink");
+ fail_unless (sinkpad != NULL);
+
+ mysinkpad = _create_sink_pad ();
+ fail_unless (mysinkpad != NULL);
+ mysrcpad = _create_src_pad_pull ();
+ fail_unless (mysrcpad != NULL);
+
+ fail_unless (gst_pad_link (mysrcpad, sinkpad) == GST_PAD_LINK_OK);
+ gst_object_unref (sinkpad);
+
+ gst_pad_set_active (mysinkpad, TRUE);
+ gst_pad_set_active (mysrcpad, TRUE);
+
+ gst_element_set_state (mxfdemux, GST_STATE_PLAYING);
+
+ g_main_loop_run (loop);
+ fail_unless (have_eos == TRUE);
+ fail_unless (have_data == TRUE);
+
+ gst_element_set_state (mxfdemux, GST_STATE_NULL);
+ gst_pad_set_active (mysinkpad, FALSE);
+ gst_pad_set_active (mysrcpad, FALSE);
+
+ gst_object_unref (mxfdemux);
+ gst_object_unref (mysinkpad);
+ gst_object_unref (mysrcpad);
+ g_main_loop_unref (loop);
+ loop = NULL;
+}
+
+GST_END_TEST;
+
+GST_START_TEST (test_push)
+{
+ GstElement *mxfdemux;
+ GstBuffer *buffer;
+ GstPad *sinkpad;
+
+ have_data = FALSE;
+ have_eos = FALSE;
+
+ mxfdemux = gst_element_factory_make ("mxfdemux", NULL);
+ fail_unless (mxfdemux != NULL);
+ g_signal_connect (mxfdemux, "pad-added", G_CALLBACK (_pad_added), NULL);
+ sinkpad = gst_element_get_static_pad (mxfdemux, "sink");
+ fail_unless (sinkpad != NULL);
+
+ buffer =
+ gst_buffer_new_wrapped_full (GST_MEMORY_FLAG_READONLY,
+ (guint8 *) mxf_file, sizeof (mxf_file), 0, sizeof (mxf_file), NULL, NULL);
+ GST_BUFFER_OFFSET (buffer) = 0;
+
+ mysinkpad = _create_sink_pad ();
+ fail_unless (mysinkpad != NULL);
+ mysrcpad = _create_src_pad_push ();
+ fail_unless (mysrcpad != NULL);
+
+ fail_unless (gst_pad_link (mysrcpad, sinkpad) == GST_PAD_LINK_OK);
+ gst_object_unref (sinkpad);
+
+ gst_pad_set_active (mysinkpad, TRUE);
+ gst_pad_set_active (mysrcpad, TRUE);
+
+ gst_element_set_state (mxfdemux, GST_STATE_PLAYING);
+
+ fail_unless (gst_pad_push (mysrcpad, buffer) == GST_FLOW_OK);
+ fail_unless (gst_pad_push_event (mysrcpad, gst_event_new_eos ()));
+
+ fail_unless (have_eos == TRUE);
+ fail_unless (have_data == TRUE);
+
+ gst_element_set_state (mxfdemux, GST_STATE_NULL);
+ gst_pad_set_active (mysinkpad, FALSE);
+ gst_pad_set_active (mysrcpad, FALSE);
+
+ gst_object_unref (mxfdemux);
+ gst_object_unref (mysinkpad);
+ gst_object_unref (mysrcpad);
+}
+
+GST_END_TEST;
+
+static Suite *
+mxfdemux_suite (void)
+{
+ Suite *s = suite_create ("mxfdemux");
+ TCase *tc_chain = tcase_create ("general");
+
+ suite_add_tcase (s, tc_chain);
+ tcase_set_timeout (tc_chain, 180);
+ tcase_add_test (tc_chain, test_pull);
+ tcase_add_test (tc_chain, test_push);
+
+ return s;
+}
+
+GST_CHECK_MAIN (mxfdemux);
diff --git a/tests/check/elements/mxfdemux.h b/tests/check/elements/mxfdemux.h
new file mode 100644
index 00000000..3ad0ed30
--- /dev/null
+++ b/tests/check/elements/mxfdemux.h
@@ -0,0 +1,2552 @@
+/* Very simple MXF file containing BWF audio. Taken
+ from the Ingex project.
+ */
+#include <glib.h>
+
+static const guint8 mxf_essence[] = {
+ 0x74, 0x5d, 0x8c, 0x69, 0x74, 0x80, 0x69, 0x80,
+ 0x5d, 0x80, 0x80, 0x74, 0x8c, 0x69, 0x80, 0x74
+};
+
+static const guint8 mxf_file[] = {
+ 0x06, 0x0e, 0x2b, 0x34, 0x02, 0x05, 0x01, 0x01,
+ 0x0d, 0x01, 0x02, 0x01, 0x01, 0x02, 0x04, 0x00,
+ 0x83, 0x00, 0x00, 0x78, 0x00, 0x01, 0x00, 0x02,
+ 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x4e, 0x3f, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x4d, 0x8f, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x01, 0x06, 0x0e, 0x2b, 0x34,
+ 0x04, 0x01, 0x01, 0x01, 0x0d, 0x01, 0x02, 0x01,
+ 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02,
+ 0x00, 0x00, 0x00, 0x10, 0x06, 0x0e, 0x2b, 0x34,
+ 0x04, 0x01, 0x01, 0x03, 0x0d, 0x01, 0x03, 0x01,
+ 0x02, 0x7f, 0x01, 0x00, 0x06, 0x0e, 0x2b, 0x34,
+ 0x04, 0x01, 0x01, 0x02, 0x0d, 0x01, 0x03, 0x01,
+ 0x02, 0x06, 0x01, 0x00, 0x06, 0x0e, 0x2b, 0x34,
+ 0x02, 0x05, 0x01, 0x01, 0x0d, 0x01, 0x02, 0x01,
+ 0x01, 0x05, 0x01, 0x00, 0x83, 0x00, 0x03, 0xb0,
+ 0x00, 0x00, 0x00, 0x34, 0x00, 0x00, 0x00, 0x12,
+ 0x01, 0x02, 0x06, 0x0e, 0x2b, 0x34, 0x01, 0x01,
+ 0x01, 0x02, 0x05, 0x20, 0x07, 0x01, 0x08, 0x00,
+ 0x00, 0x00, 0x02, 0x01, 0x06, 0x0e, 0x2b, 0x34,
+ 0x01, 0x01, 0x01, 0x02, 0x04, 0x07, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x02, 0x02, 0x06, 0x0e,
+ 0x2b, 0x34, 0x01, 0x01, 0x01, 0x02, 0x07, 0x02,
+ 0x02, 0x01, 0x01, 0x03, 0x00, 0x00, 0x10, 0x01,
+ 0x06, 0x0e, 0x2b, 0x34, 0x01, 0x01, 0x01, 0x02,
+ 0x06, 0x01, 0x01, 0x04, 0x06, 0x09, 0x00, 0x00,
+ 0x11, 0x01, 0x06, 0x0e, 0x2b, 0x34, 0x01, 0x01,
+ 0x01, 0x02, 0x06, 0x01, 0x01, 0x03, 0x01, 0x00,
+ 0x00, 0x00, 0x11, 0x02, 0x06, 0x0e, 0x2b, 0x34,
+ 0x01, 0x01, 0x01, 0x02, 0x06, 0x01, 0x01, 0x03,
+ 0x02, 0x00, 0x00, 0x00, 0x12, 0x01, 0x06, 0x0e,
+ 0x2b, 0x34, 0x01, 0x01, 0x01, 0x02, 0x07, 0x02,
+ 0x01, 0x03, 0x01, 0x04, 0x00, 0x00, 0x15, 0x01,
+ 0x06, 0x0e, 0x2b, 0x34, 0x01, 0x01, 0x01, 0x02,
+ 0x07, 0x02, 0x01, 0x03, 0x01, 0x05, 0x00, 0x00,
+ 0x15, 0x02, 0x06, 0x0e, 0x2b, 0x34, 0x01, 0x01,
+ 0x01, 0x02, 0x04, 0x04, 0x01, 0x01, 0x02, 0x06,
+ 0x00, 0x00, 0x15, 0x03, 0x06, 0x0e, 0x2b, 0x34,
+ 0x01, 0x01, 0x01, 0x01, 0x04, 0x04, 0x01, 0x01,
+ 0x05, 0x00, 0x00, 0x00, 0x19, 0x01, 0x06, 0x0e,
+ 0x2b, 0x34, 0x01, 0x01, 0x01, 0x02, 0x06, 0x01,
+ 0x01, 0x04, 0x05, 0x01, 0x00, 0x00, 0x19, 0x02,
+ 0x06, 0x0e, 0x2b, 0x34, 0x01, 0x01, 0x01, 0x02,
+ 0x06, 0x01, 0x01, 0x04, 0x05, 0x02, 0x00, 0x00,
+ 0x27, 0x01, 0x06, 0x0e, 0x2b, 0x34, 0x01, 0x01,
+ 0x01, 0x02, 0x06, 0x01, 0x01, 0x06, 0x01, 0x00,
+ 0x00, 0x00, 0x30, 0x01, 0x06, 0x0e, 0x2b, 0x34,
+ 0x01, 0x01, 0x01, 0x01, 0x04, 0x06, 0x01, 0x01,
+ 0x00, 0x00, 0x00, 0x00, 0x30, 0x02, 0x06, 0x0e,
+ 0x2b, 0x34, 0x01, 0x01, 0x01, 0x01, 0x04, 0x06,
+ 0x01, 0x02, 0x00, 0x00, 0x00, 0x00, 0x30, 0x04,
+ 0x06, 0x0e, 0x2b, 0x34, 0x01, 0x01, 0x01, 0x02,
+ 0x06, 0x01, 0x01, 0x04, 0x01, 0x02, 0x00, 0x00,
+ 0x30, 0x06, 0x06, 0x0e, 0x2b, 0x34, 0x01, 0x01,
+ 0x01, 0x05, 0x06, 0x01, 0x01, 0x03, 0x05, 0x00,
+ 0x00, 0x00, 0x3b, 0x02, 0x06, 0x0e, 0x2b, 0x34,
+ 0x01, 0x01, 0x01, 0x02, 0x07, 0x02, 0x01, 0x10,
+ 0x02, 0x04, 0x00, 0x00, 0x3b, 0x03, 0x06, 0x0e,
+ 0x2b, 0x34, 0x01, 0x01, 0x01, 0x02, 0x06, 0x01,
+ 0x01, 0x04, 0x02, 0x01, 0x00, 0x00, 0x3b, 0x05,
+ 0x06, 0x0e, 0x2b, 0x34, 0x01, 0x01, 0x01, 0x02,
+ 0x03, 0x01, 0x02, 0x01, 0x05, 0x00, 0x00, 0x00,
+ 0x3b, 0x06, 0x06, 0x0e, 0x2b, 0x34, 0x01, 0x01,
+ 0x01, 0x02, 0x06, 0x01, 0x01, 0x04, 0x06, 0x04,
+ 0x00, 0x00, 0x3b, 0x08, 0x06, 0x0e, 0x2b, 0x34,
+ 0x01, 0x01, 0x01, 0x04, 0x06, 0x01, 0x01, 0x04,
+ 0x01, 0x08, 0x00, 0x00, 0x3b, 0x09, 0x06, 0x0e,
+ 0x2b, 0x34, 0x01, 0x01, 0x01, 0x05, 0x01, 0x02,
+ 0x02, 0x03, 0x00, 0x00, 0x00, 0x00, 0x3b, 0x0a,
+ 0x06, 0x0e, 0x2b, 0x34, 0x01, 0x01, 0x01, 0x05,
+ 0x01, 0x02, 0x02, 0x10, 0x02, 0x01, 0x00, 0x00,
+ 0x3b, 0x0b, 0x06, 0x0e, 0x2b, 0x34, 0x01, 0x01,
+ 0x01, 0x05, 0x01, 0x02, 0x02, 0x10, 0x02, 0x02,
+ 0x00, 0x00, 0x3c, 0x01, 0x06, 0x0e, 0x2b, 0x34,
+ 0x01, 0x01, 0x01, 0x02, 0x05, 0x20, 0x07, 0x01,
+ 0x02, 0x01, 0x00, 0x00, 0x3c, 0x02, 0x06, 0x0e,
+ 0x2b, 0x34, 0x01, 0x01, 0x01, 0x02, 0x05, 0x20,
+ 0x07, 0x01, 0x03, 0x01, 0x00, 0x00, 0x3c, 0x04,
+ 0x06, 0x0e, 0x2b, 0x34, 0x01, 0x01, 0x01, 0x02,
+ 0x05, 0x20, 0x07, 0x01, 0x05, 0x01, 0x00, 0x00,
+ 0x3c, 0x05, 0x06, 0x0e, 0x2b, 0x34, 0x01, 0x01,
+ 0x01, 0x02, 0x05, 0x20, 0x07, 0x01, 0x07, 0x00,
+ 0x00, 0x00, 0x3c, 0x06, 0x06, 0x0e, 0x2b, 0x34,
+ 0x01, 0x01, 0x01, 0x02, 0x07, 0x02, 0x01, 0x10,
+ 0x02, 0x03, 0x00, 0x00, 0x3c, 0x09, 0x06, 0x0e,
+ 0x2b, 0x34, 0x01, 0x01, 0x01, 0x02, 0x05, 0x20,
+ 0x07, 0x01, 0x01, 0x00, 0x00, 0x00, 0x3c, 0x0a,
+ 0x06, 0x0e, 0x2b, 0x34, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x15, 0x02, 0x00, 0x00, 0x00, 0x00,
+ 0x3d, 0x01, 0x06, 0x0e, 0x2b, 0x34, 0x01, 0x01,
+ 0x01, 0x04, 0x04, 0x02, 0x03, 0x03, 0x04, 0x00,
+ 0x00, 0x00, 0x3d, 0x02, 0x06, 0x0e, 0x2b, 0x34,
+ 0x01, 0x01, 0x01, 0x04, 0x04, 0x02, 0x03, 0x01,
+ 0x04, 0x00, 0x00, 0x00, 0x3d, 0x03, 0x06, 0x0e,
+ 0x2b, 0x34, 0x01, 0x01, 0x01, 0x05, 0x04, 0x02,
+ 0x03, 0x01, 0x01, 0x01, 0x00, 0x00, 0x3d, 0x07,
+ 0x06, 0x0e, 0x2b, 0x34, 0x01, 0x01, 0x01, 0x05,
+ 0x04, 0x02, 0x01, 0x01, 0x04, 0x00, 0x00, 0x00,
+ 0x3d, 0x09, 0x06, 0x0e, 0x2b, 0x34, 0x01, 0x01,
+ 0x01, 0x05, 0x04, 0x02, 0x03, 0x03, 0x05, 0x00,
+ 0x00, 0x00, 0x3d, 0x0a, 0x06, 0x0e, 0x2b, 0x34,
+ 0x01, 0x01, 0x01, 0x05, 0x04, 0x02, 0x03, 0x02,
+ 0x01, 0x00, 0x00, 0x00, 0x3f, 0x06, 0x06, 0x0e,
+ 0x2b, 0x34, 0x01, 0x01, 0x01, 0x04, 0x01, 0x03,
+ 0x04, 0x05, 0x00, 0x00, 0x00, 0x00, 0x3f, 0x07,
+ 0x06, 0x0e, 0x2b, 0x34, 0x01, 0x01, 0x01, 0x04,
+ 0x01, 0x03, 0x04, 0x04, 0x00, 0x00, 0x00, 0x00,
+ 0x44, 0x01, 0x06, 0x0e, 0x2b, 0x34, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x01, 0x15, 0x10, 0x00, 0x00,
+ 0x00, 0x00, 0x44, 0x02, 0x06, 0x0e, 0x2b, 0x34,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x03, 0x03, 0x02,
+ 0x01, 0x00, 0x00, 0x00, 0x44, 0x03, 0x06, 0x0e,
+ 0x2b, 0x34, 0x01, 0x01, 0x01, 0x02, 0x06, 0x01,
+ 0x01, 0x04, 0x06, 0x05, 0x00, 0x00, 0x44, 0x04,
+ 0x06, 0x0e, 0x2b, 0x34, 0x01, 0x01, 0x01, 0x02,
+ 0x07, 0x02, 0x01, 0x10, 0x02, 0x05, 0x00, 0x00,
+ 0x44, 0x05, 0x06, 0x0e, 0x2b, 0x34, 0x01, 0x01,
+ 0x01, 0x02, 0x07, 0x02, 0x01, 0x10, 0x01, 0x03,
+ 0x00, 0x00, 0x47, 0x01, 0x06, 0x0e, 0x2b, 0x34,
+ 0x01, 0x01, 0x01, 0x02, 0x06, 0x01, 0x01, 0x04,
+ 0x02, 0x03, 0x00, 0x00, 0x48, 0x01, 0x06, 0x0e,
+ 0x2b, 0x34, 0x01, 0x01, 0x01, 0x02, 0x01, 0x07,
+ 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x48, 0x02,
+ 0x06, 0x0e, 0x2b, 0x34, 0x01, 0x01, 0x01, 0x02,
+ 0x01, 0x07, 0x01, 0x02, 0x01, 0x00, 0x00, 0x00,
+ 0x48, 0x03, 0x06, 0x0e, 0x2b, 0x34, 0x01, 0x01,
+ 0x01, 0x02, 0x06, 0x01, 0x01, 0x04, 0x02, 0x04,
+ 0x00, 0x00, 0x48, 0x04, 0x06, 0x0e, 0x2b, 0x34,
+ 0x01, 0x01, 0x01, 0x02, 0x01, 0x04, 0x01, 0x03,
+ 0x00, 0x00, 0x00, 0x00, 0x4b, 0x01, 0x06, 0x0e,
+ 0x2b, 0x34, 0x01, 0x01, 0x01, 0x02, 0x05, 0x30,
+ 0x04, 0x05, 0x00, 0x00, 0x00, 0x00, 0x4b, 0x02,
+ 0x06, 0x0e, 0x2b, 0x34, 0x01, 0x01, 0x01, 0x02,
+ 0x07, 0x02, 0x01, 0x03, 0x01, 0x03, 0x00, 0x00,
+ 0x06, 0x0e, 0x2b, 0x34, 0x02, 0x53, 0x01, 0x01,
+ 0x0d, 0x01, 0x01, 0x01, 0x01, 0x01, 0x2f, 0x00,
+ 0x83, 0x00, 0x00, 0xda, 0x3c, 0x0a, 0x00, 0x10,
+ 0x5d, 0xce, 0xec, 0x07, 0x72, 0xe0, 0x4b, 0xfd,
+ 0x95, 0xde, 0x33, 0x15, 0x18, 0x9c, 0x0c, 0x38,
+ 0x3b, 0x02, 0x00, 0x08, 0x07, 0xd4, 0x04, 0x1a,
+ 0x0e, 0x12, 0x1d, 0x5c, 0x3b, 0x05, 0x00, 0x02,
+ 0x01, 0x02, 0x3b, 0x06, 0x00, 0x28, 0x00, 0x00,
+ 0x00, 0x02, 0x00, 0x00, 0x00, 0x10, 0x1b, 0xe6,
+ 0x28, 0xa1, 0xa1, 0x47, 0x4c, 0x87, 0xad, 0xc6,
+ 0x6a, 0xce, 0x8a, 0x93, 0x51, 0xb3, 0x2c, 0xf4,
+ 0xbc, 0x4e, 0x65, 0x7f, 0x4e, 0x05, 0x87, 0xb4,
+ 0x4c, 0xfd, 0xaa, 0xe3, 0x0a, 0x2b, 0x3b, 0x0a,
+ 0x00, 0x28, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00,
+ 0x00, 0x10, 0x06, 0x0e, 0x2b, 0x34, 0x04, 0x01,
+ 0x01, 0x03, 0x0d, 0x01, 0x03, 0x01, 0x02, 0x7f,
+ 0x01, 0x00, 0x06, 0x0e, 0x2b, 0x34, 0x04, 0x01,
+ 0x01, 0x02, 0x0d, 0x01, 0x03, 0x01, 0x02, 0x06,
+ 0x01, 0x00, 0x3b, 0x0b, 0x00, 0x08, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x3b, 0x03,
+ 0x00, 0x10, 0x89, 0x8a, 0x44, 0x70, 0x32, 0x7a,
+ 0x40, 0xaa, 0x9c, 0x41, 0xc6, 0xc6, 0x3a, 0x64,
+ 0x77, 0x18, 0x3b, 0x09, 0x00, 0x10, 0x06, 0x0e,
+ 0x2b, 0x34, 0x04, 0x01, 0x01, 0x01, 0x0d, 0x01,
+ 0x02, 0x01, 0x10, 0x00, 0x00, 0x00, 0x3b, 0x08,
+ 0x00, 0x10, 0x08, 0x7c, 0x01, 0x83, 0xbe, 0xde,
+ 0x4f, 0x1e, 0x8b, 0x1e, 0x16, 0x33, 0x6e, 0x35,
+ 0xc4, 0x5e, 0x01, 0x02, 0x00, 0x10, 0x35, 0xac,
+ 0x10, 0x04, 0x0e, 0xe7, 0x4e, 0x21, 0x94, 0xbf,
+ 0x0d, 0xf4, 0xe4, 0xe5, 0x24, 0x14, 0x06, 0x0e,
+ 0x2b, 0x34, 0x02, 0x53, 0x01, 0x01, 0x0d, 0x01,
+ 0x01, 0x01, 0x01, 0x01, 0x30, 0x00, 0x83, 0x00,
+ 0x00, 0xc4, 0x3c, 0x01, 0x00, 0x16, 0x00, 0x46,
+ 0x00, 0x72, 0x00, 0x65, 0x00, 0x65, 0x00, 0x4d,
+ 0x00, 0x58, 0x00, 0x46, 0x00, 0x2e, 0x00, 0x6f,
+ 0x00, 0x72, 0x00, 0x67, 0x3c, 0x02, 0x00, 0x28,
+ 0x00, 0x6d, 0x00, 0x78, 0x00, 0x66, 0x00, 0x77,
+ 0x00, 0x72, 0x00, 0x61, 0x00, 0x70, 0x00, 0x20,
+ 0x00, 0x66, 0x00, 0x69, 0x00, 0x6c, 0x00, 0x65,
+ 0x00, 0x20, 0x00, 0x77, 0x00, 0x72, 0x00, 0x61,
+ 0x00, 0x70, 0x00, 0x70, 0x00, 0x65, 0x00, 0x72,
+ 0x3c, 0x04, 0x00, 0x32, 0x00, 0x55, 0x00, 0x6e,
+ 0x00, 0x72, 0x00, 0x65, 0x00, 0x6c, 0x00, 0x65,
+ 0x00, 0x61, 0x00, 0x73, 0x00, 0x65, 0x00, 0x64,
+ 0x00, 0x20, 0x00, 0x6d, 0x00, 0x78, 0x00, 0x66,
+ 0x00, 0x6c, 0x00, 0x69, 0x00, 0x62, 0x00, 0x20,
+ 0x00, 0x30, 0x00, 0x2e, 0x00, 0x33, 0x00, 0x2e,
+ 0x00, 0x33, 0x00, 0x2e, 0x00, 0x31, 0x3c, 0x05,
+ 0x00, 0x10, 0x84, 0x66, 0x14, 0xf3, 0x27, 0xdd,
+ 0xde, 0x40, 0x86, 0xdc, 0xe0, 0x99, 0xda, 0x7f,
+ 0xd0, 0x52, 0x3c, 0x06, 0x00, 0x08, 0x07, 0xd4,
+ 0x04, 0x1a, 0x0e, 0x12, 0x1d, 0x57, 0x3c, 0x0a,
+ 0x00, 0x10, 0x1b, 0xe6, 0x28, 0xa1, 0xa1, 0x47,
+ 0x4c, 0x87, 0xad, 0xc6, 0x6a, 0xce, 0x8a, 0x93,
+ 0x51, 0xb3, 0x3c, 0x09, 0x00, 0x10, 0x3f, 0x12,
+ 0xad, 0x30, 0x44, 0xea, 0x40, 0xe2, 0xbe, 0x1c,
+ 0x1a, 0x48, 0xe6, 0x0c, 0xc7, 0x13, 0x06, 0x0e,
+ 0x2b, 0x34, 0x02, 0x53, 0x01, 0x01, 0x0d, 0x01,
+ 0x01, 0x01, 0x01, 0x01, 0x30, 0x00, 0x83, 0x00,
+ 0x00, 0xc4, 0x3c, 0x01, 0x00, 0x16, 0x00, 0x46,
+ 0x00, 0x72, 0x00, 0x65, 0x00, 0x65, 0x00, 0x4d,
+ 0x00, 0x58, 0x00, 0x46, 0x00, 0x2e, 0x00, 0x6f,
+ 0x00, 0x72, 0x00, 0x67, 0x3c, 0x02, 0x00, 0x28,
+ 0x00, 0x6d, 0x00, 0x78, 0x00, 0x66, 0x00, 0x77,
+ 0x00, 0x72, 0x00, 0x61, 0x00, 0x70, 0x00, 0x20,
+ 0x00, 0x66, 0x00, 0x69, 0x00, 0x6c, 0x00, 0x65,
+ 0x00, 0x20, 0x00, 0x77, 0x00, 0x72, 0x00, 0x61,
+ 0x00, 0x70, 0x00, 0x70, 0x00, 0x65, 0x00, 0x72,
+ 0x3c, 0x04, 0x00, 0x32, 0x00, 0x55, 0x00, 0x6e,
+ 0x00, 0x72, 0x00, 0x65, 0x00, 0x6c, 0x00, 0x65,
+ 0x00, 0x61, 0x00, 0x73, 0x00, 0x65, 0x00, 0x64,
+ 0x00, 0x20, 0x00, 0x6d, 0x00, 0x78, 0x00, 0x66,
+ 0x00, 0x6c, 0x00, 0x69, 0x00, 0x62, 0x00, 0x20,
+ 0x00, 0x30, 0x00, 0x2e, 0x00, 0x33, 0x00, 0x2e,
+ 0x00, 0x33, 0x00, 0x2e, 0x00, 0x31, 0x3c, 0x05,
+ 0x00, 0x10, 0x84, 0x66, 0x14, 0xf3, 0x27, 0xdd,
+ 0xde, 0x40, 0x86, 0xdc, 0xe0, 0x99, 0xda, 0x7f,
+ 0xd0, 0x52, 0x3c, 0x06, 0x00, 0x08, 0x07, 0xd4,
+ 0x04, 0x1a, 0x0e, 0x12, 0x1d, 0x5c, 0x3c, 0x0a,
+ 0x00, 0x10, 0x2c, 0xf4, 0xbc, 0x4e, 0x65, 0x7f,
+ 0x4e, 0x05, 0x87, 0xb4, 0x4c, 0xfd, 0xaa, 0xe3,
+ 0x0a, 0x2b, 0x3c, 0x09, 0x00, 0x10, 0x35, 0xac,
+ 0x10, 0x04, 0x0e, 0xe7, 0x4e, 0x21, 0x94, 0xbf,
+ 0x0d, 0xf4, 0xe4, 0xe5, 0x24, 0x14, 0x06, 0x0e,
+ 0x2b, 0x34, 0x02, 0x53, 0x01, 0x01, 0x0d, 0x01,
+ 0x01, 0x01, 0x01, 0x01, 0x18, 0x00, 0x83, 0x00,
+ 0x00, 0x5c, 0x19, 0x01, 0x00, 0x28, 0x00, 0x00,
+ 0x00, 0x02, 0x00, 0x00, 0x00, 0x10, 0xc0, 0x7c,
+ 0x8b, 0x06, 0x0e, 0xe3, 0x4b, 0x75, 0x9f, 0xfb,
+ 0x89, 0x05, 0xa4, 0x6f, 0xda, 0x18, 0x08, 0x7c,
+ 0x01, 0x83, 0xbe, 0xde, 0x4f, 0x1e, 0x8b, 0x1e,
+ 0x16, 0x33, 0x6e, 0x35, 0xc4, 0x5e, 0x19, 0x02,
+ 0x00, 0x18, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00,
+ 0x00, 0x10, 0x0f, 0x46, 0xb4, 0x10, 0x8b, 0xa9,
+ 0x45, 0xa2, 0xa4, 0x0a, 0x17, 0x5b, 0x0b, 0x62,
+ 0x50, 0xf3, 0x3c, 0x0a, 0x00, 0x10, 0x89, 0x8a,
+ 0x44, 0x70, 0x32, 0x7a, 0x40, 0xaa, 0x9c, 0x41,
+ 0xc6, 0xc6, 0x3a, 0x64, 0x77, 0x18, 0x06, 0x0e,
+ 0x2b, 0x34, 0x02, 0x53, 0x01, 0x01, 0x0d, 0x01,
+ 0x01, 0x01, 0x01, 0x01, 0x36, 0x00, 0x83, 0x00,
+ 0x00, 0xa4, 0x44, 0x02, 0x00, 0x24, 0x00, 0x41,
+ 0x00, 0x20, 0x00, 0x4d, 0x00, 0x61, 0x00, 0x74,
+ 0x00, 0x65, 0x00, 0x72, 0x00, 0x69, 0x00, 0x61,
+ 0x00, 0x6c, 0x00, 0x20, 0x00, 0x50, 0x00, 0x61,
+ 0x00, 0x63, 0x00, 0x6b, 0x00, 0x61, 0x00, 0x67,
+ 0x00, 0x65, 0x44, 0x01, 0x00, 0x20, 0x06, 0x0a,
+ 0x2b, 0x34, 0x01, 0x01, 0x01, 0x05, 0x01, 0x01,
+ 0x0d, 0x20, 0x13, 0x00, 0x00, 0x00, 0x9a, 0xb6,
+ 0x5c, 0xc0, 0xf9, 0x54, 0x41, 0x20, 0xa4, 0x2d,
+ 0xa5, 0xf3, 0x4b, 0x6c, 0x3d, 0xd7, 0x44, 0x05,
+ 0x00, 0x08, 0x07, 0xd4, 0x04, 0x1a, 0x0e, 0x12,
+ 0x1d, 0x57, 0x44, 0x04, 0x00, 0x08, 0x07, 0xd4,
+ 0x04, 0x1a, 0x0e, 0x12, 0x1d, 0x57, 0x44, 0x03,
+ 0x00, 0x28, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00,
+ 0x00, 0x10, 0x9e, 0x69, 0xd9, 0x47, 0x1a, 0x63,
+ 0x45, 0xd7, 0xa3, 0x85, 0xc5, 0x79, 0xfa, 0x48,
+ 0x3f, 0xcf, 0x3a, 0x21, 0x3b, 0xc8, 0x7b, 0xb9,
+ 0x40, 0xbd, 0xa0, 0x54, 0x14, 0x4f, 0x38, 0x34,
+ 0xe8, 0x08, 0x3c, 0x0a, 0x00, 0x10, 0xc0, 0x7c,
+ 0x8b, 0x06, 0x0e, 0xe3, 0x4b, 0x75, 0x9f, 0xfb,
+ 0x89, 0x05, 0xa4, 0x6f, 0xda, 0x18, 0x06, 0x0e,
+ 0x2b, 0x34, 0x02, 0x53, 0x01, 0x01, 0x0d, 0x01,
+ 0x01, 0x01, 0x01, 0x01, 0x3b, 0x00, 0x83, 0x00,
+ 0x00, 0x70, 0x48, 0x02, 0x00, 0x1c, 0x00, 0x54,
+ 0x00, 0x69, 0x00, 0x6d, 0x00, 0x65, 0x00, 0x63,
+ 0x00, 0x6f, 0x00, 0x64, 0x00, 0x65, 0x00, 0x20,
+ 0x00, 0x54, 0x00, 0x72, 0x00, 0x61, 0x00, 0x63,
+ 0x00, 0x6b, 0x48, 0x04, 0x00, 0x04, 0x00, 0x00,
+ 0x00, 0x00, 0x4b, 0x02, 0x00, 0x08, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x4b, 0x01,
+ 0x00, 0x08, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00,
+ 0x00, 0x01, 0x48, 0x01, 0x00, 0x04, 0x00, 0x00,
+ 0x00, 0x01, 0x48, 0x03, 0x00, 0x10, 0xb1, 0x5d,
+ 0x1a, 0xad, 0x9e, 0x13, 0x4f, 0x9d, 0x89, 0xa6,
+ 0x28, 0x00, 0x6f, 0x0b, 0x23, 0xd7, 0x3c, 0x0a,
+ 0x00, 0x10, 0x9e, 0x69, 0xd9, 0x47, 0x1a, 0x63,
+ 0x45, 0xd7, 0xa3, 0x85, 0xc5, 0x79, 0xfa, 0x48,
+ 0x3f, 0xcf, 0x06, 0x0e, 0x2b, 0x34, 0x02, 0x53,
+ 0x01, 0x01, 0x0d, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x0f, 0x00, 0x83, 0x00, 0x00, 0x64, 0x02, 0x01,
+ 0x00, 0x10, 0x06, 0x0e, 0x2b, 0x34, 0x04, 0x01,
+ 0x01, 0x01, 0x01, 0x03, 0x02, 0x01, 0x01, 0x00,
+ 0x00, 0x00, 0x02, 0x02, 0x00, 0x08, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x10, 0x01,
+ 0x00, 0x18, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00,
+ 0x00, 0x10, 0xa4, 0x5f, 0x10, 0x3a, 0x63, 0x79,
+ 0x45, 0x56, 0xb6, 0x65, 0x17, 0x2d, 0xf2, 0xf0,
+ 0x0e, 0x6e, 0x3c, 0x0a, 0x00, 0x10, 0xb1, 0x5d,
+ 0x1a, 0xad, 0x9e, 0x13, 0x4f, 0x9d, 0x89, 0xa6,
+ 0x28, 0x00, 0x6f, 0x0b, 0x23, 0xd7, 0x01, 0x02,
+ 0x00, 0x10, 0x35, 0xac, 0x10, 0x04, 0x0e, 0xe7,
+ 0x4e, 0x21, 0x94, 0xbf, 0x0d, 0xf4, 0xe4, 0xe5,
+ 0x24, 0x14, 0x06, 0x0e, 0x2b, 0x34, 0x02, 0x53,
+ 0x01, 0x01, 0x0d, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x14, 0x00, 0x83, 0x00, 0x00, 0x5f, 0x15, 0x02,
+ 0x00, 0x02, 0x00, 0x05, 0x15, 0x03, 0x00, 0x01,
+ 0x00, 0x15, 0x01, 0x00, 0x08, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x02, 0x00,
+ 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x01, 0x3c, 0x0a, 0x00, 0x10, 0xa4, 0x5f, 0x10,
+ 0x3a, 0x63, 0x79, 0x45, 0x56, 0xb6, 0x65, 0x17,
+ 0x2d, 0xf2, 0xf0, 0x0e, 0x6e, 0x02, 0x01, 0x00,
+ 0x10, 0x06, 0x0e, 0x2b, 0x34, 0x04, 0x01, 0x01,
+ 0x01, 0x01, 0x03, 0x02, 0x01, 0x01, 0x00, 0x00,
+ 0x00, 0x01, 0x02, 0x00, 0x10, 0x35, 0xac, 0x10,
+ 0x04, 0x0e, 0xe7, 0x4e, 0x21, 0x94, 0xbf, 0x0d,
+ 0xf4, 0xe4, 0xe5, 0x24, 0x14, 0x06, 0x0e, 0x2b,
+ 0x34, 0x02, 0x53, 0x01, 0x01, 0x0d, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x3b, 0x00, 0x83, 0x00, 0x00,
+ 0x6a, 0x48, 0x02, 0x00, 0x16, 0x00, 0x53, 0x00,
+ 0x6f, 0x00, 0x75, 0x00, 0x6e, 0x00, 0x64, 0x00,
+ 0x20, 0x00, 0x54, 0x00, 0x72, 0x00, 0x61, 0x00,
+ 0x63, 0x00, 0x6b, 0x48, 0x04, 0x00, 0x04, 0x00,
+ 0x00, 0x00, 0x00, 0x4b, 0x02, 0x00, 0x08, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x4b,
+ 0x01, 0x00, 0x08, 0x00, 0x00, 0x00, 0x05, 0x00,
+ 0x00, 0x00, 0x01, 0x48, 0x01, 0x00, 0x04, 0x00,
+ 0x00, 0x00, 0x02, 0x48, 0x03, 0x00, 0x10, 0xbf,
+ 0x20, 0x73, 0x31, 0xe2, 0xc5, 0x45, 0x47, 0x9b,
+ 0xe1, 0x1a, 0x07, 0x89, 0x94, 0x97, 0xef, 0x3c,
+ 0x0a, 0x00, 0x10, 0x3a, 0x21, 0x3b, 0xc8, 0x7b,
+ 0xb9, 0x40, 0xbd, 0xa0, 0x54, 0x14, 0x4f, 0x38,
+ 0x34, 0xe8, 0x08, 0x06, 0x0e, 0x2b, 0x34, 0x02,
+ 0x53, 0x01, 0x01, 0x0d, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x0f, 0x00, 0x83, 0x00, 0x00, 0x64, 0x02,
+ 0x01, 0x00, 0x10, 0x06, 0x0e, 0x2b, 0x34, 0x04,
+ 0x01, 0x01, 0x01, 0x01, 0x03, 0x02, 0x02, 0x02,
+ 0x00, 0x00, 0x00, 0x02, 0x02, 0x00, 0x08, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x10,
+ 0x01, 0x00, 0x18, 0x00, 0x00, 0x00, 0x01, 0x00,
+ 0x00, 0x00, 0x10, 0x9b, 0x27, 0xfe, 0xda, 0x8d,
+ 0x2f, 0x45, 0x72, 0xaf, 0x06, 0xf6, 0x99, 0xb8,
+ 0xc8, 0x9e, 0xb5, 0x3c, 0x0a, 0x00, 0x10, 0xbf,
+ 0x20, 0x73, 0x31, 0xe2, 0xc5, 0x45, 0x47, 0x9b,
+ 0xe1, 0x1a, 0x07, 0x89, 0x94, 0x97, 0xef, 0x01,
+ 0x02, 0x00, 0x10, 0x35, 0xac, 0x10, 0x04, 0x0e,
+ 0xe7, 0x4e, 0x21, 0x94, 0xbf, 0x0d, 0xf4, 0xe4,
+ 0xe5, 0x24, 0x14, 0x06, 0x0e, 0x2b, 0x34, 0x02,
+ 0x53, 0x01, 0x01, 0x0d, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x11, 0x00, 0x83, 0x00, 0x00, 0x80, 0x02,
+ 0x02, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x01, 0x11, 0x01, 0x00, 0x20, 0x06,
+ 0x0a, 0x2b, 0x34, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x02, 0x20, 0x13, 0x00, 0x00, 0x00, 0x14,
+ 0x5d, 0x1e, 0x9f, 0x7a, 0x3f, 0x41, 0x03, 0xad,
+ 0xb6, 0x24, 0x9c, 0x87, 0x0d, 0x7e, 0xc3, 0x11,
+ 0x02, 0x00, 0x04, 0x00, 0x00, 0x00, 0x02, 0x12,
+ 0x01, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x3c, 0x0a, 0x00, 0x10, 0x9b,
+ 0x27, 0xfe, 0xda, 0x8d, 0x2f, 0x45, 0x72, 0xaf,
+ 0x06, 0xf6, 0x99, 0xb8, 0xc8, 0x9e, 0xb5, 0x02,
+ 0x01, 0x00, 0x10, 0x06, 0x0e, 0x2b, 0x34, 0x04,
+ 0x01, 0x01, 0x01, 0x01, 0x03, 0x02, 0x02, 0x02,
+ 0x00, 0x00, 0x00, 0x01, 0x02, 0x00, 0x10, 0x35,
+ 0xac, 0x10, 0x04, 0x0e, 0xe7, 0x4e, 0x21, 0x94,
+ 0xbf, 0x0d, 0xf4, 0xe4, 0xe5, 0x24, 0x14, 0x06,
+ 0x0e, 0x2b, 0x34, 0x02, 0x53, 0x01, 0x01, 0x0d,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x37, 0x00, 0x83,
+ 0x00, 0x00, 0xfe, 0x44, 0x02, 0x00, 0x6a, 0x00,
+ 0x46, 0x00, 0x69, 0x00, 0x6c, 0x00, 0x65, 0x00,
+ 0x20, 0x00, 0x50, 0x00, 0x61, 0x00, 0x63, 0x00,
+ 0x6b, 0x00, 0x61, 0x00, 0x67, 0x00, 0x65, 0x00,
+ 0x3a, 0x00, 0x20, 0x00, 0x53, 0x00, 0x4d, 0x00,
+ 0x50, 0x00, 0x54, 0x00, 0x45, 0x00, 0x20, 0x00,
+ 0x33, 0x00, 0x38, 0x00, 0x32, 0x00, 0x4d, 0x00,
+ 0x20, 0x00, 0x66, 0x00, 0x72, 0x00, 0x61, 0x00,
+ 0x6d, 0x00, 0x65, 0x00, 0x20, 0x00, 0x77, 0x00,
+ 0x72, 0x00, 0x61, 0x00, 0x70, 0x00, 0x70, 0x00,
+ 0x69, 0x00, 0x6e, 0x00, 0x67, 0x00, 0x20, 0x00,
+ 0x6f, 0x00, 0x66, 0x00, 0x20, 0x00, 0x77, 0x00,
+ 0x61, 0x00, 0x76, 0x00, 0x65, 0x00, 0x20, 0x00,
+ 0x61, 0x00, 0x75, 0x00, 0x64, 0x00, 0x69, 0x00,
+ 0x6f, 0x44, 0x01, 0x00, 0x20, 0x06, 0x0a, 0x2b,
+ 0x34, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02,
+ 0x20, 0x13, 0x00, 0x00, 0x00, 0x14, 0x5d, 0x1e,
+ 0x9f, 0x7a, 0x3f, 0x41, 0x03, 0xad, 0xb6, 0x24,
+ 0x9c, 0x87, 0x0d, 0x7e, 0xc3, 0x44, 0x05, 0x00,
+ 0x08, 0x07, 0xd4, 0x04, 0x1a, 0x0e, 0x12, 0x1d,
+ 0x57, 0x44, 0x04, 0x00, 0x08, 0x07, 0xd4, 0x04,
+ 0x1a, 0x0e, 0x12, 0x1d, 0x57, 0x44, 0x03, 0x00,
+ 0x28, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,
+ 0x10, 0xf2, 0xbf, 0xb3, 0x60, 0x10, 0xb7, 0x49,
+ 0xa7, 0xaf, 0x2e, 0xc4, 0xfa, 0x62, 0x19, 0xbc,
+ 0x01, 0x2a, 0xae, 0x1e, 0xb3, 0xc5, 0xa0, 0x4d,
+ 0xa5, 0xb1, 0x78, 0xf1, 0xeb, 0x9a, 0x68, 0xf0,
+ 0x8c, 0x3c, 0x0a, 0x00, 0x10, 0x08, 0x7c, 0x01,
+ 0x83, 0xbe, 0xde, 0x4f, 0x1e, 0x8b, 0x1e, 0x16,
+ 0x33, 0x6e, 0x35, 0xc4, 0x5e, 0x47, 0x01, 0x00,
+ 0x10, 0xc4, 0xe1, 0xba, 0xb5, 0x66, 0x8d, 0x4f,
+ 0x3c, 0xb4, 0x16, 0x78, 0x06, 0x26, 0x4d, 0xc6,
+ 0xe8, 0x06, 0x0e, 0x2b, 0x34, 0x02, 0x53, 0x01,
+ 0x01, 0x0d, 0x01, 0x01, 0x01, 0x01, 0x01, 0x3b,
+ 0x00, 0x83, 0x00, 0x00, 0x70, 0x48, 0x02, 0x00,
+ 0x1c, 0x00, 0x54, 0x00, 0x69, 0x00, 0x6d, 0x00,
+ 0x65, 0x00, 0x63, 0x00, 0x6f, 0x00, 0x64, 0x00,
+ 0x65, 0x00, 0x20, 0x00, 0x54, 0x00, 0x72, 0x00,
+ 0x61, 0x00, 0x63, 0x00, 0x6b, 0x48, 0x04, 0x00,
+ 0x04, 0x00, 0x00, 0x00, 0x00, 0x4b, 0x02, 0x00,
+ 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x4b, 0x01, 0x00, 0x08, 0x00, 0x00, 0x00,
+ 0x05, 0x00, 0x00, 0x00, 0x01, 0x48, 0x01, 0x00,
+ 0x04, 0x00, 0x00, 0x00, 0x01, 0x48, 0x03, 0x00,
+ 0x10, 0x77, 0xb2, 0x7d, 0x53, 0xcb, 0xef, 0x43,
+ 0x1c, 0x84, 0xbd, 0xe6, 0x42, 0x59, 0x0e, 0x92,
+ 0xcc, 0x3c, 0x0a, 0x00, 0x10, 0xf2, 0xbf, 0xb3,
+ 0x60, 0x10, 0xb7, 0x49, 0xa7, 0xaf, 0x2e, 0xc4,
+ 0xfa, 0x62, 0x19, 0xbc, 0x01, 0x06, 0x0e, 0x2b,
+ 0x34, 0x02, 0x53, 0x01, 0x01, 0x0d, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x0f, 0x00, 0x83, 0x00, 0x00,
+ 0x64, 0x02, 0x01, 0x00, 0x10, 0x06, 0x0e, 0x2b,
+ 0x34, 0x04, 0x01, 0x01, 0x01, 0x01, 0x03, 0x02,
+ 0x01, 0x01, 0x00, 0x00, 0x00, 0x02, 0x02, 0x00,
+ 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x01, 0x10, 0x01, 0x00, 0x18, 0x00, 0x00, 0x00,
+ 0x01, 0x00, 0x00, 0x00, 0x10, 0x6d, 0x85, 0x87,
+ 0x23, 0xb9, 0x0e, 0x4d, 0x67, 0x8d, 0xd8, 0xe1,
+ 0x28, 0xf2, 0x4b, 0xbc, 0xf5, 0x3c, 0x0a, 0x00,
+ 0x10, 0x77, 0xb2, 0x7d, 0x53, 0xcb, 0xef, 0x43,
+ 0x1c, 0x84, 0xbd, 0xe6, 0x42, 0x59, 0x0e, 0x92,
+ 0xcc, 0x01, 0x02, 0x00, 0x10, 0x35, 0xac, 0x10,
+ 0x04, 0x0e, 0xe7, 0x4e, 0x21, 0x94, 0xbf, 0x0d,
+ 0xf4, 0xe4, 0xe5, 0x24, 0x14, 0x06, 0x0e, 0x2b,
+ 0x34, 0x02, 0x53, 0x01, 0x01, 0x0d, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x14, 0x00, 0x83, 0x00, 0x00,
+ 0x5f, 0x15, 0x02, 0x00, 0x02, 0x00, 0x05, 0x15,
+ 0x03, 0x00, 0x01, 0x00, 0x15, 0x01, 0x00, 0x08,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x46, 0x50,
+ 0x02, 0x02, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x01, 0x3c, 0x0a, 0x00, 0x10,
+ 0x6d, 0x85, 0x87, 0x23, 0xb9, 0x0e, 0x4d, 0x67,
+ 0x8d, 0xd8, 0xe1, 0x28, 0xf2, 0x4b, 0xbc, 0xf5,
+ 0x02, 0x01, 0x00, 0x10, 0x06, 0x0e, 0x2b, 0x34,
+ 0x04, 0x01, 0x01, 0x01, 0x01, 0x03, 0x02, 0x01,
+ 0x01, 0x00, 0x00, 0x00, 0x01, 0x02, 0x00, 0x10,
+ 0x35, 0xac, 0x10, 0x04, 0x0e, 0xe7, 0x4e, 0x21,
+ 0x94, 0xbf, 0x0d, 0xf4, 0xe4, 0xe5, 0x24, 0x14,
+ 0x06, 0x0e, 0x2b, 0x34, 0x02, 0x53, 0x01, 0x01,
+ 0x0d, 0x01, 0x01, 0x01, 0x01, 0x01, 0x3b, 0x00,
+ 0x83, 0x00, 0x00, 0x6a, 0x48, 0x02, 0x00, 0x16,
+ 0x00, 0x53, 0x00, 0x6f, 0x00, 0x75, 0x00, 0x6e,
+ 0x00, 0x64, 0x00, 0x20, 0x00, 0x54, 0x00, 0x72,
+ 0x00, 0x61, 0x00, 0x63, 0x00, 0x6b, 0x48, 0x04,
+ 0x00, 0x04, 0x16, 0x01, 0x01, 0x01, 0x4b, 0x02,
+ 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x4b, 0x01, 0x00, 0x08, 0x00, 0x00,
+ 0x00, 0x05, 0x00, 0x00, 0x00, 0x01, 0x48, 0x01,
+ 0x00, 0x04, 0x00, 0x00, 0x00, 0x02, 0x48, 0x03,
+ 0x00, 0x10, 0xf2, 0x67, 0xd5, 0x27, 0x0f, 0xbd,
+ 0x45, 0x55, 0xa0, 0x3e, 0x35, 0x52, 0xae, 0x31,
+ 0x7c, 0x4a, 0x3c, 0x0a, 0x00, 0x10, 0x2a, 0xae,
+ 0x1e, 0xb3, 0xc5, 0xa0, 0x4d, 0xa5, 0xb1, 0x78,
+ 0xf1, 0xeb, 0x9a, 0x68, 0xf0, 0x8c, 0x06, 0x0e,
+ 0x2b, 0x34, 0x02, 0x53, 0x01, 0x01, 0x0d, 0x01,
+ 0x01, 0x01, 0x01, 0x01, 0x0f, 0x00, 0x83, 0x00,
+ 0x00, 0x64, 0x02, 0x01, 0x00, 0x10, 0x06, 0x0e,
+ 0x2b, 0x34, 0x04, 0x01, 0x01, 0x01, 0x01, 0x03,
+ 0x02, 0x02, 0x02, 0x00, 0x00, 0x00, 0x02, 0x02,
+ 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x01, 0x10, 0x01, 0x00, 0x18, 0x00, 0x00,
+ 0x00, 0x01, 0x00, 0x00, 0x00, 0x10, 0xdf, 0x85,
+ 0x49, 0x8b, 0x72, 0x43, 0x4b, 0xa4, 0xa2, 0x4e,
+ 0xfa, 0xed, 0xd8, 0x7a, 0xa0, 0x0d, 0x3c, 0x0a,
+ 0x00, 0x10, 0xf2, 0x67, 0xd5, 0x27, 0x0f, 0xbd,
+ 0x45, 0x55, 0xa0, 0x3e, 0x35, 0x52, 0xae, 0x31,
+ 0x7c, 0x4a, 0x01, 0x02, 0x00, 0x10, 0x35, 0xac,
+ 0x10, 0x04, 0x0e, 0xe7, 0x4e, 0x21, 0x94, 0xbf,
+ 0x0d, 0xf4, 0xe4, 0xe5, 0x24, 0x14, 0x06, 0x0e,
+ 0x2b, 0x34, 0x02, 0x53, 0x01, 0x01, 0x0d, 0x01,
+ 0x01, 0x01, 0x01, 0x01, 0x11, 0x00, 0x83, 0x00,
+ 0x00, 0x80, 0x02, 0x02, 0x00, 0x08, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x11, 0x01,
+ 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x11, 0x02, 0x00, 0x04, 0x00, 0x00,
+ 0x00, 0x00, 0x12, 0x01, 0x00, 0x08, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3c, 0x0a,
+ 0x00, 0x10, 0xdf, 0x85, 0x49, 0x8b, 0x72, 0x43,
+ 0x4b, 0xa4, 0xa2, 0x4e, 0xfa, 0xed, 0xd8, 0x7a,
+ 0xa0, 0x0d, 0x02, 0x01, 0x00, 0x10, 0x06, 0x0e,
+ 0x2b, 0x34, 0x04, 0x01, 0x01, 0x01, 0x01, 0x03,
+ 0x02, 0x02, 0x02, 0x00, 0x00, 0x00, 0x01, 0x02,
+ 0x00, 0x10, 0x35, 0xac, 0x10, 0x04, 0x0e, 0xe7,
+ 0x4e, 0x21, 0x94, 0xbf, 0x0d, 0xf4, 0xe4, 0xe5,
+ 0x24, 0x14, 0x06, 0x0e, 0x2b, 0x34, 0x02, 0x53,
+ 0x01, 0x01, 0x0d, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x48, 0x00, 0x83, 0x00, 0x00, 0x8b, 0x30, 0x01,
+ 0x00, 0x08, 0x00, 0x00, 0x2b, 0x11, 0x00, 0x00,
+ 0x00, 0x01, 0x3d, 0x03, 0x00, 0x08, 0x00, 0x00,
+ 0x2b, 0x11, 0x00, 0x00, 0x00, 0x01, 0x3d, 0x02,
+ 0x00, 0x01, 0x00, 0x3d, 0x07, 0x00, 0x04, 0x00,
+ 0x00, 0x00, 0x01, 0x3d, 0x01, 0x00, 0x04, 0x00,
+ 0x00, 0x00, 0x08, 0x3d, 0x0a, 0x00, 0x02, 0x00,
+ 0x01, 0x3d, 0x09, 0x00, 0x04, 0x00, 0x00, 0x2b,
+ 0x11, 0x30, 0x04, 0x00, 0x10, 0x06, 0x0e, 0x2b,
+ 0x34, 0x04, 0x01, 0x01, 0x02, 0x0d, 0x01, 0x03,
+ 0x01, 0x02, 0x06, 0x01, 0x00, 0x30, 0x06, 0x00,
+ 0x04, 0x00, 0x00, 0x00, 0x02, 0x3c, 0x0a, 0x00,
+ 0x10, 0xc4, 0xe1, 0xba, 0xb5, 0x66, 0x8d, 0x4f,
+ 0x3c, 0xb4, 0x16, 0x78, 0x06, 0x26, 0x4d, 0xc6,
+ 0xe8, 0x30, 0x02, 0x00, 0x08, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x02, 0x00,
+ 0x10, 0x35, 0xac, 0x10, 0x04, 0x0e, 0xe7, 0x4e,
+ 0x21, 0x94, 0xbf, 0x0d, 0xf4, 0xe4, 0xe5, 0x24,
+ 0x14, 0x06, 0x0e, 0x2b, 0x34, 0x02, 0x53, 0x01,
+ 0x01, 0x0d, 0x01, 0x01, 0x01, 0x01, 0x01, 0x23,
+ 0x00, 0x83, 0x00, 0x00, 0x5c, 0x27, 0x01, 0x00,
+ 0x20, 0x06, 0x0a, 0x2b, 0x34, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x02, 0x20, 0x13, 0x00, 0x00,
+ 0x00, 0x14, 0x5d, 0x1e, 0x9f, 0x7a, 0x3f, 0x41,
+ 0x03, 0xad, 0xb6, 0x24, 0x9c, 0x87, 0x0d, 0x7e,
+ 0xc3, 0x3f, 0x07, 0x00, 0x04, 0x00, 0x00, 0x00,
+ 0x01, 0x3c, 0x0a, 0x00, 0x10, 0x0f, 0x46, 0xb4,
+ 0x10, 0x8b, 0xa9, 0x45, 0xa2, 0xa4, 0x0a, 0x17,
+ 0x5b, 0x0b, 0x62, 0x50, 0xf3, 0x3f, 0x06, 0x00,
+ 0x04, 0x00, 0x00, 0x00, 0x81, 0x01, 0x02, 0x00,
+ 0x10, 0x35, 0xac, 0x10, 0x04, 0x0e, 0xe7, 0x4e,
+ 0x21, 0x94, 0xbf, 0x0d, 0xf4, 0xe4, 0xe5, 0x24,
+ 0x14, 0x06, 0x0e, 0x2b, 0x34, 0x01, 0x01, 0x01,
+ 0x01, 0x03, 0x01, 0x02, 0x10, 0x01, 0x00, 0x00,
+ 0x00, 0x83, 0x00, 0x3d, 0xde, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x06, 0x0e, 0x2b, 0x34, 0x01,
+ 0x02, 0x01, 0x01, 0x0d, 0x01, 0x03, 0x01, 0x16,
+ 0x01, 0x01, 0x01, 0x83, 0x00, 0x00, 0x10, 0x74,
+ 0x5d, 0x8c, 0x69, 0x74, 0x80, 0x69, 0x80, 0x5d,
+ 0x80, 0x80, 0x74, 0x8c, 0x69, 0x80, 0x74, 0x06,
+ 0x0e, 0x2b, 0x34, 0x02, 0x05, 0x01, 0x01, 0x0d,
+ 0x01, 0x02, 0x01, 0x01, 0x04, 0x04, 0x00, 0x83,
+ 0x00, 0x00, 0x78, 0x00, 0x01, 0x00, 0x02, 0x00,
+ 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x4e, 0x3f, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x4e, 0x3f, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x64, 0x00, 0x00, 0x00, 0x81, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x06, 0x0e, 0x2b, 0x34, 0x04,
+ 0x01, 0x01, 0x01, 0x0d, 0x01, 0x02, 0x01, 0x10,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00,
+ 0x00, 0x00, 0x10, 0x06, 0x0e, 0x2b, 0x34, 0x04,
+ 0x01, 0x01, 0x03, 0x0d, 0x01, 0x03, 0x01, 0x02,
+ 0x7f, 0x01, 0x00, 0x06, 0x0e, 0x2b, 0x34, 0x04,
+ 0x01, 0x01, 0x02, 0x0d, 0x01, 0x03, 0x01, 0x02,
+ 0x06, 0x01, 0x00, 0x06, 0x0e, 0x2b, 0x34, 0x02,
+ 0x53, 0x01, 0x01, 0x0d, 0x01, 0x02, 0x01, 0x01,
+ 0x10, 0x01, 0x00, 0x83, 0x00, 0x00, 0x50, 0x3c,
+ 0x0a, 0x00, 0x10, 0xba, 0xc8, 0x72, 0x86, 0xb4,
+ 0xc4, 0x43, 0x30, 0x95, 0x5c, 0x3d, 0x89, 0x2a,
+ 0x7a, 0xfc, 0x01, 0x3f, 0x0b, 0x00, 0x08, 0x00,
+ 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x01, 0x3f,
+ 0x0c, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x3f, 0x0d, 0x00, 0x08, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3f,
+ 0x05, 0x00, 0x04, 0x00, 0x00, 0x08, 0x9d, 0x3f,
+ 0x06, 0x00, 0x04, 0x00, 0x00, 0x00, 0x81, 0x3f,
+ 0x07, 0x00, 0x04, 0x00, 0x00, 0x00, 0x01, 0x06,
+ 0x0e, 0x2b, 0x34, 0x02, 0x05, 0x01, 0x01, 0x0d,
+ 0x01, 0x02, 0x01, 0x01, 0x11, 0x01, 0x00, 0x83,
+ 0x00, 0x00, 0x1c, 0x00, 0x00, 0x00, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x4e, 0x3f, 0x00, 0x00, 0x00, 0x30,
+};
diff --git a/tests/check/elements/mxfmux.c b/tests/check/elements/mxfmux.c
new file mode 100644
index 00000000..f8c931e2
--- /dev/null
+++ b/tests/check/elements/mxfmux.c
@@ -0,0 +1,261 @@
+/* GStreamer
+ *
+ * unit test for mxfmux
+ *
+ * Copyright (C) <2009> Sebastian Dröge <sebastian.droege@collabora.co.uk>
+ *
+ * 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>
+#include <string.h>
+
+static const gchar *
+get_mpeg2enc_element_name (void)
+{
+ GstElementFactory *factory = NULL;
+
+ if ((factory = gst_element_factory_find ("mpeg2enc"))) {
+ gst_object_unref (factory);
+ return "mpeg2enc";
+ } else if ((factory = gst_element_factory_find ("ffenc_mpeg2video"))) {
+ gst_object_unref (factory);
+ return "ffenc_mpeg2video";
+ } else {
+ return NULL;
+ }
+}
+
+typedef struct
+{
+ GMainLoop *loop;
+ gboolean eos;
+} OnMessageUserData;
+
+static void
+on_message_cb (GstBus * bus, GstMessage * message, gpointer user_data)
+{
+ OnMessageUserData *d = user_data;
+
+ switch (GST_MESSAGE_TYPE (message)) {
+ case GST_MESSAGE_ERROR:
+ case GST_MESSAGE_WARNING:
+ g_assert_not_reached ();
+ break;
+ case GST_MESSAGE_EOS:
+ g_main_loop_quit (d->loop);
+ d->eos = TRUE;
+ break;
+ default:
+ break;
+ }
+}
+
+static void
+run_test (const gchar * pipeline_string)
+{
+ GstElement *pipeline;
+ GstBus *bus;
+ GMainLoop *loop;
+ OnMessageUserData omud = { NULL, };
+ GstStateChangeReturn ret;
+
+ GST_DEBUG ("Testing pipeline '%s'", pipeline_string);
+
+ pipeline = gst_parse_launch (pipeline_string, NULL);
+ fail_unless (pipeline != NULL);
+ g_object_set (G_OBJECT (pipeline), "async-handling", TRUE, NULL);
+
+ loop = g_main_loop_new (NULL, FALSE);
+
+ bus = gst_element_get_bus (pipeline);
+ fail_unless (bus != NULL);
+ gst_bus_add_signal_watch (bus);
+
+ omud.loop = loop;
+ omud.eos = FALSE;
+
+ g_signal_connect (bus, "message", (GCallback) on_message_cb, &omud);
+
+ ret = gst_element_set_state (pipeline, GST_STATE_PLAYING);
+ fail_unless (ret == GST_STATE_CHANGE_SUCCESS
+ || ret == GST_STATE_CHANGE_ASYNC);
+
+ g_main_loop_run (loop);
+
+ fail_unless (gst_element_set_state (pipeline,
+ GST_STATE_NULL) == GST_STATE_CHANGE_SUCCESS);
+
+ fail_unless (omud.eos == TRUE);
+
+ gst_object_unref (pipeline);
+ g_main_loop_unref (loop);
+ gst_bus_remove_signal_watch (bus);
+ gst_object_unref (bus);
+}
+
+GST_START_TEST (test_mpeg2)
+{
+ const gchar *mpeg2enc_name = get_mpeg2enc_element_name ();
+ gchar *pipeline;
+
+ if (!mpeg2enc_name)
+ return;
+
+ pipeline = g_strdup_printf ("videotestsrc num-buffers=250 ! "
+ "video/x-raw,framerate=25/1 ! "
+ "%s ! " "mxfmux name=mux ! " "fakesink", mpeg2enc_name);
+
+ run_test (pipeline);
+ g_free (pipeline);
+}
+
+GST_END_TEST;
+
+GST_START_TEST (test_raw_video_raw_audio)
+{
+ gchar *pipeline;
+
+ pipeline = g_strdup_printf ("videotestsrc num-buffers=250 ! "
+ "video/x-raw,format=(string)v308,width=1920,height=1080,framerate=25/1 ! "
+ "mxfmux name=mux ! "
+ "fakesink "
+ "audiotestsrc num-buffers=250 ! "
+ "audioconvert ! " "audio/x-raw,rate=48000,channels=2 ! " "mux. ");
+
+ run_test (pipeline);
+ g_free (pipeline);
+}
+
+GST_END_TEST;
+
+GST_START_TEST (test_raw_video_stride_transform)
+{
+ gchar *pipeline;
+
+ pipeline = g_strdup_printf ("videotestsrc num-buffers=250 ! "
+ "video/x-raw,format=(string)v308,width=1001,height=501,framerate=25/1 ! "
+ "mxfmux name=mux ! " "fakesink");
+
+ run_test (pipeline);
+ g_free (pipeline);
+}
+
+GST_END_TEST;
+
+GST_START_TEST (test_jpeg2000_alaw)
+{
+ gchar *pipeline;
+ GstElementFactory *factory = NULL;
+
+ if ((factory = gst_element_factory_find ("jp2kenc")) == NULL)
+ return;
+ gst_object_unref (factory);
+ if ((factory = gst_element_factory_find ("alawenc")) == NULL)
+ return;
+ gst_object_unref (factory);
+
+ pipeline = g_strdup_printf ("videotestsrc num-buffers=250 ! "
+ "video/x-raw,framerate=25/1 ! "
+ "jp2kenc ! "
+ "mxfmux name=mux ! "
+ "fakesink "
+ "audiotestsrc num-buffers=250 ! " "audioconvert ! " "alawenc ! " "mux. ");
+
+ run_test (pipeline);
+ g_free (pipeline);
+}
+
+GST_END_TEST;
+
+GST_START_TEST (test_dnxhd_mp3)
+{
+ gchar *pipeline;
+ GstElementFactory *factory = NULL;
+
+ if ((factory = gst_element_factory_find ("ffenc_dnxhd")) == NULL)
+ return;
+ gst_object_unref (factory);
+ if ((factory = gst_element_factory_find ("lame")) == NULL)
+ return;
+ gst_object_unref (factory);
+ if ((factory = gst_element_factory_find ("mp3parse")) == NULL)
+ return;
+ gst_object_unref (factory);
+
+ pipeline = g_strdup_printf ("videotestsrc num-buffers=250 ! "
+ "video/x-raw,format=(string)Y42B,width=1920,height=1080,framerate=25/1 ! "
+ "ffenc_dnxhd bitrate=36000000 ! "
+ "mxfmux name=mux ! "
+ "fakesink "
+ "audiotestsrc num-buffers=250 ! "
+ "audioconvert ! "
+ "audio/x-raw,channels=2 ! " "lame ! " "mp3parse ! " "mux. ");
+
+ run_test (pipeline);
+ g_free (pipeline);
+}
+
+GST_END_TEST;
+
+GST_START_TEST (test_multiple_av_streams)
+{
+ gchar *pipeline;
+
+ pipeline = g_strdup_printf ("videotestsrc num-buffers=250 ! "
+ "video/x-raw,format=(string)v308,width=1920,height=1080,framerate=25/1 ! "
+ "mxfmux name=mux ! "
+ "fakesink "
+ "audiotestsrc num-buffers=250 ! "
+ "audioconvert ! "
+ "audio/x-raw,rate=48000,channels=2 ! "
+ "mux. "
+ "videotestsrc num-buffers=100 ! "
+ "video/x-raw,format=(string)v308,width=1920,height=1080,framerate=25/1 ! "
+ "mux. "
+ "audiotestsrc num-buffers=100 ! "
+ "audioconvert ! "
+ "audio/x-raw,rate=48000,channels=2 ! "
+ "mux. "
+ "audiotestsrc num-buffers=250 ! "
+ "audioconvert ! " "audio/x-raw,rate=48000,channels=2 ! " "mux. ");
+
+ run_test (pipeline);
+ g_free (pipeline);
+}
+
+GST_END_TEST;
+
+static Suite *
+mxfmux_suite (void)
+{
+ Suite *s = suite_create ("mxfmux");
+ TCase *tc_chain = tcase_create ("general");
+
+ suite_add_tcase (s, tc_chain);
+ tcase_set_timeout (tc_chain, 180);
+
+ tcase_add_test (tc_chain, test_mpeg2);
+ tcase_add_test (tc_chain, test_raw_video_raw_audio);
+ tcase_add_test (tc_chain, test_raw_video_stride_transform);
+ tcase_add_test (tc_chain, test_jpeg2000_alaw);
+ tcase_add_test (tc_chain, test_dnxhd_mp3);
+ tcase_add_test (tc_chain, test_multiple_av_streams);
+
+ return s;
+}
+
+GST_CHECK_MAIN (mxfmux);
diff --git a/tests/check/elements/neonhttpsrc.c b/tests/check/elements/neonhttpsrc.c
new file mode 100644
index 00000000..49e36525
--- /dev/null
+++ b/tests/check/elements/neonhttpsrc.c
@@ -0,0 +1,190 @@
+/* GStreamer unit tests for the neonhttpsrc element
+ * Copyright (C) 2006-2007 Tim-Philipp Müller <tim centricular net>
+ *
+ * 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.
+ */
+
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+#include <gst/check/gstcheck.h>
+
+static void
+handoff_cb (GstElement * fakesink, GstBuffer * buf, GstPad * pad,
+ GstBuffer ** p_outbuf)
+{
+ GST_LOG ("handoff, buf = %p", buf);
+ if (*p_outbuf == NULL)
+ *p_outbuf = gst_buffer_ref (buf);
+}
+
+GST_START_TEST (test_first_buffer_has_offset)
+{
+ GstStateChangeReturn ret;
+ GstElement *pipe, *src, *sink;
+ GstBuffer *buf = NULL;
+ gchar **cookies;
+
+ pipe = gst_pipeline_new (NULL);
+
+ src = gst_element_factory_make ("neonhttpsrc", NULL);
+ fail_unless (src != NULL);
+
+ sink = gst_element_factory_make ("fakesink", NULL);
+ fail_unless (sink != NULL);
+
+ gst_bin_add (GST_BIN (pipe), src);
+ gst_bin_add (GST_BIN (pipe), sink);
+ fail_unless (gst_element_link (src, sink));
+
+ g_object_set (src, "location", "http://gstreamer.freedesktop.org/", NULL);
+ g_object_set (src, "automatic-redirect", TRUE, NULL);
+
+ /* set some cookies (shouldn't hurt) */
+ cookies = g_strsplit ("foo=1234,bar=9871615348162523726337x99FB", ",", -1);
+ g_object_set (src, "cookies", cookies, NULL);
+ g_strfreev (cookies);
+
+ g_object_set (sink, "signal-handoffs", TRUE, NULL);
+ g_signal_connect (sink, "preroll-handoff", G_CALLBACK (handoff_cb), &buf);
+
+ ret = gst_element_set_state (pipe, GST_STATE_PAUSED);
+ if (ret != GST_STATE_CHANGE_ASYNC) {
+ GST_DEBUG ("failed to start up neon http src, ret = %d", ret);
+ goto done;
+ }
+
+ /* don't wait for more than 10 seconds */
+ ret = gst_element_get_state (pipe, NULL, NULL, 10 * GST_SECOND);
+ GST_LOG ("ret = %u", ret);
+
+ if (buf == NULL) {
+ /* we want to test the buffer offset, nothing else; if there's a failure
+ * it might be for lots of reasons (no network connection, whatever), we're
+ * not interested in those */
+ GST_DEBUG ("didn't manage to get data within 10 seconds, skipping test");
+ goto done;
+ }
+
+ GST_DEBUG ("buffer offset = %" G_GUINT64_FORMAT, GST_BUFFER_OFFSET (buf));
+
+ /* first buffer should have a 0 offset */
+ fail_unless (GST_BUFFER_OFFSET (buf) == 0);
+ gst_buffer_unref (buf);
+
+done:
+
+ gst_element_set_state (pipe, GST_STATE_NULL);
+ gst_object_unref (pipe);
+}
+
+GST_END_TEST;
+
+GST_START_TEST (test_icy_stream)
+{
+ GstElement *pipe, *src, *sink;
+ GstMessage *msg;
+
+ pipe = gst_pipeline_new (NULL);
+
+ src = gst_element_factory_make ("neonhttpsrc", NULL);
+ fail_unless (src != NULL);
+
+ sink = gst_element_factory_make ("fakesink", NULL);
+ fail_unless (sink != NULL);
+
+ gst_bin_add (GST_BIN (pipe), src);
+ gst_bin_add (GST_BIN (pipe), sink);
+ fail_unless (gst_element_link (src, sink));
+
+ /* First try Virgin Radio Ogg stream, to see if there's connectivity and all
+ * (which is an attempt to work around the completely horrid error reporting
+ * and that we can't distinguish different types of failures here).
+ * Note that neonhttpsrc does the whole connect + session initiation all in
+ * the state change function. */
+
+ g_object_set (src, "location", "http://ogg2.smgradio.com/vr32.ogg", NULL);
+ g_object_set (src, "automatic-redirect", FALSE, NULL);
+ g_object_set (src, "num-buffers", 1, NULL);
+ gst_element_set_state (pipe, GST_STATE_PLAYING);
+
+ msg = gst_bus_poll (GST_ELEMENT_BUS (pipe),
+ GST_MESSAGE_EOS | GST_MESSAGE_ERROR, -1);
+ if (GST_MESSAGE_TYPE (msg) == GST_MESSAGE_ERROR) {
+ GST_INFO ("looks like there's no net connectivity or sgmradio.com is "
+ "down. In any case, let's just skip this test");
+ gst_message_unref (msg);
+ goto done;
+ }
+ gst_message_unref (msg);
+ msg = NULL;
+ gst_element_set_state (pipe, GST_STATE_NULL);
+
+ /* Now, if the ogg stream works, the mp3 shoutcast stream should work as
+ * well (time will tell if that's true) */
+
+ /* Virgin Radio 32kbps mp3 shoutcast stream */
+ g_object_set (src, "location", "http://mp3-vr-32.smgradio.com:80/", NULL);
+ g_object_set (src, "automatic-redirect", FALSE, NULL);
+
+ /* g_object_set (src, "neon-http-debug", TRUE, NULL); */
+
+ /* EOS after the first buffer */
+ g_object_set (src, "num-buffers", 1, NULL);
+
+ gst_element_set_state (pipe, GST_STATE_PLAYING);
+ msg = gst_bus_poll (GST_ELEMENT_BUS (pipe),
+ GST_MESSAGE_EOS | GST_MESSAGE_ERROR, -1);
+
+ if (GST_MESSAGE_TYPE (msg) == GST_MESSAGE_EOS) {
+ GST_DEBUG ("success, we're done here");
+ gst_message_unref (msg);
+ goto done;
+ }
+
+ {
+ GError *err = NULL;
+
+ gst_message_parse_error (msg, &err, NULL);
+ gst_message_unref (msg);
+ g_error ("Error with ICY mp3 shoutcast stream: %s", err->message);
+ g_error_free (err);
+ }
+
+done:
+
+ gst_element_set_state (pipe, GST_STATE_NULL);
+ gst_object_unref (pipe);
+}
+
+GST_END_TEST;
+
+static Suite *
+neonhttpsrc_suite (void)
+{
+ Suite *s = suite_create ("neonhttpsrc");
+ TCase *tc_chain = tcase_create ("general");
+
+ suite_add_tcase (s, tc_chain);
+ tcase_set_timeout (tc_chain, 5);
+ tcase_add_test (tc_chain, test_first_buffer_has_offset);
+ tcase_add_test (tc_chain, test_icy_stream);
+
+ return s;
+}
+
+GST_CHECK_MAIN (neonhttpsrc);
diff --git a/tests/check/elements/ofa.c b/tests/check/elements/ofa.c
new file mode 100644
index 00000000..d1d61be5
--- /dev/null
+++ b/tests/check/elements/ofa.c
@@ -0,0 +1,396 @@
+/* GStreamer
+ * Copyright (C) 2008 Sebastian Dröge <slomo@circular-chaos.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>
+
+static gboolean found_fingerprint = FALSE;
+
+static gboolean
+bus_handler (GstBus * bus, GstMessage * message, gpointer data)
+{
+ GMainLoop *loop = (GMainLoop *) data;
+
+ switch (message->type) {
+ case GST_MESSAGE_EOS:
+ g_main_loop_quit (loop);
+ break;
+ case GST_MESSAGE_WARNING:
+ case GST_MESSAGE_ERROR:{
+ GError *gerror;
+ gchar *debug;
+
+ if (message->type == GST_MESSAGE_WARNING)
+ gst_message_parse_warning (message, &gerror, &debug);
+ else
+ gst_message_parse_error (message, &gerror, &debug);
+ gst_object_default_error (GST_MESSAGE_SRC (message), gerror, debug);
+ gst_message_unref (message);
+ g_error_free (gerror);
+ g_free (debug);
+ g_main_loop_quit (loop);
+ break;
+ }
+ case GST_MESSAGE_TAG:
+ {
+ GstTagList *tag_list;
+ gchar *fpr, *p;
+
+ gst_message_parse_tag (message, &tag_list);
+
+ fail_unless (gst_tag_list_get_string (tag_list, "ofa-fingerprint", &fpr));
+
+ p = fpr;
+ while (*p) {
+ fail_unless (g_ascii_isalnum (*p) || *p == '=' || *p == '+'
+ || *p == '/');
+ p++;
+ }
+
+ g_free (fpr);
+ gst_tag_list_free (tag_list);
+
+ found_fingerprint = TRUE;
+
+ g_main_loop_quit (loop);
+ break;
+ }
+ default:
+ break;
+ }
+
+ return TRUE;
+}
+
+GST_START_TEST (test_ofa_le_1ch)
+{
+ GstElement *pipeline;
+ GstElement *audiotestsrc, *audioconvert, *capsfilter, *ofa, *fakesink;
+
+ GstBus *bus;
+ GMainLoop *loop;
+ GstCaps *caps;
+ gint64 position;
+ GstFormat fmt = GST_FORMAT_TIME;
+ guint bus_watch = 0;
+
+ pipeline = gst_pipeline_new ("pipeline");
+ fail_unless (pipeline != NULL);
+
+ audiotestsrc = gst_element_factory_make ("audiotestsrc", "src");
+ fail_unless (audiotestsrc != NULL);
+ g_object_set (G_OBJECT (audiotestsrc), "wave", 0, "freq", 440.0, NULL);
+
+ audioconvert = gst_element_factory_make ("audioconvert", "audioconvert");
+ fail_unless (audioconvert != NULL);
+ g_object_set (G_OBJECT (audioconvert), "dithering", 0, NULL);
+
+ capsfilter = gst_element_factory_make ("capsfilter", "capsfilter");
+ fail_unless (capsfilter != NULL);
+ caps = gst_caps_new_simple ("audio/x-raw-int",
+ "rate", G_TYPE_INT, 44100,
+ "channels", G_TYPE_INT, 1,
+ "endianness", G_TYPE_INT, G_LITTLE_ENDIAN,
+ "width", G_TYPE_INT, 16,
+ "depth", G_TYPE_INT, 16, "signed", G_TYPE_BOOLEAN, TRUE, NULL);
+ g_object_set (G_OBJECT (capsfilter), "caps", caps, NULL);
+ gst_caps_unref (caps);
+
+ ofa = gst_element_factory_make ("ofa", "ofa");
+ fail_unless (ofa != NULL);
+
+ fakesink = gst_element_factory_make ("fakesink", "sink");
+ fail_unless (fakesink != NULL);
+
+ gst_bin_add_many (GST_BIN (pipeline), audiotestsrc, audioconvert, capsfilter,
+ ofa, fakesink, NULL);
+
+ fail_unless (gst_element_link_many (audiotestsrc, audioconvert, capsfilter,
+ ofa, fakesink, NULL));
+
+ loop = g_main_loop_new (NULL, TRUE);
+ fail_unless (loop != NULL);
+
+ bus = gst_element_get_bus (pipeline);
+ fail_unless (bus != NULL);
+ bus_watch = gst_bus_add_watch (bus, bus_handler, loop);
+ gst_object_unref (bus);
+
+ found_fingerprint = FALSE;
+ gst_element_set_state (pipeline, GST_STATE_PLAYING);
+ g_main_loop_run (loop);
+
+ fail_unless (gst_element_query_position (audiotestsrc, &fmt, &position));
+ fail_unless (position >= 135 * GST_SECOND);
+
+ gst_element_set_state (pipeline, GST_STATE_NULL);
+
+ fail_unless (found_fingerprint == TRUE);
+ g_object_unref (pipeline);
+ g_main_loop_unref (loop);
+ g_source_remove (bus_watch);
+}
+
+GST_END_TEST;
+
+
+GST_START_TEST (test_ofa_be_1ch)
+{
+ GstElement *pipeline;
+ GstElement *audiotestsrc, *audioconvert, *capsfilter, *ofa, *fakesink;
+ GstBus *bus;
+ GMainLoop *loop;
+ GstCaps *caps;
+ gint64 position;
+ GstFormat fmt = GST_FORMAT_TIME;
+ guint bus_watch = 0;
+
+ pipeline = gst_pipeline_new ("pipeline");
+ fail_unless (pipeline != NULL);
+
+ audiotestsrc = gst_element_factory_make ("audiotestsrc", "src");
+ fail_unless (audiotestsrc != NULL);
+ g_object_set (G_OBJECT (audiotestsrc), "wave", 0, "freq", 440.0, NULL);
+
+ audioconvert = gst_element_factory_make ("audioconvert", "audioconvert");
+ fail_unless (audioconvert != NULL);
+ g_object_set (G_OBJECT (audioconvert), "dithering", 0, NULL);
+
+ capsfilter = gst_element_factory_make ("capsfilter", "capsfilter");
+ fail_unless (capsfilter != NULL);
+ caps = gst_caps_new_simple ("audio/x-raw-int",
+ "rate", G_TYPE_INT, 44100,
+ "channels", G_TYPE_INT, 1,
+ "endianness", G_TYPE_INT, G_BIG_ENDIAN,
+ "width", G_TYPE_INT, 16,
+ "depth", G_TYPE_INT, 16, "signed", G_TYPE_BOOLEAN, TRUE, NULL);
+ g_object_set (G_OBJECT (capsfilter), "caps", caps, NULL);
+ gst_caps_unref (caps);
+
+ ofa = gst_element_factory_make ("ofa", "ofa");
+ fail_unless (ofa != NULL);
+
+ fakesink = gst_element_factory_make ("fakesink", "sink");
+ fail_unless (fakesink != NULL);
+
+ gst_bin_add_many (GST_BIN (pipeline), audiotestsrc, audioconvert, capsfilter,
+ ofa, fakesink, NULL);
+
+ fail_unless (gst_element_link_many (audiotestsrc, audioconvert, capsfilter,
+ ofa, fakesink, NULL));
+
+ loop = g_main_loop_new (NULL, TRUE);
+ fail_unless (loop != NULL);
+
+ bus = gst_element_get_bus (pipeline);
+ fail_unless (bus != NULL);
+ bus_watch = gst_bus_add_watch (bus, bus_handler, loop);
+ gst_object_unref (bus);
+
+ found_fingerprint = FALSE;
+ gst_element_set_state (pipeline, GST_STATE_PLAYING);
+ g_main_loop_run (loop);
+
+ fail_unless (gst_element_query_position (audiotestsrc, &fmt, &position));
+ fail_unless (position >= 135 * GST_SECOND);
+
+ gst_element_set_state (pipeline, GST_STATE_NULL);
+
+ fail_unless (found_fingerprint == TRUE);
+ g_object_unref (pipeline);
+ g_main_loop_unref (loop);
+ g_source_remove (bus_watch);
+}
+
+GST_END_TEST;
+
+GST_START_TEST (test_ofa_le_2ch)
+{
+ GstElement *pipeline;
+ GstElement *audiotestsrc, *audioconvert, *capsfilter, *ofa, *fakesink;
+ GstBus *bus;
+ GMainLoop *loop;
+ GstCaps *caps;
+ gint64 position;
+ GstFormat fmt = GST_FORMAT_TIME;
+ guint bus_watch = 0;
+
+ pipeline = gst_pipeline_new ("pipeline");
+ fail_unless (pipeline != NULL);
+
+ audiotestsrc = gst_element_factory_make ("audiotestsrc", "src");
+ fail_unless (audiotestsrc != NULL);
+ g_object_set (G_OBJECT (audiotestsrc), "wave", 0, "freq", 440.0, NULL);
+
+ audioconvert = gst_element_factory_make ("audioconvert", "audioconvert");
+ fail_unless (audioconvert != NULL);
+ g_object_set (G_OBJECT (audioconvert), "dithering", 0, NULL);
+
+ capsfilter = gst_element_factory_make ("capsfilter", "capsfilter");
+ fail_unless (capsfilter != NULL);
+ caps = gst_caps_new_simple ("audio/x-raw-int",
+ "rate", G_TYPE_INT, 44100,
+ "channels", G_TYPE_INT, 2,
+ "endianness", G_TYPE_INT, G_LITTLE_ENDIAN,
+ "width", G_TYPE_INT, 16,
+ "depth", G_TYPE_INT, 16, "signed", G_TYPE_BOOLEAN, TRUE, NULL);
+ g_object_set (G_OBJECT (capsfilter), "caps", caps, NULL);
+ gst_caps_unref (caps);
+
+ ofa = gst_element_factory_make ("ofa", "ofa");
+ fail_unless (ofa != NULL);
+
+ fakesink = gst_element_factory_make ("fakesink", "sink");
+ fail_unless (fakesink != NULL);
+
+ gst_bin_add_many (GST_BIN (pipeline), audiotestsrc, audioconvert, capsfilter,
+ ofa, fakesink, NULL);
+
+ fail_unless (gst_element_link_many (audiotestsrc, audioconvert, capsfilter,
+ ofa, fakesink, NULL));
+
+ loop = g_main_loop_new (NULL, TRUE);
+ fail_unless (loop != NULL);
+
+ bus = gst_element_get_bus (pipeline);
+ fail_unless (bus != NULL);
+ bus_watch = gst_bus_add_watch (bus, bus_handler, loop);
+ gst_object_unref (bus);
+
+ found_fingerprint = FALSE;
+ gst_element_set_state (pipeline, GST_STATE_PLAYING);
+ g_main_loop_run (loop);
+
+ fail_unless (gst_element_query_position (audiotestsrc, &fmt, &position));
+ fail_unless (position >= 135 * GST_SECOND);
+
+ gst_element_set_state (pipeline, GST_STATE_NULL);
+
+ fail_unless (found_fingerprint == TRUE);
+ g_object_unref (pipeline);
+ g_main_loop_unref (loop);
+ g_source_remove (bus_watch);
+}
+
+GST_END_TEST;
+
+
+GST_START_TEST (test_ofa_be_2ch)
+{
+ GstElement *pipeline;
+ GstElement *audiotestsrc, *audioconvert, *capsfilter, *ofa, *fakesink;
+ GstBus *bus;
+ GMainLoop *loop;
+ GstCaps *caps;
+ gint64 position;
+ GstFormat fmt = GST_FORMAT_TIME;
+ guint bus_watch = 0;
+
+ pipeline = gst_pipeline_new ("pipeline");
+ fail_unless (pipeline != NULL);
+
+ audiotestsrc = gst_element_factory_make ("audiotestsrc", "src");
+ fail_unless (audiotestsrc != NULL);
+ g_object_set (G_OBJECT (audiotestsrc), "wave", 0, "freq", 440.0, NULL);
+
+ audioconvert = gst_element_factory_make ("audioconvert", "audioconvert");
+ fail_unless (audioconvert != NULL);
+ g_object_set (G_OBJECT (audioconvert), "dithering", 0, NULL);
+
+ capsfilter = gst_element_factory_make ("capsfilter", "capsfilter");
+ fail_unless (capsfilter != NULL);
+ caps = gst_caps_new_simple ("audio/x-raw-int",
+ "rate", G_TYPE_INT, 44100,
+ "channels", G_TYPE_INT, 2,
+ "endianness", G_TYPE_INT, G_BIG_ENDIAN,
+ "width", G_TYPE_INT, 16,
+ "depth", G_TYPE_INT, 16, "signed", G_TYPE_BOOLEAN, TRUE, NULL);
+ g_object_set (G_OBJECT (capsfilter), "caps", caps, NULL);
+ gst_caps_unref (caps);
+
+ ofa = gst_element_factory_make ("ofa", "ofa");
+ fail_unless (ofa != NULL);
+
+ fakesink = gst_element_factory_make ("fakesink", "sink");
+ fail_unless (fakesink != NULL);
+
+ gst_bin_add_many (GST_BIN (pipeline), audiotestsrc, audioconvert, capsfilter,
+ ofa, fakesink, NULL);
+
+ fail_unless (gst_element_link_many (audiotestsrc, audioconvert, capsfilter,
+ ofa, fakesink, NULL));
+
+ loop = g_main_loop_new (NULL, TRUE);
+ fail_unless (loop != NULL);
+
+ bus = gst_element_get_bus (pipeline);
+ fail_unless (bus != NULL);
+ bus_watch = gst_bus_add_watch (bus, bus_handler, loop);
+ gst_object_unref (bus);
+
+ found_fingerprint = FALSE;
+ gst_element_set_state (pipeline, GST_STATE_PLAYING);
+ g_main_loop_run (loop);
+
+ fail_unless (gst_element_query_position (audiotestsrc, &fmt, &position));
+ fail_unless (position >= 135 * GST_SECOND);
+
+ gst_element_set_state (pipeline, GST_STATE_NULL);
+
+ fail_unless (found_fingerprint == TRUE);
+ g_object_unref (pipeline);
+ g_main_loop_unref (loop);
+ g_source_remove (bus_watch);
+}
+
+GST_END_TEST;
+
+static Suite *
+ofa_suite (void)
+{
+ Suite *s = suite_create ("OFA");
+ TCase *tc_chain = tcase_create ("linear");
+
+ /* time out after 120s, not the default 3 */
+ tcase_set_timeout (tc_chain, 120);
+
+ suite_add_tcase (s, tc_chain);
+ tcase_add_test (tc_chain, test_ofa_le_1ch);
+ tcase_add_test (tc_chain, test_ofa_be_1ch);
+ tcase_add_test (tc_chain, test_ofa_le_2ch);
+ tcase_add_test (tc_chain, test_ofa_be_2ch);
+
+ return s;
+}
+
+int
+main (int argc, char **argv)
+{
+ int nf;
+
+ Suite *s = ofa_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/opus.c b/tests/check/elements/opus.c
new file mode 100644
index 00000000..be5b2cf6
--- /dev/null
+++ b/tests/check/elements/opus.c
@@ -0,0 +1,385 @@
+/* GStreamer
+ *
+ * unit test for opus
+ *
+ * Copyright (C) <2011> Vincent Penquerc'h <vincent.penquerch@collbaora.co.uk>
+ *
+ * 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 <unistd.h>
+
+#include <gst/check/gstcheck.h>
+
+#if G_BYTE_ORDER == G_BIG_ENDIAN
+#define AFORMAT "S16BE"
+#else
+#define AFORMAT "S16LE"
+#endif
+
+#define AUDIO_CAPS_STRING "audio/x-raw, " \
+ "format = (string) " AFORMAT ", "\
+ "layout = (string) interleaved, " \
+ "rate = (int) 48000, " \
+ "channels = (int) 1 "
+
+static const guint8 opus_ogg_id_header[19] = {
+ 0x4f, 0x70, 0x75, 0x73, 0x48, 0x65, 0x61, 0x64, 0x00, 0x02, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+};
+
+static const guint8 opus_ogg_comments_header[] = {
+ 0x4f, 0x70, 0x75, 0x73, 0x54, 0x61, 0x67, 0x73, 0x1e, 0x00, 0x00, 0x00, 0x45,
+ 0x6e, 0x63, 0x6f, 0x64, 0x65, 0x64, 0x20, 0x77, 0x69, 0x74, 0x68, 0x20, 0x47,
+ 0x53, 0x74, 0x72, 0x65, 0x61, 0x6d, 0x65, 0x72, 0x20, 0x4f, 0x70, 0x75, 0x73,
+ 0x65, 0x6e, 0x63, 0x00, 0x00, 0x00, 0x00
+};
+
+/* A lot of these taken from the vorbisdec test */
+
+/* For ease of programming we use globals to keep refs for our floating
+ * src and sink pads we create; otherwise we always have to do get_pad,
+ * get_peer, and then remove references in every test function */
+static GstPad *mydecsrcpad, *mydecsinkpad;
+static GstPad *myencsrcpad, *myencsinkpad;
+
+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_ANY);
+
+static GstElement *
+setup_opusdec (void)
+{
+ GstElement *opusdec;
+
+ GST_DEBUG ("setup_opusdec");
+ opusdec = gst_check_setup_element ("opusdec");
+ mydecsrcpad = gst_check_setup_src_pad (opusdec, &srctemplate);
+ mydecsinkpad = gst_check_setup_sink_pad (opusdec, &sinktemplate);
+ gst_pad_set_active (mydecsrcpad, TRUE);
+ gst_pad_set_active (mydecsinkpad, TRUE);
+
+ return opusdec;
+}
+
+static void
+cleanup_opusdec (GstElement * opusdec)
+{
+ GST_DEBUG ("cleanup_opusdec");
+ gst_element_set_state (opusdec, GST_STATE_NULL);
+
+ gst_pad_set_active (mydecsrcpad, FALSE);
+ gst_pad_set_active (mydecsinkpad, FALSE);
+ gst_check_teardown_src_pad (opusdec);
+ gst_check_teardown_sink_pad (opusdec);
+ gst_check_teardown_element (opusdec);
+}
+
+static GstElement *
+setup_opusenc (void)
+{
+ GstElement *opusenc;
+
+ GST_DEBUG ("setup_opusenc");
+ opusenc = gst_check_setup_element ("opusenc");
+ myencsrcpad = gst_check_setup_src_pad (opusenc, &srctemplate);
+ myencsinkpad = gst_check_setup_sink_pad (opusenc, &sinktemplate);
+ gst_pad_set_active (myencsrcpad, TRUE);
+ gst_pad_set_active (myencsinkpad, TRUE);
+
+ return opusenc;
+}
+
+static void
+cleanup_opusenc (GstElement * opusenc)
+{
+ GST_DEBUG ("cleanup_opusenc");
+ gst_element_set_state (opusenc, GST_STATE_NULL);
+
+ gst_pad_set_active (myencsrcpad, FALSE);
+ gst_pad_set_active (myencsinkpad, FALSE);
+ gst_check_teardown_src_pad (opusenc);
+ gst_check_teardown_sink_pad (opusenc);
+ gst_check_teardown_element (opusenc);
+}
+
+static void
+check_buffers (guint expected)
+{
+ GstBuffer *outbuffer;
+ guint i, num_buffers;
+
+ /* check buffers are the type we expect */
+ num_buffers = g_list_length (buffers);
+ fail_unless (num_buffers >= expected);
+ for (i = 0; i < num_buffers; ++i) {
+ outbuffer = GST_BUFFER (buffers->data);
+ fail_if (outbuffer == NULL);
+ fail_if (gst_buffer_get_size (outbuffer) == 0);
+
+ buffers = g_list_remove (buffers, outbuffer);
+
+ ASSERT_BUFFER_REFCOUNT (outbuffer, "outbuffer", 1);
+ gst_buffer_unref (outbuffer);
+ outbuffer = NULL;
+ }
+}
+
+GST_START_TEST (test_opus_id_header)
+{
+ GstElement *opusdec;
+ GstBuffer *inbuffer;
+
+ opusdec = setup_opusdec ();
+ fail_unless (gst_element_set_state (opusdec,
+ GST_STATE_PLAYING) == GST_STATE_CHANGE_SUCCESS,
+ "could not set to playing");
+
+ inbuffer = gst_buffer_new_and_alloc (sizeof (opus_ogg_id_header));
+ gst_buffer_fill (inbuffer, 0, opus_ogg_id_header,
+ sizeof (opus_ogg_id_header));
+ ASSERT_BUFFER_REFCOUNT (inbuffer, "inbuffer", 1);
+ gst_buffer_ref (inbuffer);
+
+ /* pushing gives away my reference ... */
+ fail_unless (gst_pad_push (mydecsrcpad, inbuffer) == GST_FLOW_OK);
+ /* ... and nothing ends up on the global buffer list */
+ ASSERT_BUFFER_REFCOUNT (inbuffer, "inbuffer", 1);
+ gst_buffer_unref (inbuffer);
+ check_buffers (0);
+
+ /* cleanup */
+ cleanup_opusdec (opusdec);
+}
+
+GST_END_TEST;
+
+GST_START_TEST (test_opus_encode_nothing)
+{
+ GstElement *opusenc;
+
+ opusenc = setup_opusenc ();
+ fail_unless (gst_element_set_state (opusenc,
+ GST_STATE_PLAYING) == GST_STATE_CHANGE_SUCCESS,
+ "could not set to playing");
+
+ fail_unless (gst_pad_push_event (myencsrcpad, gst_event_new_eos ()) == TRUE);
+
+ fail_unless (gst_element_set_state (opusenc,
+ GST_STATE_READY) == GST_STATE_CHANGE_SUCCESS,
+ "could not set to ready");
+
+ /* cleanup */
+ cleanup_opusenc (opusenc);
+}
+
+GST_END_TEST;
+
+GST_START_TEST (test_opus_decode_nothing)
+{
+ GstElement *opusdec;
+
+ opusdec = setup_opusdec ();
+ fail_unless (gst_element_set_state (opusdec,
+ GST_STATE_PLAYING) == GST_STATE_CHANGE_SUCCESS,
+ "could not set to playing");
+
+ fail_unless (gst_pad_push_event (mydecsrcpad, gst_event_new_eos ()) == TRUE);
+
+ fail_unless (gst_element_set_state (opusdec,
+ GST_STATE_READY) == GST_STATE_CHANGE_SUCCESS,
+ "could not set to ready");
+
+ /* cleanup */
+ cleanup_opusdec (opusdec);
+}
+
+GST_END_TEST;
+
+GST_START_TEST (test_opus_encode_samples)
+{
+ const unsigned int nsamples = 4096;
+ GstElement *opusenc;
+ GstBuffer *inbuffer;
+ GstCaps *caps;
+
+ opusenc = setup_opusenc ();
+
+ fail_unless (gst_element_set_state (opusenc,
+ GST_STATE_PLAYING) == GST_STATE_CHANGE_SUCCESS,
+ "could not set to playing");
+
+ inbuffer = gst_buffer_new_and_alloc (nsamples * 2);
+ gst_buffer_memset (inbuffer, 0, 0, nsamples * 2);
+
+ GST_BUFFER_TIMESTAMP (inbuffer) = GST_BUFFER_OFFSET (inbuffer) = 0;
+ GST_BUFFER_DURATION (inbuffer) = GST_CLOCK_TIME_NONE;
+ ASSERT_BUFFER_REFCOUNT (inbuffer, "inbuffer", 1);
+
+ caps = gst_caps_from_string (AUDIO_CAPS_STRING);
+ fail_unless (caps != NULL);
+ gst_pad_set_caps (myencsrcpad, caps);
+ gst_caps_unref (caps);
+ gst_buffer_ref (inbuffer);
+
+ /* pushing gives away my reference ... */
+ fail_unless (gst_pad_push (myencsrcpad, inbuffer) == GST_FLOW_OK);
+ /* ... and nothing ends up on the global buffer list */
+ fail_unless (gst_pad_push_event (myencsrcpad, gst_event_new_eos ()) == TRUE);
+
+ ASSERT_BUFFER_REFCOUNT (inbuffer, "inbuffer", 1);
+ gst_buffer_unref (inbuffer);
+
+ fail_unless (gst_element_set_state (opusenc,
+ GST_STATE_READY) == GST_STATE_CHANGE_SUCCESS,
+ "could not set to ready");
+
+ /* default frame size is 20 ms, at 48000 Hz that's 960 samples */
+ check_buffers ((nsamples + 959) / 960);
+
+ /* cleanup */
+ cleanup_opusenc (opusenc);
+ g_list_free (buffers);
+}
+
+GST_END_TEST;
+
+GST_START_TEST (test_opus_encode_properties)
+{
+ const unsigned int nsamples = 4096;
+ enum
+ { steps = 20 };
+ GstElement *opusenc;
+ GstBuffer *inbuffer;
+ GstCaps *caps;
+ unsigned int step;
+ static const struct
+ {
+ const char *param;
+ int value;
+ } param_changes[steps] = {
+ {
+ "frame-size", 40}, {
+ "inband-fec", 1}, {
+ "complexity", 5}, {
+ "bandwidth", 1104}, {
+ "frame-size", 2}, {
+ "max-payload-size", 80}, {
+ "frame-size", 60}, {
+ "max-payload-size", 900}, {
+ "complexity", 1}, {
+ "bitrate", 30000}, {
+ "frame-size", 10}, {
+ "bitrate", 300000}, {
+ "inband-fec", 0}, {
+ "frame-size", 5}, {
+ "bandwidth", 1101}, {
+ "frame-size", 10}, {
+ "bitrate", 500000}, {
+ "frame-size", 5}, {
+ "bitrate", 80000}, {
+ "complexity", 8},};
+
+ opusenc = setup_opusenc ();
+
+ fail_unless (gst_element_set_state (opusenc,
+ GST_STATE_PLAYING) == GST_STATE_CHANGE_SUCCESS,
+ "could not set to playing");
+
+ caps = gst_caps_from_string (AUDIO_CAPS_STRING);
+ fail_unless (caps != NULL);
+
+ gst_pad_set_caps (myencsrcpad, caps);
+
+ for (step = 0; step < steps; ++step) {
+ inbuffer = gst_buffer_new_and_alloc (nsamples * 2);
+ gst_buffer_memset (inbuffer, 0, 0, nsamples * 2);
+
+ GST_BUFFER_TIMESTAMP (inbuffer) = GST_BUFFER_OFFSET (inbuffer) = 0;
+ GST_BUFFER_DURATION (inbuffer) = GST_CLOCK_TIME_NONE;
+ ASSERT_BUFFER_REFCOUNT (inbuffer, "inbuffer", 1);
+
+ gst_buffer_ref (inbuffer);
+
+ /* pushing gives away my reference ... */
+ fail_unless (gst_pad_push (myencsrcpad, inbuffer) == GST_FLOW_OK);
+ /* ... and nothing ends up on the global buffer list */
+ fail_unless (gst_pad_push_event (myencsrcpad,
+ gst_event_new_eos ()) == TRUE);
+
+ ASSERT_BUFFER_REFCOUNT (inbuffer, "inbuffer", 1);
+ gst_buffer_unref (inbuffer);
+
+ /* change random parameters */
+ g_object_set (opusenc, param_changes[step].param, param_changes[step].value,
+ NULL);
+
+ check_buffers (1);
+ }
+
+ gst_caps_unref (caps);
+
+ fail_unless (gst_element_set_state (opusenc,
+ GST_STATE_READY) == GST_STATE_CHANGE_SUCCESS,
+ "could not set to ready");
+
+ /* cleanup */
+ cleanup_opusenc (opusenc);
+ g_list_free (buffers);
+}
+
+GST_END_TEST;
+
+static Suite *
+opus_suite (void)
+{
+ Suite *s = suite_create ("opus");
+ TCase *tc_chain = tcase_create ("general");
+
+ suite_add_tcase (s, tc_chain);
+
+#define X if (0)
+ tcase_add_test (tc_chain, test_opus_id_header);
+ tcase_add_test (tc_chain, test_opus_encode_nothing);
+ tcase_add_test (tc_chain, test_opus_decode_nothing);
+ tcase_add_test (tc_chain, test_opus_encode_samples);
+ tcase_add_test (tc_chain, test_opus_encode_properties);
+#undef X
+
+ return s;
+}
+
+int
+main (int argc, char **argv)
+{
+ int nf;
+
+ Suite *s = opus_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/parser.c b/tests/check/elements/parser.c
new file mode 100644
index 00000000..356b7738
--- /dev/null
+++ b/tests/check/elements/parser.c
@@ -0,0 +1,428 @@
+/*
+ * GStreamer
+ *
+ * unit test for (audio) parser
+ *
+ * Copyright (C) 2008 Nokia Corporation. All rights reserved.
+ *
+ * Contact: Stefan Kost <stefan.kost@nokia.com>
+ *
+ * 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>
+#include "elements/parser.h"
+
+
+/* context state variables */
+const gchar *ctx_factory;
+GstStaticPadTemplate *ctx_sink_template;
+GstStaticPadTemplate *ctx_src_template;
+GstCaps *ctx_input_caps;
+GstCaps *ctx_output_caps;
+guint ctx_discard = 0;
+datablob ctx_headers[MAX_HEADERS] = { {NULL, 0}, };
+
+VerifyBuffer ctx_verify_buffer = NULL;
+ElementSetup ctx_setup = NULL;
+
+gboolean ctx_no_metadata = FALSE;
+
+/* helper variables */
+GList *current_buf = NULL;
+
+GstPad *srcpad, *sinkpad;
+guint dataoffset = 0;
+
+/* takes a copy of the passed buffer data */
+static GstBuffer *
+buffer_new (const unsigned char *buffer_data, guint size)
+{
+ GstBuffer *buffer;
+
+ buffer = gst_buffer_new_and_alloc (size);
+ if (buffer_data) {
+ gst_buffer_fill (buffer, 0, buffer_data, size);
+ } else {
+ guint i;
+ GstMapInfo map;
+
+ /* Create a recognizable pattern (loop 0x00 -> 0xff) in the data block */
+ gst_buffer_map (buffer, &map, GST_MAP_WRITE);
+ for (i = 0; i < size; i++) {
+ map.data[i] = i % 0x100;
+ }
+ gst_buffer_unmap (buffer, &map);
+ }
+
+ GST_BUFFER_OFFSET (buffer) = dataoffset;
+ dataoffset += size;
+ return buffer;
+}
+
+/*
+ * Adds buffer sizes together.
+ */
+static void
+buffer_count_size (void *buffer, void *user_data)
+{
+ guint *sum = (guint *) user_data;
+ *sum += gst_buffer_get_size (buffer);
+}
+
+/*
+ * Verify that given buffer contains predefined ADTS frame.
+ */
+static void
+buffer_verify_data (void *buffer, void *user_data)
+{
+ buffer_verify_data_s *vdata;
+
+ if (!user_data) {
+ return;
+ }
+
+ vdata = (buffer_verify_data_s *) user_data;
+
+ GST_DEBUG ("discard: %d", vdata->discard);
+ if (vdata->discard) {
+ if (ctx_verify_buffer)
+ ctx_verify_buffer (vdata, buffer);
+ vdata->buffer_counter++;
+ vdata->offset_counter += gst_buffer_get_size (buffer);
+ if (vdata->buffer_counter == vdata->discard) {
+ vdata->buffer_counter = 0;
+ vdata->discard = 0;
+ }
+ return;
+ }
+
+ if (!ctx_verify_buffer || !ctx_verify_buffer (vdata, buffer)) {
+ fail_unless (gst_buffer_get_size (buffer) == vdata->data_to_verify_size);
+ fail_unless (gst_buffer_memcmp (buffer, 0, vdata->data_to_verify,
+ vdata->data_to_verify_size) == 0);
+ }
+
+ if (vdata->buffers_before_offset_skip) {
+ /* This is for skipping the garbage in some test cases */
+ if (vdata->buffer_counter == vdata->buffers_before_offset_skip) {
+ vdata->offset_counter += vdata->offset_skip_amount;
+ }
+ }
+ if (!vdata->no_metadata) {
+ fail_unless (GST_BUFFER_TIMESTAMP (buffer) == vdata->ts_counter);
+ fail_unless (GST_BUFFER_DURATION (buffer) != 0);
+ fail_unless (GST_BUFFER_OFFSET (buffer) == vdata->offset_counter);
+ }
+
+ vdata->ts_counter += GST_BUFFER_DURATION (buffer);
+ vdata->offset_counter += gst_buffer_get_size (buffer);
+ vdata->buffer_counter++;
+}
+
+static GstElement *
+setup_element (const gchar * factory, ElementSetup setup,
+ GstStaticPadTemplate * sink_template,
+ GstCaps * sink_caps, GstStaticPadTemplate * src_template,
+ GstCaps * src_caps)
+{
+ GstElement *element;
+ GstBus *bus;
+
+ if (setup) {
+ element = setup (factory);
+ } else {
+ element = gst_check_setup_element (factory);
+ }
+ srcpad = gst_check_setup_src_pad (element, src_template);
+ sinkpad = gst_check_setup_sink_pad (element, sink_template);
+ gst_pad_set_active (srcpad, TRUE);
+ gst_pad_set_active (sinkpad, TRUE);
+ if (src_caps)
+ fail_unless (gst_pad_set_caps (srcpad, src_caps));
+ if (sink_caps)
+ fail_unless (gst_pad_set_caps (sinkpad, sink_caps));
+
+ bus = gst_bus_new ();
+ gst_element_set_bus (element, bus);
+
+ fail_unless (gst_element_set_state (element,
+ GST_STATE_PLAYING) != GST_STATE_CHANGE_FAILURE,
+ "could not set to playing");
+
+ buffers = NULL;
+ return element;
+}
+
+static void
+cleanup_element (GstElement * element)
+{
+ GstBus *bus;
+
+ /* Free parsed buffers */
+ gst_check_drop_buffers ();
+
+ bus = GST_ELEMENT_BUS (element);
+ gst_bus_set_flushing (bus, TRUE);
+ gst_object_unref (bus);
+
+ gst_pad_set_active (srcpad, FALSE);
+ gst_pad_set_active (sinkpad, FALSE);
+ gst_check_teardown_src_pad (element);
+ gst_check_teardown_sink_pad (element);
+ gst_check_teardown_element (element);
+}
+
+/* inits a standard test */
+void
+gst_parser_test_init (GstParserTest * ptest, guint8 * data, guint size,
+ guint num)
+{
+ /* need these */
+ fail_unless (ctx_factory != NULL);
+ fail_unless (ctx_src_template != NULL);
+ fail_unless (ctx_sink_template != NULL);
+
+ /* basics */
+ memset (ptest, 0, sizeof (*ptest));
+ ptest->factory = ctx_factory;
+ ptest->factory_setup = ctx_setup;
+ ptest->sink_template = ctx_sink_template;
+ ptest->src_template = ctx_src_template;
+ ptest->framed = TRUE;
+ /* could be NULL if not relevant/needed */
+ ptest->src_caps = ctx_input_caps;
+ ptest->sink_caps = ctx_output_caps;
+ memcpy (ptest->headers, ctx_headers, sizeof (ptest->headers));
+ ptest->discard = ctx_discard;
+ /* some data that pleases caller */
+ ptest->series[0].data = data;
+ ptest->series[0].size = size;
+ ptest->series[0].num = num;
+ ptest->series[0].fpb = 1;
+ ptest->series[1].fpb = 1;
+ ptest->series[2].fpb = 1;
+ ptest->no_metadata = ctx_no_metadata;
+}
+
+/*
+ * Test if the parser pushes clean data properly.
+ */
+void
+gst_parser_test_run (GstParserTest * test, GstCaps ** out_caps)
+{
+ buffer_verify_data_s vdata = { 0, 0, 0, NULL, 0, NULL, FALSE, 0, 0, 0 };
+ GstElement *element;
+ GstBuffer *buffer = NULL;
+ GstCaps *src_caps;
+ guint i, j, k;
+ guint frames = 0, size = 0;
+
+ element = setup_element (test->factory, test->factory_setup,
+ test->sink_template, NULL, test->src_template, test->src_caps);
+
+ /* push some setup headers */
+ for (j = 0; j < G_N_ELEMENTS (test->headers) && test->headers[j].data; j++) {
+ buffer = buffer_new (test->headers[j].data, test->headers[j].size);
+ fail_unless_equals_int (gst_pad_push (srcpad, buffer), GST_FLOW_OK);
+ }
+
+ for (j = 0; j < 3; j++) {
+ for (i = 0; i < test->series[j].num; i++) {
+ /* sanity enforcing */
+ for (k = 0; k < MAX (1, test->series[j].fpb); k++) {
+ if (!k)
+ buffer = buffer_new (test->series[j].data, test->series[j].size);
+ else {
+ buffer = gst_buffer_append (buffer,
+ buffer_new (test->series[j].data, test->series[j].size));
+ }
+ }
+ fail_unless_equals_int (gst_pad_push (srcpad, buffer), GST_FLOW_OK);
+ if (j == 0)
+ vdata.buffers_before_offset_skip++;
+ else if (j == 1)
+ vdata.offset_skip_amount += test->series[j].size * test->series[j].fpb;
+ if (j != 1) {
+ frames += test->series[j].fpb;
+ size += test->series[j].size * test->series[j].fpb;
+ }
+ }
+ }
+ gst_pad_push_event (srcpad, gst_event_new_eos ());
+
+ if (G_LIKELY (test->framed))
+ fail_unless_equals_int (g_list_length (buffers) - test->discard, frames);
+
+ /* if all frames are identical, do extended test,
+ * otherwise only verify total data size */
+ if (test->series[0].data && (!test->series[2].size ||
+ (test->series[0].size == test->series[2].size && test->series[2].data
+ && !memcmp (test->series[0].data, test->series[2].data,
+ test->series[0].size)))) {
+ vdata.data_to_verify = test->series[0].data;
+ vdata.data_to_verify_size = test->series[0].size;
+ vdata.caps = test->sink_caps;
+ vdata.discard = test->discard;
+ vdata.no_metadata = test->no_metadata;
+ g_list_foreach (buffers, buffer_verify_data, &vdata);
+ } else {
+ guint datasum = 0;
+
+ g_list_foreach (buffers, buffer_count_size, &datasum);
+ size -= test->dropped;
+ fail_unless_equals_int (datasum, size);
+ }
+
+ src_caps = gst_pad_get_current_caps (sinkpad);
+ GST_LOG ("output caps: %" GST_PTR_FORMAT, src_caps);
+
+ if (test->sink_caps) {
+ GST_LOG ("%" GST_PTR_FORMAT " = %" GST_PTR_FORMAT " ?", src_caps,
+ test->sink_caps);
+ fail_unless (gst_caps_is_equal (src_caps, test->sink_caps));
+ }
+
+ if (out_caps)
+ *out_caps = src_caps;
+ else
+ gst_caps_unref (src_caps);
+
+ cleanup_element (element);
+}
+
+/*
+ * Test if the parser pushes clean data properly.
+ */
+void
+gst_parser_test_normal (guint8 * data, guint size)
+{
+ GstParserTest ptest;
+
+ gst_parser_test_init (&ptest, data, size, 10);
+ gst_parser_test_run (&ptest, NULL);
+}
+
+/*
+ * Test if parser drains its buffers properly. Even one single frame
+ * should be drained and pushed forward when EOS occurs. This single frame
+ * case is special, since normally the parser needs more data to be sure
+ * about stream format. But it should still push the frame forward in EOS.
+ */
+void
+gst_parser_test_drain_single (guint8 * data, guint size)
+{
+ GstParserTest ptest;
+
+ gst_parser_test_init (&ptest, data, size, 1);
+ gst_parser_test_run (&ptest, NULL);
+}
+
+/*
+ * Make sure that parser does not drain garbage when EOS occurs.
+ */
+void
+gst_parser_test_drain_garbage (guint8 * data, guint size, guint8 * garbage,
+ guint gsize)
+{
+ GstParserTest ptest;
+
+ gst_parser_test_init (&ptest, data, size, 1);
+ ptest.series[1].data = garbage;
+ ptest.series[1].size = gsize;
+ ptest.series[1].num = 1;
+ gst_parser_test_run (&ptest, NULL);
+}
+
+/*
+ * Test if parser splits a buffer that contains two frames into two
+ * separate buffers properly.
+ */
+void
+gst_parser_test_split (guint8 * data, guint size)
+{
+ GstParserTest ptest;
+
+ gst_parser_test_init (&ptest, data, size, 10);
+ ptest.series[0].fpb = 2;
+ gst_parser_test_run (&ptest, NULL);
+}
+
+/*
+ * Test if the parser skips garbage between frames properly.
+ */
+void
+gst_parser_test_skip_garbage (guint8 * data, guint size, guint8 * garbage,
+ guint gsize)
+{
+ GstParserTest ptest;
+
+ gst_parser_test_init (&ptest, data, size, 10);
+ ptest.series[1].data = garbage;
+ ptest.series[1].size = gsize;
+ ptest.series[1].num = 1;
+ ptest.series[2].data = data;
+ ptest.series[2].size = size;
+ ptest.series[2].num = 10;
+ gst_parser_test_run (&ptest, NULL);
+}
+
+/*
+ * Test if the src caps are set according to stream format.
+ */
+void
+gst_parser_test_output_caps (guint8 * data, guint size,
+ const gchar * input_caps, const gchar * output_caps)
+{
+ GstParserTest ptest;
+
+ gst_parser_test_init (&ptest, data, size, 10);
+ if (input_caps) {
+ ptest.src_caps = gst_caps_from_string (input_caps);
+ fail_unless (ptest.src_caps != NULL);
+ }
+ if (output_caps) {
+ ptest.sink_caps = gst_caps_from_string (output_caps);
+ fail_unless (ptest.sink_caps != NULL);
+ }
+ gst_parser_test_run (&ptest, NULL);
+ if (ptest.sink_caps)
+ gst_caps_unref (ptest.sink_caps);
+ if (ptest.src_caps)
+ gst_caps_unref (ptest.src_caps);
+}
+
+/*
+ * Test if the src caps are set according to stream format.
+ */
+GstCaps *
+gst_parser_test_get_output_caps (guint8 * data, guint size,
+ const gchar * input_caps)
+{
+ GstParserTest ptest;
+ GstCaps *out_caps;
+
+ gst_parser_test_init (&ptest, data, size, 10);
+ if (input_caps) {
+ ptest.src_caps = gst_caps_from_string (input_caps);
+ fail_unless (ptest.src_caps != NULL);
+ }
+ gst_parser_test_run (&ptest, &out_caps);
+ if (ptest.src_caps)
+ gst_caps_unref (ptest.src_caps);
+
+ return out_caps;
+}
diff --git a/tests/check/elements/parser.h b/tests/check/elements/parser.h
new file mode 100644
index 00000000..7ae85c51
--- /dev/null
+++ b/tests/check/elements/parser.h
@@ -0,0 +1,117 @@
+/*
+ * GStreamer
+ *
+ * unit test for (audio) parser
+ *
+ * Copyright (C) 2008 Nokia Corporation. All rights reserved.
+ *
+ * Contact: Stefan Kost <stefan.kost@nokia.com>
+ *
+ * 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 MAX_HEADERS 10
+
+typedef struct
+{
+ guint discard;
+ guint buffers_before_offset_skip;
+ guint offset_skip_amount;
+ const guint8 *data_to_verify;
+ guint data_to_verify_size;
+ GstCaps *caps;
+ gboolean no_metadata;
+
+ GstClockTime ts_counter;
+ gint64 offset_counter;
+ guint buffer_counter;
+} buffer_verify_data_s;
+
+typedef struct {
+ guint8 *data;
+ guint size;
+} datablob;
+
+typedef gboolean (*VerifyBuffer) (buffer_verify_data_s * vdata, GstBuffer * buf);
+typedef GstElement* (*ElementSetup) (const gchar * desc);
+
+/* context state variables; to be set by test using this helper */
+/* mandatory */
+extern const gchar *ctx_factory;
+extern GstStaticPadTemplate *ctx_sink_template;
+extern GstStaticPadTemplate *ctx_src_template;
+/* optional */
+extern GstCaps *ctx_input_caps;
+extern GstCaps *ctx_output_caps;
+extern guint ctx_discard;
+extern datablob ctx_headers[MAX_HEADERS];
+extern gboolean ctx_no_metadata;
+
+extern VerifyBuffer ctx_verify_buffer;
+extern ElementSetup ctx_setup;
+
+/* no refs taken/kept, all up to caller */
+typedef struct
+{
+ const gchar *factory;
+ ElementSetup factory_setup;
+ GstStaticPadTemplate *sink_template;
+ GstStaticPadTemplate *src_template;
+ /* caps that go into element */
+ GstCaps *src_caps;
+ /* optional: output caps to verify */
+ GstCaps *sink_caps;
+ /* initial headers */
+ datablob headers[MAX_HEADERS];
+ /* initial (header) output to forego checking */
+ guint discard;
+ /* series of buffers; middle series considered garbage */
+ struct {
+ /* data and size */
+ guint8 *data;
+ guint size;
+ /* num of frames with above data per buffer */
+ guint fpb;
+ /* num of buffers */
+ guint num;
+ } series[3];
+ /* sigh, weird cases */
+ gboolean framed;
+ guint dropped;
+ gboolean no_metadata;
+} GstParserTest;
+
+void gst_parser_test_init (GstParserTest * ptest, guint8 * data, guint size, guint num);
+
+void gst_parser_test_run (GstParserTest * test, GstCaps ** out_caps);
+
+void gst_parser_test_normal (guint8 *data, guint size);
+
+void gst_parser_test_drain_single (guint8 *data, guint size);
+
+void gst_parser_test_drain_garbage (guint8 *data, guint size, guint8 *garbage, guint gsize);
+
+void gst_parser_test_split (guint8 *data, guint size);
+
+void gst_parser_test_skip_garbage (guint8 *data, guint size, guint8 *garbage, guint gsize);
+
+void gst_parser_test_output_caps (guint8 *data, guint size, const gchar * input_caps,
+ const gchar * output_caps);
+
+GstCaps *gst_parser_test_get_output_caps (guint8 *data, guint size, const gchar * input_caps);
+
diff --git a/tests/check/elements/rtpmux.c b/tests/check/elements/rtpmux.c
new file mode 100644
index 00000000..1228e5b8
--- /dev/null
+++ b/tests/check/elements/rtpmux.c
@@ -0,0 +1,305 @@
+/* GStreamer
+ *
+ * unit test for rtpmux elements
+ *
+ * Copyright 2009 Collabora Ltd.
+ * @author: Olivier Crete <olivier.crete@collabora.co.uk>
+ * Copyright 2009 Nokia Corp.
+ *
+ * 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>
+#include <gst/rtp/gstrtpbuffer.h>
+#include <gst/gst.h>
+
+static GstStaticPadTemplate sinktemplate = GST_STATIC_PAD_TEMPLATE ("sink",
+ GST_PAD_SINK,
+ GST_PAD_ALWAYS,
+ GST_STATIC_CAPS ("application/x-rtp"));
+
+static GstStaticPadTemplate srctemplate = GST_STATIC_PAD_TEMPLATE ("src",
+ GST_PAD_SRC,
+ GST_PAD_ALWAYS,
+ GST_STATIC_CAPS ("application/x-rtp"));
+
+typedef void (*check_cb) (GstPad * pad, int i);
+
+static gboolean
+query_func (GstPad * pad, GstObject * noparent, GstQuery * query)
+{
+ switch (GST_QUERY_TYPE (query)) {
+ case GST_QUERY_CAPS:
+ {
+ GstCaps **caps = g_object_get_data (G_OBJECT (pad), "caps");
+
+ fail_unless (caps != NULL && *caps != NULL);
+ gst_query_set_caps_result (query, *caps);
+ break;
+ }
+ default:
+ break;
+ }
+
+ return TRUE;
+}
+
+static gboolean
+event_func (GstPad * pad, GstObject * noparent, GstEvent * event)
+{
+ switch (GST_EVENT_TYPE (event)) {
+ case GST_EVENT_CAPS:
+ {
+ GstCaps *caps;
+ GstCaps **caps2 = g_object_get_data (G_OBJECT (pad), "caps");
+
+ gst_event_parse_caps (event, &caps);
+ fail_unless (caps2 != NULL && *caps2 != NULL);
+ fail_unless (gst_caps_is_equal (caps, *caps2));
+ break;
+ }
+ default:
+ gst_event_unref (event);
+ break;
+ }
+
+ return TRUE;
+}
+
+static void
+test_basic (const gchar * elem_name, const gchar * sink2, int count,
+ check_cb cb)
+{
+ GstElement *rtpmux = NULL;
+ GstPad *reqpad1 = NULL;
+ GstPad *reqpad2 = NULL;
+ GstPad *src1 = NULL;
+ GstPad *src2 = NULL;
+ GstPad *sink = NULL;
+ GstBuffer *inbuf = NULL;
+ GstCaps *src1caps = NULL;
+ GstCaps *src2caps = NULL;
+ GstCaps *sinkcaps = NULL;
+ GstCaps *caps;
+ GstSegment segment;
+ int i;
+
+ rtpmux = gst_check_setup_element (elem_name);
+
+ reqpad1 = gst_element_get_request_pad (rtpmux, "sink_1");
+ fail_unless (reqpad1 != NULL);
+ reqpad2 = gst_element_get_request_pad (rtpmux, sink2);
+ fail_unless (reqpad2 != NULL);
+ sink = gst_check_setup_sink_pad_by_name (rtpmux, &sinktemplate, "src");
+
+ src1 = gst_pad_new_from_static_template (&srctemplate, "src");
+ src2 = gst_pad_new_from_static_template (&srctemplate, "src");
+ fail_unless (gst_pad_link (src1, reqpad1) == GST_PAD_LINK_OK);
+ fail_unless (gst_pad_link (src2, reqpad2) == GST_PAD_LINK_OK);
+ gst_pad_set_query_function (src1, query_func);
+ gst_pad_set_query_function (src2, query_func);
+ gst_pad_set_query_function (sink, query_func);
+ gst_pad_set_event_function (sink, event_func);
+ g_object_set_data (G_OBJECT (src1), "caps", &src1caps);
+ g_object_set_data (G_OBJECT (src2), "caps", &src2caps);
+ g_object_set_data (G_OBJECT (sink), "caps", &sinkcaps);
+
+ src1caps = gst_caps_new_simple ("application/x-rtp",
+ "clock-rate", G_TYPE_INT, 1, "ssrc", G_TYPE_UINT, 11, NULL);
+ src2caps = gst_caps_new_simple ("application/x-rtp",
+ "clock-rate", G_TYPE_INT, 2, "ssrc", G_TYPE_UINT, 12, NULL);
+ sinkcaps = gst_caps_new_simple ("application/x-rtp",
+ "clock-rate", G_TYPE_INT, 3, "ssrc", G_TYPE_UINT, 13, NULL);
+
+ caps = gst_pad_peer_query_caps (src1, NULL);
+ fail_unless (gst_caps_is_empty (caps));
+ gst_caps_unref (caps);
+
+ gst_caps_set_simple (src2caps, "clock-rate", G_TYPE_INT, 3, NULL);
+ caps = gst_pad_peer_query_caps (src1, NULL);
+ fail_unless (gst_caps_is_equal (caps, sinkcaps));
+ gst_caps_unref (caps);
+
+ g_object_set (rtpmux, "seqnum-offset", 100, "timestamp-offset", 1000,
+ "ssrc", 55, NULL);
+
+ fail_unless (gst_element_set_state (rtpmux,
+ GST_STATE_PLAYING) == GST_STATE_CHANGE_SUCCESS);
+ gst_pad_set_active (sink, TRUE);
+ gst_pad_set_active (src1, TRUE);
+ gst_pad_set_active (src2, TRUE);
+
+ gst_caps_set_simple (sinkcaps,
+ "payload", G_TYPE_INT, 98, "seqnum-base", G_TYPE_UINT, 100,
+ "clock-base", G_TYPE_UINT, 1000, "ssrc", G_TYPE_UINT, 66, NULL);
+ caps = gst_caps_new_simple ("application/x-rtp",
+ "payload", G_TYPE_INT, 98, "clock-rate", G_TYPE_INT, 3,
+ "seqnum-base", G_TYPE_UINT, 56, "clock-base", G_TYPE_UINT, 57,
+ "ssrc", G_TYPE_UINT, 66, NULL);
+ fail_unless (gst_pad_set_caps (src1, caps));
+
+ gst_segment_init (&segment, GST_FORMAT_TIME);
+ segment.start = 100000;
+ fail_unless (gst_pad_push_event (src1, gst_event_new_segment (&segment)));
+ segment.start = 0;
+ fail_unless (gst_pad_push_event (src2, gst_event_new_segment (&segment)));
+
+
+ for (i = 0; i < count; i++) {
+ GstRTPBuffer rtpbuffer = GST_RTP_BUFFER_INIT;
+
+ inbuf = gst_rtp_buffer_new_allocate (10, 0, 0);
+ GST_BUFFER_PTS (inbuf) = i * 1000 + 100000;
+ GST_BUFFER_DURATION (inbuf) = 1000;
+
+ gst_rtp_buffer_map (inbuf, GST_MAP_WRITE, &rtpbuffer);
+
+ gst_rtp_buffer_set_version (&rtpbuffer, 2);
+ gst_rtp_buffer_set_payload_type (&rtpbuffer, 98);
+ gst_rtp_buffer_set_ssrc (&rtpbuffer, 44);
+ gst_rtp_buffer_set_timestamp (&rtpbuffer, 200 + i);
+ gst_rtp_buffer_set_seq (&rtpbuffer, 2000 + i);
+ gst_rtp_buffer_unmap (&rtpbuffer);
+ fail_unless (gst_pad_push (src1, inbuf) == GST_FLOW_OK);
+
+ if (buffers)
+ fail_unless (GST_BUFFER_PTS (buffers->data) == i * 1000, "%lld",
+ GST_BUFFER_PTS (buffers->data));
+
+ cb (src2, i);
+
+ g_list_foreach (buffers, (GFunc) gst_buffer_unref, NULL);
+ g_list_free (buffers);
+ buffers = NULL;
+ }
+
+
+ gst_pad_set_active (sink, FALSE);
+ gst_pad_set_active (src1, FALSE);
+ gst_pad_set_active (src2, FALSE);
+ fail_unless (gst_element_set_state (rtpmux,
+ GST_STATE_NULL) == GST_STATE_CHANGE_SUCCESS);
+ gst_check_teardown_pad_by_name (rtpmux, "src");
+ gst_object_unref (reqpad1);
+ gst_object_unref (reqpad2);
+ gst_check_teardown_pad_by_name (rtpmux, "sink_1");
+ gst_check_teardown_pad_by_name (rtpmux, sink2);
+ gst_element_release_request_pad (rtpmux, reqpad1);
+ gst_element_release_request_pad (rtpmux, reqpad2);
+
+ gst_caps_unref (caps);
+ gst_caps_replace (&src1caps, NULL);
+ gst_caps_replace (&src2caps, NULL);
+ gst_caps_replace (&sinkcaps, NULL);
+
+ gst_check_teardown_element (rtpmux);
+}
+
+static void
+basic_check_cb (GstPad * pad, int i)
+{
+ GstRTPBuffer rtpbuffer = GST_RTP_BUFFER_INIT;
+ fail_unless (buffers && g_list_length (buffers) == 1);
+
+ gst_rtp_buffer_map (buffers->data, GST_MAP_READ, &rtpbuffer);
+ fail_unless (gst_rtp_buffer_get_ssrc (&rtpbuffer) == 55);
+ fail_unless (gst_rtp_buffer_get_timestamp (&rtpbuffer) ==
+ 200 - 57 + 1000 + i);
+ fail_unless (gst_rtp_buffer_get_seq (&rtpbuffer) == 100 + 1 + i);
+ gst_rtp_buffer_unmap (&rtpbuffer);
+}
+
+
+GST_START_TEST (test_rtpmux_basic)
+{
+ test_basic ("rtpmux", "sink_2", 10, basic_check_cb);
+}
+
+GST_END_TEST;
+
+GST_START_TEST (test_rtpdtmfmux_basic)
+{
+ test_basic ("rtpdtmfmux", "sink_2", 10, basic_check_cb);
+}
+
+GST_END_TEST;
+
+static void
+lock_check_cb (GstPad * pad, int i)
+{
+ GstBuffer *inbuf;
+
+ if (i % 2) {
+ fail_unless (buffers == NULL);
+ } else {
+ GstRTPBuffer rtpbuffer = GST_RTP_BUFFER_INIT;
+
+ fail_unless (buffers && g_list_length (buffers) == 1);
+ gst_rtp_buffer_map (buffers->data, GST_MAP_READ, &rtpbuffer);
+ fail_unless (gst_rtp_buffer_get_ssrc (&rtpbuffer) == 55);
+ fail_unless (gst_rtp_buffer_get_timestamp (&rtpbuffer) ==
+ 200 - 57 + 1000 + i);
+ fail_unless (gst_rtp_buffer_get_seq (&rtpbuffer) == 100 + 1 + i);
+ gst_rtp_buffer_unmap (&rtpbuffer);
+
+ inbuf = gst_rtp_buffer_new_allocate (10, 0, 0);
+ GST_BUFFER_PTS (inbuf) = i * 1000 + 500;
+ GST_BUFFER_DURATION (inbuf) = 1000;
+ gst_rtp_buffer_map (inbuf, GST_MAP_WRITE, &rtpbuffer);
+ gst_rtp_buffer_set_version (&rtpbuffer, 2);
+ gst_rtp_buffer_set_payload_type (&rtpbuffer, 98);
+ gst_rtp_buffer_set_ssrc (&rtpbuffer, 44);
+ gst_rtp_buffer_set_timestamp (&rtpbuffer, 200 + i);
+ gst_rtp_buffer_set_seq (&rtpbuffer, 2000 + i);
+ gst_rtp_buffer_unmap (&rtpbuffer);
+ fail_unless (gst_pad_push (pad, inbuf) == GST_FLOW_OK);
+
+
+ g_list_foreach (buffers, (GFunc) gst_buffer_unref, NULL);
+ g_list_free (buffers);
+ buffers = NULL;
+ }
+}
+
+GST_START_TEST (test_rtpdtmfmux_lock)
+{
+ test_basic ("rtpdtmfmux", "priority_sink_2", 10, lock_check_cb);
+}
+
+GST_END_TEST;
+
+static Suite *
+rtpmux_suite (void)
+{
+ Suite *s = suite_create ("rtpmux");
+ TCase *tc_chain;
+
+ tc_chain = tcase_create ("rtpmux_basic");
+ tcase_add_test (tc_chain, test_rtpmux_basic);
+ suite_add_tcase (s, tc_chain);
+
+ tc_chain = tcase_create ("rtpdtmfmux_basic");
+ tcase_add_test (tc_chain, test_rtpdtmfmux_basic);
+ suite_add_tcase (s, tc_chain);
+
+ tc_chain = tcase_create ("rtpdtmfmux_lock");
+ tcase_add_test (tc_chain, test_rtpdtmfmux_lock);
+ suite_add_tcase (s, tc_chain);
+
+ return s;
+}
+
+GST_CHECK_MAIN (rtpmux)
diff --git a/tests/check/elements/schroenc.c b/tests/check/elements/schroenc.c
new file mode 100644
index 00000000..00afa183
--- /dev/null
+++ b/tests/check/elements/schroenc.c
@@ -0,0 +1,177 @@
+/* GStreamer
+ *
+ * Copyright (c) 2010 Sebastian Dröge <sebastian.droege@collabora.co.uk>
+ * Copyright (c) 2010 David Schleef <ds@schleef.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>
+
+static GstStaticPadTemplate sinktemplate = GST_STATIC_PAD_TEMPLATE ("sink",
+ GST_PAD_SINK,
+ GST_PAD_ALWAYS,
+ GST_STATIC_CAPS ("video/x-dirac, "
+ "width = (int) [1, MAX], "
+ "height = (int) [1, MAX], " "framerate = (fraction) [0, MAX]"));
+
+static GstStaticPadTemplate srctemplate = GST_STATIC_PAD_TEMPLATE ("src",
+ GST_PAD_SRC,
+ GST_PAD_ALWAYS,
+ GST_STATIC_CAPS ("video/x-raw, "
+ "format = (string) I420, "
+ "width = (int) [1, MAX], "
+ "height = (int) [1, MAX], " "framerate = (fraction) [0, MAX]"));
+
+static GstPad *sinkpad, *srcpad;
+
+static GstElement *
+setup_schroenc (const gchar * src_caps_str)
+{
+ GstElement *schroenc;
+ GstCaps *srccaps = NULL;
+ GstBus *bus;
+
+ if (src_caps_str) {
+ srccaps = gst_caps_from_string (src_caps_str);
+ fail_unless (srccaps != NULL);
+ }
+
+ schroenc = gst_check_setup_element ("schroenc");
+ fail_unless (schroenc != NULL);
+ srcpad = gst_check_setup_src_pad (schroenc, &srctemplate);
+ sinkpad = gst_check_setup_sink_pad (schroenc, &sinktemplate);
+ gst_pad_set_active (srcpad, TRUE);
+ gst_pad_set_active (sinkpad, TRUE);
+
+ gst_pad_set_caps (srcpad, srccaps);
+
+ bus = gst_bus_new ();
+ gst_element_set_bus (schroenc, bus);
+
+ fail_unless (gst_element_set_state (schroenc,
+ GST_STATE_PLAYING) != GST_STATE_CHANGE_FAILURE,
+ "could not set to playing");
+
+ if (srccaps)
+ gst_caps_unref (srccaps);
+
+ buffers = NULL;
+ return schroenc;
+}
+
+static void
+cleanup_schroenc (GstElement * schroenc)
+{
+ GstBus *bus;
+
+ /* Free parsed buffers */
+ gst_check_drop_buffers ();
+
+ bus = GST_ELEMENT_BUS (schroenc);
+ gst_bus_set_flushing (bus, TRUE);
+ gst_object_unref (bus);
+
+ gst_pad_set_active (srcpad, FALSE);
+ gst_pad_set_active (sinkpad, FALSE);
+ gst_check_teardown_src_pad (schroenc);
+ gst_check_teardown_sink_pad (schroenc);
+ gst_check_teardown_element (schroenc);
+}
+
+GST_START_TEST (test_encode_simple)
+{
+ GstElement *schroenc;
+ GstBuffer *buffer;
+ gint i;
+ GList *l;
+ GstCaps *outcaps, *sinkcaps;
+ GstSegment seg;
+
+ schroenc =
+ setup_schroenc
+ ("video/x-raw,format=(string)I420,width=(int)320,height=(int)240,framerate=(fraction)25/1");
+
+ g_object_set (schroenc, "queue-depth", 10, NULL);
+
+ gst_segment_init (&seg, GST_FORMAT_TIME);
+ seg.stop = gst_util_uint64_scale (20, GST_SECOND, 25);
+
+ fail_unless (gst_pad_push_event (srcpad, gst_event_new_segment (&seg)));
+
+ buffer = gst_buffer_new_allocate (NULL, 320 * 240 + 2 * 160 * 120, NULL);
+ gst_buffer_memset (buffer, 0, 0, -1);
+
+ for (i = 0; i < 20; i++) {
+ GST_BUFFER_TIMESTAMP (buffer) = gst_util_uint64_scale (i, GST_SECOND, 25);
+ GST_BUFFER_DURATION (buffer) = gst_util_uint64_scale (1, GST_SECOND, 25);
+ fail_unless (gst_pad_push (srcpad, gst_buffer_ref (buffer)) == GST_FLOW_OK);
+ }
+
+ gst_buffer_unref (buffer);
+
+ /* Only 5 buffers are allowed to be queued now */
+ fail_unless (g_list_length (buffers) > 10);
+
+ fail_unless (gst_pad_push_event (srcpad, gst_event_new_eos ()));
+
+
+ /* All buffers must be there now */
+ fail_unless_equals_int (g_list_length (buffers), 20);
+
+ outcaps =
+ gst_caps_from_string
+ ("video/x-dirac,width=(int)320,height=(int)240,framerate=(fraction)25/1");
+
+ for (l = buffers, i = 0; l; l = l->next, i++) {
+ buffer = l->data;
+
+ if (i == 0)
+ fail_if (GST_BUFFER_FLAG_IS_SET (buffer, GST_BUFFER_FLAG_DELTA_UNIT));
+
+#if 0
+ fail_unless_equals_uint64 (GST_BUFFER_TIMESTAMP (buffer),
+ gst_util_uint64_scale (i, GST_SECOND, 25));
+#endif
+ fail_unless_equals_uint64 (GST_BUFFER_DURATION (buffer),
+ gst_util_uint64_scale (1, GST_SECOND, 25));
+
+ sinkcaps = gst_pad_get_current_caps (sinkpad);
+ fail_unless (gst_caps_can_intersect (sinkcaps, outcaps));
+ gst_caps_unref (sinkcaps);
+ }
+
+ gst_caps_unref (outcaps);
+
+ cleanup_schroenc (schroenc);
+}
+
+GST_END_TEST;
+
+static Suite *
+schroenc_suite (void)
+{
+ Suite *s = suite_create ("schroenc");
+ TCase *tc_chain = tcase_create ("general");
+
+ suite_add_tcase (s, tc_chain);
+
+ tcase_add_test (tc_chain, test_encode_simple);
+
+ return s;
+}
+
+GST_CHECK_MAIN (schroenc);
diff --git a/tests/check/elements/timidity.c b/tests/check/elements/timidity.c
new file mode 100644
index 00000000..b30de314
--- /dev/null
+++ b/tests/check/elements/timidity.c
@@ -0,0 +1,89 @@
+/* GStreamer
+ *
+ * unit test for timidity/wildmidi
+ *
+ * Copyright (C) <2007> Stefan Kost <ensonic@users.sf.net>
+ *
+ * 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 <unistd.h>
+
+#include <gst/check/gstcheck.h>
+#include <gst/base/gsttypefindhelper.h>
+
+
+GST_START_TEST (test_midi_typefind)
+{
+ const guint8 midi_header[] = {
+ 0x4d, 0x54, 0x68, 0x64, 0x00, 0x00, 0x00, 0x06,
+ 0x00, 0x00, 0x00, 0x01, 0x00, 0x60, 0x4d, 0x54,
+ 0x72, 0x6b, 0x00, 0x00
+ };
+ GstTypeFindProbability prob;
+ const gchar *type;
+ GstBuffer *buf;
+ GstCaps *caps = NULL;
+
+ buf = gst_buffer_new ();
+ GST_BUFFER_DATA (buf) = (guint8 *) midi_header;
+ GST_BUFFER_SIZE (buf) = sizeof (midi_header);
+ GST_BUFFER_OFFSET (buf) = 0;
+
+ caps = gst_type_find_helper_for_buffer (NULL, buf, &prob);
+ fail_unless (caps != NULL);
+ GST_LOG ("Found type: %" GST_PTR_FORMAT, caps);
+
+ type = gst_structure_get_name (gst_caps_get_structure (caps, 0));
+ fail_unless_equals_string (type, "audio/midi");
+ fail_unless (prob > GST_TYPE_FIND_MINIMUM && prob <= GST_TYPE_FIND_MAXIMUM);
+
+ gst_buffer_unref (buf);
+ gst_caps_unref (caps);
+
+}
+
+GST_END_TEST;
+
+
+static Suite *
+timidity_suite (void)
+{
+ Suite *s = suite_create ("timidity");
+ TCase *tc_chain = tcase_create ("general");
+
+ suite_add_tcase (s, tc_chain);
+ tcase_add_test (tc_chain, test_midi_typefind);
+
+ return s;
+}
+
+int
+main (int argc, char **argv)
+{
+ int nf;
+
+ Suite *s = timidity_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/viewfinderbin.c b/tests/check/elements/viewfinderbin.c
new file mode 100644
index 00000000..c5766052
--- /dev/null
+++ b/tests/check/elements/viewfinderbin.c
@@ -0,0 +1,103 @@
+/* GStreamer unit test for the viewfinderbin element
+ * Copyright (C) 2010 Thiago Santos <thiago.sousa.santos@collabora.co.uk>
+ *
+ * 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.
+ */
+
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+#include <stdio.h>
+#include <gst/check/gstcheck.h>
+
+typedef struct
+{
+ GstElement *pipe;
+ GstElement *src;
+ GstElement *vfbin;
+} GstViewFinderBinTestContext;
+
+static void
+gstviewfinderbin_init_test_context (GstViewFinderBinTestContext * ctx,
+ gint num_buffers)
+{
+ GstElement *sink;
+ fail_unless (ctx != NULL);
+
+ ctx->pipe = gst_pipeline_new ("pipeline");
+ fail_unless (ctx->pipe != NULL);
+ ctx->src = gst_element_factory_make ("videotestsrc", "src");
+ fail_unless (ctx->src != NULL, "Failed to create videotestsrc element");
+ sink = gst_element_factory_make ("fakesink", NULL);
+ ctx->vfbin = gst_element_factory_make ("viewfinderbin", "vfbin");
+ fail_unless (ctx->vfbin != NULL, "Failed to create viewfinderbin element");
+ g_object_set (ctx->vfbin, "video-sink", sink, NULL);
+ gst_object_unref (sink);
+
+ if (num_buffers > 0)
+ g_object_set (ctx->src, "num-buffers", num_buffers, NULL);
+
+ fail_unless (gst_bin_add (GST_BIN (ctx->pipe), ctx->src));
+ fail_unless (gst_bin_add (GST_BIN (ctx->pipe), ctx->vfbin));
+ fail_unless (gst_element_link (ctx->src, ctx->vfbin));
+}
+
+static void
+gstviewfinderbin_unset_test_context (GstViewFinderBinTestContext * ctx)
+{
+ gst_element_set_state (ctx->pipe, GST_STATE_NULL);
+ gst_object_unref (ctx->pipe);
+ memset (ctx, 0, sizeof (GstViewFinderBinTestContext));
+}
+
+GST_START_TEST (test_simple_run)
+{
+ GstViewFinderBinTestContext ctx;
+ GstBus *bus;
+ GstMessage *msg;
+
+ gstviewfinderbin_init_test_context (&ctx, 10);
+ bus = gst_element_get_bus (ctx.pipe);
+
+ fail_if (gst_element_set_state (ctx.pipe, GST_STATE_PLAYING) ==
+ GST_STATE_CHANGE_FAILURE);
+
+ msg = gst_bus_timed_pop_filtered (bus, GST_SECOND * 30,
+ GST_MESSAGE_EOS | GST_MESSAGE_ERROR);
+ fail_unless (msg != NULL);
+ fail_unless (GST_MESSAGE_TYPE (msg) == GST_MESSAGE_EOS);
+ gst_message_unref (msg);
+
+ gstviewfinderbin_unset_test_context (&ctx);
+ gst_object_unref (bus);
+}
+
+GST_END_TEST;
+
+static Suite *
+viewfinderbin_suite (void)
+{
+ Suite *s = suite_create ("viewfinderbin");
+ TCase *tc_chain = tcase_create ("general");
+
+ suite_add_tcase (s, tc_chain);
+ tcase_add_test (tc_chain, test_simple_run);
+
+ return s;
+}
+
+GST_CHECK_MAIN (viewfinderbin);
diff --git a/tests/check/elements/voaacenc.c b/tests/check/elements/voaacenc.c
new file mode 100644
index 00000000..d12849b7
--- /dev/null
+++ b/tests/check/elements/voaacenc.c
@@ -0,0 +1,263 @@
+/* GStreamer
+ *
+ * unit test for voaacenc
+ *
+ * Copyright (C) <2009> Mark Nauwelaerts <mnauw@users.sf.net>
+ *
+ * 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 <unistd.h>
+
+#include <gst/check/gstcheck.h>
+#include <gst/audio/audio.h>
+
+/* For ease of programming we use globals to keep refs for our floating
+ * src and sink pads we create; otherwise we always have to do get_pad,
+ * get_peer, and then remove references in every test function */
+static GstPad *mysrcpad, *mysinkpad;
+
+#define AUDIO_CAPS_STRING "audio/x-raw, " \
+ "format = (string) " GST_AUDIO_NE (S16) ", "\
+ "layout = (string) interleaved, " \
+ "rate = (int) 48000, " \
+ "channels = (int) 2, " \
+ "channel-mask = (bitmask) 3"
+
+#define AAC_RAW_CAPS_STRING "audio/mpeg, " \
+ "mpegversion = (int) 4, " \
+ "rate = (int) 48000, " \
+ "channels = (int) 2, " \
+ "stream-format = \"raw\""
+
+#define AAC_ADTS_CAPS_STRING "audio/mpeg, " \
+ "mpegversion = (int) 4, " \
+ "rate = (int) 48000, " \
+ "channels = (int) 2, " \
+ "stream-format = \"adts\""
+
+
+static GstStaticPadTemplate sinktemplate_adts = GST_STATIC_PAD_TEMPLATE ("sink",
+ GST_PAD_SINK,
+ GST_PAD_ALWAYS,
+ GST_STATIC_CAPS (AAC_ADTS_CAPS_STRING));
+
+static GstStaticPadTemplate sinktemplate_raw = GST_STATIC_PAD_TEMPLATE ("sink",
+ GST_PAD_SINK,
+ GST_PAD_ALWAYS,
+ GST_STATIC_CAPS (AAC_RAW_CAPS_STRING));
+
+
+static GstStaticPadTemplate srctemplate = GST_STATIC_PAD_TEMPLATE ("src",
+ GST_PAD_SRC,
+ GST_PAD_ALWAYS,
+ GST_STATIC_CAPS (AUDIO_CAPS_STRING));
+
+
+static GstElement *
+setup_voaacenc (gboolean adts)
+{
+ GstElement *voaacenc;
+
+ GST_DEBUG ("setup_voaacenc");
+ voaacenc = gst_check_setup_element ("voaacenc");
+ mysrcpad = gst_check_setup_src_pad (voaacenc, &srctemplate);
+
+ if (adts)
+ mysinkpad = gst_check_setup_sink_pad (voaacenc, &sinktemplate_adts);
+ else
+ mysinkpad = gst_check_setup_sink_pad (voaacenc, &sinktemplate_raw);
+
+ gst_pad_set_active (mysrcpad, TRUE);
+ gst_pad_set_active (mysinkpad, TRUE);
+
+ return voaacenc;
+}
+
+static void
+cleanup_voaacenc (GstElement * voaacenc)
+{
+ GST_DEBUG ("cleanup_aacenc");
+ gst_element_set_state (voaacenc, GST_STATE_NULL);
+
+ gst_pad_set_active (mysrcpad, FALSE);
+ gst_pad_set_active (mysinkpad, FALSE);
+ gst_check_teardown_src_pad (voaacenc);
+ gst_check_teardown_sink_pad (voaacenc);
+ gst_check_teardown_element (voaacenc);
+}
+
+static void
+do_test (gboolean adts)
+{
+ GstElement *voaacenc;
+ GstBuffer *inbuffer, *outbuffer;
+ GstCaps *caps;
+ gint i, num_buffers;
+ const gint nbuffers = 10;
+
+ voaacenc = setup_voaacenc (adts);
+ fail_unless (gst_element_set_state (voaacenc,
+ GST_STATE_PLAYING) == GST_STATE_CHANGE_SUCCESS,
+ "could not set to playing");
+
+ /* corresponds to audio buffer mentioned in the caps */
+ inbuffer = gst_buffer_new_and_alloc (1024 * nbuffers * 2 * 2);
+ /* makes valgrind's memcheck happier */
+ gst_buffer_memset (inbuffer, 0, 0, 1024 * nbuffers * 2 * 2);
+ caps = gst_caps_from_string (AUDIO_CAPS_STRING);
+
+ gst_pad_set_caps (mysrcpad, caps);
+ gst_caps_unref (caps);
+ GST_BUFFER_TIMESTAMP (inbuffer) = 0;
+ ASSERT_BUFFER_REFCOUNT (inbuffer, "inbuffer", 1);
+ fail_unless (gst_pad_push (mysrcpad, inbuffer) == GST_FLOW_OK);
+
+ /* send eos to have all flushed if needed */
+ fail_unless (gst_pad_push_event (mysrcpad, gst_event_new_eos ()) == TRUE);
+
+ num_buffers = g_list_length (buffers);
+ fail_unless_equals_int (num_buffers, nbuffers);
+
+ /* clean up buffers */
+ for (i = 0; i < num_buffers; ++i) {
+ gint header = 0, id;
+ GstMapInfo map;
+ gsize size;
+ guint8 *data;
+
+ outbuffer = GST_BUFFER (buffers->data);
+ fail_if (outbuffer == NULL);
+
+ gst_buffer_map (outbuffer, &map, GST_MAP_READ);
+ data = map.data;
+ size = map.size;
+
+ if (adts) {
+ gboolean protection;
+ gint k;
+
+ fail_if (size < 7);
+ protection = !(data[1] & 0x1);
+ /* expect only 1 raw data block */
+ k = (data[6] & 0x3) + 1;
+ fail_if (k != 1);
+
+ header = 7;
+ if (protection)
+ header += (k - 1) * 2 + 2;
+
+ /* check header */
+ k = GST_READ_UINT16_BE (data) & 0xFFF6;
+ /* sync */
+ fail_unless (k == 0xFFF0);
+ k = data[2];
+ /* profile */
+ fail_unless ((k >> 6) == 0x1);
+ /* rate */
+ fail_unless (((k >> 2) & 0xF) == 0x3);
+ /* channels */
+ fail_unless ((k & 0x1) == 0);
+ k = data[3];
+ fail_unless ((k >> 6) == 0x2);
+
+ } else {
+ GstCaps *caps;
+ GstStructure *s;
+ const GValue *value;
+ GstBuffer *buf;
+ gint k;
+ GstMapInfo cmap;
+
+ caps = gst_pad_get_current_caps (mysinkpad);
+ fail_if (caps == NULL);
+ s = gst_caps_get_structure (caps, 0);
+ fail_if (s == NULL);
+ value = gst_structure_get_value (s, "codec_data");
+ fail_if (value == NULL);
+ buf = gst_value_get_buffer (value);
+ fail_if (buf == NULL);
+ gst_buffer_map (buf, &cmap, GST_MAP_READ);
+ fail_if (cmap.size < 2);
+ k = GST_READ_UINT16_BE (cmap.data);
+ gst_buffer_unmap (buf, &cmap);
+ /* profile, rate, channels */
+ fail_unless ((k & 0xFFF8) == ((0x02 << 11) | (0x3 << 7) | (0x02 << 3)));
+ gst_caps_unref (caps);
+
+ }
+
+ fail_if (size <= header);
+ id = data[header] & (0x7 << 5);
+ /* allow all but ID_END or ID_LFE */
+ fail_if (id == 7 || id == 3);
+ gst_buffer_unmap (outbuffer, &map);
+
+ buffers = g_list_remove (buffers, outbuffer);
+
+ ASSERT_BUFFER_REFCOUNT (outbuffer, "outbuffer", 1);
+ gst_buffer_unref (outbuffer);
+ outbuffer = NULL;
+ }
+
+ cleanup_voaacenc (voaacenc);
+ g_list_free (buffers);
+ buffers = NULL;
+}
+
+GST_START_TEST (test_adts)
+{
+ do_test (TRUE);
+}
+
+GST_END_TEST;
+
+GST_START_TEST (test_raw)
+{
+ do_test (FALSE);
+}
+
+GST_END_TEST;
+
+static Suite *
+voaacenc_suite (void)
+{
+ Suite *s = suite_create ("voaacenc");
+ TCase *tc_chain = tcase_create ("general");
+
+ suite_add_tcase (s, tc_chain);
+ tcase_add_test (tc_chain, test_adts);
+ tcase_add_test (tc_chain, test_raw);
+
+ return s;
+}
+
+int
+main (int argc, char **argv)
+{
+ int nf;
+
+ Suite *s = voaacenc_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/voamrwbenc.c b/tests/check/elements/voamrwbenc.c
new file mode 100644
index 00000000..b3e674ce
--- /dev/null
+++ b/tests/check/elements/voamrwbenc.c
@@ -0,0 +1,194 @@
+/* GStreamer
+ *
+ * unit test for voamrwbenc
+ *
+ * Copyright (C) <2011> Mark Nauwelaerts <mark.nauwelaerts@collabora.co.uk>
+ *
+ * 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 <unistd.h>
+
+#include <gst/check/gstcheck.h>
+
+/* For ease of programming we use globals to keep refs for our floating
+ * src and sink pads we create; otherwise we always have to do get_pad,
+ * get_peer, and then remove references in every test function */
+static GstPad *mysrcpad, *mysinkpad;
+
+#if G_BYTE_ORDER == G_BIG_ENDIAN
+#define AFORMAT "S16BE"
+#else
+#define AFORMAT "S16LE"
+#endif
+
+#define AUDIO_CAPS_STRING "audio/x-raw, " \
+ "format = (string) " AFORMAT ", "\
+ "layout = (string) interleaved, " \
+ "rate = (int) 16000, " \
+ "channels = (int) 1 "
+
+
+#define AMRWB_CAPS_STRING "audio/AMR-WB"
+
+
+static GstStaticPadTemplate sinktemplate = GST_STATIC_PAD_TEMPLATE ("sink",
+ GST_PAD_SINK,
+ GST_PAD_ALWAYS,
+ GST_STATIC_CAPS (AMRWB_CAPS_STRING));
+
+
+static GstStaticPadTemplate srctemplate = GST_STATIC_PAD_TEMPLATE ("src",
+ GST_PAD_SRC,
+ GST_PAD_ALWAYS,
+ GST_STATIC_CAPS (AUDIO_CAPS_STRING));
+
+
+static GstElement *
+setup_voamrwbenc (void)
+{
+ GstElement *voamrwbenc;
+
+ GST_DEBUG ("setup_voamrwbenc");
+ voamrwbenc = gst_check_setup_element ("voamrwbenc");
+ /* ensure mode as expected */
+ g_object_set (voamrwbenc, "band-mode", 0, NULL);
+ mysrcpad = gst_check_setup_src_pad (voamrwbenc, &srctemplate);
+ mysinkpad = gst_check_setup_sink_pad (voamrwbenc, &sinktemplate);
+ gst_pad_set_active (mysrcpad, TRUE);
+ gst_pad_set_active (mysinkpad, TRUE);
+
+ return voamrwbenc;
+}
+
+static void
+cleanup_voamrwbenc (GstElement * voamrwbenc)
+{
+ GST_DEBUG ("cleanup_aacenc");
+ gst_element_set_state (voamrwbenc, GST_STATE_NULL);
+
+ gst_pad_set_active (mysrcpad, FALSE);
+ gst_pad_set_active (mysinkpad, FALSE);
+ gst_check_teardown_src_pad (voamrwbenc);
+ gst_check_teardown_sink_pad (voamrwbenc);
+ gst_check_teardown_element (voamrwbenc);
+}
+
+static void
+do_test (void)
+{
+ GstElement *voamrwbenc;
+ GstBuffer *inbuffer, *outbuffer;
+ GstCaps *caps;
+ gint i, num_buffers;
+ const gint nbuffers = 10;
+
+ voamrwbenc = setup_voamrwbenc ();
+ fail_unless (gst_element_set_state (voamrwbenc,
+ GST_STATE_PLAYING) == GST_STATE_CHANGE_SUCCESS,
+ "could not set to playing");
+
+ /* corresponds to audio buffer mentioned in the caps */
+ inbuffer = gst_buffer_new_and_alloc (320 * nbuffers * 2);
+ /* makes valgrind's memcheck happier */
+ gst_buffer_memset (inbuffer, 0, 0, 1024 * nbuffers * 2 * 2);
+ caps = gst_caps_from_string (AUDIO_CAPS_STRING);
+
+ gst_pad_set_caps (mysrcpad, caps);
+ gst_caps_unref (caps);
+ GST_BUFFER_TIMESTAMP (inbuffer) = 0;
+ ASSERT_BUFFER_REFCOUNT (inbuffer, "inbuffer", 1);
+ fail_unless (gst_pad_push (mysrcpad, inbuffer) == GST_FLOW_OK);
+
+ /* send eos to have all flushed if needed */
+ fail_unless (gst_pad_push_event (mysrcpad, gst_event_new_eos ()) == TRUE);
+
+ num_buffers = g_list_length (buffers);
+ fail_unless_equals_int (num_buffers, nbuffers);
+
+ /* clean up buffers */
+ for (i = 0; i < num_buffers; ++i) {
+ GstMapInfo map;
+ gsize size;
+ guint8 *data;
+ GstClockTime time, dur;
+
+ outbuffer = GST_BUFFER (buffers->data);
+ fail_if (outbuffer == NULL);
+
+ gst_buffer_map (outbuffer, &map, GST_MAP_READ);
+ data = map.data;
+ size = map.size;
+
+ /* at least for mode 0 */
+ fail_unless (size == 18);
+ fail_unless ((data[0] & 0x83) == 0);
+ fail_unless (((data[0] >> 3) & 0xF) == 0);
+
+ time = GST_BUFFER_TIMESTAMP (outbuffer);
+ dur = GST_BUFFER_DURATION (outbuffer);
+ fail_unless (time == 20 * GST_MSECOND * i);
+ fail_unless (dur == 20 * GST_MSECOND);
+ gst_buffer_unmap (outbuffer, &map);
+
+ buffers = g_list_remove (buffers, outbuffer);
+
+ ASSERT_BUFFER_REFCOUNT (outbuffer, "outbuffer", 1);
+ gst_buffer_unref (outbuffer);
+ outbuffer = NULL;
+ }
+
+ cleanup_voamrwbenc (voamrwbenc);
+ g_list_free (buffers);
+ buffers = NULL;
+}
+
+GST_START_TEST (test_enc)
+{
+ do_test ();
+}
+
+GST_END_TEST;
+
+
+static Suite *
+voamrwbenc_suite (void)
+{
+ Suite *s = suite_create ("voamrwbenc");
+ TCase *tc_chain = tcase_create ("general");
+
+ suite_add_tcase (s, tc_chain);
+ tcase_add_test (tc_chain, test_enc);
+
+ return s;
+}
+
+int
+main (int argc, char **argv)
+{
+ int nf;
+
+ Suite *s = voamrwbenc_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/vp8dec.c b/tests/check/elements/vp8dec.c
new file mode 100644
index 00000000..25648401
--- /dev/null
+++ b/tests/check/elements/vp8dec.c
@@ -0,0 +1,178 @@
+/* GStreamer
+ *
+ * Copyright (c) 2010 Sebastian Dröge <sebastian.droege@collabora.co.uk>
+ *
+ * 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>
+
+static GstStaticPadTemplate sinktemplate = GST_STATIC_PAD_TEMPLATE ("sink",
+ GST_PAD_SINK,
+ GST_PAD_ALWAYS,
+ GST_STATIC_CAPS ("video/x-raw, "
+ "format = (string) I420, "
+ "width = (int) [1, MAX], "
+ "height = (int) [1, MAX], " "framerate = (fraction) [0, MAX]"));
+
+static GstStaticPadTemplate srctemplate = GST_STATIC_PAD_TEMPLATE ("src",
+ GST_PAD_SRC,
+ GST_PAD_ALWAYS,
+ GST_STATIC_CAPS ("video/x-raw, "
+ "format = (string) I420, "
+ "width = (int) [1, MAX], "
+ "height = (int) [1, MAX], " "framerate = (fraction) [0, MAX]"));
+
+static GstPad *sinkpad, *srcpad;
+
+static GstElement *
+setup_vp8dec (const gchar * src_caps_str)
+{
+ GstElement *bin;
+ GstElement *vp8enc, *vp8dec;
+ GstCaps *srccaps = NULL;
+ GstBus *bus;
+ GstPad *ghostpad, *targetpad;
+
+ if (src_caps_str) {
+ srccaps = gst_caps_from_string (src_caps_str);
+ fail_unless (srccaps != NULL);
+ }
+
+ bin = gst_bin_new ("bin");
+
+ vp8enc = gst_check_setup_element ("vp8enc");
+ fail_unless (vp8enc != NULL);
+ vp8dec = gst_check_setup_element ("vp8dec");
+ fail_unless (vp8dec != NULL);
+
+ gst_bin_add_many (GST_BIN (bin), vp8enc, vp8dec, NULL);
+ fail_unless (gst_element_link_pads (vp8enc, "src", vp8dec, "sink"));
+
+ targetpad = gst_element_get_static_pad (vp8enc, "sink");
+ fail_unless (targetpad != NULL);
+ ghostpad = gst_ghost_pad_new ("sink", targetpad);
+ fail_unless (ghostpad != NULL);
+ gst_element_add_pad (bin, ghostpad);
+ gst_object_unref (targetpad);
+
+ targetpad = gst_element_get_static_pad (vp8dec, "src");
+ fail_unless (targetpad != NULL);
+ ghostpad = gst_ghost_pad_new ("src", targetpad);
+ fail_unless (ghostpad != NULL);
+ gst_element_add_pad (bin, ghostpad);
+ gst_object_unref (targetpad);
+
+ srcpad = gst_check_setup_src_pad (bin, &srctemplate);
+ sinkpad = gst_check_setup_sink_pad (bin, &sinktemplate);
+ gst_pad_set_active (srcpad, TRUE);
+ gst_pad_set_active (sinkpad, TRUE);
+ fail_unless (gst_pad_set_caps (srcpad, srccaps));
+
+ bus = gst_bus_new ();
+ gst_element_set_bus (bin, bus);
+
+ fail_unless (gst_element_set_state (bin,
+ GST_STATE_PLAYING) != GST_STATE_CHANGE_FAILURE,
+ "could not set to playing");
+
+ if (srccaps)
+ gst_caps_unref (srccaps);
+
+ buffers = NULL;
+ return bin;
+}
+
+static void
+cleanup_vp8dec (GstElement * bin)
+{
+ GstBus *bus;
+
+ /* Free parsed buffers */
+ gst_check_drop_buffers ();
+
+ bus = GST_ELEMENT_BUS (bin);
+ gst_bus_set_flushing (bus, TRUE);
+ gst_object_unref (bus);
+
+ gst_pad_set_active (srcpad, FALSE);
+ gst_pad_set_active (sinkpad, FALSE);
+
+ gst_check_teardown_src_pad (bin);
+ gst_check_teardown_sink_pad (bin);
+ gst_check_teardown_element (bin);
+}
+
+GST_START_TEST (test_decode_simple)
+{
+ GstElement *bin;
+ GstBuffer *buffer;
+ gint i;
+ GList *l;
+ GstSegment seg;
+
+ bin =
+ setup_vp8dec
+ ("video/x-raw,format=(string)I420,width=(int)320,height=(int)240,framerate=(fraction)25/1");
+
+ gst_segment_init (&seg, GST_FORMAT_TIME);
+ seg.stop = gst_util_uint64_scale (20, GST_SECOND, 25);
+ fail_unless (gst_pad_push_event (srcpad, gst_event_new_segment (&seg)));
+
+ buffer = gst_buffer_new_and_alloc (320 * 240 + 2 * 160 * 120);
+ gst_buffer_memset (buffer, 0, 0, -1);
+
+ for (i = 0; i < 20; i++) {
+ GST_BUFFER_TIMESTAMP (buffer) = gst_util_uint64_scale (i, GST_SECOND, 25);
+ GST_BUFFER_DURATION (buffer) = gst_util_uint64_scale (1, GST_SECOND, 25);
+ fail_unless (gst_pad_push (srcpad, gst_buffer_ref (buffer)) == GST_FLOW_OK);
+ }
+
+ gst_buffer_unref (buffer);
+
+ fail_unless (gst_pad_push_event (srcpad, gst_event_new_eos ()));
+
+ /* All buffers must be there now */
+ fail_unless_equals_int (g_list_length (buffers), 20);
+
+ for (l = buffers, i = 0; l; l = l->next, i++) {
+ buffer = l->data;
+
+ fail_unless_equals_uint64 (GST_BUFFER_TIMESTAMP (buffer),
+ gst_util_uint64_scale (i, GST_SECOND, 25));
+ fail_unless_equals_uint64 (GST_BUFFER_DURATION (buffer),
+ gst_util_uint64_scale (1, GST_SECOND, 25));
+ }
+
+ cleanup_vp8dec (bin);
+}
+
+GST_END_TEST;
+
+static Suite *
+vp8dec_suite (void)
+{
+ Suite *s = suite_create ("vp8dec");
+ TCase *tc_chain = tcase_create ("general");
+
+ suite_add_tcase (s, tc_chain);
+
+ tcase_add_test (tc_chain, test_decode_simple);
+
+ return s;
+}
+
+GST_CHECK_MAIN (vp8dec);
diff --git a/tests/check/elements/vp8enc.c b/tests/check/elements/vp8enc.c
new file mode 100644
index 00000000..19be2479
--- /dev/null
+++ b/tests/check/elements/vp8enc.c
@@ -0,0 +1,168 @@
+/* GStreamer
+ *
+ * Copyright (c) 2010 Sebastian Dröge <sebastian.droege@collabora.co.uk>
+ *
+ * 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>
+
+static GstStaticPadTemplate sinktemplate = GST_STATIC_PAD_TEMPLATE ("sink",
+ GST_PAD_SINK,
+ GST_PAD_ALWAYS,
+ GST_STATIC_CAPS ("video/x-vp8, "
+ "width = (int) [1, MAX], "
+ "height = (int) [1, MAX], " "framerate = (fraction) [0, MAX]"));
+
+static GstStaticPadTemplate srctemplate = GST_STATIC_PAD_TEMPLATE ("src",
+ GST_PAD_SRC,
+ GST_PAD_ALWAYS,
+ GST_STATIC_CAPS ("video/x-raw, "
+ "format = (string) I420, "
+ "width = (int) [1, MAX], "
+ "height = (int) [1, MAX], " "framerate = (fraction) [0, MAX]"));
+
+static GstPad *sinkpad, *srcpad;
+
+static GstElement *
+setup_vp8enc (const gchar * src_caps_str)
+{
+ GstElement *vp8enc;
+ GstCaps *srccaps = NULL;
+ GstBus *bus;
+
+ if (src_caps_str) {
+ srccaps = gst_caps_from_string (src_caps_str);
+ fail_unless (srccaps != NULL);
+ }
+
+ vp8enc = gst_check_setup_element ("vp8enc");
+ fail_unless (vp8enc != NULL);
+ srcpad = gst_check_setup_src_pad (vp8enc, &srctemplate);
+ sinkpad = gst_check_setup_sink_pad (vp8enc, &sinktemplate);
+ gst_pad_set_active (srcpad, TRUE);
+ gst_pad_set_active (sinkpad, TRUE);
+ fail_unless (gst_pad_set_caps (srcpad, srccaps));
+
+ bus = gst_bus_new ();
+ gst_element_set_bus (vp8enc, bus);
+
+ fail_unless (gst_element_set_state (vp8enc,
+ GST_STATE_PLAYING) != GST_STATE_CHANGE_FAILURE,
+ "could not set to playing");
+
+ if (srccaps)
+ gst_caps_unref (srccaps);
+
+ buffers = NULL;
+ return vp8enc;
+}
+
+static void
+cleanup_vp8enc (GstElement * vp8enc)
+{
+ GstBus *bus;
+
+ /* Free parsed buffers */
+ gst_check_drop_buffers ();
+
+ bus = GST_ELEMENT_BUS (vp8enc);
+ gst_bus_set_flushing (bus, TRUE);
+ gst_object_unref (bus);
+
+ gst_pad_set_active (srcpad, FALSE);
+ gst_pad_set_active (sinkpad, FALSE);
+ gst_check_teardown_src_pad (vp8enc);
+ gst_check_teardown_sink_pad (vp8enc);
+ gst_check_teardown_element (vp8enc);
+}
+
+GST_START_TEST (test_encode_simple)
+{
+ GstElement *vp8enc;
+ GstBuffer *buffer;
+ gint i;
+ GList *l;
+ GstCaps *outcaps;
+ GstSegment seg;
+
+ vp8enc =
+ setup_vp8enc
+ ("video/x-raw,format=(string)I420,width=(int)320,height=(int)240,framerate=(fraction)25/1");
+
+ g_object_set (vp8enc, "max-latency", 5, NULL);
+
+ gst_segment_init (&seg, GST_FORMAT_TIME);
+ seg.stop = gst_util_uint64_scale (20, GST_SECOND, 25);
+ fail_unless (gst_pad_push_event (srcpad, gst_event_new_segment (&seg)));
+
+ buffer = gst_buffer_new_and_alloc (320 * 240 + 2 * 160 * 120);
+ gst_buffer_memset (buffer, 0, 0, -1);
+
+ for (i = 0; i < 20; i++) {
+ GST_BUFFER_TIMESTAMP (buffer) = gst_util_uint64_scale (i, GST_SECOND, 25);
+ GST_BUFFER_DURATION (buffer) = gst_util_uint64_scale (1, GST_SECOND, 25);
+ fail_unless (gst_pad_push (srcpad, gst_buffer_ref (buffer)) == GST_FLOW_OK);
+ }
+
+ gst_buffer_unref (buffer);
+
+ /* Only 5 buffers are allowed to be queued now */
+ fail_unless (g_list_length (buffers) > 15);
+
+ fail_unless (gst_pad_push_event (srcpad, gst_event_new_eos ()));
+
+
+ /* All buffers must be there now */
+ fail_unless_equals_int (g_list_length (buffers), 20);
+
+ outcaps =
+ gst_caps_from_string
+ ("video/x-vp8,width=(int)320,height=(int)240,framerate=(fraction)25/1");
+
+ for (l = buffers, i = 0; l; l = l->next, i++) {
+ buffer = l->data;
+
+ if (i == 0)
+ fail_if (GST_BUFFER_FLAG_IS_SET (buffer, GST_BUFFER_FLAG_DELTA_UNIT));
+
+ fail_unless_equals_uint64 (GST_BUFFER_TIMESTAMP (buffer),
+ gst_util_uint64_scale (i, GST_SECOND, 25));
+ fail_unless_equals_uint64 (GST_BUFFER_DURATION (buffer),
+ gst_util_uint64_scale (1, GST_SECOND, 25));
+ }
+
+ gst_caps_unref (outcaps);
+
+ cleanup_vp8enc (vp8enc);
+}
+
+GST_END_TEST;
+
+static Suite *
+vp8enc_suite (void)
+{
+ Suite *s = suite_create ("vp8enc");
+ TCase *tc_chain = tcase_create ("general");
+
+ suite_add_tcase (s, tc_chain);
+
+ tcase_add_test (tc_chain, test_encode_simple);
+
+ return s;
+}
+
+GST_CHECK_MAIN (vp8enc);
diff --git a/tests/check/elements/zbar.c b/tests/check/elements/zbar.c
new file mode 100644
index 00000000..38f4961e
--- /dev/null
+++ b/tests/check/elements/zbar.c
@@ -0,0 +1,116 @@
+/* GStreamer zbar element unit test
+ *
+ * Copyright (C) 2010 Tim-Philipp Müller <tim centricular net>
+ *
+ * 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>
+
+GST_START_TEST (test_still_image)
+{
+ GstMessage *zbar_msg = NULL;
+ const GstStructure *s;
+ GstElement *pipeline, *src, *dec, *csp, *zbar, *sink;
+ const gchar *type, *symbol;
+ gchar *path;
+ int qual;
+
+ pipeline = gst_pipeline_new ("pipeline");
+
+ src = gst_element_factory_make ("filesrc", NULL);
+ dec = gst_element_factory_make ("pngdec", NULL);
+ csp = gst_element_factory_make ("ffmpegcolorspace", NULL);
+ zbar = gst_element_factory_make ("zbar", NULL);
+ sink = gst_element_factory_make ("fakesink", NULL);
+
+ path = g_build_filename (GST_TEST_FILES_PATH, "barcode.png", NULL);
+ GST_LOG ("reading file '%s'", path);
+ g_object_set (src, "location", path, NULL);
+ g_free (path);
+
+ gst_bin_add_many (GST_BIN (pipeline), src, dec, csp, zbar, sink, NULL);
+ fail_unless (gst_element_link_many (src, dec, csp, zbar, sink, NULL));
+
+ fail_unless_equals_int (gst_element_set_state (pipeline, GST_STATE_PLAYING),
+ GST_STATE_CHANGE_ASYNC);
+
+ do {
+ GstMessage *msg;
+
+ msg = gst_bus_timed_pop_filtered (GST_ELEMENT_BUS (pipeline), -1,
+ GST_MESSAGE_ELEMENT | GST_MESSAGE_EOS | GST_MESSAGE_ERROR);
+
+ GST_INFO ("message: %" GST_PTR_FORMAT, msg);
+
+ fail_if (GST_MESSAGE_TYPE (msg) == GST_MESSAGE_ERROR);
+
+ if (GST_MESSAGE_TYPE (msg) == GST_MESSAGE_EOS) {
+ gst_message_unref (msg);
+ break;
+ }
+
+ if (GST_MESSAGE_SRC (msg) == GST_OBJECT_CAST (zbar) && zbar_msg == NULL) {
+ zbar_msg = msg;
+ } else {
+ gst_message_unref (msg);
+ }
+ } while (1);
+
+ fail_unless (zbar_msg != NULL);
+ s = gst_message_get_structure (zbar_msg);
+ fail_unless (s != NULL);
+
+ fail_unless (gst_structure_has_name (s, "barcode"));
+ fail_unless (gst_structure_has_field (s, "timestamp"));
+ fail_unless (gst_structure_has_field (s, "type"));
+ fail_unless (gst_structure_has_field (s, "symbol"));
+ fail_unless (gst_structure_has_field (s, "quality"));
+ fail_unless (gst_structure_get_int (s, "quality", &qual));
+ fail_unless (qual >= 90);
+ type = gst_structure_get_string (s, "type");
+ fail_unless_equals_string (type, "EAN-13");
+ symbol = gst_structure_get_string (s, "symbol");
+ fail_unless_equals_string (symbol, "9876543210128");
+
+ fail_unless_equals_int (gst_element_set_state (pipeline, GST_STATE_NULL),
+ GST_STATE_CHANGE_SUCCESS);
+
+ gst_object_unref (pipeline);
+ gst_message_unref (zbar_msg);
+}
+
+GST_END_TEST;
+
+static Suite *
+zbar_suite (void)
+{
+ Suite *s = suite_create ("zbar");
+ TCase *tc_chain = tcase_create ("general");
+
+ suite_add_tcase (s, tc_chain);
+
+ if (!gst_registry_check_feature_version (gst_registry_get (), "pngdec", 0, 10,
+ 25)) {
+ GST_INFO ("Skipping test, pngdec either not available or too old");
+ } else {
+ tcase_add_test (tc_chain, test_still_image);
+ }
+
+ return s;
+}
+
+GST_CHECK_MAIN (zbar);