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: <https://gitlab.freedesktop.org/gstreamer/gst-editing-services/-/merge_requests/227>
This commit is contained in:
Thibault Saunier 2021-01-15 15:03:20 -03:00
parent 7499d41213
commit 70e3b8ae2a
6 changed files with 154 additions and 70 deletions

View file

@ -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:

View file

@ -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

View file

@ -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;

View file

@ -21,6 +21,8 @@
#include <ges/ges.h>
#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;

View file

@ -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

View file

@ -21,7 +21,38 @@
#include <gst/pbutils/pbutils.h>
#include <gst/pbutils/encoding-profile.h>
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);