mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer.git
synced 2024-11-27 04:01:08 +00:00
command-line-formatter: Add track management to timeline description
Instead of having it all handled by the tool, this way we can set the restriction before clips are added to the timeline, leading to better behavior in term of video images placement in the scene. Without that we would have the clips positioned before setting the restriction caps which leads to weird behavior for the end users. Part-of: <https://gitlab.freedesktop.org/gstreamer/gst-editing-services/-/merge_requests/227>
This commit is contained in:
parent
e3a30744e8
commit
6c5daf8c81
6 changed files with 143 additions and 20 deletions
|
@ -50,6 +50,9 @@ _ges_command_line_formatter_add_test_clip (GESTimeline * timeline,
|
|||
static gboolean
|
||||
_ges_command_line_formatter_add_title_clip (GESTimeline * timeline,
|
||||
GstStructure * structure, GError ** error);
|
||||
static gboolean
|
||||
_ges_command_line_formatter_add_track (GESTimeline * timeline,
|
||||
GstStructure * structure, GError ** error);
|
||||
|
||||
typedef struct
|
||||
{
|
||||
|
@ -232,6 +235,16 @@ static GESCommandLineOption options[] = {
|
|||
{NULL, 0, 0, NULL, FALSE},
|
||||
},
|
||||
},
|
||||
{"track", 't', (ActionFromStructureFunc) _ges_command_line_formatter_add_track,
|
||||
"<track type>", "Adds a track to the timeline.", NULL,
|
||||
{
|
||||
{
|
||||
"restrictions", "r", 0, NULL,
|
||||
"The restriction caps to set on the track."
|
||||
},
|
||||
{NULL, 0, 0, NULL, FALSE},
|
||||
},
|
||||
},
|
||||
{
|
||||
"set-", 0, NULL,
|
||||
"<property name> <value>", "Set a property on the last added element."
|
||||
|
@ -259,6 +272,7 @@ typedef enum
|
|||
EFFECT,
|
||||
TEST_CLIP,
|
||||
TITLE,
|
||||
TRACK,
|
||||
SET,
|
||||
} GESCommandLineOptionType;
|
||||
|
||||
|
@ -441,6 +455,16 @@ _ges_command_line_formatter_add_title_clip (GESTimeline * timeline,
|
|||
return _ges_add_clip_from_struct (timeline, structure, error);
|
||||
}
|
||||
|
||||
static gboolean
|
||||
_ges_command_line_formatter_add_track (GESTimeline * timeline,
|
||||
GstStructure * structure, GError ** error)
|
||||
{
|
||||
if (!_cleanup_fields (options[TRACK].properties, structure, error))
|
||||
return FALSE;
|
||||
|
||||
return _ges_add_track_from_struct (timeline, structure, error);
|
||||
}
|
||||
|
||||
static gboolean
|
||||
_ges_command_line_formatter_add_effect (GESTimeline * timeline,
|
||||
GstStructure * structure, GError ** error)
|
||||
|
@ -603,11 +627,6 @@ _load (GESFormatter * self, GESTimeline * timeline, const gchar * string,
|
|||
}
|
||||
|
||||
g_object_set (timeline, "auto-transition", TRUE, NULL);
|
||||
if (!(ges_timeline_add_track (timeline, GES_TRACK (ges_video_track_new ()))))
|
||||
goto fail;
|
||||
|
||||
if (!(ges_timeline_add_track (timeline, GES_TRACK (ges_audio_track_new ()))))
|
||||
goto fail;
|
||||
|
||||
/* Here we've finished initializing our timeline, we're
|
||||
* ready to start using it... by solely working with the layer !*/
|
||||
|
|
|
@ -99,25 +99,28 @@ ges_structure_parser_parse_whitespace (GESStructureParser * self)
|
|||
static void
|
||||
_finish_structure (GESStructureParser * self)
|
||||
{
|
||||
if (self->current_string) {
|
||||
GstStructure *structure =
|
||||
gst_structure_new_from_string (self->current_string);
|
||||
GstStructure *structure;
|
||||
|
||||
if (structure == NULL) {
|
||||
GST_ERROR ("Could not parse %s", self->current_string);
|
||||
if (!self->current_string)
|
||||
return;
|
||||
|
||||
self->wrong_strings = g_list_append (self->wrong_strings,
|
||||
g_strdup (self->current_string));
|
||||
structure = gst_structure_new_from_string (self->current_string);
|
||||
|
||||
return;
|
||||
}
|
||||
if (structure == NULL) {
|
||||
GST_ERROR ("Could not parse %s", self->current_string);
|
||||
|
||||
self->structures = g_list_append (self->structures, structure);
|
||||
g_free (self->current_string);
|
||||
self->current_string = NULL;
|
||||
self->wrong_strings = g_list_append (self->wrong_strings,
|
||||
g_strdup (self->current_string));
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
self->structures = g_list_append (self->structures, structure);
|
||||
g_free (self->current_string);
|
||||
self->current_string = NULL;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
ges_structure_parser_end_of_file (GESStructureParser * self)
|
||||
{
|
||||
|
@ -146,6 +149,8 @@ ges_structure_parser_parse_symbol (GESStructureParser * self,
|
|||
ges_structure_parser_parse_string (self, "transition, type=(string)", TRUE);
|
||||
else if (!g_ascii_strncasecmp (symbol, "title", 5))
|
||||
ges_structure_parser_parse_string (self, "title, text=(string)", TRUE);
|
||||
else if (!g_ascii_strncasecmp (symbol, "track", 5))
|
||||
ges_structure_parser_parse_string (self, "track, type=(string)", TRUE);
|
||||
}
|
||||
|
||||
void
|
||||
|
|
|
@ -569,6 +569,69 @@ beach:
|
|||
return res;
|
||||
}
|
||||
|
||||
gboolean
|
||||
_ges_add_track_from_struct (GESTimeline * timeline,
|
||||
GstStructure * structure, GError ** error)
|
||||
{
|
||||
const gchar *ttype;
|
||||
GESTrack *track;
|
||||
GstCaps *caps;
|
||||
|
||||
const gchar *valid_fields[] = { "type", "restrictions", NULL };
|
||||
|
||||
FieldsError fields_error = { valid_fields, NULL };
|
||||
|
||||
if (!_check_fields (structure, fields_error, error))
|
||||
return FALSE;
|
||||
|
||||
ttype = gst_structure_get_string (structure, "type");
|
||||
if (!g_strcmp0 (ttype, "video")) {
|
||||
track = GES_TRACK (ges_video_track_new ());
|
||||
} else if (!g_strcmp0 (ttype, "audio")) {
|
||||
track = GES_TRACK (ges_audio_track_new ());
|
||||
} else {
|
||||
g_set_error (error, GES_ERROR, 0, "Unhandled track type: `%s`", ttype);
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
if (gst_structure_has_field (structure, "restrictions")) {
|
||||
GstStructure *restriction_struct;
|
||||
gchar *restriction_str;
|
||||
|
||||
if (gst_structure_get (structure, "restrictions", GST_TYPE_STRUCTURE,
|
||||
&restriction_struct, NULL)) {
|
||||
caps = gst_caps_new_full (restriction_struct, NULL);
|
||||
} else if (gst_structure_get (structure, "restrictions", G_TYPE_STRING,
|
||||
&restriction_str, NULL)) {
|
||||
caps = gst_caps_from_string (restriction_str);
|
||||
|
||||
if (!caps) {
|
||||
g_set_error (error, GES_ERROR, 0, "Invalid restrictions caps: %s",
|
||||
restriction_str);
|
||||
|
||||
g_free (restriction_str);
|
||||
return FALSE;
|
||||
}
|
||||
g_free (restriction_str);
|
||||
} else if (!gst_structure_get (structure, "restrictions", GST_TYPE_CAPS,
|
||||
&caps, NULL)) {
|
||||
gchar *tmp = gst_structure_to_string (structure);
|
||||
|
||||
g_set_error (error, GES_ERROR, 0, "Can't use restrictions caps from %s",
|
||||
tmp);
|
||||
|
||||
g_object_unref (track);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
ges_track_set_restriction_caps (track, caps);
|
||||
gst_caps_unref (caps);
|
||||
}
|
||||
|
||||
return ges_timeline_add_track (timeline, track);
|
||||
}
|
||||
|
||||
gboolean
|
||||
_ges_container_add_child_from_struct (GESTimeline * timeline,
|
||||
GstStructure * structure, GError ** error)
|
||||
|
|
|
@ -36,6 +36,11 @@ _ges_add_clip_from_struct (GESTimeline * timeline,
|
|||
GstStructure * structure,
|
||||
GError ** error);
|
||||
|
||||
G_GNUC_INTERNAL gboolean
|
||||
_ges_add_track_from_struct (GESTimeline * timeline,
|
||||
GstStructure * structure,
|
||||
GError ** error);
|
||||
|
||||
G_GNUC_INTERNAL gboolean
|
||||
_ges_container_add_child_from_struct (GESTimeline * timeline,
|
||||
GstStructure * structure,
|
||||
|
|
|
@ -16,6 +16,7 @@ TEST_CLIP [ ]+\+test-clip[ ]+
|
|||
TRANSITION [ ]+\+transition[ ]+
|
||||
EFFECT [ ]+\+effect[ ]+
|
||||
TITLE [ ]+\+title[ ]+
|
||||
TRACK [ ]+\+track[ ]+
|
||||
|
||||
SETTER [ ]+set-[^ ]+[ ]+
|
||||
|
||||
|
@ -35,7 +36,7 @@ VALUE {STRING}|([abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0
|
|||
ges_structure_parser_parse_string (yyextra, yytext, FALSE);
|
||||
}
|
||||
|
||||
{CLIP}|{TRANSITION}|{EFFECT}|{TEST_CLIP}|{TITLE} {
|
||||
{TRACK}|{CLIP}|{TRANSITION}|{EFFECT}|{TEST_CLIP}|{TITLE} {
|
||||
ges_structure_parser_parse_symbol (yyextra, yytext);
|
||||
}
|
||||
|
||||
|
|
|
@ -716,6 +716,7 @@ 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;
|
||||
|
@ -723,8 +724,37 @@ _create_timeline (GESLauncher * self, const gchar * serialized_timeline,
|
|||
if (proj_uri != NULL) {
|
||||
project = ges_project_new (proj_uri);
|
||||
} else if (!validate) {
|
||||
GST_INFO ("serialized timeline is %s", serialized_timeline);
|
||||
project = ges_project_new (serialized_timeline);
|
||||
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);
|
||||
} else {
|
||||
project = ges_project_new (NULL);
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue