mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer.git
synced 2024-11-23 10:11:08 +00:00
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>
This commit is contained in:
parent
ee35cba6e8
commit
148c751bc0
2 changed files with 136 additions and 12 deletions
|
@ -388,25 +388,93 @@ sort_encoding_profiles (gconstpointer a, gconstpointer b)
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
static GstEncodingProfile *
|
static GList *
|
||||||
get_smart_profile (GESLauncher * self)
|
_timeline_assets (GESLauncher * self)
|
||||||
{
|
{
|
||||||
gint n_audio, n_video;
|
GList *tmp, *assets = NULL;
|
||||||
GList *tmp, *assets = NULL, *possible_profiles = NULL;
|
|
||||||
GstEncodingProfile *res = NULL;
|
|
||||||
|
|
||||||
_check_has_audio_video (self, &n_audio, &n_video);
|
|
||||||
for (tmp = self->priv->timeline->layers; tmp; tmp = tmp->next) {
|
for (tmp = self->priv->timeline->layers; tmp; tmp = tmp->next) {
|
||||||
GList *tclip, *clips = ges_layer_get_clips (tmp->data);
|
GList *tclip, *clips = ges_layer_get_clips (tmp->data);
|
||||||
|
|
||||||
for (tclip = clips; tclip; tclip = tclip->next) {
|
for (tclip = clips; tclip; tclip = tclip->next) {
|
||||||
if (GES_IS_URI_CLIP (tclip->data))
|
if (GES_IS_URI_CLIP (tclip->data)) {
|
||||||
assets =
|
assets =
|
||||||
g_list_append (assets, ges_extractable_get_asset (tclip->data));
|
g_list_append (assets, ges_extractable_get_asset (tclip->data));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
g_list_free_full (clips, gst_object_unref);
|
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) {
|
for (tmp = assets; tmp; tmp = tmp->next) {
|
||||||
GESAsset *asset = tmp->data;
|
GESAsset *asset = tmp->data;
|
||||||
GList *audio_streams, *video_streams;
|
GList *audio_streams, *video_streams;
|
||||||
|
@ -503,7 +571,9 @@ _set_rendering_details (GESLauncher * self)
|
||||||
|
|
||||||
if (!prof) {
|
if (!prof) {
|
||||||
if (opts->format == NULL) {
|
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);
|
prof = get_smart_profile (self);
|
||||||
if (prof)
|
if (prof)
|
||||||
smart_profile = TRUE;
|
smart_profile = TRUE;
|
||||||
|
@ -591,6 +661,46 @@ _timeline_set_user_options (GESLauncher * self, GESTimeline * timeline,
|
||||||
gboolean has_audio = FALSE, has_video = FALSE;
|
gboolean has_audio = FALSE, has_video = FALSE;
|
||||||
GESLauncherParsedOptions *opts = &self->priv->parsed_options;
|
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:
|
retry:
|
||||||
for (tmp = timeline->tracks; tmp; tmp = tmp->next) {
|
for (tmp = timeline->tracks; tmp; tmp = tmp->next) {
|
||||||
|
|
||||||
|
@ -600,13 +710,17 @@ retry:
|
||||||
has_audio = TRUE;
|
has_audio = TRUE;
|
||||||
|
|
||||||
_track_set_mixing (tmp->data, opts);
|
_track_set_mixing (tmp->data, opts);
|
||||||
if (!(GES_TRACK (tmp->data)->type & opts->track_types)) {
|
|
||||||
ges_timeline_remove_track (timeline, tmp->data);
|
if (!self->priv->parsed_options.profile_from) {
|
||||||
goto retry;
|
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) {
|
if (!has_video && opts->track_types & GES_TRACK_TYPE_VIDEO) {
|
||||||
trackv = GES_TRACK (ges_video_track_new ());
|
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 ();
|
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
|
if (!_create_timeline (self, serialized_timeline, uri, opts->scenario
|
||||||
|| opts->testfile)) {
|
|| opts->testfile)) {
|
||||||
GST_ERROR ("Could not create the timeline");
|
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. "
|
"See ges-launch-1.0 help profile for more information. "
|
||||||
"This will have no effect if no outputuri has been specified.",
|
"This will have no effect if no outputuri has been specified.",
|
||||||
"<profile-name>"},
|
"<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,
|
{"smart-rendering", 0, 0, G_OPTION_ARG_NONE, &opts->smartrender,
|
||||||
"Avoid reencoding when rendering. This option implies --disable-mixing.",
|
"Avoid reencoding when rendering. This option implies --disable-mixing.",
|
||||||
NULL},
|
NULL},
|
||||||
|
@ -1505,6 +1627,7 @@ _finalize (GObject * object)
|
||||||
g_free (opts->outputuri);
|
g_free (opts->outputuri);
|
||||||
g_free (opts->format);
|
g_free (opts->format);
|
||||||
g_free (opts->encoding_profile);
|
g_free (opts->encoding_profile);
|
||||||
|
g_free (opts->profile_from);
|
||||||
g_free (opts->videosink);
|
g_free (opts->videosink);
|
||||||
g_free (opts->audiosink);
|
g_free (opts->audiosink);
|
||||||
g_free (opts->video_track_caps);
|
g_free (opts->video_track_caps);
|
||||||
|
|
|
@ -38,6 +38,7 @@ typedef struct
|
||||||
gchar *format;
|
gchar *format;
|
||||||
gchar *outputuri;
|
gchar *outputuri;
|
||||||
gchar *encoding_profile;
|
gchar *encoding_profile;
|
||||||
|
gchar *profile_from;
|
||||||
gchar *videosink;
|
gchar *videosink;
|
||||||
gchar *audiosink;
|
gchar *audiosink;
|
||||||
gboolean list_transitions;
|
gboolean list_transitions;
|
||||||
|
|
Loading…
Reference in a new issue