mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer.git
synced 2024-11-22 01:31:03 +00:00
validate: Allow overriding features rank early in testfiles meta
Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/7700>
This commit is contained in:
parent
f5b0f91d33
commit
2c88bbf07f
9 changed files with 151 additions and 12 deletions
|
@ -0,0 +1,16 @@
|
||||||
|
The `features-rank` field is an array of structures that defines how to
|
||||||
|
override `GstPluginFeature::rank` to ensure some features will be used,
|
||||||
|
or at contrary won't be used.
|
||||||
|
|
||||||
|
For example:
|
||||||
|
|
||||||
|
``` yaml
|
||||||
|
features-rank = {
|
||||||
|
[mandatory, glvideomixer=9999],
|
||||||
|
[optional, someoptionalfeature=0],
|
||||||
|
},
|
||||||
|
```
|
||||||
|
|
||||||
|
One could also use the `set-feature-rank` scenario action, but that
|
||||||
|
happens after GStreamer or other components are initialized which might
|
||||||
|
be a problem in some cases.
|
|
@ -64,6 +64,7 @@ G_GNUC_INTERNAL void gst_validate_deinit_runner (void);
|
||||||
G_GNUC_INTERNAL void gst_validate_report_deinit (void);
|
G_GNUC_INTERNAL void gst_validate_report_deinit (void);
|
||||||
G_GNUC_INTERNAL gboolean gst_validate_send (JsonNode * root);
|
G_GNUC_INTERNAL gboolean gst_validate_send (JsonNode * root);
|
||||||
G_GNUC_INTERNAL void gst_validate_set_test_file_globals (GstStructure* meta, const gchar* testfile, gboolean use_fakesinks);
|
G_GNUC_INTERNAL void gst_validate_set_test_file_globals (GstStructure* meta, const gchar* testfile, gboolean use_fakesinks);
|
||||||
|
G_GNUC_INTERNAL gboolean gst_validate_structure_file_field_is_metadata (const GstIdStr *field_id);
|
||||||
G_GNUC_INTERNAL gboolean gst_validate_get_test_file_scenario (GList** structs, const gchar** scenario_name, gchar** original_name);
|
G_GNUC_INTERNAL gboolean gst_validate_get_test_file_scenario (GList** structs, const gchar** scenario_name, gchar** original_name);
|
||||||
G_GNUC_INTERNAL GstValidateScenario* gst_validate_scenario_from_structs (GstValidateRunner* runner, GstElement* pipeline, GList* structures,
|
G_GNUC_INTERNAL GstValidateScenario* gst_validate_scenario_from_structs (GstValidateRunner* runner, GstElement* pipeline, GList* structures,
|
||||||
const gchar* origin_file);
|
const gchar* origin_file);
|
||||||
|
|
|
@ -7698,6 +7698,9 @@ register_action_types (void)
|
||||||
GBytes *meta_expected_issues_doc =
|
GBytes *meta_expected_issues_doc =
|
||||||
g_resource_lookup_data (resource, "/validate/doc/meta-expected-issues.md",
|
g_resource_lookup_data (resource, "/validate/doc/meta-expected-issues.md",
|
||||||
G_RESOURCE_LOOKUP_FLAGS_NONE, NULL);
|
G_RESOURCE_LOOKUP_FLAGS_NONE, NULL);
|
||||||
|
GBytes *meta_features_rank_doc =
|
||||||
|
g_resource_lookup_data (resource, "/validate/doc/meta-features-rank.md",
|
||||||
|
G_RESOURCE_LOOKUP_FLAGS_NONE, NULL);
|
||||||
|
|
||||||
/* *INDENT-OFF* */
|
/* *INDENT-OFF* */
|
||||||
REGISTER_ACTION_TYPE ("meta", NULL,
|
REGISTER_ACTION_TYPE ("meta", NULL,
|
||||||
|
@ -7874,12 +7877,31 @@ register_action_types (void)
|
||||||
.possible_variables = NULL,
|
.possible_variables = NULL,
|
||||||
.def = "{}"
|
.def = "{}"
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
.name="features-rank",
|
||||||
|
.description=g_bytes_get_data (meta_features_rank_doc, NULL),
|
||||||
|
.mandatory = FALSE,
|
||||||
|
.types = "bool",
|
||||||
|
.possible_variables = NULL,
|
||||||
|
.def = "false"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
.name="monitor-all-pipelines",
|
||||||
|
.description="This should only be used in `.validatetest` files, and allows forcing to monitor "
|
||||||
|
"all pipelines instead of only the one the tools wanted to monitor, for example to "
|
||||||
|
"use `validateflow` on auxilary pipelines",
|
||||||
|
.mandatory = FALSE,
|
||||||
|
.types = "bool",
|
||||||
|
.possible_variables = NULL,
|
||||||
|
.def = "false"
|
||||||
|
},
|
||||||
{NULL}
|
{NULL}
|
||||||
}),
|
}),
|
||||||
"Scenario metadata.\n\nNOTE: it used to be called \"description\"",
|
"Scenario metadata.\n\nNOTE: it used to be called \"description\"",
|
||||||
GST_VALIDATE_ACTION_TYPE_CONFIG);
|
GST_VALIDATE_ACTION_TYPE_CONFIG);
|
||||||
g_bytes_unref (meta_config_doc);
|
g_bytes_unref (meta_config_doc);
|
||||||
g_bytes_unref (meta_expected_issues_doc);
|
g_bytes_unref (meta_expected_issues_doc);
|
||||||
|
g_bytes_unref (meta_features_rank_doc);
|
||||||
|
|
||||||
REGISTER_ACTION_TYPE ("seek", _execute_seek,
|
REGISTER_ACTION_TYPE ("seek", _execute_seek,
|
||||||
((GstValidateActionParameter []) {
|
((GstValidateActionParameter []) {
|
||||||
|
|
|
@ -1352,9 +1352,8 @@ done:
|
||||||
g_clear_pointer (&match_info, g_match_info_free);
|
g_clear_pointer (&match_info, g_match_info_free);
|
||||||
}
|
}
|
||||||
|
|
||||||
static gboolean
|
gboolean
|
||||||
_structure_set_variables (const GstIdStr * fieldname, GValue * value,
|
gst_validate_structure_file_field_is_metadata (const GstIdStr * fieldname)
|
||||||
ReplaceData * data)
|
|
||||||
{
|
{
|
||||||
static const gchar *skip_fields[] = {
|
static const gchar *skip_fields[] = {
|
||||||
"__filename__",
|
"__filename__",
|
||||||
|
@ -1363,7 +1362,15 @@ _structure_set_variables (const GstIdStr * fieldname, GValue * value,
|
||||||
NULL,
|
NULL,
|
||||||
};
|
};
|
||||||
|
|
||||||
if (fieldname && g_strv_contains (skip_fields, gst_id_str_as_str (fieldname)))
|
return fieldname
|
||||||
|
&& g_strv_contains (skip_fields, gst_id_str_as_str (fieldname));
|
||||||
|
}
|
||||||
|
|
||||||
|
static gboolean
|
||||||
|
_structure_set_variables (const GstIdStr * fieldname, GValue * value,
|
||||||
|
ReplaceData * data)
|
||||||
|
{
|
||||||
|
if (gst_validate_structure_file_field_is_metadata (fieldname))
|
||||||
return TRUE;
|
return TRUE;
|
||||||
|
|
||||||
if (GST_VALUE_HOLDS_LIST (value)) {
|
if (GST_VALUE_HOLDS_LIST (value)) {
|
||||||
|
|
|
@ -93,6 +93,7 @@ GST_VALIDATE_API
|
||||||
void gst_validate_structure_resolve_variables (gpointer source, GstStructure *structure, GstStructure *local_variables,
|
void gst_validate_structure_resolve_variables (gpointer source, GstStructure *structure, GstStructure *local_variables,
|
||||||
GstValidateStructureResolveVariablesFlags flags);
|
GstValidateStructureResolveVariablesFlags flags);
|
||||||
void gst_validate_structure_set_variables_from_struct_file(GstStructure* vars, const gchar* struct_file);
|
void gst_validate_structure_set_variables_from_struct_file(GstStructure* vars, const gchar* struct_file);
|
||||||
|
GST_VALIDATE_API
|
||||||
void gst_validate_set_globals(GstStructure* structure);
|
void gst_validate_set_globals(GstStructure* structure);
|
||||||
GST_VALIDATE_API
|
GST_VALIDATE_API
|
||||||
gboolean gst_validate_fail_on_missing_plugin(void);
|
gboolean gst_validate_fail_on_missing_plugin(void);
|
||||||
|
|
|
@ -26,6 +26,7 @@
|
||||||
* @short_description: Initialize GstValidate
|
* @short_description: Initialize GstValidate
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
#include "gst/gstidstr.h"
|
||||||
#ifdef HAVE_CONFIG_H
|
#ifdef HAVE_CONFIG_H
|
||||||
# include "config.h"
|
# include "config.h"
|
||||||
#endif /* HAVE_CONFIG_H */
|
#endif /* HAVE_CONFIG_H */
|
||||||
|
@ -265,16 +266,23 @@ get_structures_from_array_in_meta (const gchar * fieldname)
|
||||||
if (!meta)
|
if (!meta)
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
res = get_structures_from_array (meta, fieldname);
|
|
||||||
if (res)
|
|
||||||
return res;
|
|
||||||
|
|
||||||
gst_structure_get (meta,
|
gst_structure_get (meta,
|
||||||
"__lineno__", G_TYPE_INT, ¤t_lineno,
|
"__lineno__", G_TYPE_INT, ¤t_lineno,
|
||||||
"__debug__", G_TYPE_STRING, &debug,
|
"__debug__", G_TYPE_STRING, &debug,
|
||||||
"__filename__", G_TYPE_STRING, &filename, NULL);
|
"__filename__", G_TYPE_STRING, &filename, NULL);
|
||||||
strs = gst_validate_utils_get_strv (meta, fieldname);
|
|
||||||
|
|
||||||
|
res = get_structures_from_array (meta, fieldname);
|
||||||
|
if (res) {
|
||||||
|
for (GList * tmp = res; tmp; tmp = tmp->next) {
|
||||||
|
gst_structure_set (tmp->data,
|
||||||
|
"__lineno__", G_TYPE_INT, current_lineno,
|
||||||
|
"__filename__", G_TYPE_STRING, filename,
|
||||||
|
"__debug__", G_TYPE_STRING, debug, NULL);
|
||||||
|
}
|
||||||
|
goto done;
|
||||||
|
}
|
||||||
|
|
||||||
|
strs = gst_validate_utils_get_strv (meta, fieldname);
|
||||||
if (strs) {
|
if (strs) {
|
||||||
gint i;
|
gint i;
|
||||||
|
|
||||||
|
@ -294,6 +302,7 @@ get_structures_from_array_in_meta (const gchar * fieldname)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
done:
|
||||||
g_free (filename);
|
g_free (filename);
|
||||||
g_free (debug);
|
g_free (debug);
|
||||||
g_strfreev (strs);
|
g_strfreev (strs);
|
||||||
|
@ -612,6 +621,46 @@ validate_test_include_paths (const gchar * includer_file)
|
||||||
return env_configdir;
|
return env_configdir;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static gboolean
|
||||||
|
_set_feature_rank (const GstIdStr * fieldname, GValue * value,
|
||||||
|
GstStructure * structure)
|
||||||
|
{
|
||||||
|
GstRegistry *registry = gst_registry_get ();
|
||||||
|
guint rank = 0;
|
||||||
|
|
||||||
|
if (gst_validate_structure_file_field_is_metadata (fieldname))
|
||||||
|
return TRUE;
|
||||||
|
|
||||||
|
if (G_VALUE_TYPE (value) == G_TYPE_UINT) {
|
||||||
|
rank = (guint) g_value_get_uint (value);
|
||||||
|
} else if (G_VALUE_TYPE (value) == G_TYPE_INT) {
|
||||||
|
rank = g_value_get_int (value);
|
||||||
|
} else {
|
||||||
|
gst_validate_error_structure (structure,
|
||||||
|
"Invalid value %s for field '%s' (expecting int) in the 'features-rank' structure",
|
||||||
|
G_VALUE_TYPE_NAME (value), gst_value_serialize (value));
|
||||||
|
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
GstPluginFeature *feature =
|
||||||
|
gst_registry_lookup_feature (registry, gst_id_str_as_str (fieldname));
|
||||||
|
if (!feature) {
|
||||||
|
if (gst_structure_has_name (structure, "mandatory")) {
|
||||||
|
gst_validate_error_structure (structure,
|
||||||
|
"Feature `%s` not found while its ranks has been requested to be set to %d",
|
||||||
|
gst_id_str_as_str (fieldname), rank);
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
gst_plugin_feature_set_rank (feature, rank);
|
||||||
|
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
/* Only the first monitor pipeline will be used */
|
/* Only the first monitor pipeline will be used */
|
||||||
GstStructure *
|
GstStructure *
|
||||||
gst_validate_setup_test_file (const gchar * testfile, gboolean use_fakesinks)
|
gst_validate_setup_test_file (const gchar * testfile, gboolean use_fakesinks)
|
||||||
|
@ -653,6 +702,21 @@ gst_validate_setup_test_file (const gchar * testfile, gboolean use_fakesinks)
|
||||||
register_action_types ();
|
register_action_types ();
|
||||||
gst_validate_scenario_check_and_set_needs_clock_sync (testfile_structs, &res);
|
gst_validate_scenario_check_and_set_needs_clock_sync (testfile_structs, &res);
|
||||||
|
|
||||||
|
GList *feature_ranks_def =
|
||||||
|
get_structures_from_array_in_meta ("features-rank");
|
||||||
|
for (GList * tmp = feature_ranks_def; tmp; tmp = tmp->next) {
|
||||||
|
GstStructure *feature_ranks = tmp->data;
|
||||||
|
if (!gst_structure_has_name (feature_ranks, "mandatory")
|
||||||
|
&& !gst_structure_has_name (feature_ranks, "optional")) {
|
||||||
|
gst_validate_error_structure (res,
|
||||||
|
"Feature rank structures should have either `mandatory` or `optional` as a name, got: %s",
|
||||||
|
gst_structure_to_string (feature_ranks));
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
gst_structure_filter_and_map_in_place_id_str (feature_ranks,
|
||||||
|
(GstStructureFilterMapIdStrFunc) _set_feature_rank, feature_ranks);
|
||||||
|
}
|
||||||
|
|
||||||
gst_validate_set_test_file_globals (res, global_testfile, use_fakesinks);
|
gst_validate_set_test_file_globals (res, global_testfile, use_fakesinks);
|
||||||
gst_validate_structure_resolve_variables (NULL, res, NULL, 0);
|
gst_validate_structure_resolve_variables (NULL, res, NULL, 0);
|
||||||
|
|
||||||
|
|
|
@ -3,6 +3,7 @@
|
||||||
<gresource prefix="/validate/">
|
<gresource prefix="/validate/">
|
||||||
<file>doc/meta-configs.md</file>
|
<file>doc/meta-configs.md</file>
|
||||||
<file>doc/meta-expected-issues.md</file>
|
<file>doc/meta-expected-issues.md</file>
|
||||||
|
<file>doc/meta-features-rank.md</file>
|
||||||
</gresource>
|
</gresource>
|
||||||
</gresources>
|
</gresources>
|
||||||
|
|
||||||
|
|
|
@ -33,6 +33,10 @@
|
||||||
#include "utils.h"
|
#include "utils.h"
|
||||||
#include "ges-launcher-kb.h"
|
#include "ges-launcher-kb.h"
|
||||||
|
|
||||||
|
#ifdef HAVE_GST_VALIDATE
|
||||||
|
#include <gst/validate/validate.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
typedef enum
|
typedef enum
|
||||||
{
|
{
|
||||||
GST_PLAY_TRICK_MODE_NONE = 0,
|
GST_PLAY_TRICK_MODE_NONE = 0,
|
||||||
|
@ -321,6 +325,19 @@ _parse_track_type (const gchar * option_name, const gchar * value,
|
||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#ifdef HAVE_GST_VALIDATE
|
||||||
|
static gboolean
|
||||||
|
_parse_test_file (const gchar * option_name, const gchar * value,
|
||||||
|
GESLauncherParsedOptions * opts, GError ** error)
|
||||||
|
{
|
||||||
|
opts->testfile = g_strdup (value);
|
||||||
|
gst_validate_init_debug ();
|
||||||
|
gst_validate_setup_test_file (opts->testfile, FALSE);
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
static gboolean
|
static gboolean
|
||||||
_set_track_restriction_caps (GESTrack * track, const gchar * caps_str)
|
_set_track_restriction_caps (GESTrack * track, const gchar * caps_str)
|
||||||
{
|
{
|
||||||
|
@ -1037,6 +1054,8 @@ bus_message_cb (GstBus * bus, GstMessage * message, GESLauncher * self)
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case GST_MESSAGE_EOS:
|
case GST_MESSAGE_EOS:
|
||||||
|
GST_DEBUG_BIN_TO_DOT_FILE_WITH_TS (GST_BIN (self->priv->pipeline),
|
||||||
|
GST_DEBUG_GRAPH_SHOW_ALL, "ges-launch.eos");
|
||||||
if (!self->priv->parsed_options.ignore_eos) {
|
if (!self->priv->parsed_options.ignore_eos) {
|
||||||
ges_ok ("\nDone\n");
|
ges_ok ("\nDone\n");
|
||||||
g_application_quit (G_APPLICATION (self));
|
g_application_quit (G_APPLICATION (self));
|
||||||
|
@ -1177,7 +1196,8 @@ _run_pipeline (GESLauncher * self)
|
||||||
|
|
||||||
bus = gst_pipeline_get_bus (GST_PIPELINE (self->priv->pipeline));
|
bus = gst_pipeline_get_bus (GST_PIPELINE (self->priv->pipeline));
|
||||||
gst_bus_add_signal_watch (bus);
|
gst_bus_add_signal_watch (bus);
|
||||||
g_signal_connect (bus, "message", G_CALLBACK (bus_message_cb), self);
|
g_signal_connect_object (bus, "message", G_CALLBACK (bus_message_cb), self,
|
||||||
|
0);
|
||||||
|
|
||||||
g_application_hold (G_APPLICATION (self));
|
g_application_hold (G_APPLICATION (self));
|
||||||
|
|
||||||
|
@ -1433,7 +1453,7 @@ ges_launcher_parse_options (GESLauncher * self,
|
||||||
"Specify the track restriction caps of the audio track.",
|
"Specify the track restriction caps of the audio track.",
|
||||||
},
|
},
|
||||||
#ifdef HAVE_GST_VALIDATE
|
#ifdef HAVE_GST_VALIDATE
|
||||||
{"set-test-file", 0, 0, G_OPTION_ARG_STRING, &opts->testfile,
|
{"set-test-file", 0, 0, G_OPTION_ARG_CALLBACK, &_parse_test_file,
|
||||||
"ges-launch-1.0 exposes gst-validate functionalities, such as test files and scenarios."
|
"ges-launch-1.0 exposes gst-validate functionalities, such as test files and scenarios."
|
||||||
" Scenarios describe actions to execute, such as seeks or setting of "
|
" Scenarios describe actions to execute, such as seeks or setting of "
|
||||||
"properties. "
|
"properties. "
|
||||||
|
|
|
@ -138,7 +138,14 @@ ges_validate_activate (GstPipeline * pipeline, GESLauncher * launcher,
|
||||||
if (opts->testfile) {
|
if (opts->testfile) {
|
||||||
if (opts->scenario)
|
if (opts->scenario)
|
||||||
g_error ("Can not specify scenario and testfile at the same time");
|
g_error ("Can not specify scenario and testfile at the same time");
|
||||||
gst_validate_setup_test_file (opts->testfile, opts->mute);
|
if (!opts->mute) {
|
||||||
|
gst_validate_set_globals (gst_structure_new ("globals",
|
||||||
|
"videosink", G_TYPE_STRING,
|
||||||
|
opts->videosink ? opts->videosink : "autovideosink", "audiosink",
|
||||||
|
G_TYPE_STRING,
|
||||||
|
opts->audiosink ? opts->audiosink : "autoaudiosink", NULL)
|
||||||
|
);
|
||||||
|
}
|
||||||
} else if (opts->scenario) {
|
} else if (opts->scenario) {
|
||||||
if (g_strcmp0 (opts->scenario, "none")) {
|
if (g_strcmp0 (opts->scenario, "none")) {
|
||||||
gchar *scenario_name =
|
gchar *scenario_name =
|
||||||
|
|
Loading…
Reference in a new issue