From 70e3b8ae2a8d13b50f52305b71cfa4b590bb63f6 Mon Sep 17 00:00:00 2001 From: Thibault Saunier Date: Fri, 15 Jan 2021 15:03:20 -0300 Subject: [PATCH] ges: Use a `ges:` uri to define timeline from description This way the command line formatter actually uses an URI and not an ugly hack where were passing a random string instead of an URI. This also allows the `gessrc` element to handle timelines described in its URI meaning that you can now use, for example: gst-play-1.0 "ges:+test-clip blue d=4.0 Part-of: --- ges/ges-command-line-formatter.c | 60 ++++++++++++++++++++++++++++++-- plugins/ges/gessrc.c | 25 +++++++++++-- tools/ges-launcher.c | 35 ++----------------- tools/ges-launcher.h | 31 ++--------------- tools/utils.c | 40 +++++++++++++++++++-- tools/utils.h | 33 +++++++++++++++++- 6 files changed, 154 insertions(+), 70 deletions(-) diff --git a/ges/ges-command-line-formatter.c b/ges/ges-command-line-formatter.c index 475cf5f554..777ec9ebd6 100644 --- a/ges/ges-command-line-formatter.c +++ b/ges/ges-command-line-formatter.c @@ -660,26 +660,74 @@ _parse_structures (const gchar * string) return parser; } +/* @uri: (transfer full): */ +static gchar * +get_timeline_desc_from_uri (GstUri * uri) +{ + gchar *res, *path; + + if (!uri) + return NULL; + + /* Working around parser requiring a space to begin with */ + path = gst_uri_get_path (uri); + res = g_strconcat (" ", path, NULL); + g_free (path); + + gst_uri_unref (uri); + + return res; +} + static gboolean _can_load (GESFormatter * dummy_formatter, const gchar * string, GError ** error) { gboolean res = FALSE; + GstUri *uri; + const gchar *scheme; + gchar *timeline_desc = NULL; GESStructureParser *parser; - if (string == NULL) + if (string == NULL) { + GST_ERROR ("No URI!"); return FALSE; + } - parser = _parse_structures (string); + uri = gst_uri_from_string (string); + if (!uri) { + GST_INFO_OBJECT (dummy_formatter, "Wrong uri: %s", string); + return FALSE; + } + scheme = gst_uri_get_scheme (uri); + if (!g_strcmp0 (scheme, "ges:")) { + GST_INFO_OBJECT (dummy_formatter, "Wrong scheme: %s", string); + gst_uri_unref (uri); + + return FALSE; + } + + timeline_desc = get_timeline_desc_from_uri (uri); + parser = _parse_structures (timeline_desc); if (parser->structures) res = TRUE; gst_object_unref (parser); + g_free (timeline_desc); return res; } +static gboolean +_set_project_loaded (GESFormatter * self) +{ + ges_project_set_loaded (self->project, self, NULL); + gst_object_unref (self); + + return FALSE; +} + static gboolean _load (GESFormatter * self, GESTimeline * timeline, const gchar * string, GError ** error) @@ -687,7 +735,11 @@ _load (GESFormatter * self, GESTimeline * timeline, const gchar * string, guint i; GList *tmp; GError *err; - GESStructureParser *parser = _parse_structures (string); + gchar *timeline_desc = + get_timeline_desc_from_uri (gst_uri_from_string (string)); + GESStructureParser *parser = _parse_structures (timeline_desc); + + g_free (timeline_desc); err = ges_structure_parser_get_error (parser); @@ -719,6 +771,8 @@ _load (GESFormatter * self, GESTimeline * timeline, const gchar * string, gst_object_unref (parser); + ges_idle_add ((GSourceFunc) _set_project_loaded, g_object_ref (self), NULL); + return TRUE; fail: diff --git a/plugins/ges/gessrc.c b/plugins/ges/gessrc.c index e726c3841e..103efe9a63 100644 --- a/plugins/ges/gessrc.c +++ b/plugins/ges/gessrc.c @@ -87,10 +87,31 @@ ges_src_uri_get_uri (GstURIHandler * handler) } static gboolean -ges_src_uri_set_uri (GstURIHandler * handler, const gchar * uri, +ges_src_uri_set_uri (GstURIHandler * handler, const gchar * uristr, GError ** error) { - return TRUE; + gboolean res = FALSE; + GstUri *uri = gst_uri_from_string (uristr); + GESProject *project = NULL; + GESTimeline *timeline = NULL; + + if (!gst_uri_get_path (uri)) { + GST_INFO_OBJECT (handler, "User need to specify the timeline"); + res = TRUE; + goto done; + } + + project = ges_project_new (uristr); + timeline = (GESTimeline *) ges_asset_extract (GES_ASSET (project), NULL); + + if (timeline) + res = ges_base_bin_set_timeline (GES_BASE_BIN (handler), timeline); + +done: + gst_uri_unref (uri); + gst_clear_object (&project); + + return res; } static void diff --git a/tools/ges-launcher.c b/tools/ges-launcher.c index be33bd0e9c..72dda86c57 100644 --- a/tools/ges-launcher.c +++ b/tools/ges-launcher.c @@ -716,7 +716,6 @@ static gboolean _create_timeline (GESLauncher * self, const gchar * serialized_timeline, const gchar * proj_uri, gboolean validate) { - GESLauncherParsedOptions *opts = &self->priv->parsed_options; GESProject *project; GError *error = NULL; @@ -724,37 +723,7 @@ _create_timeline (GESLauncher * self, const gchar * serialized_timeline, if (proj_uri != NULL) { project = ges_project_new (proj_uri); } else if (!validate) { - GString *timeline_str = g_string_new (serialized_timeline); - - if (!strstr (serialized_timeline, "+track")) { - GString *track_def; - - if (opts->track_types & GES_TRACK_TYPE_VIDEO) { - track_def = g_string_new (" +track video "); - - if (opts->video_track_caps) - g_string_append_printf (track_def, " restrictions=[%s] ", - opts->video_track_caps); - - g_string_prepend (timeline_str, track_def->str); - g_string_free (track_def, TRUE); - } - - if (opts->track_types & GES_TRACK_TYPE_AUDIO) { - track_def = g_string_new (" +track audio "); - - if (opts->audio_track_caps) - g_string_append_printf (track_def, " restrictions=[%s] ", - opts->audio_track_caps); - - g_string_prepend (timeline_str, track_def->str); - g_string_free (track_def, TRUE); - } - } - - GST_INFO ("Launching timeline: `%s`", timeline_str->str); - project = ges_project_new (timeline_str->str); - g_string_free (timeline_str, TRUE); + project = ges_project_new (serialized_timeline); } else { project = ges_project_new (NULL); } @@ -1366,7 +1335,7 @@ _local_command_line (GApplication * application, gchar ** arguments[], g_option_context_free (ctx); - opts->sanitized_timeline = sanitize_timeline_description (*arguments); + opts->sanitized_timeline = sanitize_timeline_description (*arguments, opts); if (!g_application_register (application, NULL, &error)) { *exit_status = 1; diff --git a/tools/ges-launcher.h b/tools/ges-launcher.h index 4021b14286..108ca8446c 100644 --- a/tools/ges-launcher.h +++ b/tools/ges-launcher.h @@ -21,6 +21,8 @@ #include +#include "utils.h" + G_BEGIN_DECLS #define GES_TYPE_LAUNCHER ges_launcher_get_type() @@ -28,35 +30,6 @@ G_BEGIN_DECLS typedef struct _GESLauncherPrivate GESLauncherPrivate; G_DECLARE_FINAL_TYPE(GESLauncher, ges_launcher, GES, LAUNCHER, GApplication); -typedef struct -{ - gboolean mute; - gboolean disable_mixing; - gchar *save_path; - gchar *save_only_path; - gchar *load_path; - GESTrackType track_types; - gboolean needs_set_state; - gboolean smartrender; - gchar *scenario; - gchar *testfile; - gchar *format; - gchar *outputuri; - gchar *encoding_profile; - gchar *videosink; - gchar *audiosink; - gboolean list_transitions; - gboolean inspect_action_type; - gchar *sanitized_timeline; - gchar *video_track_caps; - gchar *audio_track_caps; - gboolean embed_nesteds; - gboolean disable_validate; - - gboolean ignore_eos; - gboolean interactive; -} GESLauncherParsedOptions; - struct _GESLauncher { GApplication parent; diff --git a/tools/utils.c b/tools/utils.c index 78015cdfaa..2815ad2345 100644 --- a/tools/utils.c +++ b/tools/utils.c @@ -89,10 +89,12 @@ _sanitize_argument (gchar * arg, const gchar * prev_arg) } gchar * -sanitize_timeline_description (gchar ** args) +sanitize_timeline_description (gchar ** args, GESLauncherParsedOptions * opts) { gint i; gchar *prev_arg = NULL; + GString *track_def; + GString *timeline_str; gchar *string = g_strdup (" "); @@ -108,7 +110,41 @@ sanitize_timeline_description (gchar ** args) prev_arg = args[i]; } - return string; + if (strstr (string, "+track")) { + gchar *res = g_strconcat ("ges:", string, NULL); + g_free (string); + + return res; + } + + timeline_str = g_string_new (string); + g_free (string); + + if (opts->track_types & GES_TRACK_TYPE_VIDEO) { + track_def = g_string_new (" +track video "); + + if (opts->video_track_caps) + g_string_append_printf (track_def, " restrictions=[%s] ", + opts->video_track_caps); + + g_string_prepend (timeline_str, track_def->str); + g_string_free (track_def, TRUE); + } + + if (opts->track_types & GES_TRACK_TYPE_AUDIO) { + track_def = g_string_new (" +track audio "); + + if (opts->audio_track_caps) + g_string_append_printf (track_def, " restrictions=[%s] ", + opts->audio_track_caps); + + g_string_prepend (timeline_str, track_def->str); + g_string_free (track_def, TRUE); + } + + g_string_prepend (timeline_str, "ges:"); + + return g_string_free (timeline_str, FALSE); } gboolean diff --git a/tools/utils.h b/tools/utils.h index 63e21011b7..afd5ab26b2 100644 --- a/tools/utils.h +++ b/tools/utils.h @@ -21,7 +21,38 @@ #include #include -gchar * sanitize_timeline_description (gchar **args); +#pragma once + +typedef struct +{ + gboolean mute; + gboolean disable_mixing; + gchar *save_path; + gchar *save_only_path; + gchar *load_path; + GESTrackType track_types; + gboolean needs_set_state; + gboolean smartrender; + gchar *scenario; + gchar *testfile; + gchar *format; + gchar *outputuri; + gchar *encoding_profile; + gchar *videosink; + gchar *audiosink; + gboolean list_transitions; + gboolean inspect_action_type; + gchar *sanitized_timeline; + gchar *video_track_caps; + gchar *audio_track_caps; + gboolean embed_nesteds; + gboolean disable_validate; + + gboolean ignore_eos; + gboolean interactive; +} GESLauncherParsedOptions; + +gchar * sanitize_timeline_description (gchar **args, GESLauncherParsedOptions *opts); gboolean get_flags_from_string (GType type, const gchar * str_flags, guint *val); gchar * ensure_uri (const gchar * location); GstEncodingProfile * parse_encoding_profile (const gchar * format);