From 61d39d6e74bfb3a5b2d29c437528d53743461cf3 Mon Sep 17 00:00:00 2001 From: Thiago Santos Date: Wed, 7 Aug 2013 11:31:04 -0300 Subject: [PATCH] file-checker: add file playback testing feature Adds a property that triggers the file playback tests on GstQaFileCheker. Also enable it in the gst-transcoding post file checks. The implementation is simple, just create a playbin2 and use fakesinks as sinks, set it to playing and wait for either EOS or ERROR messages. --- validate/gst/qa/gst-qa-file-checker.c | 81 +++++++++++++++++++++++++++ validate/gst/qa/gst-qa-file-checker.h | 2 + validate/gst/qa/gst-qa-report.c | 9 +++ validate/gst/qa/gst-qa-report.h | 3 + validate/gst/qa/gst-qa-transcoding.c | 2 +- 5 files changed, 96 insertions(+), 1 deletion(-) diff --git a/validate/gst/qa/gst-qa-file-checker.c b/validate/gst/qa/gst-qa-file-checker.c index 50705c2d08..0466c61614 100644 --- a/validate/gst/qa/gst-qa-file-checker.c +++ b/validate/gst/qa/gst-qa-file-checker.c @@ -41,6 +41,7 @@ enum PROP_FILE_SIZE, PROP_FILE_SIZE_TOLERANCE, PROP_SEEKABLE, + PROP_TEST_PLAYBACK, PROP_LAST }; @@ -49,6 +50,7 @@ enum #define DEFAULT_FILE_SIZE 0 #define DEFAULT_FILE_SIZE_TOLERANCE 0 #define DEFAULT_SEEKABLE FALSE +#define DEFAULT_PLAYBACK FALSE GST_DEBUG_CATEGORY_STATIC (gst_qa_file_checker_debug); #define GST_CAT_DEFAULT gst_qa_file_checker_debug @@ -146,6 +148,11 @@ gst_qa_file_checker_class_init (GstQaFileCheckerClass * klass) g_param_spec_boolean ("is-seekable", "is seekable", "If the resulting file should be seekable", DEFAULT_SEEKABLE, G_PARAM_READWRITE | G_PARAM_STATIC_NAME)); + + g_object_class_install_property (gobject_class, PROP_TEST_PLAYBACK, + g_param_spec_boolean ("test-playback", "test playback", + "If the file should be tested for playback", DEFAULT_PLAYBACK, + G_PARAM_READWRITE | G_PARAM_STATIC_NAME)); } static void @@ -158,6 +165,7 @@ gst_qa_file_checker_init (GstQaFileChecker * fc) fc->file_size = DEFAULT_FILE_SIZE; fc->file_size_tolerance = DEFAULT_FILE_SIZE_TOLERANCE; fc->seekable = DEFAULT_SEEKABLE; + fc->test_playback = DEFAULT_PLAYBACK; } static void @@ -197,6 +205,9 @@ gst_qa_file_checker_set_property (GObject * object, guint prop_id, case PROP_SEEKABLE: fc->seekable = g_value_get_boolean (value); break; + case PROP_TEST_PLAYBACK: + fc->test_playback = g_value_get_boolean (value); + break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); break; @@ -237,6 +248,9 @@ gst_qa_file_checker_get_property (GObject * object, guint prop_id, case PROP_SEEKABLE: g_value_set_boolean (value, fc->seekable); break; + case PROP_TEST_PLAYBACK: + g_value_set_boolean (value, fc->test_playback); + break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); break; @@ -569,6 +583,72 @@ check_encoding_profile (GstQaFileChecker * fc, GstDiscovererInfo * info) return ret; } +static gboolean +check_playback (GstQaFileChecker * fc) +{ + GstElement *playbin; + GstElement *videosink, *audiosink; + GstBus *bus; + GstMessage *msg; + gboolean ret = TRUE; + + if (!fc->test_playback) + return TRUE; + + playbin = gst_element_factory_make ("playbin2", "fc-playbin"); + videosink = gst_element_factory_make ("fakesink", "fc-videosink"); + audiosink = gst_element_factory_make ("fakesink", "fc-audiosink"); + + if (!playbin || !videosink || !audiosink) { + GST_QA_REPORT (fc, GST_QA_ISSUE_ID_MISSING_PLUGIN, "file check requires " + "playbin2 and fakesink to be available"); + } + + g_object_set (playbin, "video-sink", videosink, "audio-sink", audiosink, + "uri", fc->uri, NULL); + + if (gst_element_set_state (playbin, + GST_STATE_PLAYING) == GST_STATE_CHANGE_FAILURE) { + GST_QA_REPORT (fc, GST_QA_ISSUE_ID_FILE_PLAYBACK_START_FAILURE, + "Failed to " "change pipeline state to playing"); + ret = FALSE; + goto end; + } + + bus = gst_pipeline_get_bus (GST_PIPELINE (playbin)); + msg = + gst_bus_timed_pop_filtered (bus, GST_CLOCK_TIME_NONE, + GST_MESSAGE_ERROR | GST_MESSAGE_EOS); + if (msg) { + if (GST_MESSAGE_TYPE (msg) == GST_MESSAGE_EOS) { + /* all good */ + } else if (GST_MESSAGE_TYPE (msg) == GST_MESSAGE_ERROR) { + GError *error = NULL; + gchar *debug = NULL; + + gst_message_parse_error (msg, &error, &debug); + GST_QA_REPORT (fc, GST_QA_ISSUE_ID_FILE_PLAYBACK_ERROR, "File %s failed " + "during playback. Error: %s : %s", fc->uri, error->message, debug); + g_error_free (error); + g_free (debug); + + ret = FALSE; + } else { + g_assert_not_reached (); + } + gst_message_unref (msg); + } else { + GST_QA_REPORT (fc, GST_QA_ISSUE_ID_FILE_PLAYBACK_ERROR, "File playback " + "finished unexpectedly"); + } + gst_object_unref (bus); + +end: + gst_element_set_state (playbin, GST_STATE_NULL); + gst_object_unref (playbin); + + return ret; +} gboolean gst_qa_file_checker_run (GstQaFileChecker * fc) @@ -599,6 +679,7 @@ gst_qa_file_checker_run (GstQaFileChecker * fc) ret = check_file_duration (fc, info) & ret; ret = check_seekable (fc, info) & ret; ret = check_encoding_profile (fc, info) & ret; + ret = check_playback (fc) & ret; return ret; } diff --git a/validate/gst/qa/gst-qa-file-checker.h b/validate/gst/qa/gst-qa-file-checker.h index d967760ef1..fde4dc56a1 100644 --- a/validate/gst/qa/gst-qa-file-checker.h +++ b/validate/gst/qa/gst-qa-file-checker.h @@ -63,6 +63,8 @@ struct _GstQaFileChecker { gboolean seekable; /* TODO should we care about disabling this check? */ + gboolean test_playback; + gchar *uri; /* Set to NULL to skip check */ diff --git a/validate/gst/qa/gst-qa-report.c b/validate/gst/qa/gst-qa-report.c index 0d406a6382..45f1169938 100644 --- a/validate/gst/qa/gst-qa-report.c +++ b/validate/gst/qa/gst-qa-report.c @@ -193,10 +193,19 @@ gst_qa_report_load_issues (void) REGISTER_QA_ISSUE (GST_QA_ISSUE_ID_FILE_CHECK_FAILURE, _("an error occured while checking the file for conformance"), NULL, GST_QA_REPORT_LEVEL_CRITICAL); + REGISTER_QA_ISSUE (GST_QA_ISSUE_ID_FILE_PLAYBACK_START_FAILURE, + _("an error occured while starting playback of the test file"), NULL, + GST_QA_REPORT_LEVEL_CRITICAL); + REGISTER_QA_ISSUE (GST_QA_ISSUE_ID_FILE_PLAYBACK_ERROR, + _("an error during playback of the file"), NULL, + GST_QA_REPORT_LEVEL_CRITICAL); REGISTER_QA_ISSUE (GST_QA_ISSUE_ID_ALLOCATION_FAILURE, _("a memory allocation failed during QA run"), NULL, GST_QA_REPORT_LEVEL_CRITICAL); + REGISTER_QA_ISSUE (GST_QA_ISSUE_ID_MISSING_PLUGIN, + _("a gstreamer plugin is missing and prevented QA from running"), + NULL, GST_QA_REPORT_LEVEL_CRITICAL); } void diff --git a/validate/gst/qa/gst-qa-report.h b/validate/gst/qa/gst-qa-report.h index a698acf1fe..33089c1070 100644 --- a/validate/gst/qa/gst-qa-report.h +++ b/validate/gst/qa/gst-qa-report.h @@ -98,8 +98,11 @@ typedef guintptr GstQaIssueId; #define GST_QA_ISSUE_ID_FILE_PROFILE_INCORRECT (((GstQaIssueId) GST_QA_AREA_FILE_CHECK) << GST_QA_ISSUE_ID_SHIFT | 5) #define GST_QA_ISSUE_ID_FILE_NOT_FOUND (((GstQaIssueId) GST_QA_AREA_FILE_CHECK) << GST_QA_ISSUE_ID_SHIFT | 6) #define GST_QA_ISSUE_ID_FILE_CHECK_FAILURE (((GstQaIssueId) GST_QA_AREA_FILE_CHECK) << GST_QA_ISSUE_ID_SHIFT | 7) +#define GST_QA_ISSUE_ID_FILE_PLAYBACK_START_FAILURE (((GstQaIssueId) GST_QA_AREA_FILE_CHECK) << GST_QA_ISSUE_ID_SHIFT | 8) +#define GST_QA_ISSUE_ID_FILE_PLAYBACK_ERROR (((GstQaIssueId) GST_QA_AREA_FILE_CHECK) << GST_QA_ISSUE_ID_SHIFT | 9) #define GST_QA_ISSUE_ID_ALLOCATION_FAILURE (((GstQaIssueId) GST_QA_AREA_RUN_ERROR) << GST_QA_ISSUE_ID_SHIFT | 1) +#define GST_QA_ISSUE_ID_MISSING_PLUGIN (((GstQaIssueId) GST_QA_AREA_RUN_ERROR) << GST_QA_ISSUE_ID_SHIFT | 2) #define GST_QA_ISSUE_ID_AREA(id) ((guintptr)(id >> GST_QA_ISSUE_ID_SHIFT)) diff --git a/validate/gst/qa/gst-qa-transcoding.c b/validate/gst/qa/gst-qa-transcoding.c index 346d15a085..db7e0d3051 100644 --- a/validate/gst/qa/gst-qa-transcoding.c +++ b/validate/gst/qa/gst-qa-transcoding.c @@ -333,7 +333,7 @@ exit: if (run_file_checks) { GstQaFileChecker *fc = g_object_new (GST_TYPE_QA_FILE_CHECKER, "uri", - argv[2], "profile", encoding_profile, NULL); + argv[2], "profile", encoding_profile, "test-playback", TRUE, NULL); if (!gst_qa_file_checker_run (fc)) { g_print ("Failed file checking\n");