mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer.git
synced 2024-11-22 01:31:03 +00:00
nle: Add validate tests support
This allows us to start testing internal of the elements by linking the nle pluging directly with validate and implement validate tests with specific action types. Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/5035>
This commit is contained in:
parent
a39ac67d70
commit
daa1519e3d
9 changed files with 356 additions and 4 deletions
|
@ -7,10 +7,18 @@ nle_sources = ['nleobject.c',
|
|||
'gstnle.c'
|
||||
]
|
||||
|
||||
deps = [gst_dep, gstbase_dep]
|
||||
c_args = ges_c_args
|
||||
if gstvalidate_dep.found()
|
||||
deps += [gstvalidate_dep]
|
||||
nle_sources += ['validate.c']
|
||||
endif
|
||||
|
||||
|
||||
nle = library('gstnle', nle_sources,
|
||||
dependencies : [gst_dep, gstbase_dep],
|
||||
dependencies : deps,
|
||||
include_directories: [configinc],
|
||||
c_args : ges_c_args,
|
||||
c_args : c_args,
|
||||
install : true,
|
||||
install_dir : plugins_install_dir,
|
||||
)
|
||||
|
|
|
@ -3729,3 +3729,105 @@ _nle_composition_remove_object (NleComposition * comp, NleObject * object)
|
|||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
|
||||
|
||||
GstElement *nle_composition_get_nle_object_by_name (NleComposition * comp,
|
||||
const gchar * name);
|
||||
|
||||
GstElement *
|
||||
nle_find_object_in_bin_recurse (GstBin * object, const gchar * name)
|
||||
{
|
||||
GstElement *res = gst_bin_get_by_name_recurse_up (GST_BIN (object), name);
|
||||
|
||||
if (res)
|
||||
return res;
|
||||
|
||||
GstIterator *it =
|
||||
gst_bin_iterate_all_by_element_factory_name (GST_BIN (object),
|
||||
"nlecomposition");
|
||||
GValue item = G_VALUE_INIT;
|
||||
|
||||
while (gst_iterator_next (it, &item) == GST_ITERATOR_OK) {
|
||||
GstElement *compo = g_value_get_object (&item);
|
||||
|
||||
if (NLE_IS_COMPOSITION (compo)) {
|
||||
res =
|
||||
nle_composition_get_nle_object_by_name (NLE_COMPOSITION (compo),
|
||||
name);
|
||||
|
||||
if (res) {
|
||||
g_value_reset (&item);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
g_value_reset (&item);
|
||||
}
|
||||
gst_iterator_free (it);
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
GstElement *
|
||||
nle_composition_get_nle_object_by_name (NleComposition * comp,
|
||||
const gchar * name)
|
||||
{
|
||||
NleCompositionPrivate *priv = comp->priv;
|
||||
GList *l;
|
||||
GstElement *res = NULL;
|
||||
|
||||
GST_INFO_OBJECT (comp, "Looking for child: %s", name);
|
||||
|
||||
GST_OBJECT_LOCK (comp);
|
||||
GList *objs = NULL;
|
||||
|
||||
/* FIXME Implement a task to retrieve objects if needed */
|
||||
objs =
|
||||
g_list_copy_deep (priv->objects_start, (GCopyFunc) gst_object_ref, NULL);
|
||||
GST_OBJECT_UNLOCK (comp);
|
||||
|
||||
/* Check in the list of objects, already added */
|
||||
for (l = objs; l; l = l->next) {
|
||||
NleObject *obj = NLE_OBJECT (l->data);
|
||||
|
||||
if (!g_strcmp0 (GST_OBJECT_NAME (obj), name)) {
|
||||
res = gst_object_ref (GST_ELEMENT (obj));
|
||||
break;
|
||||
}
|
||||
|
||||
res = nle_find_object_in_bin_recurse (GST_BIN (obj), name);
|
||||
if (res) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
g_list_free_full (objs, (GDestroyNotify) gst_object_unref);
|
||||
if (res)
|
||||
goto done;
|
||||
|
||||
ACTIONS_LOCK (comp);
|
||||
/* Check if the object is about to be added */
|
||||
for (GList * tmp = comp->priv->actions; tmp != NULL; tmp = tmp->next) {
|
||||
Action *act = tmp->data;
|
||||
|
||||
if (ACTION_CALLBACK (act) == G_CALLBACK (_add_object_func)) {
|
||||
ChildIOData *d = ((GClosure *) act)->data;
|
||||
|
||||
if (!g_strcmp0 (GST_OBJECT_NAME (d->object), name)) {
|
||||
res = gst_object_ref (GST_ELEMENT (d->object));
|
||||
break;
|
||||
}
|
||||
|
||||
res = nle_find_object_in_bin_recurse (GST_BIN (d->object), name);
|
||||
if (res) {
|
||||
break;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
ACTIONS_UNLOCK (comp);
|
||||
|
||||
done:
|
||||
return res;
|
||||
}
|
||||
|
|
|
@ -61,6 +61,7 @@ struct _NleCompositionClass
|
|||
};
|
||||
|
||||
GType nle_composition_get_type (void) G_GNUC_INTERNAL;
|
||||
GstElement * nle_find_object_in_bin_recurse (GstBin * object, const gchar *name);
|
||||
|
||||
G_END_DECLS
|
||||
#endif /* __NLE_COMPOSITION_H__ */
|
||||
|
|
|
@ -56,6 +56,10 @@ GST_DEBUG_CATEGORY_STATIC (nleobject_debug);
|
|||
|
||||
static GObjectClass *parent_class = NULL;
|
||||
|
||||
#ifdef HAVE_GST_VALIDATE
|
||||
extern void nle_validate_init (void);
|
||||
#endif
|
||||
|
||||
/****************************************************
|
||||
* Helper macros *
|
||||
****************************************************/
|
||||
|
@ -334,6 +338,10 @@ nle_object_class_init (NleObjectClass * klass)
|
|||
G_TYPE_BOOLEAN, 1, G_TYPE_BOOLEAN);
|
||||
|
||||
gst_type_mark_as_plugin_api (NLE_TYPE_OBJECT, 0);
|
||||
|
||||
#ifdef HAVE_GST_VALIDATE
|
||||
nle_validate_init ();
|
||||
#endif
|
||||
}
|
||||
|
||||
static void
|
||||
|
|
170
subprojects/gst-editing-services/plugins/nle/validate.c
Normal file
170
subprojects/gst-editing-services/plugins/nle/validate.c
Normal file
|
@ -0,0 +1,170 @@
|
|||
/* Non Linear Engine plugin
|
||||
*
|
||||
* Copyright (C) 2023 Thibault Saunier <tsaunier@igalia.com>
|
||||
*
|
||||
* validate.c
|
||||
*
|
||||
* 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/gst.h>
|
||||
#include <gst/validate/validate.h>
|
||||
#include <gst/validate/gst-validate-utils.h>
|
||||
#include "nle.h"
|
||||
|
||||
GST_DEBUG_CATEGORY_STATIC (nle_validate_debug);
|
||||
#undef GST_CAT_DEFAULT
|
||||
#define GST_CAT_DEFAULT nle_validate_debug
|
||||
|
||||
void nle_validate_init (void);
|
||||
|
||||
#ifdef G_HAVE_ISO_VARARGS
|
||||
#define REPORT_UNLESS(condition, errpoint, ...) \
|
||||
G_STMT_START { \
|
||||
if (!(condition)) { \
|
||||
res = GST_VALIDATE_EXECUTE_ACTION_ERROR_REPORTED; \
|
||||
gst_validate_report_action(GST_VALIDATE_REPORTER(scenario), action, \
|
||||
SCENARIO_ACTION_EXECUTION_ERROR, \
|
||||
__VA_ARGS__); \
|
||||
goto errpoint; \
|
||||
} \
|
||||
} \
|
||||
G_STMT_END
|
||||
#else /* G_HAVE_GNUC_VARARGS */
|
||||
#ifdef G_HAVE_GNUC_VARARGS
|
||||
#define REPORT_UNLESS(condition, errpoint, args...) \
|
||||
G_STMT_START { \
|
||||
if (!(condition)) { \
|
||||
res = GST_VALIDATE_EXECUTE_ACTION_ERROR_REPORTED; \
|
||||
gst_validate_report_action(GST_VALIDATE_REPORTER(scenario), action, \
|
||||
SCENARIO_ACTION_EXECUTION_ERROR, ##args); \
|
||||
goto errpoint; \
|
||||
} \
|
||||
} \
|
||||
G_STMT_END
|
||||
#endif /* G_HAVE_ISO_VARARGS */
|
||||
#endif /* G_HAVE_GNUC_VARARGS */
|
||||
|
||||
#define NLE_START_VALIDATE_ACTION(funcname) \
|
||||
static gint \
|
||||
funcname(GstValidateScenario *scenario, GstValidateAction *action) { \
|
||||
GstValidateActionReturn res = GST_VALIDATE_EXECUTE_ACTION_OK; \
|
||||
GstElement * pipeline = gst_validate_scenario_get_pipeline(scenario);
|
||||
|
||||
#define NLE_END_VALIDATE_ACTION \
|
||||
done: \
|
||||
gst_clear_object(&pipeline); \
|
||||
return res; \
|
||||
}
|
||||
|
||||
NLE_START_VALIDATE_ACTION (_add_object)
|
||||
{
|
||||
GError *err = NULL;
|
||||
GstElement *nleobj = NULL;
|
||||
GstElement *child =
|
||||
gst_parse_bin_from_description_full (gst_structure_get_string
|
||||
(action->structure, "desc"), FALSE, NULL,
|
||||
GST_PARSE_FLAG_NO_SINGLE_ELEMENT_BINS | GST_PARSE_FLAG_PLACE_IN_BIN,
|
||||
&err);
|
||||
const gchar *objname = gst_structure_get_string (action->structure,
|
||||
"object-name");
|
||||
|
||||
REPORT_UNLESS (child, clean, "Failed to create element from description: %s",
|
||||
err ? err->message : "Unknown error");
|
||||
|
||||
nleobj = nle_find_object_in_bin_recurse (GST_BIN (pipeline), objname);
|
||||
|
||||
REPORT_UNLESS (nleobj, clean, "Could not find object `%s`", objname);
|
||||
|
||||
gboolean is_operation = NLE_IS_OPERATION (nleobj);
|
||||
gboolean is_src = NLE_IS_SOURCE (nleobj);
|
||||
if (GST_IS_BIN (child) && (is_src || is_operation)) {
|
||||
if (child->numsrcpads == 0 && !gst_element_class_get_pad_template
|
||||
(GST_ELEMENT_GET_CLASS (child), "src")) {
|
||||
GstPad *srcpad = gst_bin_find_unlinked_pad (GST_BIN (child), GST_PAD_SRC);
|
||||
if (srcpad) {
|
||||
gst_element_add_pad (child, gst_ghost_pad_new ("src", srcpad));
|
||||
gst_object_unref (srcpad);
|
||||
}
|
||||
}
|
||||
|
||||
if (is_operation && child->numsinkpads == 0
|
||||
&& !gst_element_class_get_pad_template (GST_ELEMENT_GET_CLASS (child),
|
||||
"sink")) {
|
||||
GstPad *sinkpad =
|
||||
gst_bin_find_unlinked_pad (GST_BIN (child), GST_PAD_SINK);
|
||||
if (sinkpad) {
|
||||
gst_element_add_pad (child, gst_ghost_pad_new ("sink", sinkpad));
|
||||
gst_object_unref (sinkpad);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
REPORT_UNLESS (gst_bin_add (GST_BIN (nleobj), gst_object_ref (child)), clean,
|
||||
"Could not add child to nle object");
|
||||
|
||||
clean:
|
||||
g_clear_error (&err);
|
||||
gst_clear_object (&child);
|
||||
|
||||
gst_clear_object (&nleobj);
|
||||
|
||||
goto done;
|
||||
}
|
||||
|
||||
NLE_END_VALIDATE_ACTION;
|
||||
|
||||
static void
|
||||
register_action_types ()
|
||||
{
|
||||
GST_DEBUG_CATEGORY_INIT (nle_validate_debug, "nlevalidate",
|
||||
GST_DEBUG_FG_BLUE | GST_DEBUG_BOLD, "NLE validate");
|
||||
|
||||
/* *INDENT-OFF* */
|
||||
gst_validate_register_action_type ("nle-add-child", "nle",
|
||||
_add_object,
|
||||
(GstValidateActionParameter []) {
|
||||
{
|
||||
.name = "object-name",
|
||||
.description = "The name of the nle object to which to add child, will recurse, \n"
|
||||
" potentially in `nlecompositions` to find the right object",
|
||||
.mandatory = TRUE,
|
||||
.types = "string",
|
||||
},
|
||||
{
|
||||
.name = "desc",
|
||||
.description = "The 'bin description' of the child to add",
|
||||
.mandatory = TRUE,
|
||||
.types = "string",
|
||||
},
|
||||
{NULL}
|
||||
},
|
||||
"Add a child to a NleObject\n",
|
||||
GST_VALIDATE_ACTION_TYPE_NONE);
|
||||
/* *INDENT-ON* */
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
nle_validate_init ()
|
||||
{
|
||||
register_action_types ();
|
||||
}
|
|
@ -5,7 +5,7 @@ endif
|
|||
# FIXME: make check work on windows
|
||||
if host_system != 'windows' and gstcheck_dep.found()
|
||||
subdir('check')
|
||||
subdir('validate')
|
||||
endif
|
||||
|
||||
subdir('validate')
|
||||
subdir('benchmarks')
|
||||
subdir('benchmarks')
|
||||
|
|
|
@ -7,3 +7,36 @@ install_data (['geslaunch.py'],
|
|||
env = environment()
|
||||
env.prepend('GST_VALIDATE_APPS_DIR', meson.current_source_dir())
|
||||
meson.add_devenv(env)
|
||||
|
||||
gst_tester = find_program('gst-tester-@0@'.format(apiversion), required: get_option('tests'))
|
||||
if not gst_tester.found()
|
||||
subdir_done()
|
||||
endif
|
||||
|
||||
tests = [
|
||||
'nle/simple_source_playback',
|
||||
'nle/simple_source_in_composition_playback',
|
||||
]
|
||||
|
||||
env = environment()
|
||||
env.set('GST_PLUGIN_PATH_1_0', meson.global_build_root(), pluginsdirs)
|
||||
env.set('GST_PLUGIN_SYSTEM_PATH_1_0', '')
|
||||
env.set('GST_REGISTRY', '@0@/@1@.registry'.format(meson.current_build_dir(), 'validate'))
|
||||
env.set('GST_PLUGIN_SCANNER_1_0', gst_plugin_scanner_path)
|
||||
env.set('GST_PLUGIN_LOADING_WHITELIST', 'gstreamer', 'gst-validate',
|
||||
'gst-plugins-base@' + meson.project_build_root(),
|
||||
'gst-editing-services@' + meson.project_build_root(),
|
||||
)
|
||||
|
||||
foreach t: tests
|
||||
test_dir_name = t.split('/')
|
||||
test_name = 'validate'
|
||||
foreach c: test_dir_name
|
||||
test_name += '.' + c
|
||||
endforeach
|
||||
test_env = env
|
||||
test_env.set('GST_VALIDATE_LOGSDIR', join_paths(meson.current_build_dir(), test_name))
|
||||
test_file = join_paths(meson.current_source_dir(), t + '.validatetest')
|
||||
test(test_name, gst_tester, args: [test_file, '--use-fakesinks'],
|
||||
env: test_env, timeout : 3 * 60, protocol: 'tap')
|
||||
endforeach
|
||||
|
|
|
@ -0,0 +1,15 @@
|
|||
meta,
|
||||
handles-states=true,
|
||||
ignore-eos=true,
|
||||
args={
|
||||
"nlecomposition name=compo ! $(videosink)",
|
||||
}
|
||||
|
||||
nle-add-child, object-name="compo", desc="nlesource name=s inpoint=0 duration=200000000"
|
||||
nle-add-child, object-name="s", desc="videotestsrc pattern=blue"
|
||||
|
||||
play
|
||||
check-position, on-message=eos, expected-position=0.2
|
||||
|
||||
stop
|
||||
|
|
@ -0,0 +1,15 @@
|
|||
meta,
|
||||
handles-states=true,
|
||||
ignore-eos=true,
|
||||
args={
|
||||
"nlesource name=s inpoint=0 duration=200000000 ! $(videosink)",
|
||||
}
|
||||
|
||||
nle-add-child,
|
||||
object-name="s",
|
||||
desc="videotestsrc ! timeoverlay"
|
||||
|
||||
play
|
||||
check-position, on-message=eos, expected-position=0.2
|
||||
|
||||
stop
|
Loading…
Reference in a new issue