summaryrefslogtreecommitdiff
path: root/subprojects/gst-libav/tests/check
diff options
context:
space:
mode:
Diffstat (limited to 'subprojects/gst-libav/tests/check')
-rw-r--r--subprojects/gst-libav/tests/check/elements/avaudenc.c126
-rw-r--r--subprojects/gst-libav/tests/check/elements/avdec_adpcm.c168
-rw-r--r--subprojects/gst-libav/tests/check/elements/avdemux_ape.c206
-rw-r--r--subprojects/gst-libav/tests/check/elements/avvidenc.c116
-rw-r--r--subprojects/gst-libav/tests/check/generic/libavcodec-locking.c161
-rw-r--r--subprojects/gst-libav/tests/check/generic/plugin-test.c98
-rw-r--r--subprojects/gst-libav/tests/check/gst-libav.supp0
-rw-r--r--subprojects/gst-libav/tests/check/meson.build60
8 files changed, 935 insertions, 0 deletions
diff --git a/subprojects/gst-libav/tests/check/elements/avaudenc.c b/subprojects/gst-libav/tests/check/elements/avaudenc.c
new file mode 100644
index 0000000000..e4403d7243
--- /dev/null
+++ b/subprojects/gst-libav/tests/check/elements/avaudenc.c
@@ -0,0 +1,126 @@
+/* GStreamer
+ *
+ * Copyright (C) 2020 Seungha Yang <seungha@centricular.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., 51 Franklin St, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <gst/check/gstcheck.h>
+#include <gst/check/gstharness.h>
+#include <gst/audio/audio.h>
+
+GST_START_TEST (test_audioenc_drain)
+{
+ GstHarness *h;
+ GstAudioInfo info;
+ GstBuffer *in_buf;
+ gint i = 0;
+ gint num_output = 0;
+ GstFlowReturn ret;
+ GstSegment segment;
+ GstCaps *caps;
+ gint samples_per_buffer = 1024;
+ gint rate = 44100;
+ gint size;
+ GstClockTime duration;
+
+ h = gst_harness_new ("avenc_aac");
+ fail_unless (h != NULL);
+
+ gst_audio_info_set_format (&info, GST_AUDIO_FORMAT_F32, rate, 1, NULL);
+
+ caps = gst_audio_info_to_caps (&info);
+ gst_harness_set_src_caps (h, gst_caps_copy (caps));
+
+ duration = gst_util_uint64_scale_int (samples_per_buffer, GST_SECOND, rate);
+ size = samples_per_buffer * GST_AUDIO_INFO_BPF (&info);
+
+ for (i = 0; i < 2; i++) {
+ in_buf = gst_buffer_new_and_alloc (size);
+
+ gst_buffer_memset (in_buf, 0, 0, size);
+
+ /* small rounding error would be expected, but should be fine */
+ GST_BUFFER_PTS (in_buf) = i * duration;
+ GST_BUFFER_DURATION (in_buf) = duration;
+
+ ret = gst_harness_push (h, in_buf);
+
+ fail_unless (ret == GST_FLOW_OK, "GstFlowReturn was %s",
+ gst_flow_get_name (ret));
+ }
+
+ gst_segment_init (&segment, GST_FORMAT_TIME);
+ fail_unless (gst_segment_set_running_time (&segment, GST_FORMAT_TIME,
+ 2 * duration));
+
+ /* Push new eos event to drain encoder */
+ fail_unless (gst_harness_push_event (h, gst_event_new_eos ()));
+
+ /* And start new stream */
+ fail_unless (gst_harness_push_event (h,
+ gst_event_new_stream_start ("new-stream-id")));
+ gst_harness_set_src_caps (h, caps);
+ fail_unless (gst_harness_push_event (h, gst_event_new_segment (&segment)));
+
+ in_buf = gst_buffer_new_and_alloc (size);
+
+ GST_BUFFER_PTS (in_buf) = 2 * duration;
+ GST_BUFFER_DURATION (in_buf) = duration;
+
+ ret = gst_harness_push (h, in_buf);
+ fail_unless (ret == GST_FLOW_OK, "GstFlowReturn was %s",
+ gst_flow_get_name (ret));
+
+ /* Finish encoding and drain again */
+ fail_unless (gst_harness_push_event (h, gst_event_new_eos ()));
+ do {
+ GstBuffer *out_buf = NULL;
+
+ out_buf = gst_harness_try_pull (h);
+ if (out_buf) {
+ num_output++;
+ gst_buffer_unref (out_buf);
+ continue;
+ }
+
+ break;
+ } while (1);
+
+ fail_unless (num_output >= 3);
+
+ gst_harness_teardown (h);
+}
+
+GST_END_TEST;
+
+static Suite *
+avaudenc_suite (void)
+{
+ Suite *s = suite_create ("avaudenc");
+ TCase *tc_chain = tcase_create ("general");
+
+ suite_add_tcase (s, tc_chain);
+ tcase_add_test (tc_chain, test_audioenc_drain);
+
+ return s;
+}
+
+GST_CHECK_MAIN (avaudenc)
diff --git a/subprojects/gst-libav/tests/check/elements/avdec_adpcm.c b/subprojects/gst-libav/tests/check/elements/avdec_adpcm.c
new file mode 100644
index 0000000000..2bc745d5ae
--- /dev/null
+++ b/subprojects/gst-libav/tests/check/elements/avdec_adpcm.c
@@ -0,0 +1,168 @@
+/* GStreamer unit tests for avdec_adpcm
+ *
+ * Copyright (C) 2009 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., 51 Franklin St, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ */
+
+#include <gst/check/gstcheck.h>
+
+#include <gst/gst.h>
+
+static void
+pad_added_cb (GstElement * decodebin, GstPad * pad, GstBin * pipeline)
+{
+ GstElement *sink;
+
+ GST_INFO_OBJECT (pad, "got pad");
+
+ sink = gst_bin_get_by_name (pipeline, "fakesink");
+ fail_unless (gst_element_link (decodebin, sink));
+ gst_object_unref (sink);
+
+ gst_element_set_state (sink, GST_STATE_PAUSED);
+}
+
+static GstBusSyncReply
+error_cb (GstBus * bus, GstMessage * msg, gpointer user_data)
+{
+ if (GST_MESSAGE_TYPE (msg) == GST_MESSAGE_ERROR) {
+ const gchar *file = (const gchar *) user_data;
+ GError *err = NULL;
+ gchar *dbg = NULL;
+
+ gst_message_parse_error (msg, &err, &dbg);
+ g_error ("ERROR for %s: %s\n%s\n", file, err->message, dbg);
+ }
+
+ return GST_BUS_PASS;
+}
+
+static gboolean
+decode_file (const gchar * file, gboolean push_mode)
+{
+ GstStateChangeReturn state_ret;
+ GstElement *sink, *src, *dec, *queue, *pipeline;
+ GstMessage *msg;
+ GstBus *bus;
+ gchar *path;
+
+ pipeline = gst_pipeline_new ("pipeline");
+ fail_unless (pipeline != NULL, "Failed to create pipeline!");
+
+ src = gst_element_factory_make ("filesrc", "filesrc");
+ fail_unless (src != NULL, "Failed to create filesrc!");
+
+ if (push_mode) {
+ queue = gst_element_factory_make ("queue", "queue");
+ } else {
+ queue = gst_element_factory_make ("identity", "identity");
+ }
+
+ dec = gst_element_factory_make ("decodebin", "decodebin");
+ fail_unless (dec != NULL, "Failed to create decodebin!");
+
+ sink = gst_element_factory_make ("fakesink", "fakesink");
+ fail_unless (sink != NULL, "Failed to create fakesink!");
+
+ bus = gst_element_get_bus (pipeline);
+
+ /* kids, don't use a sync handler for this at home, really; we do because
+ * we just want to abort and nothing else */
+ gst_bus_set_sync_handler (bus, error_cb, (gpointer) file, NULL);
+
+ gst_bin_add_many (GST_BIN (pipeline), src, queue, dec, sink, NULL);
+ gst_element_link_many (src, queue, dec, NULL);
+
+ path = g_build_filename (GST_TEST_FILES_PATH, file, NULL);
+ GST_LOG ("reading file '%s'", path);
+ g_object_set (src, "location", path, NULL);
+
+ /* can't link uridecodebin and sink yet, do that later */
+ g_signal_connect (dec, "pad-added", G_CALLBACK (pad_added_cb), pipeline);
+
+ state_ret = gst_element_set_state (pipeline, GST_STATE_PAUSED);
+ fail_unless (state_ret != GST_STATE_CHANGE_FAILURE);
+
+ if (state_ret == GST_STATE_CHANGE_ASYNC) {
+ GST_LOG ("waiting for pipeline to reach PAUSED state");
+ state_ret = gst_element_get_state (pipeline, NULL, NULL, -1);
+ fail_unless_equals_int (state_ret, GST_STATE_CHANGE_SUCCESS);
+ }
+
+ state_ret = gst_element_set_state (pipeline, GST_STATE_PLAYING);
+ fail_unless (state_ret != GST_STATE_CHANGE_FAILURE);
+
+ GST_LOG ("PAUSED, let's decode");
+ msg = gst_bus_timed_pop_filtered (bus, 10 * GST_SECOND, GST_MESSAGE_EOS);
+ GST_LOG ("Done, got EOS message");
+ fail_unless (msg != NULL);
+ gst_message_unref (msg);
+ gst_object_unref (bus);
+
+ fail_unless_equals_int (gst_element_set_state (pipeline, GST_STATE_NULL),
+ GST_STATE_CHANGE_SUCCESS);
+ gst_object_unref (pipeline);
+
+ g_free (path);
+
+ return TRUE;
+}
+
+static void
+run_check_for_file (const gchar * filename)
+{
+ gboolean ret;
+
+ /* first, pull-based */
+ ret = decode_file (filename, FALSE);
+ fail_unless (ret == TRUE, "Failed to decode '%s' (pull mode)", filename);
+
+ /* second, push-based */
+ ret = decode_file (filename, TRUE);
+ fail_unless (ret == TRUE, "Failed to decode '%s' (push mode)", filename);
+}
+
+GST_START_TEST (test_low_sample_rate_adpcm)
+{
+#define MIN_VERSION GST_VERSION_MAJOR, GST_VERSION_MINOR, 0
+ if (!gst_registry_check_feature_version (gst_registry_get (), "wavparse",
+ MIN_VERSION)
+ || !gst_registry_check_feature_version (gst_registry_get (), "decodebin",
+ MIN_VERSION)) {
+ g_printerr ("skipping test_low_sample_rate_adpcm: required element "
+ "wavparse or element decodebin not found\n");
+ return;
+ }
+
+ run_check_for_file ("591809.wav");
+}
+
+GST_END_TEST;
+
+static Suite *
+avdec_adpcm_suite (void)
+{
+ Suite *s = suite_create ("avdec_adpcm");
+ TCase *tc_chain = tcase_create ("general");
+
+ suite_add_tcase (s, tc_chain);
+ tcase_skip_broken_test (tc_chain, test_low_sample_rate_adpcm);
+
+ return s;
+}
+
+GST_CHECK_MAIN (avdec_adpcm)
diff --git a/subprojects/gst-libav/tests/check/elements/avdemux_ape.c b/subprojects/gst-libav/tests/check/elements/avdemux_ape.c
new file mode 100644
index 0000000000..99dbd7617b
--- /dev/null
+++ b/subprojects/gst-libav/tests/check/elements/avdemux_ape.c
@@ -0,0 +1,206 @@
+/* GStreamer unit tests for avdemux_ape
+ *
+ * Copyright (C) 2009 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., 51 Franklin St, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ */
+
+#include <gst/check/gstcheck.h>
+
+#include <gst/gst.h>
+
+typedef void (CheckTagsFunc) (const GstTagList * tags, const gchar * file);
+
+static void
+pad_added_cb (GstElement * decodebin, GstPad * pad, GstBin * pipeline)
+{
+ GstElement *sink;
+
+ sink = gst_bin_get_by_name (pipeline, "fakesink");
+ fail_unless (gst_element_link (decodebin, sink));
+ gst_object_unref (sink);
+
+ gst_element_set_state (sink, GST_STATE_PAUSED);
+}
+
+static GstBusSyncReply
+error_cb (GstBus * bus, GstMessage * msg, gpointer user_data)
+{
+ if (GST_MESSAGE_TYPE (msg) == GST_MESSAGE_ERROR) {
+ const gchar *file = (const gchar *) user_data;
+ GError *err = NULL;
+ gchar *dbg = NULL;
+
+ gst_message_parse_error (msg, &err, &dbg);
+ g_error ("ERROR for %s: %s\n%s\n", file, err->message, dbg);
+ }
+
+ return GST_BUS_PASS;
+}
+
+static GstPadProbeReturn
+event_probe (GstPad * pad, GstPadProbeInfo * info, gpointer user_data)
+{
+ GstTagList **p_tags = user_data;
+ GstEvent *event = GST_PAD_PROBE_INFO_EVENT (info);
+
+ if (GST_EVENT_TYPE (event) == GST_EVENT_TAG) {
+ GST_INFO ("tag event: %" GST_PTR_FORMAT, event);
+ if (*p_tags == NULL) {
+ GstTagList *event_tags;
+
+ GST_INFO ("first tag, saving");
+ gst_event_parse_tag (event, &event_tags);
+ *p_tags = gst_tag_list_copy (event_tags);
+ }
+ }
+ return GST_PAD_PROBE_OK; /* keep the data */
+}
+
+/* FIXME: push_mode not used currently */
+static GstTagList *
+read_tags_from_file (const gchar * file, gboolean push_mode)
+{
+ GstStateChangeReturn state_ret;
+ GstTagList *tags = NULL;
+ GstElement *sink, *src, *dec, *pipeline;
+ GstBus *bus;
+ GstPad *pad;
+ gchar *path;
+
+ pipeline = gst_pipeline_new ("pipeline");
+ fail_unless (pipeline != NULL, "Failed to create pipeline!");
+
+ src = gst_element_factory_make ("filesrc", "filesrc");
+ fail_unless (src != NULL, "Failed to create filesrc!");
+
+ dec = gst_element_factory_make ("decodebin", "decodebin");
+ fail_unless (dec != NULL, "Failed to create decodebin!");
+
+ sink = gst_element_factory_make ("fakesink", "fakesink");
+ fail_unless (sink != NULL, "Failed to create fakesink!");
+
+ bus = gst_element_get_bus (pipeline);
+
+ /* kids, don't use a sync handler for this at home, really; we do because
+ * we just want to abort and nothing else */
+ gst_bus_set_sync_handler (bus, error_cb, (gpointer) file, NULL);
+
+ gst_bin_add_many (GST_BIN (pipeline), src, dec, sink, NULL);
+ gst_element_link_many (src, dec, NULL);
+
+ path = g_build_filename (GST_TEST_FILES_PATH, file, NULL);
+ GST_LOG ("reading file '%s'", path);
+ g_object_set (src, "location", path, NULL);
+
+ /* can't link uridecodebin and sink yet, do that later */
+ g_signal_connect (dec, "pad-added", G_CALLBACK (pad_added_cb), pipeline);
+
+ /* we want to make sure there's a tag event coming out of avdemux_ape
+ * (ie. the one apedemux generated) */
+ pad = gst_element_get_static_pad (sink, "sink");
+ gst_pad_add_probe (pad, GST_PAD_PROBE_TYPE_EVENT_DOWNSTREAM, event_probe,
+ &tags, NULL);
+ gst_object_unref (pad);
+
+ state_ret = gst_element_set_state (pipeline, GST_STATE_PAUSED);
+ fail_unless (state_ret != GST_STATE_CHANGE_FAILURE);
+
+ if (state_ret == GST_STATE_CHANGE_ASYNC) {
+ GST_LOG ("waiting for pipeline to reach PAUSED state");
+ state_ret = gst_element_get_state (pipeline, NULL, NULL, -1);
+ fail_unless_equals_int (state_ret, GST_STATE_CHANGE_SUCCESS);
+ }
+
+ GST_LOG ("PAUSED, let's retrieve our tags");
+
+ fail_unless (tags != NULL, "Expected tag event! (%s)", file);
+
+ gst_object_unref (bus);
+
+ fail_unless_equals_int (gst_element_set_state (pipeline, GST_STATE_NULL),
+ GST_STATE_CHANGE_SUCCESS);
+ gst_object_unref (pipeline);
+
+ g_free (path);
+
+ GST_INFO ("%s: tags = %" GST_PTR_FORMAT, file, tags);
+ return tags;
+}
+
+static void
+run_check_for_file (const gchar * filename, CheckTagsFunc * check_func)
+{
+ GstTagList *tags;
+
+ /* first, pull-based */
+ tags = read_tags_from_file (filename, FALSE);
+ fail_unless (tags != NULL, "Failed to extract tags from '%s'", filename);
+ check_func (tags, filename);
+ gst_tag_list_unref (tags);
+}
+
+#define tag_list_has_tag(taglist,tag) \
+ (gst_tag_list_get_value_index((taglist),(tag),0) != NULL)
+
+/* just make sure avdemux_ape forwarded the tags extracted by apedemux
+ * (should be the first tag list / tag event too) */
+static void
+check_for_apedemux_tags (const GstTagList * tags, const gchar * file)
+{
+ gchar *artist = NULL;
+
+ fail_unless (gst_tag_list_get_string (tags, GST_TAG_ARTIST, &artist));
+ fail_unless (artist != NULL);
+ fail_unless_equals_string (artist, "Marvin Gaye");
+ g_free (artist);
+
+ fail_unless (tag_list_has_tag (tags, GST_TAG_CONTAINER_FORMAT));
+
+ GST_LOG ("all good");
+}
+
+GST_START_TEST (test_tag_caching)
+{
+#define MIN_VERSION GST_VERSION_MAJOR, GST_VERSION_MINOR, 0
+
+ if (!gst_registry_check_feature_version (gst_registry_get (), "apedemux",
+ MIN_VERSION)
+ || !gst_registry_check_feature_version (gst_registry_get (), "decodebin",
+ MIN_VERSION)) {
+ g_printerr ("Skipping test_tag_caching: required element apedemux or "
+ "decodebin element not found\n");
+ return;
+ }
+
+ run_check_for_file ("586957.ape", check_for_apedemux_tags);
+}
+
+GST_END_TEST;
+
+static Suite *
+avdemux_ape_suite (void)
+{
+ Suite *s = suite_create ("avdemux_ape");
+ TCase *tc_chain = tcase_create ("general");
+
+ suite_add_tcase (s, tc_chain);
+ tcase_add_test (tc_chain, test_tag_caching);
+
+ return s;
+}
+
+GST_CHECK_MAIN (avdemux_ape)
diff --git a/subprojects/gst-libav/tests/check/elements/avvidenc.c b/subprojects/gst-libav/tests/check/elements/avvidenc.c
new file mode 100644
index 0000000000..04ca20d1be
--- /dev/null
+++ b/subprojects/gst-libav/tests/check/elements/avvidenc.c
@@ -0,0 +1,116 @@
+/* GStreamer
+ *
+ * Copyright (C) 2020 Seungha Yang <seungha@centricular.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., 51 Franklin St, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <gst/check/gstcheck.h>
+#include <gst/check/gstharness.h>
+#include <gst/video/video.h>
+
+GST_START_TEST (test_videoenc_drain)
+{
+ GstHarness *h;
+ GstVideoInfo info;
+ GstBuffer *in_buf;
+ gint i = 0;
+ gint num_output = 0;
+ GstFlowReturn ret;
+ GstSegment segment;
+ GstCaps *caps;
+
+ h = gst_harness_new ("avenc_mjpeg");
+ fail_unless (h != NULL);
+
+ caps = gst_caps_from_string ("video/x-raw,format=I420,width=64,height=64");
+
+ gst_harness_set_src_caps (h, gst_caps_copy (caps));
+ gst_video_info_set_format (&info, GST_VIDEO_FORMAT_I420, 64, 64);
+
+ for (i = 0; i < 2; i++) {
+ in_buf = gst_buffer_new_and_alloc (GST_VIDEO_INFO_SIZE (&info));
+
+ GST_BUFFER_PTS (in_buf) = i * GST_SECOND;
+ GST_BUFFER_DURATION (in_buf) = GST_SECOND;
+
+ ret = gst_harness_push (h, in_buf);
+
+ fail_unless (ret == GST_FLOW_OK, "GstFlowReturn was %s",
+ gst_flow_get_name (ret));
+ }
+
+ gst_segment_init (&segment, GST_FORMAT_TIME);
+ fail_unless (gst_segment_set_running_time (&segment, GST_FORMAT_TIME,
+ 2 * GST_SECOND));
+
+ /* Push new eos event to drain encoder */
+ fail_unless (gst_harness_push_event (h, gst_event_new_eos ()));
+
+ /* And start new stream */
+ fail_unless (gst_harness_push_event (h,
+ gst_event_new_stream_start ("new-stream-id")));
+ gst_harness_set_src_caps (h, caps);
+ fail_unless (gst_harness_push_event (h, gst_event_new_segment (&segment)));
+
+ in_buf = gst_buffer_new_and_alloc (GST_VIDEO_INFO_SIZE (&info));
+
+ GST_BUFFER_PTS (in_buf) = 2 * GST_SECOND;
+ GST_BUFFER_DURATION (in_buf) = GST_SECOND;
+
+ ret = gst_harness_push (h, in_buf);
+ fail_unless (ret == GST_FLOW_OK, "GstFlowReturn was %s",
+ gst_flow_get_name (ret));
+
+ /* Finish encoding and drain again */
+ fail_unless (gst_harness_push_event (h, gst_event_new_eos ()));
+ do {
+ GstBuffer *out_buf = NULL;
+
+ out_buf = gst_harness_try_pull (h);
+ if (out_buf) {
+ num_output++;
+ gst_buffer_unref (out_buf);
+ continue;
+ }
+
+ break;
+ } while (1);
+
+ fail_unless_equals_int (num_output, 3);
+
+ gst_harness_teardown (h);
+}
+
+GST_END_TEST;
+
+static Suite *
+avvidenc_suite (void)
+{
+ Suite *s = suite_create ("avvidenc");
+ TCase *tc_chain = tcase_create ("general");
+
+ suite_add_tcase (s, tc_chain);
+ tcase_add_test (tc_chain, test_videoenc_drain);
+
+ return s;
+}
+
+GST_CHECK_MAIN (avvidenc)
diff --git a/subprojects/gst-libav/tests/check/generic/libavcodec-locking.c b/subprojects/gst-libav/tests/check/generic/libavcodec-locking.c
new file mode 100644
index 0000000000..a6dfb8e29d
--- /dev/null
+++ b/subprojects/gst-libav/tests/check/generic/libavcodec-locking.c
@@ -0,0 +1,161 @@
+/* GStreamer
+ * Copyright (C) 2005 Luca Ognibene <luogni@tin.it>
+ * Based (copied) on simple_launch_lines.c
+ *
+ * libavcodec-locking.c: Unit test for libavcodec's locks
+ *
+ * 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., 51 Franklin St, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ */
+
+
+#include <gst/check/gstcheck.h>
+#include <stdlib.h>
+
+#define NUM_SINKS 10
+
+static GstElement *
+setup_pipeline (const gchar * pipe_descr)
+{
+ GstElement *pipeline;
+
+ pipeline = gst_parse_launch (pipe_descr, NULL);
+ g_return_val_if_fail (GST_IS_PIPELINE (pipeline), NULL);
+ return pipeline;
+}
+
+/*
+ * run_pipeline:
+ * @pipe: the pipeline to run
+ * @desc: the description for use in messages
+ * @events: is a mask of expected events
+ * @tevent: is the expected terminal event.
+ *
+ * the poll call will time out after half a second.
+ */
+static void
+run_pipeline (GstElement * pipe, const gchar * descr,
+ GstMessageType events, GstMessageType tevent)
+{
+ GstBus *bus;
+ GstMessage *message;
+ GstMessageType revent;
+ GstStateChangeReturn ret;
+
+ g_assert (pipe);
+ bus = gst_element_get_bus (pipe);
+ g_assert (bus);
+
+ ret = gst_element_set_state (pipe, GST_STATE_PLAYING);
+ ret = gst_element_get_state (pipe, NULL, NULL, GST_CLOCK_TIME_NONE);
+ if (ret != GST_STATE_CHANGE_SUCCESS) {
+ g_critical ("Couldn't set pipeline to PLAYING");
+ goto done;
+ }
+
+ while (1) {
+ message = gst_bus_poll (bus, GST_MESSAGE_ANY, GST_SECOND / 2);
+
+ /* always have to pop the message before getting back into poll */
+ if (message) {
+ revent = GST_MESSAGE_TYPE (message);
+ gst_message_unref (message);
+ } else {
+ revent = GST_MESSAGE_UNKNOWN;
+ }
+
+ if (revent == tevent) {
+ break;
+ } else if (revent == GST_MESSAGE_UNKNOWN) {
+ g_critical ("Unexpected timeout in gst_bus_poll, looking for %d: %s",
+ tevent, descr);
+ break;
+ } else if (revent & events) {
+ continue;
+ }
+ g_critical
+ ("Unexpected message received of type %d, '%s', looking for %d: %s",
+ revent, gst_message_type_get_name (revent), tevent, descr);
+ }
+
+done:
+ gst_element_set_state (pipe, GST_STATE_NULL);
+ gst_object_unref (pipe);
+}
+
+GST_START_TEST (test_libavcodec_locks)
+{
+ gchar *sink[NUM_SINKS + 1], *s, *sinks;
+ gint i;
+
+ for (i = 0; i < NUM_SINKS; i++)
+ sink[i] =
+ g_strdup_printf
+ (" t.src_%u ! queue ! avenc_mpeg4 ! avdec_mpeg4 ! fakesink sync=true",
+ i);
+
+ sink[NUM_SINKS] = NULL;
+
+ sinks = g_strjoinv (" ", sink);
+
+ s = g_strdup_printf
+ ("videotestsrc ! video/x-raw,format=(string)I420,width=320,height=240,framerate=(fraction)10/1 ! tee name=t %s",
+ sinks);
+
+ run_pipeline (setup_pipeline (s), s,
+ GST_MESSAGE_ANY & ~(GST_MESSAGE_ERROR | GST_MESSAGE_WARNING),
+ GST_MESSAGE_UNKNOWN);
+ g_free (s);
+
+ for (i = 0; i < NUM_SINKS; i++)
+ g_free (sink[i]);
+ g_free (sinks);
+}
+
+GST_END_TEST;
+
+static Suite *
+simple_launch_lines_suite (void)
+{
+ gint timeout = 0;
+
+ Suite *s = suite_create ("Pipelines");
+ TCase *tc_chain = tcase_create ("linear");
+
+ if (g_getenv ("CK_DEFAULT_TIMEOUT"))
+ timeout = atoi (g_getenv ("CK_DEFAULT_TIMEOUT"));
+
+ if (timeout == 0)
+ timeout = 3;
+
+ /* set multiple of default timeout (random magic value) */
+ tcase_set_timeout (tc_chain, timeout * 12);
+
+ suite_add_tcase (s, tc_chain);
+
+#ifndef GST_DISABLE_PARSE
+ /* only run this if we haven't been configured with --disable-encoders */
+ if (gst_registry_check_feature_version (gst_registry_get (), "avenc_mpeg4",
+ GST_VERSION_MAJOR, GST_VERSION_MINOR, 0)) {
+ tcase_add_test (tc_chain, test_libavcodec_locks);
+ } else {
+ g_print ("******* Skipping libavcodec_locks test, no encoder available\n");
+ }
+#endif
+
+ return s;
+}
+
+GST_CHECK_MAIN (simple_launch_lines);
diff --git a/subprojects/gst-libav/tests/check/generic/plugin-test.c b/subprojects/gst-libav/tests/check/generic/plugin-test.c
new file mode 100644
index 0000000000..53831d249b
--- /dev/null
+++ b/subprojects/gst-libav/tests/check/generic/plugin-test.c
@@ -0,0 +1,98 @@
+/* GStreamer
+ * Copyright (C) 2009 Jan Schmidt <thaytan@noraisin.net>
+ *
+ * Test that the FFmpeg plugin is loadable, and not broken in some stupid
+ * way.
+ *
+ * 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., 51 Franklin St, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ */
+
+
+#include <gst/check/gstcheck.h>
+#include <stdlib.h>
+
+GST_START_TEST (test_libav_plugin)
+{
+ GstPlugin *plugin = gst_plugin_load_by_name ("libav");
+
+ fail_if (plugin == NULL, "Could not load FFmpeg plugin");
+
+ gst_object_unref (plugin);
+
+}
+
+GST_END_TEST;
+
+GST_START_TEST (test_libav_update_reg)
+{
+ GstElement *encoder, *muxer, *decoder;
+
+ /* Ask for elements the first time */
+ encoder = gst_element_factory_make ("avenc_mpeg2video", "sink");
+ GST_DEBUG ("Creating element avenc_mpeg2video %p", encoder);
+ fail_unless (encoder != NULL);
+
+ decoder = gst_element_factory_make ("avdec_mpeg2video", "sink");
+ GST_DEBUG ("Creating element avdec_mpeg2video %p", decoder);
+ fail_unless (decoder != NULL);
+
+ muxer = gst_element_factory_make ("avmux_dvd", "sink");
+ GST_DEBUG ("Creating element avmux_dvd %p", muxer);
+ fail_unless (muxer != NULL);
+
+ gst_object_unref (encoder);
+ gst_object_unref (decoder);
+ gst_object_unref (muxer);
+
+ GST_DEBUG ("calls gst_update_registry");
+ gst_update_registry ();
+
+ /* Ask for elements the second time */
+
+ encoder = gst_element_factory_make ("avenc_mpeg2video", "sink");
+ GST_DEBUG ("Creating element avenc_mpeg2video %p", encoder);
+ fail_unless (encoder != NULL);
+
+ decoder = gst_element_factory_make ("avdec_mpeg2video", "sink");
+ GST_DEBUG ("Creating element avdec_mpeg2video %p", decoder);
+ fail_unless (decoder != NULL);
+
+ muxer = gst_element_factory_make ("avmux_dvd", "sink");
+ GST_DEBUG ("Creating element avmux_dvd %p", muxer);
+ fail_unless (muxer != NULL);
+
+ gst_object_unref (encoder);
+ gst_object_unref (decoder);
+ gst_object_unref (muxer);
+}
+
+GST_END_TEST;
+
+static Suite *
+plugin_test_suite (void)
+{
+ Suite *s = suite_create ("Plugin");
+ TCase *tc_chain = tcase_create ("existence");
+
+ suite_add_tcase (s, tc_chain);
+
+ tcase_add_test (tc_chain, test_libav_plugin);
+ tcase_add_test (tc_chain, test_libav_update_reg);
+
+ return s;
+}
+
+GST_CHECK_MAIN (plugin_test);
diff --git a/subprojects/gst-libav/tests/check/gst-libav.supp b/subprojects/gst-libav/tests/check/gst-libav.supp
new file mode 100644
index 0000000000..e69de29bb2
--- /dev/null
+++ b/subprojects/gst-libav/tests/check/gst-libav.supp
diff --git a/subprojects/gst-libav/tests/check/meson.build b/subprojects/gst-libav/tests/check/meson.build
new file mode 100644
index 0000000000..a967f002cc
--- /dev/null
+++ b/subprojects/gst-libav/tests/check/meson.build
@@ -0,0 +1,60 @@
+# name, condition when to skip the test and extra dependencies
+libav_tests = [
+ [ 'elements/avaudenc' ],
+ [ 'elements/avdec_adpcm' ],
+ [ 'elements/avdemux_ape' ],
+ [ 'elements/avvidenc' ],
+ [ 'generic/libavcodec-locking' ],
+ [ 'generic/plugin-test' ]
+]
+
+test_defines = [
+ '-UG_DISABLE_ASSERT',
+ '-UG_DISABLE_CAST_CHECKS',
+ '-DGST_CHECK_TEST_ENVIRONMENT_BEACON="GST_PLUGIN_LOADING_WHITELIST"',
+ '-DGST_TEST_FILES_PATH="' + meson.current_source_dir() + '/../files"',
+ '-DGST_USE_UNSTABLE_API',
+]
+
+pluginsdirs = []
+if gst_dep.type_name() == 'pkgconfig'
+ pbase = dependency('gstreamer-plugins-base-' + api_version, required: true)
+ pluginsdirs = [gst_dep.get_pkgconfig_variable('pluginsdir'),
+ pbase.get_pkgconfig_variable('pluginsdir')]
+ gst_plugin_scanner_dir = gst_dep.get_pkgconfig_variable('pluginscannerdir')
+else
+ gst_plugin_scanner_dir = subproject('gstreamer').get_variable('gst_scanner_dir')
+endif
+gst_plugin_scanner_path = join_paths(gst_plugin_scanner_dir, 'gst-plugin-scanner')
+
+# FIXME: check, also + PTHREAD_CFLAGS
+test_deps = [gst_dep, gstbase_dep, gstcheck_dep, gstaudio_dep,
+ gstvideo_dep, gstpbutils_dep]
+
+# FIXME: add valgrind suppression common/gst.supp gst-libav.supp
+foreach t : libav_tests
+ fname = '@0@.c'.format(t.get(0))
+ test_name = t.get(0).underscorify()
+ extra_sources = t.get(3, [ ])
+ extra_deps = t.get(2, [ ])
+ skip_test = t.get(1, false)
+ if not skip_test
+ env = environment()
+ env.set('GST_PLUGIN_SYSTEM_PATH_1_0', '')
+ env.set('CK_DEFAULT_TIMEOUT', '20')
+ env.set('GST_PLUGIN_LOADING_WHITELIST', 'gstreamer', 'gst-plugins-base',
+ 'gst-libav@' + meson.build_root())
+ env.set('GST_PLUGIN_PATH_1_0', [meson.build_root()] + pluginsdirs)
+ env.set('GSETTINGS_BACKEND', 'memory')
+
+ env.set('GST_REGISTRY', join_paths(meson.current_build_dir(), '@0@.registry'.format(test_name)))
+ env.set('GST_PLUGIN_SCANNER_1_0', gst_plugin_scanner_path)
+ exe = executable(test_name, fname, extra_sources,
+ include_directories : [configinc],
+ c_args : ['-DHAVE_CONFIG_H=1' ] + test_defines,
+ dependencies : [libm] + test_deps + extra_deps,
+ )
+ test(test_name, exe, env: env, timeout: 3 * 60)
+ endif
+endforeach
+