summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMathieu Duponchelle <mathieu@centricular.com>2021-08-10 23:25:06 +0200
committerMathieu Duponchelle <mathieu@centricular.com>2021-08-20 00:11:45 +0200
commit148c751bc06541769123d07c418e2b00f1f57c27 (patch)
treedfe659527e5bd8b7ddf7f692cfd2d3c6abee6fd3
parentee35cba6e837d961224a20b75273e2743fd4696a (diff)
ges-launcher: allow using a clip to determine the rendering format
This includes both topology and profile Part-of: <https://gitlab.freedesktop.org/gstreamer/gst-editing-services/-/merge_requests/265>
-rw-r--r--tools/ges-launcher.c147
-rw-r--r--tools/utils.h1
2 files changed, 136 insertions, 12 deletions
diff --git a/tools/ges-launcher.c b/tools/ges-launcher.c
index 43d17d97..f6fde10e 100644
--- a/tools/ges-launcher.c
+++ b/tools/ges-launcher.c
@@ -388,25 +388,93 @@ sort_encoding_profiles (gconstpointer a, gconstpointer b)
return 1;
}
-static GstEncodingProfile *
-get_smart_profile (GESLauncher * self)
+static GList *
+_timeline_assets (GESLauncher * self)
{
- gint n_audio, n_video;
- GList *tmp, *assets = NULL, *possible_profiles = NULL;
- GstEncodingProfile *res = NULL;
+ GList *tmp, *assets = NULL;
- _check_has_audio_video (self, &n_audio, &n_video);
for (tmp = self->priv->timeline->layers; tmp; tmp = tmp->next) {
GList *tclip, *clips = ges_layer_get_clips (tmp->data);
for (tclip = clips; tclip; tclip = tclip->next) {
- if (GES_IS_URI_CLIP (tclip->data))
+ if (GES_IS_URI_CLIP (tclip->data)) {
assets =
g_list_append (assets, ges_extractable_get_asset (tclip->data));
+ }
}
g_list_free_full (clips, gst_object_unref);
}
+ return assets;
+}
+
+static GESAsset *
+_asset_for_named_clip (GESLauncher * self, const gchar * name)
+{
+ GList *tmp;
+ GESAsset *ret = NULL;
+
+ for (tmp = self->priv->timeline->layers; tmp; tmp = tmp->next) {
+ GList *tclip, *clips = ges_layer_get_clips (tmp->data);
+
+ for (tclip = clips; tclip; tclip = tclip->next) {
+ if (GES_IS_URI_CLIP (tclip->data) &&
+ !g_strcmp0 (name, ges_timeline_element_get_name (tclip->data))) {
+ ret = ges_extractable_get_asset (tclip->data);
+ break;
+ }
+ }
+
+ g_list_free_full (clips, gst_object_unref);
+
+ if (ret)
+ break;
+ }
+
+ return ret;
+}
+
+static GstEncodingProfile *
+_get_profile_from (GESLauncher * self)
+{
+ GESAsset *asset =
+ _asset_for_named_clip (self, self->priv->parsed_options.profile_from);
+ GstDiscovererInfo *info;
+ GstEncodingProfile *prof;
+
+ g_assert (asset);
+
+ info = ges_uri_clip_asset_get_info (GES_URI_CLIP_ASSET (asset));
+ prof = gst_encoding_profile_from_discoverer (info);
+
+ return prof;
+}
+
+static GstEncodingProfile *
+get_smart_profile (GESLauncher * self)
+{
+ gint n_audio, n_video;
+ GList *tmp, *assets, *possible_profiles = NULL;
+ GstEncodingProfile *res = NULL;
+
+ if (self->priv->parsed_options.profile_from) {
+ GESAsset *asset =
+ _asset_for_named_clip (self, self->priv->parsed_options.profile_from);
+ GstDiscovererInfo *info;
+ GstEncodingProfile *prof;
+
+ g_assert (asset);
+
+ info = ges_uri_clip_asset_get_info (GES_URI_CLIP_ASSET (asset));
+ prof = gst_encoding_profile_from_discoverer (info);
+
+ return prof;
+ }
+
+ _check_has_audio_video (self, &n_audio, &n_video);
+
+ assets = _timeline_assets (self);
+
for (tmp = assets; tmp; tmp = tmp->next) {
GESAsset *asset = tmp->data;
GList *audio_streams, *video_streams;
@@ -503,7 +571,9 @@ _set_rendering_details (GESLauncher * self)
if (!prof) {
if (opts->format == NULL) {
- if (opts->smartrender)
+ if (opts->profile_from)
+ prof = _get_profile_from (self);
+ else if (opts->smartrender)
prof = get_smart_profile (self);
if (prof)
smart_profile = TRUE;
@@ -591,6 +661,46 @@ _timeline_set_user_options (GESLauncher * self, GESTimeline * timeline,
gboolean has_audio = FALSE, has_video = FALSE;
GESLauncherParsedOptions *opts = &self->priv->parsed_options;
+ if (self->priv->parsed_options.profile_from) {
+ GList *tmp, *tracks;
+ GList *audio_streams, *video_streams;
+ GESAsset *asset =
+ _asset_for_named_clip (self, self->priv->parsed_options.profile_from);
+ GstDiscovererInfo *info;
+ guint i;
+
+ if (!asset) {
+ ges_printerr
+ ("\nERROR: can't create profile from named clip, no such clip %s\n\n",
+ self->priv->parsed_options.profile_from);
+ return FALSE;
+ }
+
+ tracks = ges_timeline_get_tracks (self->priv->timeline);
+
+ for (tmp = tracks; tmp; tmp = tmp->next) {
+ ges_timeline_remove_track (timeline, tmp->data);
+ }
+
+ g_list_free_full (tracks, gst_object_unref);
+
+ info = ges_uri_clip_asset_get_info (GES_URI_CLIP_ASSET (asset));
+
+ audio_streams = gst_discoverer_info_get_audio_streams (info);
+ video_streams = gst_discoverer_info_get_video_streams (info);
+
+ for (i = 0; i < g_list_length (audio_streams); i++) {
+ ges_timeline_add_track (timeline, GES_TRACK (ges_audio_track_new ()));
+ }
+
+ for (i = 0; i < g_list_length (video_streams); i++) {
+ ges_timeline_add_track (timeline, GES_TRACK (ges_video_track_new ()));
+ }
+
+ gst_discoverer_stream_info_list_free (audio_streams);
+ gst_discoverer_stream_info_list_free (video_streams);
+ }
+
retry:
for (tmp = timeline->tracks; tmp; tmp = tmp->next) {
@@ -600,13 +710,17 @@ retry:
has_audio = TRUE;
_track_set_mixing (tmp->data, opts);
- if (!(GES_TRACK (tmp->data)->type & opts->track_types)) {
- ges_timeline_remove_track (timeline, tmp->data);
- goto retry;
+
+ if (!self->priv->parsed_options.profile_from) {
+ if (!(GES_TRACK (tmp->data)->type & opts->track_types)) {
+ ges_timeline_remove_track (timeline, tmp->data);
+ goto retry;
+ }
}
}
- if ((opts->scenario || opts->testfile) && !load_path) {
+ if ((opts->scenario || opts->testfile) && !load_path
+ && !self->priv->parsed_options.profile_from) {
if (!has_video && opts->track_types & GES_TRACK_TYPE_VIDEO) {
trackv = GES_TRACK (ges_video_track_new ());
@@ -981,6 +1095,9 @@ _create_pipeline (GESLauncher * self, const gchar * serialized_timeline)
self->priv->pipeline = ges_pipeline_new ();
+ if (opts->outputuri)
+ ges_pipeline_set_mode (self->priv->pipeline, 0);
+
if (!_create_timeline (self, serialized_timeline, uri, opts->scenario
|| opts->testfile)) {
GST_ERROR ("Could not create the timeline");
@@ -1117,6 +1234,11 @@ ges_launcher_get_rendering_option_group (GESLauncherParsedOptions * opts)
"See ges-launch-1.0 help profile for more information. "
"This will have no effect if no outputuri has been specified.",
"<profile-name>"},
+ {"profile-from", 0, 0, G_OPTION_ARG_STRING, &opts->profile_from,
+ "Use clip with name <clip-name> to determine the topology and profile "
+ "of the rendered output. This will have no effect if no outputuri "
+ "has been specified.",
+ "<clip-name>"},
{"smart-rendering", 0, 0, G_OPTION_ARG_NONE, &opts->smartrender,
"Avoid reencoding when rendering. This option implies --disable-mixing.",
NULL},
@@ -1505,6 +1627,7 @@ _finalize (GObject * object)
g_free (opts->outputuri);
g_free (opts->format);
g_free (opts->encoding_profile);
+ g_free (opts->profile_from);
g_free (opts->videosink);
g_free (opts->audiosink);
g_free (opts->video_track_caps);
diff --git a/tools/utils.h b/tools/utils.h
index afd5ab26..b11b53e6 100644
--- a/tools/utils.h
+++ b/tools/utils.h
@@ -38,6 +38,7 @@ typedef struct
gchar *format;
gchar *outputuri;
gchar *encoding_profile;
+ gchar *profile_from;
gchar *videosink;
gchar *audiosink;
gboolean list_transitions;