Update
This commit is contained in:
@@ -0,0 +1,153 @@
|
||||
#!/usr/bin/env python3
|
||||
#
|
||||
# Copyright (c) 2015, Edward Hervey <edward@centricular.com>
|
||||
#
|
||||
# This program 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 program 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 program; if not, write to the
|
||||
# Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
|
||||
# Boston, MA 02110-1301, USA.
|
||||
|
||||
import os
|
||||
import sys
|
||||
import xml.etree.cElementTree
|
||||
|
||||
|
||||
def extract_info(xmlfile):
|
||||
e = xml.etree.cElementTree.parse(xmlfile).getroot()
|
||||
r = {}
|
||||
for i in e:
|
||||
r[(i.get("classname"), i.get("name"))] = i
|
||||
return r
|
||||
|
||||
|
||||
if "__main__" == __name__:
|
||||
if len(sys.argv) < 2:
|
||||
print("Usage : %s [<old run xml>] <new run xml>" % sys.argv[0])
|
||||
if len(sys.argv) == 3:
|
||||
oldfile = extract_info(sys.argv[1])
|
||||
newfile = extract_info(sys.argv[2])
|
||||
else:
|
||||
oldfile = []
|
||||
newfile = extract_info(sys.argv[1])
|
||||
|
||||
# new failures (pass in old run, fail in new run)
|
||||
newfail = []
|
||||
# new fixes (fail in old run, pass in new run)
|
||||
newfix = []
|
||||
# tests that are still failing
|
||||
stillfail = []
|
||||
# tests that are still failling but for a different reason
|
||||
failchange = []
|
||||
|
||||
# failed tests sorted by reason
|
||||
reasons = {}
|
||||
|
||||
# all files
|
||||
allfiles = []
|
||||
|
||||
# failed tests sorted by file
|
||||
failedfiles = {}
|
||||
|
||||
if oldfile:
|
||||
# tests that weren't present in old run
|
||||
newtests = [x for x in newfile.keys() if x not in oldfile]
|
||||
# tests that are no longer present in new run
|
||||
gonetests = [x for x in oldfile.keys() if x not in newfile]
|
||||
|
||||
# go over new tests
|
||||
for k, v in newfile.iteritems():
|
||||
tn, fn = k
|
||||
if not fn in allfiles:
|
||||
allfiles.append(fn)
|
||||
newf = v.findall("error")
|
||||
if newf:
|
||||
# extract the failure reason
|
||||
r = newf[0].get("message")
|
||||
if "Application returned 18" in r or "Application returned -5" in r:
|
||||
rs = r.split('[')[1].split(']')[0].split(',')
|
||||
for la in rs:
|
||||
la = la.strip()
|
||||
if la not in reasons:
|
||||
reasons[la] = []
|
||||
reasons[la].append(k)
|
||||
if fn not in failedfiles:
|
||||
failedfiles[fn] = []
|
||||
failedfiles[fn].append((tn, r))
|
||||
|
||||
if k in oldfile:
|
||||
oldone = oldfile.get(k)
|
||||
|
||||
# compare failures
|
||||
oldf = oldone.findall("error")
|
||||
if newf and not oldf:
|
||||
newfail.append(k)
|
||||
if oldf and not newf:
|
||||
newfix.append(k)
|
||||
if oldf and newf:
|
||||
stillfail.append(k)
|
||||
a = oldf[0]
|
||||
b = newf[0]
|
||||
print a, b
|
||||
# check if the failure reasons are the same
|
||||
if a.get("type") != b.get("type"):
|
||||
failchange.append(k)
|
||||
elif a.get("message") != b.get("message"):
|
||||
failchange.append(k)
|
||||
|
||||
if newfail:
|
||||
print("New failures", len(newfail))
|
||||
newfail.sort()
|
||||
for i in newfail:
|
||||
print " %s : %s" % (i[0], i[1])
|
||||
f = newfile[i].find("error")
|
||||
print " ", f.get("type"), f.get("message")
|
||||
print
|
||||
|
||||
if newfix:
|
||||
print "New fixes", len(newfix)
|
||||
newfix.sort()
|
||||
for i in newfix:
|
||||
print " %s : %s" % (i[0], i[1])
|
||||
print
|
||||
|
||||
if failchange:
|
||||
print "Failure changes", len(failchange)
|
||||
failchange.sort()
|
||||
for i in failchange:
|
||||
print " %s : %s" % (i[0], i[1])
|
||||
oldt = oldfile[i].find("error").get("type")
|
||||
newt = newfile[i].find("error").get("type")
|
||||
if oldt != newt:
|
||||
print " Went from '%s' to '%s'" % (oldt, newt)
|
||||
print " Previous message :", oldfile[i].find("error").get("message")
|
||||
print " New message :", newfile[i].find("error").get("message")
|
||||
print
|
||||
|
||||
for k, v in reasons.iteritems():
|
||||
print "Failure type : ", k, len(v)
|
||||
v.sort()
|
||||
for i in v:
|
||||
print " %s : %s" % (i[0], i[1])
|
||||
print
|
||||
|
||||
nofailfiles = sorted([fn for fn in allfiles if fn not in failedfiles])
|
||||
if nofailfiles:
|
||||
print "Files without failures", len(nofailfiles)
|
||||
for f in nofailfiles:
|
||||
print " ", f
|
||||
print
|
||||
|
||||
for k, v in failedfiles.iteritems():
|
||||
print "Failed File :", k
|
||||
for i in v:
|
||||
print " %s : %s" % (i[0], i[1])
|
||||
@@ -0,0 +1,122 @@
|
||||
/* GStreamer
|
||||
*
|
||||
* Copyright (C) 2014 Mathieu Duponchelle <mathieu.duponchelle@opencreed.com>
|
||||
* Copyright (C) 2015 Raspberry Pi Foundation
|
||||
* Author: Thibault Saunier <thibault.saunier@collabora.com>
|
||||
*
|
||||
* 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 "../gst-libs/gst/video/gstvalidatessim.h"
|
||||
|
||||
#include <gst/gst.h>
|
||||
#include <gst/validate/validate.h>
|
||||
#include <gst/video/video.h>
|
||||
#include <locale.h> /* for LC_ALL */
|
||||
|
||||
int
|
||||
main (int argc, char **argv)
|
||||
{
|
||||
GstValidateSsim *ssim;
|
||||
gint rep_err, ret = 0;
|
||||
GError *err = NULL;
|
||||
GstValidateRunner *runner = NULL;
|
||||
GOptionContext *ctx;
|
||||
gchar *outfolder = NULL;
|
||||
gfloat mssim = 0, lowest = 1, highest = -1;
|
||||
gdouble min_avg_similarity = 0.95, min_lowest_similarity = -1.0;
|
||||
|
||||
GOptionEntry options[] = {
|
||||
{"min-avg-similarity", 'a', 0, G_OPTION_ARG_DOUBLE,
|
||||
&min_avg_similarity,
|
||||
"The minimum average similarity under which we consider"
|
||||
" the test as failing",
|
||||
NULL},
|
||||
{"min-lowest-similarity", 'l', 0, G_OPTION_ARG_DOUBLE,
|
||||
&min_lowest_similarity,
|
||||
"The minimum 'lowest' similarity under which we consider"
|
||||
" the test as failing",
|
||||
NULL},
|
||||
{"result-output-folder", 'r', 0, G_OPTION_ARG_FILENAME,
|
||||
&outfolder,
|
||||
"The folder in which to store resulting grey scale images"
|
||||
" when the test failed. In that folder you will find"
|
||||
" images with the structural difference between"
|
||||
" the reference frame and the failed one",
|
||||
NULL},
|
||||
{NULL}
|
||||
};
|
||||
|
||||
setlocale (LC_ALL, "");
|
||||
|
||||
g_set_prgname ("gst-validate-images-check-" GST_API_VERSION);
|
||||
ctx = g_option_context_new ("/reference/file/path /compared/file/path");
|
||||
|
||||
g_option_context_set_summary (ctx,
|
||||
"The gst-validate-images-check calculates SSIM (Structural SIMilarity)"
|
||||
" index for the images. And according to min-lowest-similarity and"
|
||||
" min-avg-similarity, it will consider the images similar enough"
|
||||
" or report critical issues in the GstValidate reporting system");
|
||||
g_option_context_add_main_entries (ctx, options, NULL);
|
||||
|
||||
if (!g_option_context_parse (ctx, &argc, &argv, &err)) {
|
||||
g_printerr ("Error initializing: %s\n", err->message);
|
||||
g_option_context_free (ctx);
|
||||
g_clear_error (&err);
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (argc != 3) {
|
||||
gchar *help = g_option_context_get_help (ctx, FALSE, NULL);
|
||||
g_printerr ("%s", help);
|
||||
g_free (help);
|
||||
g_option_context_free (ctx);
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
gst_init (&argc, &argv);
|
||||
gst_validate_init ();
|
||||
|
||||
runner = gst_validate_runner_new ();
|
||||
ssim =
|
||||
gst_validate_ssim_new (runner, min_avg_similarity, min_lowest_similarity,
|
||||
0, 1);
|
||||
|
||||
gst_validate_ssim_compare_image_files (ssim, argv[1], argv[2], &mssim,
|
||||
&lowest, &highest, outfolder);
|
||||
|
||||
if (!g_file_test (argv[1], G_FILE_TEST_IS_DIR)) {
|
||||
gst_validate_printf (ssim, "Compared %s with %s, average: %f, Min %f\n",
|
||||
argv[1], argv[2], mssim, lowest);
|
||||
}
|
||||
|
||||
rep_err = gst_validate_runner_exit (runner, TRUE);
|
||||
if (ret == 0) {
|
||||
ret = rep_err;
|
||||
if (rep_err != 0)
|
||||
gst_validate_printf (NULL, "Returning %d as error where found", rep_err);
|
||||
}
|
||||
|
||||
g_object_unref (ssim);
|
||||
g_object_unref (runner);
|
||||
gst_validate_deinit ();
|
||||
|
||||
gst_validate_printf (NULL, "\n=======> Test %s (Return value: %i)\n\n",
|
||||
ret == 0 ? "PASSED" : "FAILED", ret);
|
||||
|
||||
return ret;
|
||||
}
|
||||
@@ -0,0 +1,55 @@
|
||||
#!/usr/bin/env python3
|
||||
#
|
||||
# Copyright (c) 2014,Thibault Saunier <thibault.saunier@collabora.com>
|
||||
#
|
||||
# This program 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 program 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 program; if not, write to the
|
||||
# Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
|
||||
# Boston, MA 02110-1301, USA.
|
||||
|
||||
import os
|
||||
import subprocess
|
||||
import sys
|
||||
|
||||
LIBDIR = r'@LIBDIR@'
|
||||
BUILDDIR = r'@BUILDDIR@'
|
||||
SRCDIR = r'@SRCDIR@'
|
||||
|
||||
|
||||
def _add_gst_launcher_path():
|
||||
f = os.path.abspath(__file__)
|
||||
if f.startswith(BUILDDIR):
|
||||
# Make sure to have the configured config.py in the python path
|
||||
sys.path.insert(0, os.path.abspath(os.path.join(BUILDDIR, "..")))
|
||||
root = os.path.abspath(os.path.join(SRCDIR, "../"))
|
||||
else:
|
||||
root = os.path.join(LIBDIR, 'gst-validate-launcher', 'python')
|
||||
|
||||
sys.path.insert(0, root)
|
||||
return os.path.join(root, "launcher")
|
||||
|
||||
|
||||
if "__main__" == __name__:
|
||||
libsdir = _add_gst_launcher_path()
|
||||
from launcher.main import main
|
||||
run_profile = os.environ.get('GST_VALIDATE_LAUNCHER_PROFILING', False)
|
||||
if run_profile:
|
||||
import cProfile
|
||||
prof = cProfile.Profile()
|
||||
try:
|
||||
res = prof.runcall(main, libsdir)
|
||||
finally:
|
||||
prof.dump_stats('gst-validate-launcher-runstats')
|
||||
exit(res)
|
||||
|
||||
exit(main(libsdir))
|
||||
@@ -0,0 +1,187 @@
|
||||
/* GStreamer
|
||||
*
|
||||
* Copyright (C) 2013 Collabora Ltd.
|
||||
* Author: Thiago Sousa Santos <thiago.sousa.santos@collabora.com>
|
||||
*
|
||||
* gst-validate-media-check.c - Media Check CLI tool
|
||||
*
|
||||
* 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.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
|
||||
* 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 <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include <gst/gst.h>
|
||||
#include <gst/validate/validate.h>
|
||||
#include <gst/validate/media-descriptor-writer.h>
|
||||
#include <gst/validate/media-descriptor-parser.h>
|
||||
#include <gst/validate/media-descriptor.h>
|
||||
#include <gst/validate/gst-validate-utils.h>
|
||||
#include <gst/pbutils/encoding-profile.h>
|
||||
#include <locale.h> /* for LC_ALL */
|
||||
|
||||
int
|
||||
main (int argc, gchar ** argv)
|
||||
{
|
||||
GOptionContext *ctx;
|
||||
|
||||
guint ret = 0;
|
||||
GError *err = NULL;
|
||||
gboolean full = FALSE;
|
||||
gboolean skip_parsers = FALSE;
|
||||
gchar *output_file = NULL;
|
||||
gchar *expected_file = NULL;
|
||||
gchar *output = NULL;
|
||||
GstValidateMediaDescriptorWriterFlags writer_flags =
|
||||
GST_VALIDATE_MEDIA_DESCRIPTOR_WRITER_FLAGS_HANDLE_GLOGS;
|
||||
GstValidateMediaDescriptorWriter *writer = NULL;
|
||||
GstValidateRunner *runner = NULL;
|
||||
GstValidateMediaDescriptorParser *reference = NULL;
|
||||
|
||||
GOptionEntry options[] = {
|
||||
{"output-file", 'o', 0, G_OPTION_ARG_FILENAME,
|
||||
&output_file, "The output file to store the results",
|
||||
NULL},
|
||||
{"full", 'f', 0, G_OPTION_ARG_NONE,
|
||||
&full, "Fully analyze the file frame by frame",
|
||||
NULL},
|
||||
{"expected-results", 'e', 0, G_OPTION_ARG_FILENAME,
|
||||
&expected_file, "Path to file containing the expected results "
|
||||
"(or the last results found) for comparison with new results",
|
||||
NULL},
|
||||
{"skip-parsers", 's', 0, G_OPTION_ARG_NONE,
|
||||
&skip_parsers, "Do not plug a parser after demuxer.",
|
||||
NULL},
|
||||
{NULL}
|
||||
};
|
||||
|
||||
setlocale (LC_ALL, "");
|
||||
g_set_prgname ("gst-validate-media-check-" GST_API_VERSION);
|
||||
ctx = g_option_context_new ("[URI]");
|
||||
g_option_context_set_summary (ctx, "Analyzes a media file and writes "
|
||||
"the results to stdout or a file. Can also compare the results found "
|
||||
"with another results file for identifying regressions. The monitoring"
|
||||
" lib from gst-validate will be enabled during the tests to identify "
|
||||
"issues with the gstreamer elements involved with the media file's "
|
||||
"container and codec types");
|
||||
g_option_context_add_main_entries (ctx, options, NULL);
|
||||
|
||||
if (!g_option_context_parse (ctx, &argc, &argv, &err)) {
|
||||
g_printerr ("Error initializing: %s\n", err->message);
|
||||
g_option_context_free (ctx);
|
||||
g_clear_error (&err);
|
||||
exit (1);
|
||||
}
|
||||
|
||||
gst_init (&argc, &argv);
|
||||
gst_validate_init ();
|
||||
|
||||
if (argc != 2) {
|
||||
gchar *msg = g_option_context_get_help (ctx, TRUE, NULL);
|
||||
g_printerr ("%s\n", msg);
|
||||
g_free (msg);
|
||||
g_option_context_free (ctx);
|
||||
ret = 1;
|
||||
goto out;
|
||||
}
|
||||
g_option_context_free (ctx);
|
||||
|
||||
gst_validate_spin_on_fault_signals ();
|
||||
|
||||
runner = gst_validate_runner_new ();
|
||||
|
||||
if (expected_file) {
|
||||
reference =
|
||||
gst_validate_media_descriptor_parser_new (runner, expected_file, NULL);
|
||||
|
||||
if (reference == NULL) {
|
||||
gst_validate_printf (NULL, "Could not parse file: %s\n", expected_file);
|
||||
ret = 1;
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (!full
|
||||
&&
|
||||
gst_validate_media_descriptor_has_frame_info (
|
||||
(GstValidateMediaDescriptor *)
|
||||
reference))
|
||||
full = TRUE; /* Reference has frame info, activate to do comparison */
|
||||
}
|
||||
|
||||
if (full)
|
||||
writer_flags |= GST_VALIDATE_MEDIA_DESCRIPTOR_WRITER_FLAGS_FULL;
|
||||
|
||||
if (skip_parsers)
|
||||
writer_flags |= GST_VALIDATE_MEDIA_DESCRIPTOR_WRITER_FLAGS_NO_PARSER;
|
||||
|
||||
|
||||
writer =
|
||||
gst_validate_media_descriptor_writer_new_discover (runner, argv[1],
|
||||
writer_flags, NULL);
|
||||
if (writer == NULL) {
|
||||
gst_validate_printf (NULL, "Could not discover file: %s\n", argv[1]);
|
||||
ret = 1;
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (output_file) {
|
||||
if (!gst_validate_media_descriptor_writer_write (writer, output_file)) {
|
||||
ret = 1;
|
||||
goto out;
|
||||
}
|
||||
}
|
||||
|
||||
if (reference) {
|
||||
if (!gst_validate_media_descriptors_compare (GST_VALIDATE_MEDIA_DESCRIPTOR
|
||||
(reference), GST_VALIDATE_MEDIA_DESCRIPTOR (writer))) {
|
||||
ret = 1;
|
||||
goto out;
|
||||
}
|
||||
} else {
|
||||
output = gst_validate_media_descriptor_writer_serialize (writer);
|
||||
gst_validate_printf (NULL, "Media info:\n%s\n", output);
|
||||
g_free (output);
|
||||
}
|
||||
|
||||
out:
|
||||
if (runner)
|
||||
ret += gst_validate_runner_exit (runner, TRUE);
|
||||
|
||||
g_free (output_file);
|
||||
g_free (expected_file);
|
||||
|
||||
if (reference) {
|
||||
gst_validate_reporter_purge_reports (GST_VALIDATE_REPORTER (reference));
|
||||
gst_object_unref (reference);
|
||||
}
|
||||
if (writer) {
|
||||
gst_validate_reporter_purge_reports (GST_VALIDATE_REPORTER (writer));
|
||||
gst_object_unref (writer);
|
||||
}
|
||||
if (runner)
|
||||
gst_object_unref (runner);
|
||||
gst_validate_deinit ();
|
||||
gst_deinit ();
|
||||
|
||||
gst_validate_printf (NULL, "\n=======> Test %s (Return value: %i)\n\n",
|
||||
ret == 0 ? "PASSED" : "FAILED", ret);
|
||||
|
||||
return ret;
|
||||
}
|
||||
@@ -0,0 +1,159 @@
|
||||
/* GStreamer
|
||||
* Copyright (C) 2008 Wim Taymans <wim.taymans at 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., 51 Franklin St, Fifth Floor,
|
||||
* Boston, MA 02110-1301, USA.
|
||||
*/
|
||||
|
||||
/* Cc'd from the test-uri example */
|
||||
#include <gst/gst.h>
|
||||
|
||||
#include <gst/validate/validate.h>
|
||||
#include <gst/rtsp-server/rtsp-server.h>
|
||||
#include <gst/rtsp-server/rtsp-media-factory-uri.h>
|
||||
|
||||
#define DEFAULT_RTSP_PORT "8554"
|
||||
|
||||
static char *port = (char *) DEFAULT_RTSP_PORT;
|
||||
|
||||
static GOptionEntry entries[] = {
|
||||
{"port", 'p', 0, G_OPTION_ARG_STRING, &port,
|
||||
"Port to listen on (default: " DEFAULT_RTSP_PORT ")", "PORT"},
|
||||
{NULL}
|
||||
};
|
||||
|
||||
|
||||
static gboolean
|
||||
timeout (GstRTSPServer * server)
|
||||
{
|
||||
GstRTSPSessionPool *pool;
|
||||
|
||||
pool = gst_rtsp_server_get_session_pool (server);
|
||||
gst_rtsp_session_pool_cleanup (pool);
|
||||
g_object_unref (pool);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
#if 0
|
||||
static gboolean
|
||||
remove_map (GstRTSPServer * server)
|
||||
{
|
||||
GstRTSPMountPoints *mounts;
|
||||
|
||||
gst_validate_printf (NULL, "removing /test mount point\n");
|
||||
mounts = gst_rtsp_server_get_mount_points (server);
|
||||
gst_rtsp_mount_points_remove_factory (mounts, "/test");
|
||||
g_object_unref (mounts);
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
#endif
|
||||
|
||||
int
|
||||
main (int argc, gchar * argv[])
|
||||
{
|
||||
GMainLoop *loop;
|
||||
GstRTSPServer *server;
|
||||
GstRTSPMountPoints *mounts;
|
||||
GstRTSPMediaFactoryURI *factory;
|
||||
GOptionContext *optctx;
|
||||
GError *error = NULL;
|
||||
gchar *uri;
|
||||
|
||||
optctx = g_option_context_new ("<uri> - GstValidate RTSP server, URI");
|
||||
g_option_context_add_main_entries (optctx, entries, NULL);
|
||||
g_option_context_add_group (optctx, gst_init_get_option_group ());
|
||||
if (!g_option_context_parse (optctx, &argc, &argv, &error)) {
|
||||
g_printerr ("Error parsing options: %s\n", error->message);
|
||||
g_option_context_free (optctx);
|
||||
g_clear_error (&error);
|
||||
return -1;
|
||||
}
|
||||
g_option_context_free (optctx);
|
||||
|
||||
if (argc < 2) {
|
||||
g_printerr ("Please pass an URI or file as argument!\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
loop = g_main_loop_new (NULL, FALSE);
|
||||
|
||||
/* create a server instance */
|
||||
server = gst_rtsp_server_new ();
|
||||
g_object_set (server, "service", port, NULL);
|
||||
|
||||
/* get the mount points for this server, every server has a default object
|
||||
* that be used to map uri mount points to media factories */
|
||||
mounts = gst_rtsp_server_get_mount_points (server);
|
||||
|
||||
/* make a URI media factory for a test stream. */
|
||||
factory = gst_rtsp_media_factory_uri_new ();
|
||||
|
||||
/* when using GStreamer as a client, one can use the gst payloader, which is
|
||||
* more efficient when there is no payloader for the compressed format */
|
||||
/* g_object_set (factory, "use-gstpay", TRUE, NULL); */
|
||||
|
||||
/* check if URI is valid, otherwise convert filename to URI if it's a file */
|
||||
if (gst_uri_is_valid (argv[1])) {
|
||||
uri = g_strdup (argv[1]);
|
||||
} else if (g_file_test (argv[1], G_FILE_TEST_EXISTS)) {
|
||||
uri = gst_filename_to_uri (argv[1], NULL);
|
||||
} else {
|
||||
g_printerr ("Unrecognised command line argument '%s'.\n"
|
||||
"Please pass an URI or file as argument!\n", argv[1]);
|
||||
return -1;
|
||||
}
|
||||
|
||||
gst_rtsp_media_factory_uri_set_uri (factory, uri);
|
||||
g_free (uri);
|
||||
|
||||
/* if you want multiple clients to see the same video, set the shared property
|
||||
* to TRUE */
|
||||
/* gst_rtsp_media_factory_set_shared ( GST_RTSP_MEDIA_FACTORY (factory), TRUE); */
|
||||
|
||||
/* attach the test factory to the /test url */
|
||||
gst_rtsp_mount_points_add_factory (mounts, "/test",
|
||||
GST_RTSP_MEDIA_FACTORY (factory));
|
||||
|
||||
/* don't need the ref to the mapper anymore */
|
||||
g_object_unref (mounts);
|
||||
|
||||
/* attach the server to the default maincontext */
|
||||
if (gst_rtsp_server_attach (server, NULL) == 0)
|
||||
goto failed;
|
||||
|
||||
/* do session cleanup every 2 seconds */
|
||||
g_timeout_add_seconds (2, (GSourceFunc) timeout, server);
|
||||
|
||||
#if 0
|
||||
/* remove the mount point after 10 seconds, new clients won't be able to use
|
||||
* the /test url anymore */
|
||||
g_timeout_add_seconds (10, (GSourceFunc) remove_map, server);
|
||||
#endif
|
||||
|
||||
/* start serving */
|
||||
g_print ("stream ready at rtsp://127.0.0.1:%s/test\n", port);
|
||||
g_main_loop_run (loop);
|
||||
|
||||
return 0;
|
||||
|
||||
/* ERRORS */
|
||||
failed:
|
||||
{
|
||||
g_print ("failed to attach the server\n");
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,389 @@
|
||||
/* GStreamer
|
||||
*
|
||||
* Copyright (C) 2013 Collabora Ltd.
|
||||
* Author: Thibault Saunier <thibault.saunier@collabora.com>
|
||||
*
|
||||
* gst-validate-transcoding.c - CLI tool to validate transcoding operations
|
||||
*
|
||||
* 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.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
|
||||
* 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 <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <locale.h> /* for LC_ALL */
|
||||
|
||||
#include <gst/gst.h>
|
||||
#include <gst/video/video.h>
|
||||
#include <gst/validate/gst-validate-utils.h>
|
||||
#include <gst/validate/validate.h>
|
||||
#include <gst/pbutils/encoding-profile.h>
|
||||
#include <gst/transcoder/gsttranscoder.h>
|
||||
|
||||
|
||||
#ifdef G_OS_UNIX
|
||||
#include <glib-unix.h>
|
||||
#endif
|
||||
|
||||
#include <gst/validate/gst-validate-scenario.h>
|
||||
#include <gst/validate/gst-validate-bin-monitor.h>
|
||||
|
||||
static gint ret = 0;
|
||||
static GstValidateMonitor *monitor = NULL;
|
||||
static GstValidateRunner *runner = NULL;
|
||||
static GstTranscoder *transcoder = NULL;
|
||||
static gboolean eos_on_shutdown = FALSE;
|
||||
|
||||
static gint
|
||||
finish_transcoding (GstElement * pipeline, gint ret)
|
||||
{
|
||||
int rep_err;
|
||||
|
||||
if (!runner) {
|
||||
ret = 1;
|
||||
goto done;
|
||||
}
|
||||
|
||||
rep_err = gst_validate_runner_exit (runner, TRUE);
|
||||
if (ret == 0)
|
||||
ret = rep_err;
|
||||
|
||||
gst_clear_object (&transcoder);
|
||||
gst_clear_object (&pipeline);
|
||||
gst_validate_reporter_purge_reports (GST_VALIDATE_REPORTER (monitor));
|
||||
g_object_unref (monitor);
|
||||
g_object_unref (runner);
|
||||
|
||||
gst_validate_deinit ();
|
||||
gst_deinit ();
|
||||
|
||||
done:
|
||||
g_print ("\n=======> Test %s (Return value: %i)\n\n",
|
||||
ret == 0 ? "PASSED" : "FAILED", ret);
|
||||
|
||||
exit (ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
#ifdef G_OS_UNIX
|
||||
static gboolean
|
||||
intr_handler (GstElement * pipeline)
|
||||
{
|
||||
GST_DEBUG_BIN_TO_DOT_FILE_WITH_TS (GST_BIN (pipeline),
|
||||
GST_DEBUG_GRAPH_SHOW_ALL, "gst-validate.interrupted");
|
||||
|
||||
if (eos_on_shutdown) {
|
||||
eos_on_shutdown = FALSE;
|
||||
gst_element_send_event (pipeline, gst_event_new_eos ());
|
||||
return TRUE;
|
||||
|
||||
}
|
||||
|
||||
finish_transcoding (pipeline, 1);
|
||||
/* remove signal handler */
|
||||
return FALSE;
|
||||
}
|
||||
#endif /* G_OS_UNIX */
|
||||
|
||||
static gboolean
|
||||
_execute_set_restriction (GstValidateScenario * scenario,
|
||||
GstValidateAction * action)
|
||||
{
|
||||
GstCaps *caps;
|
||||
GType profile_type = G_TYPE_NONE;
|
||||
const gchar *restriction_caps, *profile_type_name, *profile_name;
|
||||
GstElement *pipeline = gst_validate_scenario_get_pipeline (scenario);
|
||||
GstEncodingProfile *encoding_profile;
|
||||
|
||||
g_object_get (pipeline, "profile", &encoding_profile, NULL);
|
||||
restriction_caps =
|
||||
gst_structure_get_string (action->structure, "restriction-caps");
|
||||
profile_type_name =
|
||||
gst_structure_get_string (action->structure, "profile-type");
|
||||
profile_name = gst_structure_get_string (action->structure, "profile-name");
|
||||
|
||||
if (profile_type_name) {
|
||||
profile_type = g_type_from_name (profile_type_name);
|
||||
|
||||
if (profile_type == G_TYPE_NONE) {
|
||||
gst_validate_abort ("Profile name %s not known", profile_name);
|
||||
|
||||
return FALSE;
|
||||
} else if (profile_type == GST_TYPE_ENCODING_CONTAINER_PROFILE) {
|
||||
gst_validate_abort ("Can not set restrictions on container profiles");
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
} else if (profile_name == NULL) {
|
||||
if (g_strrstr (restriction_caps, "audio/x-raw") == restriction_caps)
|
||||
profile_type = GST_TYPE_ENCODING_AUDIO_PROFILE;
|
||||
else if (g_strrstr (restriction_caps, "video/x-raw") == restriction_caps)
|
||||
profile_type = GST_TYPE_ENCODING_VIDEO_PROFILE;
|
||||
else {
|
||||
g_error
|
||||
("No information on what profiles to apply action, you should set either "
|
||||
"profile_name or profile_type_name and the caps %s give us no hint",
|
||||
restriction_caps);
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
caps = gst_caps_from_string (restriction_caps);
|
||||
if (caps == NULL) {
|
||||
gst_validate_abort ("Could not parse caps: %s", restriction_caps);
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
if (GST_IS_ENCODING_CONTAINER_PROFILE (encoding_profile)) {
|
||||
gboolean found = FALSE;
|
||||
const GList *tmp;
|
||||
|
||||
for (tmp =
|
||||
gst_encoding_container_profile_get_profiles
|
||||
(GST_ENCODING_CONTAINER_PROFILE (encoding_profile)); tmp;
|
||||
tmp = tmp->next) {
|
||||
GstEncodingProfile *profile = tmp->data;
|
||||
|
||||
if (profile_type != G_TYPE_NONE
|
||||
&& G_OBJECT_TYPE (profile) == profile_type) {
|
||||
gst_encoding_profile_set_restriction (profile, gst_caps_copy (caps));
|
||||
found = TRUE;
|
||||
} else if (profile_name
|
||||
&& g_strcmp0 (gst_encoding_profile_get_name (profile),
|
||||
profile_name) == 0) {
|
||||
gst_encoding_profile_set_restriction (profile, gst_caps_copy (caps));
|
||||
found = TRUE;
|
||||
}
|
||||
}
|
||||
|
||||
if (!found) {
|
||||
gst_validate_abort ("Could not find profile for %s%s",
|
||||
profile_type_name ? profile_type_name : "",
|
||||
profile_name ? profile_name : "");
|
||||
|
||||
gst_caps_unref (caps);
|
||||
return FALSE;
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
if (profile_type != G_TYPE_NONE) {
|
||||
gst_validate_printf (action,
|
||||
"setting caps to %s on profiles of type %s\n",
|
||||
restriction_caps, g_type_name (profile_type));
|
||||
} else {
|
||||
gst_validate_printf (action, "setting caps to %s on profile %s\n",
|
||||
restriction_caps, profile_name);
|
||||
|
||||
}
|
||||
|
||||
gst_caps_unref (caps);
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static void
|
||||
_register_actions (void)
|
||||
{
|
||||
/* *INDENT-OFF* */
|
||||
gst_validate_register_action_type ("set-restriction", "validate-transcoding", _execute_set_restriction,
|
||||
(GstValidateActionParameter []) {
|
||||
{
|
||||
.name = "restriction-caps",
|
||||
.description = "The restriction caps to set on the encodebin "
|
||||
"encoding profile.\nSee gst_encoding_profile_set_restriction()",
|
||||
.mandatory = TRUE,
|
||||
.types = "GstCaps serialized as a string"
|
||||
},
|
||||
{NULL}
|
||||
},
|
||||
"Change the restriction caps on the fly",
|
||||
FALSE);
|
||||
|
||||
/* *INDENT-ON* */
|
||||
}
|
||||
|
||||
int
|
||||
main (int argc, gchar ** argv)
|
||||
{
|
||||
guint i;
|
||||
GOptionContext *ctx;
|
||||
gchar *output_file = NULL;
|
||||
|
||||
const gchar *profile_str;
|
||||
|
||||
GError *err = NULL;
|
||||
gchar *scenario = NULL, *configs = NULL;
|
||||
gboolean want_help = FALSE;
|
||||
gboolean list_scenarios = FALSE, inspect_action_type = FALSE;
|
||||
GstElement *pipeline = NULL;
|
||||
gboolean force_reencoding = TRUE;
|
||||
|
||||
GOptionEntry options[] = {
|
||||
{"output-format", 'o', 0, G_OPTION_ARG_STRING, &profile_str,
|
||||
"Set the properties to use for the encoding profile "
|
||||
"(in case of transcoding.) For example:\n"
|
||||
"video/mpegts:video/x-raw-yuv,width=1920,height=1080->video/x-h264:audio/x-ac3\n"
|
||||
"A preset name can be used by adding +presetname, eg:\n"
|
||||
"video/webm:video/x-vp8+mypreset:audio/x-vorbis\n"
|
||||
"The presence property of the profile can be specified with |<presence>, eg:\n"
|
||||
"video/webm:video/x-vp8|<presence>:audio/x-vorbis\n",
|
||||
"properties-values"},
|
||||
{"set-scenario", '\0', 0, G_OPTION_ARG_FILENAME, &scenario,
|
||||
"Let you set a scenario, it can be a full path to a scenario file"
|
||||
" or the name of the scenario (name of the file without the"
|
||||
" '.scenario' extension).", NULL},
|
||||
{"set-configs", '\0', 0, G_OPTION_ARG_STRING, &configs,
|
||||
"Select a config scenario (one including 'is-config=true' in its"
|
||||
" description). Specify multiple ones using ':' as separator."
|
||||
" This option overrides the GST_VALIDATE_SCENARIO environment variable.",
|
||||
NULL},
|
||||
{"list-scenarios", 'l', 0, G_OPTION_ARG_NONE, &list_scenarios,
|
||||
"List the available scenarios that can be run", NULL},
|
||||
{"inspect-action-type", 't', 0, G_OPTION_ARG_NONE, &inspect_action_type,
|
||||
"Inspect the available action types with which to write scenarios"
|
||||
" if no parameter passed, it will list all available action types"
|
||||
" otherwise will print the full description of the wanted types",
|
||||
NULL},
|
||||
{"scenarios-defs-output-file", '\0', 0, G_OPTION_ARG_FILENAME,
|
||||
&output_file, "The output file to store scenarios details. "
|
||||
"Implies --list-scenarios",
|
||||
NULL},
|
||||
{"force-reencoding", 'r', 0, G_OPTION_ARG_NONE, &force_reencoding,
|
||||
"Whether to try to force reencoding, meaning trying to only remux "
|
||||
"if possible(default: TRUE)", NULL},
|
||||
{"eos-on-shutdown", 'e', 0, G_OPTION_ARG_NONE, &eos_on_shutdown,
|
||||
"If an EOS event should be sent to the pipeline if an interrupt is "
|
||||
"received, instead of forcing the pipeline to stop. Sending an EOS "
|
||||
"will allow the transcoding to finish the files properly before "
|
||||
"exiting.", NULL},
|
||||
{NULL}
|
||||
};
|
||||
|
||||
setlocale (LC_ALL, "");
|
||||
/* There is a bug that make gst_init remove the help param when initializing,
|
||||
* it is FIXED in 1.0 */
|
||||
for (i = 1; i < argc; i++) {
|
||||
if (!g_strcmp0 (argv[i], "--help") || !g_strcmp0 (argv[i], "-h"))
|
||||
want_help = TRUE;
|
||||
}
|
||||
|
||||
if (!want_help)
|
||||
gst_init (&argc, &argv);
|
||||
|
||||
g_set_prgname ("gst-validate-transcoding-" GST_API_VERSION);
|
||||
ctx = g_option_context_new ("[input-uri] [output-uri]");
|
||||
g_option_context_set_summary (ctx, "Transcodes input-uri to output-uri, "
|
||||
"using the given encoding profile. The pipeline will be monitored for "
|
||||
"possible issues detection using the gst-validate lib."
|
||||
"\nCan also perform file conformance "
|
||||
"tests after transcoding to make sure the result is correct");
|
||||
g_option_context_add_main_entries (ctx, options, NULL);
|
||||
if (want_help) {
|
||||
g_option_context_add_group (ctx, gst_init_get_option_group ());
|
||||
}
|
||||
|
||||
if (!g_option_context_parse (ctx, &argc, &argv, &err)) {
|
||||
g_printerr ("Error initializing: %s\n", err->message);
|
||||
g_option_context_free (ctx);
|
||||
g_clear_error (&err);
|
||||
exit (1);
|
||||
}
|
||||
|
||||
g_option_context_free (ctx);
|
||||
|
||||
if (want_help)
|
||||
exit (0);
|
||||
|
||||
if (scenario || configs) {
|
||||
gchar *scenarios;
|
||||
|
||||
if (scenario)
|
||||
scenarios = g_strjoin (":", scenario, configs, NULL);
|
||||
else
|
||||
scenarios = g_strdup (configs);
|
||||
|
||||
g_setenv ("GST_VALIDATE_SCENARIO", scenarios, TRUE);
|
||||
g_free (scenarios);
|
||||
}
|
||||
|
||||
gst_validate_init ();
|
||||
|
||||
if (list_scenarios || output_file) {
|
||||
if (gst_validate_list_scenarios (argv + 1, argc - 1, output_file))
|
||||
return 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
_register_actions ();
|
||||
|
||||
if (inspect_action_type) {
|
||||
if (gst_validate_print_action_types ((const gchar **) argv + 1, argc - 1))
|
||||
return 0;
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (argc != 3) {
|
||||
g_printerr ("%i arguments received, 2 expected.\n"
|
||||
"You should run the test using:\n"
|
||||
" ./gst-validate-transcoding-1.0 <input-uri> <output-uri> [options]\n",
|
||||
argc - 1);
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (profile_str == NULL) {
|
||||
GST_INFO ("Creating default encoding profile");
|
||||
|
||||
profile_str = "application/ogg:video/x-theora:audio/x-vorbis";
|
||||
}
|
||||
|
||||
transcoder = gst_transcoder_new (argv[1], argv[2], profile_str);
|
||||
gst_transcoder_set_avoid_reencoding (transcoder, !force_reencoding);
|
||||
|
||||
/* Create the pipeline */
|
||||
runner = gst_validate_runner_new ();
|
||||
|
||||
pipeline = gst_transcoder_get_pipeline (transcoder);
|
||||
#ifdef G_OS_UNIX
|
||||
g_unix_signal_add (SIGINT, (GSourceFunc) intr_handler, pipeline);
|
||||
#endif
|
||||
|
||||
gst_validate_spin_on_fault_signals ();
|
||||
|
||||
monitor =
|
||||
gst_validate_monitor_factory_create (GST_OBJECT_CAST (pipeline), runner,
|
||||
NULL);
|
||||
gst_validate_reporter_set_handle_g_logs (GST_VALIDATE_REPORTER (monitor));
|
||||
|
||||
if (!runner) {
|
||||
gst_object_unref (pipeline);
|
||||
gst_object_unref (transcoder);
|
||||
g_printerr ("Failed to setup Validate Runner\n");
|
||||
exit (1);
|
||||
}
|
||||
|
||||
if (!gst_transcoder_run (transcoder, &err)) {
|
||||
ret = -1;
|
||||
GST_ERROR ("\nFAILURE: %s", err->message);
|
||||
}
|
||||
|
||||
return finish_transcoding (pipeline, ret);
|
||||
}
|
||||
@@ -0,0 +1,631 @@
|
||||
/* GStreamer
|
||||
*
|
||||
* Copyright (C) 2013 Collabora Ltd.
|
||||
* Author: Thiago Sousa Santos <thiago.sousa.santos@collabora.com>
|
||||
*
|
||||
* gst-validate.c - Validate CLI launch line tool
|
||||
*
|
||||
* 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.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
|
||||
* 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 <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include <gst/gst.h>
|
||||
#include <gio/gio.h>
|
||||
#include <gst/validate/validate.h>
|
||||
#include <gst/validate/gst-validate-scenario.h>
|
||||
#include <gst/validate/gst-validate-utils.h>
|
||||
#include <gst/validate/media-descriptor-parser.h>
|
||||
#include <gst/validate/gst-validate-bin-monitor.h>
|
||||
#include <gst/validate/gst-validate-pipeline-monitor.h>
|
||||
|
||||
#ifdef G_OS_UNIX
|
||||
#include <glib-unix.h>
|
||||
#endif
|
||||
#include <locale.h> /* for LC_ALL */
|
||||
|
||||
static gint ret = 0;
|
||||
static GMainLoop *mainloop;
|
||||
static GstElement *pipeline;
|
||||
static gboolean is_testfile;
|
||||
static gboolean buffering = FALSE;
|
||||
|
||||
static gboolean is_live = FALSE;
|
||||
|
||||
#ifdef G_OS_UNIX
|
||||
static gboolean
|
||||
intr_handler (gpointer user_data)
|
||||
{
|
||||
gst_validate_printf (NULL, "interrupt received.\n");
|
||||
|
||||
GST_DEBUG_BIN_TO_DOT_FILE_WITH_TS (GST_BIN (pipeline),
|
||||
GST_DEBUG_GRAPH_SHOW_ALL, "gst-validate.interrupted");
|
||||
|
||||
g_main_loop_quit (mainloop);
|
||||
|
||||
ret = SIGINT;
|
||||
|
||||
/* Keep signal handler, it will be removed later anyway */
|
||||
return TRUE;
|
||||
}
|
||||
#endif /* G_OS_UNIX */
|
||||
|
||||
typedef struct
|
||||
{
|
||||
GMainLoop *mainloop;
|
||||
GstValidateMonitor *monitor;
|
||||
} BusCallbackData;
|
||||
|
||||
static gboolean
|
||||
bus_callback (GstBus * bus, GstMessage * message, gpointer data)
|
||||
{
|
||||
BusCallbackData *bus_callback_data = data;
|
||||
GMainLoop *loop = bus_callback_data->mainloop;
|
||||
GstValidateMonitor *monitor = bus_callback_data->monitor;
|
||||
|
||||
switch (GST_MESSAGE_TYPE (message)) {
|
||||
case GST_MESSAGE_ERROR:
|
||||
{
|
||||
GST_DEBUG_BIN_TO_DOT_FILE_WITH_TS (GST_BIN (pipeline),
|
||||
GST_DEBUG_GRAPH_SHOW_ALL, "gst-validate.error");
|
||||
|
||||
g_main_loop_quit (loop);
|
||||
break;
|
||||
}
|
||||
case GST_MESSAGE_EOS:
|
||||
if (!g_getenv ("GST_VALIDATE_SCENARIO") && !is_testfile)
|
||||
g_main_loop_quit (loop);
|
||||
break;
|
||||
case GST_MESSAGE_ASYNC_DONE:
|
||||
break;
|
||||
case GST_MESSAGE_LATENCY:
|
||||
gst_bin_recalculate_latency (GST_BIN (pipeline));
|
||||
break;
|
||||
case GST_MESSAGE_STATE_CHANGED:
|
||||
if (GST_MESSAGE_SRC (message) == GST_OBJECT (pipeline)) {
|
||||
GstState oldstate, newstate, pending;
|
||||
gchar *dump_name;
|
||||
gchar *state_transition_name;
|
||||
|
||||
gst_message_parse_state_changed (message, &oldstate, &newstate,
|
||||
&pending);
|
||||
|
||||
GST_DEBUG ("State changed (old: %s, new: %s, pending: %s)",
|
||||
gst_element_state_get_name (oldstate),
|
||||
gst_element_state_get_name (newstate),
|
||||
gst_element_state_get_name (pending));
|
||||
|
||||
state_transition_name = g_strdup_printf ("%s_%s",
|
||||
gst_element_state_get_name (oldstate),
|
||||
gst_element_state_get_name (newstate));
|
||||
dump_name = g_strconcat ("gst-validate.", state_transition_name, NULL);
|
||||
|
||||
|
||||
GST_DEBUG_BIN_TO_DOT_FILE_WITH_TS (GST_BIN (pipeline),
|
||||
GST_DEBUG_GRAPH_SHOW_ALL, dump_name);
|
||||
|
||||
g_free (dump_name);
|
||||
g_free (state_transition_name);
|
||||
}
|
||||
|
||||
break;
|
||||
case GST_MESSAGE_WARNING:{
|
||||
GError *gerror;
|
||||
gchar *debug;
|
||||
gchar *name = gst_object_get_path_string (GST_MESSAGE_SRC (message));
|
||||
|
||||
/* dump graph on warning */
|
||||
GST_DEBUG_BIN_TO_DOT_FILE_WITH_TS (GST_BIN (pipeline),
|
||||
GST_DEBUG_GRAPH_SHOW_ALL, "gst-validate.warning");
|
||||
|
||||
gst_message_parse_warning (message, &gerror, &debug);
|
||||
gst_validate_printf (NULL, "WARNING: from element %s: %s\n", name,
|
||||
gerror->message);
|
||||
if (debug)
|
||||
gst_validate_printf (NULL, "Additional debug info:\n%s\n", debug);
|
||||
|
||||
g_clear_error (&gerror);
|
||||
g_free (debug);
|
||||
g_free (name);
|
||||
break;
|
||||
}
|
||||
case GST_MESSAGE_BUFFERING:{
|
||||
gint percent;
|
||||
GstBufferingMode mode;
|
||||
GstState target_state = GST_STATE_PLAYING;
|
||||
gboolean monitor_handles_state;
|
||||
|
||||
g_object_get (monitor, "handles-states", &monitor_handles_state, NULL);
|
||||
if (monitor_handles_state && GST_IS_VALIDATE_BIN_MONITOR (monitor)) {
|
||||
target_state =
|
||||
gst_validate_scenario_get_target_state (GST_VALIDATE_BIN_MONITOR
|
||||
(monitor)->scenario);
|
||||
}
|
||||
|
||||
if (!buffering) {
|
||||
gst_validate_printf (NULL, "\n");
|
||||
}
|
||||
|
||||
gst_message_parse_buffering (message, &percent);
|
||||
gst_message_parse_buffering_stats (message, &mode, NULL, NULL, NULL);
|
||||
|
||||
/* no state management needed for live pipelines */
|
||||
if (mode == GST_BUFFERING_LIVE) {
|
||||
is_live = TRUE;
|
||||
break;
|
||||
}
|
||||
|
||||
if (percent == 100) {
|
||||
/* a 100% message means buffering is done */
|
||||
if (buffering) {
|
||||
buffering = FALSE;
|
||||
|
||||
if (target_state == GST_STATE_PLAYING) {
|
||||
gst_element_set_state (pipeline, GST_STATE_PLAYING);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
/* buffering... */
|
||||
if (!buffering) {
|
||||
gst_element_set_state (pipeline, GST_STATE_PAUSED);
|
||||
buffering = TRUE;
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
case GST_MESSAGE_REQUEST_STATE:
|
||||
{
|
||||
GstState state;
|
||||
|
||||
gst_message_parse_request_state (message, &state);
|
||||
|
||||
if (GST_IS_VALIDATE_SCENARIO (GST_MESSAGE_SRC (message))
|
||||
&& state == GST_STATE_NULL) {
|
||||
gst_validate_printf (GST_MESSAGE_SRC (message),
|
||||
"State change request NULL, quitting mainloop\n");
|
||||
g_main_loop_quit (mainloop);
|
||||
}
|
||||
break;
|
||||
}
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
_is_playbin_pipeline (int argc, gchar ** argv)
|
||||
{
|
||||
gint i;
|
||||
|
||||
for (i = 0; i < argc; i++) {
|
||||
if (g_ascii_strncasecmp (argv[i], "playbin", 7) == 0) {
|
||||
return TRUE;
|
||||
}
|
||||
}
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
_execute_set_subtitles (GstValidateScenario * scenario,
|
||||
GstValidateAction * action)
|
||||
{
|
||||
gchar *uri, *fname;
|
||||
GFile *tmpfile, *folder;
|
||||
const gchar *subtitle_file, *subtitle_dir;
|
||||
GstElement *pipeline = gst_validate_scenario_get_pipeline (scenario);
|
||||
|
||||
if (pipeline == NULL) {
|
||||
GST_VALIDATE_REPORT (scenario, SCENARIO_ACTION_EXECUTION_ERROR,
|
||||
"Can't execute a '%s' action after the pipeline "
|
||||
"has been destroyed.", action->type);
|
||||
return GST_VALIDATE_EXECUTE_ACTION_ERROR_REPORTED;
|
||||
}
|
||||
|
||||
subtitle_file = gst_structure_get_string (action->structure, "subtitle-file");
|
||||
if (subtitle_file == NULL) {
|
||||
GST_VALIDATE_REPORT (scenario, SCENARIO_ACTION_EXECUTION_ERROR,
|
||||
"No 'subtitle-file' specified in 'set-subtile'");
|
||||
gst_object_unref (pipeline);
|
||||
|
||||
return GST_VALIDATE_EXECUTE_ACTION_ERROR;
|
||||
}
|
||||
|
||||
subtitle_dir = gst_structure_get_string (action->structure, "subtitle-dir");
|
||||
g_object_get (pipeline, "current-uri", &uri, NULL);
|
||||
tmpfile = g_file_new_for_uri (uri);
|
||||
g_free (uri);
|
||||
|
||||
folder = g_file_get_parent (tmpfile);
|
||||
|
||||
fname = g_strdup_printf ("%s%s%s%s",
|
||||
subtitle_dir ? subtitle_dir : "",
|
||||
subtitle_dir ? G_DIR_SEPARATOR_S : "",
|
||||
g_file_get_basename (tmpfile), subtitle_file);
|
||||
gst_object_unref (tmpfile);
|
||||
|
||||
tmpfile = g_file_get_child (folder, fname);
|
||||
g_free (fname);
|
||||
gst_object_unref (folder);
|
||||
|
||||
uri = g_file_get_uri (tmpfile);
|
||||
gst_validate_printf (action, "Setting subtitle file to: %s", uri);
|
||||
g_object_set (pipeline, "suburi", uri, NULL);
|
||||
g_free (uri);
|
||||
gst_object_unref (pipeline);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static void
|
||||
_register_playbin_actions (void)
|
||||
{
|
||||
/* *INDENT-OFF* */
|
||||
gst_validate_register_action_type ("set-subtitle", "validate-launcher", _execute_set_subtitles,
|
||||
(GstValidateActionParameter []) {
|
||||
{
|
||||
.name = "subtitle-file",
|
||||
.description = "Sets a subtitles file on a playbin pipeline",
|
||||
.mandatory = TRUE,
|
||||
.types = "string (A URI)",
|
||||
NULL
|
||||
},
|
||||
{NULL}
|
||||
},
|
||||
"Action to set a subtitle file to use on a playbin pipeline.\n"
|
||||
"The subtitles file that will be used should be specified\n"
|
||||
"relative to the playbin URI in use thanks to the subtitle-file\n"
|
||||
"action property. You can also specify a folder with subtitle-dir\n"
|
||||
"For example if playbin.uri='file://some/uri.mov'\n"
|
||||
"and action looks like 'set-subtitle, subtitle-file=en.srt'\n"
|
||||
"the subtitle URI will be set to 'file:///some/uri.mov.en.srt'\n",
|
||||
FALSE);
|
||||
/* *INDENT-ON* */
|
||||
}
|
||||
|
||||
int main (int argc, gchar ** argv);
|
||||
|
||||
static int
|
||||
run_test_from_file (gchar * testfile, gboolean use_fakesinks)
|
||||
{
|
||||
gint argc, ret;
|
||||
gchar **args, **argv;
|
||||
GstStructure *meta = gst_validate_setup_test_file (testfile, use_fakesinks);
|
||||
|
||||
args = gst_validate_utils_get_strv (meta, "args");
|
||||
if (!args)
|
||||
gst_validate_abort ("No 'args' in .validatetest meta structure: %s",
|
||||
gst_structure_to_string (meta));
|
||||
|
||||
for (argc = 0; args[argc]; argc++);
|
||||
argc++;
|
||||
|
||||
argv = g_new0 (char *, argc + 1);
|
||||
argv[0] = (gchar *) "gst-validate-" GST_API_VERSION;
|
||||
memcpy (&argv[1], args, sizeof (char *) * (argc));
|
||||
|
||||
ret = main (argc, argv);
|
||||
|
||||
g_strfreev (args);
|
||||
g_free (argv);
|
||||
g_free (testfile);
|
||||
return ret;
|
||||
}
|
||||
|
||||
int
|
||||
main (int argc, gchar ** argv)
|
||||
{
|
||||
GError *err = NULL;
|
||||
gchar *scenario = NULL, *configs = NULL, *media_info = NULL,
|
||||
*verbosity = NULL, *testfile = NULL;
|
||||
gboolean list_scenarios = FALSE, monitor_handles_state,
|
||||
inspect_action_type = FALSE, print_issue_types = FALSE;
|
||||
GstStateChangeReturn sret;
|
||||
gchar *output_file = NULL;
|
||||
BusCallbackData bus_callback_data = { 0, };
|
||||
gboolean use_fakesinks = FALSE;
|
||||
|
||||
#ifdef G_OS_UNIX
|
||||
guint signal_watch_id;
|
||||
#endif
|
||||
int rep_err;
|
||||
|
||||
GOptionEntry options[] = {
|
||||
{"set-test-file", '\0', 0, G_OPTION_ARG_FILENAME, &testfile,
|
||||
"Let you set a all container testfile", NULL},
|
||||
{"set-scenario", '\0', 0, G_OPTION_ARG_FILENAME, &scenario,
|
||||
"Let you set a scenario, it can be a full path to a scenario file"
|
||||
" or the name of the scenario (name of the file without the"
|
||||
" '.scenario' extension).", NULL},
|
||||
{"list-scenarios", 'l', 0, G_OPTION_ARG_NONE, &list_scenarios,
|
||||
"List the available scenarios that can be run", NULL},
|
||||
{"use-fakesinks", 'm', 0, G_OPTION_ARG_NONE, &use_fakesinks,
|
||||
"Use fakesinks when possible. This will have effect when using"
|
||||
" test files.", NULL},
|
||||
{"verbosity", 'v', 0, G_OPTION_ARG_STRING, &verbosity,
|
||||
"Set overall verbosity as defined by GstValidateVerbosityFlags"
|
||||
" as a string", NULL},
|
||||
{"scenarios-defs-output-file", '\0', 0, G_OPTION_ARG_FILENAME,
|
||||
&output_file, "The output file to store scenarios details. "
|
||||
"Implies --list-scenarios",
|
||||
NULL},
|
||||
{"inspect-action-type", 't', 0, G_OPTION_ARG_NONE, &inspect_action_type,
|
||||
"Inspect the available action types with which to write scenarios."
|
||||
" Specify an action type if you want its full description."
|
||||
" If no action type is given the full list of available ones gets printed."
|
||||
"Note that passing \"all\" as action type name, makes it output the"
|
||||
" full documentation for all types.",
|
||||
NULL},
|
||||
{"print-issue-types", '\0', 0, G_OPTION_ARG_NONE, &print_issue_types,
|
||||
"List all known issue types and their descriptions.",
|
||||
NULL},
|
||||
{"set-media-info", '\0', 0, G_OPTION_ARG_FILENAME, &media_info,
|
||||
"Set a media_info XML file descriptor to share information about the"
|
||||
" media file that will be reproduced.",
|
||||
NULL},
|
||||
{"set-configs", '\0', 0, G_OPTION_ARG_STRING, &configs,
|
||||
"Select a config scenario (one including 'is-config=true' in its"
|
||||
" description). Specify multiple ones using ':' as separator."
|
||||
" This option overrides the GST_VALIDATE_SCENARIO environment variable.",
|
||||
NULL},
|
||||
{NULL}
|
||||
};
|
||||
GOptionContext *ctx;
|
||||
gchar **argvn;
|
||||
GstValidateRunner *runner;
|
||||
GstValidateMonitor *monitor;
|
||||
GstBus *bus;
|
||||
|
||||
setlocale (LC_ALL, "");
|
||||
|
||||
g_set_prgname ("gst-validate-" GST_API_VERSION);
|
||||
ctx = g_option_context_new ("PIPELINE-DESCRIPTION");
|
||||
g_option_context_add_main_entries (ctx, options, NULL);
|
||||
g_option_context_set_summary (ctx, "Runs a gst launch pipeline, adding "
|
||||
"monitors to it to identify issues in the used elements. At the end"
|
||||
" a report will be printed. To view issues as they are created, set"
|
||||
" the env var GST_DEBUG=validate:2 and it will be printed "
|
||||
"as gstreamer debugging");
|
||||
|
||||
if (argc == 1) {
|
||||
g_print ("%s", g_option_context_get_help (ctx, FALSE, NULL));
|
||||
exit (1);
|
||||
}
|
||||
|
||||
if (!g_option_context_parse (ctx, &argc, &argv, &err)) {
|
||||
g_printerr ("Error initializing: %s\n", err->message);
|
||||
g_option_context_free (ctx);
|
||||
g_clear_error (&err);
|
||||
exit (1);
|
||||
}
|
||||
|
||||
gst_init (&argc, &argv);
|
||||
gst_validate_init_debug ();
|
||||
if (testfile) {
|
||||
is_testfile = TRUE;
|
||||
if (scenario)
|
||||
gst_validate_abort
|
||||
("Can not specify scenario and testfile at the same time");
|
||||
g_option_context_free (ctx);
|
||||
return run_test_from_file (testfile, use_fakesinks);
|
||||
}
|
||||
|
||||
if (scenario || configs) {
|
||||
gchar *scenarios;
|
||||
|
||||
if (scenario)
|
||||
scenarios = g_strjoin (":", scenario, configs, NULL);
|
||||
else
|
||||
scenarios = g_strdup (configs);
|
||||
|
||||
g_setenv ("GST_VALIDATE_SCENARIO", scenarios, TRUE);
|
||||
g_free (scenarios);
|
||||
g_free (scenario);
|
||||
g_free (configs);
|
||||
}
|
||||
|
||||
gst_validate_init ();
|
||||
|
||||
if (list_scenarios || output_file) {
|
||||
g_option_context_free (ctx);
|
||||
if (gst_validate_list_scenarios (argv + 1, argc - 1, output_file))
|
||||
return 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (inspect_action_type) {
|
||||
_register_playbin_actions ();
|
||||
|
||||
if (!gst_validate_print_action_types ((const gchar **) argv + 1, argc - 1)) {
|
||||
GST_ERROR ("Could not print all wanted types");
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (print_issue_types) {
|
||||
gst_validate_print_issues ();
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (argc == 1) {
|
||||
gst_validate_printf (NULL, "%s", g_option_context_get_help (ctx, FALSE,
|
||||
NULL));
|
||||
g_option_context_free (ctx);
|
||||
exit (1);
|
||||
}
|
||||
|
||||
g_option_context_free (ctx);
|
||||
|
||||
runner = gst_validate_runner_new ();
|
||||
if (!runner) {
|
||||
g_printerr ("Failed to setup Validate Runner\n");
|
||||
exit (1);
|
||||
}
|
||||
|
||||
/* Create the pipeline */
|
||||
argvn = g_new0 (char *, argc);
|
||||
memcpy (argvn, argv + 1, sizeof (char *) * (argc - 1));
|
||||
if (argc == 2) {
|
||||
gst_validate_printf (NULL, "**-> Pipeline: '%s'**\n", argvn[0]);
|
||||
pipeline = (GstElement *) gst_parse_launch (argvn[0], &err);
|
||||
} else {
|
||||
pipeline = (GstElement *) gst_parse_launchv ((const gchar **) argvn, &err);
|
||||
}
|
||||
|
||||
if (!pipeline) {
|
||||
gst_validate_printf (NULL, "Failed to create pipeline: %s\n",
|
||||
err ? err->message : "unknown reason");
|
||||
g_clear_error (&err);
|
||||
g_object_unref (runner);
|
||||
|
||||
g_free (argvn);
|
||||
exit (1);
|
||||
} else if (err) {
|
||||
if (g_error_matches (err, GST_PARSE_ERROR, GST_PARSE_ERROR_NO_SUCH_ELEMENT)) {
|
||||
if (!gst_validate_fail_on_missing_plugin ())
|
||||
gst_validate_skip_test ("missing plugin: %s", err->message);
|
||||
}
|
||||
g_printerr ("Erroneous pipeline: %s\n",
|
||||
err->message ? err->message : "unknown reason");
|
||||
g_clear_error (&err);
|
||||
g_free (argvn);
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (!GST_IS_PIPELINE (pipeline)) {
|
||||
GstElement *new_pipeline = gst_pipeline_new ("");
|
||||
|
||||
gst_bin_add (GST_BIN (new_pipeline), pipeline);
|
||||
pipeline = new_pipeline;
|
||||
}
|
||||
|
||||
gst_pipeline_set_auto_flush_bus (GST_PIPELINE (pipeline), FALSE);
|
||||
#ifdef G_OS_UNIX
|
||||
signal_watch_id =
|
||||
g_unix_signal_add (SIGINT, (GSourceFunc) intr_handler, pipeline);
|
||||
#endif
|
||||
|
||||
gst_validate_spin_on_fault_signals ();
|
||||
|
||||
if (_is_playbin_pipeline (argc - 1, argv + 1)) {
|
||||
_register_playbin_actions ();
|
||||
}
|
||||
|
||||
monitor = gst_validate_monitor_factory_create (GST_OBJECT_CAST (pipeline),
|
||||
runner, NULL);
|
||||
if (verbosity)
|
||||
gst_util_set_object_arg (G_OBJECT (monitor), "verbosity", verbosity);
|
||||
gst_validate_reporter_set_handle_g_logs (GST_VALIDATE_REPORTER (monitor));
|
||||
|
||||
if (media_info) {
|
||||
GError *err = NULL;
|
||||
GstValidateMediaDescriptorParser *parser =
|
||||
gst_validate_media_descriptor_parser_new (runner,
|
||||
media_info, &err);
|
||||
|
||||
if (parser == NULL) {
|
||||
GST_ERROR ("Could not use %s as a media-info file (error: %s)",
|
||||
media_info, err ? err->message : "Unknown error");
|
||||
|
||||
g_free (media_info);
|
||||
exit (1);
|
||||
}
|
||||
|
||||
gst_validate_monitor_set_media_descriptor (monitor,
|
||||
GST_VALIDATE_MEDIA_DESCRIPTOR (parser));
|
||||
gst_object_unref (parser);
|
||||
g_free (media_info);
|
||||
}
|
||||
|
||||
mainloop = g_main_loop_new (NULL, FALSE);
|
||||
bus = gst_element_get_bus (pipeline);
|
||||
gst_bus_add_signal_watch (bus);
|
||||
bus_callback_data.mainloop = mainloop;
|
||||
bus_callback_data.monitor = monitor;
|
||||
g_signal_connect (bus, "message", (GCallback) bus_callback,
|
||||
&bus_callback_data);
|
||||
|
||||
gst_validate_printf (NULL, "**-> Starting pipeline**\n");
|
||||
g_free (argvn);
|
||||
g_object_get (monitor, "handles-states", &monitor_handles_state, NULL);
|
||||
if (monitor_handles_state == FALSE) {
|
||||
sret = gst_element_set_state (pipeline, GST_STATE_PLAYING);
|
||||
switch (sret) {
|
||||
case GST_STATE_CHANGE_FAILURE:
|
||||
/* ignore, we should get an error message posted on the bus */
|
||||
gst_validate_printf (NULL, "Pipeline failed to go to PLAYING state\n");
|
||||
gst_element_set_state (pipeline, GST_STATE_NULL);
|
||||
ret = -1;
|
||||
goto exit;
|
||||
case GST_STATE_CHANGE_NO_PREROLL:
|
||||
gst_validate_printf (NULL, "Pipeline is live.\n");
|
||||
is_live = TRUE;
|
||||
break;
|
||||
case GST_STATE_CHANGE_ASYNC:
|
||||
gst_validate_printf (NULL, "Prerolling...\r");
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
gst_validate_printf (NULL, "**-> Pipeline started**\n");
|
||||
} else {
|
||||
gst_validate_printf (NULL, "**-> Letting scenario handle set state**\n");
|
||||
}
|
||||
|
||||
g_main_loop_run (mainloop);
|
||||
gst_element_set_state (pipeline, GST_STATE_NULL);
|
||||
gst_element_get_state (pipeline, NULL, NULL, GST_CLOCK_TIME_NONE);
|
||||
|
||||
/* Clean the bus */
|
||||
gst_bus_set_flushing (bus, TRUE);
|
||||
gst_bus_remove_signal_watch (bus);
|
||||
gst_object_unref (bus);
|
||||
|
||||
rep_err = gst_validate_runner_exit (runner, TRUE);
|
||||
if (ret == 0) {
|
||||
ret = rep_err;
|
||||
if (rep_err != 0)
|
||||
gst_validate_printf (NULL, "Returning %d as errors were found\n",
|
||||
rep_err);
|
||||
}
|
||||
|
||||
exit:
|
||||
g_main_loop_unref (mainloop);
|
||||
g_object_unref (pipeline);
|
||||
g_object_unref (runner);
|
||||
gst_validate_reporter_purge_reports (GST_VALIDATE_REPORTER (monitor));
|
||||
g_object_unref (monitor);
|
||||
g_clear_error (&err);
|
||||
#ifdef G_OS_UNIX
|
||||
g_source_remove (signal_watch_id);
|
||||
#endif
|
||||
|
||||
gst_validate_printf (NULL, "\n=======> Test %s (Return value: %i)\n\n",
|
||||
ret == 0 ? "PASSED" : "FAILED", ret);
|
||||
|
||||
gst_validate_deinit ();
|
||||
gst_deinit ();
|
||||
return ret;
|
||||
}
|
||||
@@ -0,0 +1,67 @@
|
||||
executable('gst-validate-' + apiversion,
|
||||
'gst-validate.c',
|
||||
install: true,
|
||||
include_directories : inc_dirs,
|
||||
dependencies : validate_dep,
|
||||
c_args : [gst_c_args] + ['-DG_LOG_DOMAIN="gst-validate-@0@"'.format(apiversion)],
|
||||
)
|
||||
|
||||
gst_transcoder_dep = dependency('gstreamer-transcoder-' + apiversion, version : gst_req,
|
||||
fallback : ['gst-plugins-bad', 'gst_transcoder_dep'], required: false)
|
||||
|
||||
if gst_transcoder_dep.found()
|
||||
executable('gst-validate-transcoding-' + apiversion,
|
||||
'gst-validate-transcoding.c',
|
||||
install: true,
|
||||
include_directories : inc_dirs,
|
||||
dependencies : [validate_dep, gst_transcoder_dep],
|
||||
c_args : [gst_c_args] + ['-DG_LOG_DOMAIN="gst-validate-transcoding-@0@"'.format(apiversion)],
|
||||
)
|
||||
else
|
||||
warning('Can not build gst-validate-transcoding-' + apiversion)
|
||||
endif
|
||||
|
||||
executable('gst-validate-media-check-' + apiversion,
|
||||
'gst-validate-media-check.c',
|
||||
install: true,
|
||||
include_directories : inc_dirs,
|
||||
dependencies : validate_dep,
|
||||
c_args : [gst_c_args] + ['-DG_LOG_DOMAIN="gst-validate-media-check-@0@"'.format(apiversion)],
|
||||
)
|
||||
|
||||
rtsp_server_dep = dependency('gstreamer-rtsp-server-' + apiversion,
|
||||
fallback: ['gst-rtsp-server', 'gst_rtsp_server_dep'],
|
||||
version : gst_req,
|
||||
required: false)
|
||||
|
||||
if rtsp_server_dep.found()
|
||||
executable('gst-validate-rtsp-server-' + apiversion,
|
||||
'gst-validate-rtsp-server.c',
|
||||
install: true,
|
||||
include_directories: inc_dirs,
|
||||
dependencies : [rtsp_server_dep, validate_dep],
|
||||
c_args: [gst_c_args] + ['-DG_LOG_DOMAIN="gst-validate-rtsp-server-@0@"'.format(apiversion)],
|
||||
)
|
||||
endif
|
||||
|
||||
if validate_video_dep.found()
|
||||
executable('gst-validate-images-check-' + apiversion,
|
||||
'gst-validate-images-check.c',
|
||||
install: true,
|
||||
include_directories : inc_dirs,
|
||||
dependencies : [validate_dep, validate_video_dep],
|
||||
c_args : [gst_c_args] + ['-DG_LOG_DOMAIN="gst-validate-images-check-@0@"'.format(apiversion)]
|
||||
)
|
||||
endif
|
||||
|
||||
tmpconf = configuration_data()
|
||||
tmpconf.set('LIBDIR', join_paths(get_option('prefix'), get_option('libdir')))
|
||||
tmpconf.set('BUILDDIR', meson.current_build_dir())
|
||||
tmpconf.set('SRCDIR', meson.current_source_dir())
|
||||
|
||||
configure_file(input : 'gst-validate-launcher.in',
|
||||
install_dir: get_option('bindir'),
|
||||
output : 'gst-validate-launcher',
|
||||
configuration : tmpconf)
|
||||
|
||||
launcher = find_program(meson.current_build_dir() + '/gst-validate-launcher')
|
||||
Reference in New Issue
Block a user