diff options
author | Vivia Nikolaidou <n.vivia@gmail.com> | 2012-04-24 17:09:03 +0300 |
---|---|---|
committer | Sebastian Dröge <sebastian.droege@collabora.co.uk> | 2012-04-25 17:18:38 +0200 |
commit | b699d198a2d411040818b51f387b5871327c65fa (patch) | |
tree | 11f28be023e9ca379a13e6abfb1c68560df05772 | |
parent | 9ac43d4f463bd13593ea96e27390f94eba62271c (diff) |
play/seek: Optionally use appsink as the audio/video sinks
-rw-r--r-- | tests/Makefile.am | 10 | ||||
-rw-r--r-- | tests/insanity-fake-appsink.c | 142 | ||||
-rw-r--r-- | tests/insanity-fake-appsink.h | 41 | ||||
-rw-r--r-- | tests/insanity-file-appsrc.c | 30 | ||||
-rw-r--r-- | tests/insanity-file-appsrc.h | 3 | ||||
-rw-r--r-- | tests/insanity-test-gst-play.c | 88 | ||||
-rw-r--r-- | tests/insanity-test-gst-seek.c | 68 |
7 files changed, 325 insertions, 57 deletions
diff --git a/tests/Makefile.am b/tests/Makefile.am index 072a87c..5a0dda8 100644 --- a/tests/Makefile.am +++ b/tests/Makefile.am @@ -64,12 +64,12 @@ endif libinsanityhelper_la_LIBADD=$(GIO_LIBS) $(common_ldadd) libinsanityhelper_la_CFLAGS=$(GIO_CFLAGS) $(common_cflags) -libinsanityhelper_la_SOURCES = insanity-file-appsrc.c -appsrc_noinst_libraries=libinsanityhelper.la -appsrc_noinst_headers=insanity-file-appsrc.h +libinsanityhelper_la_SOURCES = insanity-file-appsrc.c insanity-fake-appsink.c +helper_noinst_libraries=libinsanityhelper.la +helper_noinst_headers=insanity-file-appsrc.h insanity-fake-appsink.h -noinst_LTLIBRARIES=$(http_noinst_libraries) $(appsrc_noinst_libraries) -noinst_HEADERS=$(http_noinst_headers) $(appsrc_noinst_headers) +noinst_LTLIBRARIES=$(http_noinst_libraries) $(helper_noinst_libraries) +noinst_HEADERS=$(http_noinst_headers) $(helper_noinst_headers) BUILT_SOURCES = $(built_headers) $(built_sources) EXTRA_DIST = run-insanity-test-gst-generic-pipeline diff --git a/tests/insanity-fake-appsink.c b/tests/insanity-fake-appsink.c new file mode 100644 index 0000000..333e5ce --- /dev/null +++ b/tests/insanity-fake-appsink.c @@ -0,0 +1,142 @@ +/** + * Insanity QA system + * + * Copyright (c) 2012, Collabora Ltd + * Author: Vivia Nikolaidou <vivia.nikolaidou@collabora.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/gst.h> +#include <insanity-gst/insanity-gst.h> +#include "insanity-fake-appsink.h" + +#define LOG(format, args...) \ + INSANITY_LOG (app->test, "appsink", INSANITY_LOG_LEVEL_DEBUG, format, ##args) + +typedef struct _App App; + +struct _App +{ + GstElement *appsink; + + InsanityTest *test; + + guint64 bufcount; + guint64 cbcount; +}; + +static void +on_new_buffer (GstElement * appsink, gpointer userdata) +{ + + GstBuffer *buffer = NULL; + App *app = NULL; + + app = (App *) g_object_get_qdata ((GObject *) appsink, + g_quark_from_static_string ("app")); + + g_signal_emit_by_name (appsink, "pull-buffer", &buffer); + if (buffer) { + gst_buffer_unref (buffer); + app->bufcount++; + } + +} + +static gboolean +cb_have_data (GstPad * pad, GstBuffer * buffer, gpointer u_data) +{ + + App *app = NULL; + GstElement *appsink = NULL; + + appsink = gst_pad_get_parent_element (pad); + + app = (App *) g_object_get_qdata ((GObject *) appsink, + g_quark_from_static_string ("app")); + + app->cbcount++; + + gst_object_unref (appsink); + + return TRUE; + +} + +static void +cleanup (App * app) +{ + + g_free (app); + +} + +guint64 +insanity_fake_appsink_get_buffers_received (GstElement * sink) +{ + + App *app; + + app = (App *) g_object_get_qdata ((GObject *) sink, + g_quark_from_static_string ("app")); + return app->bufcount; + +} + +gboolean +insanity_fake_appsink_check_bufcount (GstElement * sink) +{ + + App *app; + + app = (App *) g_object_get_qdata ((GObject *) sink, + g_quark_from_static_string ("app")); + LOG ("Element %s: Received %" G_GUINT64_FORMAT " buffers (probe says %" + G_GUINT64_FORMAT ")\n", GST_OBJECT_NAME (sink), + app->bufcount, app->cbcount); + return (app->bufcount == app->cbcount); + +} + +GstElement * +insanity_fake_appsink_new (const gchar * name, InsanityTest * test) +{ + + GstElement *appsink; + App *app; + GstPad *pad; + + appsink = gst_element_factory_make ("appsink", name); + g_object_set (G_OBJECT (appsink), "emit-signals", TRUE, "sync", FALSE, NULL); + g_signal_connect (appsink, "new-buffer", G_CALLBACK (on_new_buffer), NULL); + + app = g_new0 (App, 1); + app->bufcount = 0; + app->cbcount = 0; + app->appsink = appsink; + app->test = test; + + pad = gst_element_get_pad (appsink, "sink"); + gst_pad_add_buffer_probe (pad, G_CALLBACK (cb_have_data), NULL); + gst_object_unref (pad); + + g_object_set_qdata_full ((GObject *) appsink, + g_quark_from_static_string ("app"), app, (GDestroyNotify) cleanup); + + return appsink; + +} diff --git a/tests/insanity-fake-appsink.h b/tests/insanity-fake-appsink.h new file mode 100644 index 0000000..8dad279 --- /dev/null +++ b/tests/insanity-fake-appsink.h @@ -0,0 +1,41 @@ +/** + * Insanity QA system + * + * Copyright (c) 2012, Collabora Ltd + * Author: Vivia Nikolaidou <vivia.nikolaidou@collabora.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. + */ + +#ifndef INSANITY_FAKE_APPSINK_H +#define INSANITY_FAKE_APPSINK_H + +#include <gst/gst.h> + +G_BEGIN_DECLS + +guint64 +insanity_fake_appsink_get_buffers_received (GstElement * sink); + +gboolean +insanity_fake_appsink_check_bufcount (GstElement * sink); + +GstElement * +insanity_fake_appsink_new (const gchar * name, InsanityTest * test); + +G_END_DECLS + +#endif diff --git a/tests/insanity-file-appsrc.c b/tests/insanity-file-appsrc.c index 1f38788..1e092e5 100644 --- a/tests/insanity-file-appsrc.c +++ b/tests/insanity-file-appsrc.c @@ -34,6 +34,10 @@ #include <stdlib.h> #include "insanity-file-appsrc.h" +#include <insanity-gst/insanity-gst.h> + +#define LOG(format, args...) \ + INSANITY_LOG (app->test, "appsrc", INSANITY_LOG_LEVEL_DEBUG, format, ##args) typedef struct _App App; @@ -41,6 +45,8 @@ struct _App { GstElement *appsrc; + InsanityTest *test; + GFileInputStream *stream; gint64 length; guint64 offset; @@ -64,7 +70,6 @@ feed_data (GstElement * appsrc, guint size, App * app) return; } if (app->offset + size > app->length) { - g_print ("Reached EOF\n"); size = app->length - app->offset; } @@ -75,7 +80,7 @@ feed_data (GstElement * appsrc, guint size, App * app) g_input_stream_read_all (G_INPUT_STREAM (app->stream), GST_BUFFER_DATA (buffer), size, &len, NULL, &error); if (error) { - g_print ("ERROR: %s\n", error->message); + LOG ("ERROR: %s\n", error->message); g_error_free (error); } /* we need to set an offset for random access */ @@ -86,7 +91,7 @@ feed_data (GstElement * appsrc, guint size, App * app) len = g_input_stream_read (G_INPUT_STREAM (app->stream), GST_BUFFER_DATA (buffer), size, NULL, &error); if (error) { - g_print ("ERROR: %s\n", error->message); + LOG ("ERROR: %s\n", error->message); g_error_free (error); } } @@ -94,13 +99,13 @@ feed_data (GstElement * appsrc, guint size, App * app) GST_BUFFER_SIZE (buffer) = len; if (error) { - GST_DEBUG ("Cannot read file: %s\n", error->message); + LOG ("Cannot read file: %s\n", error->message); /* probably explode? */ g_error_free (error); return; } - GST_DEBUG ("feed buffer %p, offset %" G_GUINT64_FORMAT "-%u", buffer, + LOG ("feed buffer %p, offset %" G_GUINT64_FORMAT "-%u", buffer, app->offset, len); g_signal_emit_by_name (app->appsrc, "push-buffer", buffer, &ret); gst_buffer_unref (buffer); @@ -118,13 +123,13 @@ seek_data (GstElement * appsrc, guint64 position, App * app) GError *error = NULL; - GST_DEBUG ("seek to offset %" G_GUINT64_FORMAT, position); + LOG ("seek to offset %" G_GUINT64_FORMAT, position); app->offset = position; g_seekable_seek (G_SEEKABLE (app->stream), position, G_SEEK_SET, NULL, &error); if (error) { - GST_DEBUG ("Cannot seek: %s\n", error->message); + LOG ("Cannot seek: %s\n", error->message); g_error_free (error); return FALSE; } @@ -142,8 +147,8 @@ cleanup (App * app) } -void -insanity_file_appsrc_prepare (GstElement * appsrc, gchar * uri) +void insanity_file_appsrc_prepare + (GstElement * appsrc, gchar * uri, InsanityTest * test) { App *app; @@ -154,6 +159,7 @@ insanity_file_appsrc_prepare (GstElement * appsrc, gchar * uri) GFile *file = NULL; app = g_new0 (App, 1); + app->test = test; filename = uri; while (!g_str_has_prefix (filename, "/")) { @@ -165,13 +171,13 @@ insanity_file_appsrc_prepare (GstElement * appsrc, gchar * uri) g_strfreev (dump); app->appsrc = appsrc; - GST_DEBUG ("Opening file %s\n", filename); + LOG ("Opening file %s\n", filename); /* try to open the file as an mmapped file */ file = g_file_new_for_path (filename); app->stream = g_file_read (file, NULL, &error); if (error) { - GST_DEBUG ("failed to open file: %s\n", error->message); + LOG ("failed to open file: %s\n", error->message); g_error_free (error); g_object_unref (file); cleanup (app); @@ -186,7 +192,7 @@ insanity_file_appsrc_prepare (GstElement * appsrc, gchar * uri) info = g_file_query_info (file, G_FILE_ATTRIBUTE_STANDARD_SIZE, G_FILE_QUERY_INFO_NONE, NULL, &error); if (error) { - GST_DEBUG ("failed to get file size: %s\n", error->message); + LOG ("failed to get file size: %s\n", error->message); g_error_free (error); } else { app->length = g_file_info_get_size (info); diff --git a/tests/insanity-file-appsrc.h b/tests/insanity-file-appsrc.h index a46a3fa..098936a 100644 --- a/tests/insanity-file-appsrc.h +++ b/tests/insanity-file-appsrc.h @@ -30,11 +30,12 @@ #endif #include <gst/gst.h> +#include <insanity-gst/insanity-gst.h> G_BEGIN_DECLS void -insanity_file_appsrc_prepare (GstElement *appsrc, gchar *uri); +insanity_file_appsrc_prepare (GstElement *appsrc, gchar *uri, InsanityTest *test); G_END_DECLS diff --git a/tests/insanity-test-gst-play.c b/tests/insanity-test-gst-play.c index 7f70823..58a5b2c 100644 --- a/tests/insanity-test-gst-play.c +++ b/tests/insanity-test-gst-play.c @@ -28,12 +28,17 @@ #include <glib-object.h> #include <insanity-gst/insanity-gst.h> #include "insanity-file-appsrc.h" +#include "insanity-fake-appsink.h" + +#define LOG(format, args...) \ + INSANITY_LOG (INSANITY_TEST (ptest), "play", INSANITY_LOG_LEVEL_DEBUG, format, ##args) static GstElement *global_pipeline = NULL; static guint check_position_id = 0; static GstClockTime first_position = GST_CLOCK_TIME_NONE; static GstClockTime last_position = GST_CLOCK_TIME_NONE; static GstClockTime playback_duration = GST_CLOCK_TIME_NONE; +static gboolean appsink = FALSE; static void found_source (GstElement * playbin, GstElement * appsrc, gpointer ptest) @@ -56,13 +61,13 @@ found_source (GstElement * playbin, GstElement * appsrc, gpointer ptest) if (!g_str_equal (pluginname, "appsrc")) { /* Oops - something went very wrong! */ - g_print ("Requested an appsrc uri but found %s instead!\n", pluginname); + LOG ("Requested an appsrc uri but found %s instead!\n", pluginname); insanity_test_done (INSANITY_TEST (ptest)); g_free (uri); return; } - insanity_file_appsrc_prepare (appsrc, uri); + insanity_file_appsrc_prepare (appsrc, uri, INSANITY_TEST (ptest)); g_free (uri); @@ -72,31 +77,49 @@ static GstPipeline * play_gst_test_create_pipeline (InsanityGstPipelineTest * ptest, gpointer userdata) { - GstElement *pipeline; - const char *launch_line = "playbin2 audio-sink=fakesink video-sink=fakesink"; + GstElement *playbin; + GstElement *audiosink; + GstElement *videosink; GError *error = NULL; - pipeline = gst_parse_launch (launch_line, &error); - if (!pipeline) { + /* Just try to get the argument, use default if not found */ + insanity_test_get_boolean_argument (INSANITY_TEST (ptest), "appsink", + &appsink); + + playbin = gst_element_factory_make ("playbin2", "playbin2"); + global_pipeline = playbin; + + if (appsink) { + audiosink = insanity_fake_appsink_new ("audiosink", INSANITY_TEST (ptest)); + videosink = insanity_fake_appsink_new ("videosink", INSANITY_TEST (ptest)); + } else { + audiosink = gst_element_factory_make ("fakesink", "audiosink"); + videosink = gst_element_factory_make ("fakesink", "videosink"); + } + + if (!playbin || !audiosink || !videosink) { insanity_test_validate_checklist_item (INSANITY_TEST (ptest), "valid-pipeline", FALSE, error ? error->message : NULL); if (error) g_error_free (error); return NULL; - } else if (error) { - /* Do we get a dangling pointer here ? gst-launch.c does not unref */ +/* } else if (error) { + // Do we get a dangling pointer here ? gst-launch.c does not unref pipeline = NULL; insanity_test_validate_checklist_item (INSANITY_TEST (ptest), "valid-pipeline", FALSE, error->message); g_error_free (error); - return NULL; + return NULL; */ } g_print ("Connecting signal\n"); - g_signal_connect (pipeline, "source-setup", (GCallback) found_source, ptest); - global_pipeline = pipeline; - return GST_PIPELINE (pipeline); + g_object_set (playbin, "video-sink", videosink, NULL); + g_object_set (playbin, "audio-sink", audiosink, NULL); + + g_signal_connect (playbin, "source-setup", (GCallback) found_source, ptest); + + return GST_PIPELINE (playbin); } static gboolean @@ -130,25 +153,21 @@ check_position (InsanityTest * test) static gboolean play_test_start (InsanityTest * test) { - GValue uri = { 0 }; - GValue duration = { 0 }; + gchar *uri; - if (!insanity_test_get_argument (test, "uri", &uri)) + if (!insanity_test_get_string_argument (test, "uri", &uri)) return FALSE; - if (!strcmp (g_value_get_string (&uri), "")) { + if (!strcmp (uri, "")) { insanity_test_validate_checklist_item (test, "valid-pipeline", FALSE, "No URI to test on"); - g_value_unset (&uri); return FALSE; } - g_object_set (global_pipeline, "uri", g_value_get_string (&uri), NULL); - g_value_unset (&uri); + g_object_set (global_pipeline, "uri", uri, NULL); - if (!insanity_test_get_argument (test, "playback-duration", &duration)) + if (!insanity_test_get_uint64_argument (test, "playback-duration", + &playback_duration)) return FALSE; - playback_duration = g_value_get_uint64 (&duration); - g_value_unset (&duration); first_position = GST_CLOCK_TIME_NONE; last_position = GST_CLOCK_TIME_NONE; @@ -163,6 +182,22 @@ play_test_stop (InsanityTest * test) if (check_position_id) g_source_remove (check_position_id); check_position_id = 0; + if (appsink) { + GstElement *audiosink; + GstElement *videosink; + g_object_get (global_pipeline, "audio-sink", &audiosink, NULL); + g_object_get (global_pipeline, "video-sink", &videosink, NULL); + if (insanity_fake_appsink_check_bufcount (audiosink) && + insanity_fake_appsink_check_bufcount (videosink)) { + insanity_test_validate_checklist_item (test, "all-buffers-received", + TRUE, "All sinks received all their buffers"); + } else { + insanity_test_validate_checklist_item (test, "all-buffers-received", + FALSE, "Sinks didn't receive all buffers"); + } + gst_object_unref (audiosink); + gst_object_unref (videosink); + } return TRUE; } @@ -191,6 +226,15 @@ main (int argc, char **argv) "Stop playback after this many nanoseconds", NULL, FALSE, &vdef); g_value_unset (&vdef); + g_value_init (&vdef, G_TYPE_BOOLEAN); + g_value_set_boolean (&vdef, FALSE); + insanity_test_add_argument (test, "appsink", + "Use appsink instead of fakesink", NULL, TRUE, &vdef); + g_value_unset (&vdef); + + insanity_test_add_checklist_item (test, "all-buffers-received", + "Appsinks (if used) received all buffers", NULL); + insanity_gst_pipeline_test_set_create_pipeline_function (INSANITY_GST_PIPELINE_TEST (test), &play_gst_test_create_pipeline, NULL, NULL); diff --git a/tests/insanity-test-gst-seek.c b/tests/insanity-test-gst-seek.c index 59a4a2b..8dca4dd 100644 --- a/tests/insanity-test-gst-seek.c +++ b/tests/insanity-test-gst-seek.c @@ -29,6 +29,7 @@ #include <glib-object.h> #include <insanity-gst/insanity-gst.h> #include "insanity-file-appsrc.h" +#include "insanity-fake-appsink.h" /* Various bits and pieces taken/adapted from -base/tests/examples/seek/seek.c */ @@ -95,6 +96,7 @@ static guint global_duration_timeout = 0; static guint global_idle_timeout = 0; static gint64 global_last_probe = 0; static GstSegment global_segment[2]; +static gboolean appsink = FALSE; static GStaticMutex global_mutex = G_STATIC_MUTEX_INIT; #define SEEK_TEST_LOCK() g_static_mutex_lock (&global_mutex) @@ -131,7 +133,7 @@ found_source (GstElement * playbin, GstElement * appsrc, gpointer ptest) return; } - insanity_file_appsrc_prepare (appsrc, uri); + insanity_file_appsrc_prepare (appsrc, uri, INSANITY_TEST (ptest)); g_free (uri); @@ -279,33 +281,40 @@ seek_test_bus_message (InsanityGstPipelineTest * ptest, GstMessage * msg) static GstPipeline * seek_test_create_pipeline (InsanityGstPipelineTest * ptest, gpointer userdata) { - GstElement *pipeline = NULL; - const char *launch_line = - "playbin2 audio-sink=\"fakesink name=asink\" video-sink=\"fakesink name=vsink\""; + GstElement *playbin = NULL; + GstElement *audiosink; + GstElement *videosink; GError *error = NULL; - pipeline = gst_parse_launch (launch_line, &error); - if (!pipeline) { + /* Just try to get the argument, use default if not found */ + insanity_test_get_boolean_argument (INSANITY_TEST (ptest), "appsink", + &appsink); + + playbin = gst_element_factory_make ("playbin2", "playbin2"); + global_pipeline = playbin; + + if (appsink) { + audiosink = insanity_fake_appsink_new ("asink", INSANITY_TEST (ptest)); + videosink = insanity_fake_appsink_new ("vsink", INSANITY_TEST (ptest)); + } else { + audiosink = gst_element_factory_make ("fakesink", "asink"); + videosink = gst_element_factory_make ("fakesink", "vsink"); + } + + if (!playbin || !audiosink || !videosink) { insanity_test_validate_checklist_item (INSANITY_TEST (ptest), "valid-pipeline", FALSE, error ? error->message : NULL); if (error) g_error_free (error); return NULL; - } else if (error) { - /* Do we get a dangling pointer here ? gst-launch.c does not unref */ - pipeline = NULL; - insanity_test_validate_checklist_item (INSANITY_TEST (ptest), - "valid-pipeline", FALSE, error->message); - g_error_free (error); - return NULL; } - g_print ("Connecting signal\n"); - g_signal_connect (pipeline, "source-setup", (GCallback) found_source, ptest); + g_object_set (playbin, "video-sink", videosink, NULL); + g_object_set (playbin, "audio-sink", audiosink, NULL); - global_pipeline = pipeline; + g_signal_connect (playbin, "source-setup", (GCallback) found_source, ptest); - return GST_PIPELINE (pipeline); + return GST_PIPELINE (playbin); } static const char * @@ -813,6 +822,23 @@ seek_test_stop (InsanityTest * test) NULL); } + if (appsink) { + GstElement *audiosink; + GstElement *videosink; + g_object_get (global_pipeline, "audio-sink", &audiosink, NULL); + g_object_get (global_pipeline, "video-sink", &videosink, NULL); + if (insanity_fake_appsink_get_buffers_received (audiosink) + + insanity_fake_appsink_get_buffers_received (videosink) > 0) { + insanity_test_validate_checklist_item (test, "buffers-received", + TRUE, "Sinks received buffers"); + } else { + insanity_test_validate_checklist_item (test, "buffers-received", + FALSE, "Sinks received no buffers"); + } + gst_object_unref (audiosink); + gst_object_unref (videosink); + } + started = FALSE; SEEK_TEST_UNLOCK (); @@ -920,6 +946,12 @@ main (int argc, char **argv) NULL, TRUE, &vdef); g_value_unset (&vdef); + g_value_init (&vdef, G_TYPE_BOOLEAN); + g_value_set_boolean (&vdef, FALSE); + insanity_test_add_argument (test, "appsink", + "Use appsink instead of fakesink", NULL, TRUE, &vdef); + g_value_unset (&vdef); + insanity_test_add_checklist_item (test, "install-probes", "Probes were installed on the sinks", NULL); insanity_test_add_checklist_item (test, "duration-known", @@ -936,6 +968,8 @@ main (int argc, char **argv) NULL); insanity_test_add_checklist_item (test, "segment-clipping", "Buffers were correctly clipped to the configured segment", NULL); + insanity_test_add_checklist_item (test, "buffers-received", + "Appsinks (if used) received some buffers", NULL); insanity_test_add_extra_info (test, "max-seek-error", "The maximum timestamp difference between a seek target and the buffer received after the seek (absolute value in nanoseconds)"); |