Mark nested timeline assets as such

Adding a property to let the application know

Also make sure that the duration of nested timeline assets is reported
as CLOCK_TIME_NONE as those are extended as necessary.

And make a difference between asset duration and their max duration
As nested timelines can be extended 'infinitely' those max duration
is GST_CLOCK_TIME_NONE, but their duration is the real duration of
the timeline.
This commit is contained in:
Thibault Saunier 2019-07-11 16:23:47 -04:00
parent 6f9e6d3586
commit abb4f005e3
4 changed files with 61 additions and 4 deletions

View file

@ -94,6 +94,7 @@ enum
{
PROP_0,
PROP_DURATION,
PROP_IS_NESTED_TIMELINE,
PROP_LAST
};
static GParamSpec *properties[PROP_LAST];
@ -102,7 +103,9 @@ struct _GESUriClipAssetPrivate
{
GstDiscovererInfo *info;
GstClockTime duration;
GstClockTime max_duration;
gboolean is_image;
gboolean is_nested_timeline;
GList *asset_trackfilesources;
};
@ -136,6 +139,9 @@ ges_uri_clip_asset_get_property (GObject * object, guint property_id,
case PROP_DURATION:
g_value_set_uint64 (value, priv->duration);
break;
case PROP_IS_NESTED_TIMELINE:
g_value_set_boolean (value, priv->is_nested_timeline);
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
}
@ -272,6 +278,17 @@ ges_uri_clip_asset_class_init (GESUriClipAssetClass * klass)
g_object_class_install_property (object_class, PROP_DURATION,
properties[PROP_DURATION]);
/**
* GESUriClipAsset:is-nested-timeline:
*
* The duration (in nanoseconds) of the media file
*/
properties[PROP_IS_NESTED_TIMELINE] =
g_param_spec_boolean ("is-nested-timeline", "Is nested timeline",
"Whether this is a nested timeline", FALSE, G_PARAM_READABLE);
g_object_class_install_property (object_class, PROP_IS_NESTED_TIMELINE,
properties[PROP_IS_NESTED_TIMELINE]);
_ges_uri_asset_ensure_setup (klass);
}
@ -283,7 +300,7 @@ ges_uri_clip_asset_init (GESUriClipAsset * self)
priv = self->priv = ges_uri_clip_asset_get_instance_private (self);
priv->info = NULL;
priv->duration = GST_CLOCK_TIME_NONE;
priv->max_duration = priv->duration = GST_CLOCK_TIME_NONE;
priv->is_image = FALSE;
}
@ -329,6 +346,7 @@ ges_uri_clip_asset_set_info (GESUriClipAsset * self, GstDiscovererInfo * info)
GESTrackType supportedformats = GES_TRACK_TYPE_UNKNOWN;
GESUriClipAssetPrivate *priv = GES_URI_CLIP_ASSET (self)->priv;
const GstTagList *tlist = gst_discoverer_info_get_tags (info);
/* Extract infos from the GstDiscovererInfo */
stream_list = gst_discoverer_info_get_stream_list (info);
@ -364,8 +382,16 @@ ges_uri_clip_asset_set_info (GESUriClipAsset * self, GstDiscovererInfo * info)
if (stream_list)
gst_discoverer_stream_info_list_free (stream_list);
if (priv->is_image == FALSE)
priv->duration = gst_discoverer_info_get_duration (info);
if (tlist)
gst_tag_list_get_boolean (tlist, "is-ges-timeline",
&priv->is_nested_timeline);
if (priv->is_image == FALSE) {
priv->max_duration = priv->duration =
gst_discoverer_info_get_duration (info);
if (priv->is_nested_timeline)
priv->max_duration = GST_CLOCK_TIME_NONE;
}
/* else we keep #GST_CLOCK_TIME_NONE */
priv->info = gst_object_ref (info);
@ -500,6 +526,28 @@ ges_uri_clip_asset_get_duration (GESUriClipAsset * self)
return self->priv->duration;
}
/**
* ges_uri_clip_asset_get_max_duration:
* @self: a #GESUriClipAsset
*
* Gets maximum duration of the file represented by @self,
* it is usually the same as GESUriClipAsset::duration,
* but in the case of nested timelines, for example, they
* are different as those can be extended 'infinitely'.
*
* Returns: The maximum duration of @self
*
* Since: 1.18
*/
GstClockTime
ges_uri_clip_asset_get_max_duration (GESUriClipAsset * self)
{
g_return_val_if_fail (GES_IS_URI_CLIP_ASSET (self), GST_CLOCK_TIME_NONE);
return self->priv->max_duration;
}
/**
* ges_uri_clip_asset_is_image:
* @self: a #GESUriClipAsset

View file

@ -78,6 +78,8 @@ GstDiscovererInfo *ges_uri_clip_asset_get_info (const GESUriClipAsset * sel
GES_API
GstClockTime ges_uri_clip_asset_get_duration (GESUriClipAsset *self);
GES_API
GstClockTime ges_uri_clip_asset_get_max_duration (GESUriClipAsset *self);
GES_API
gboolean ges_uri_clip_asset_is_image (GESUriClipAsset *self);
GES_API
void ges_uri_clip_asset_new (const gchar *uri,

View file

@ -299,7 +299,7 @@ extractable_set_asset (GESExtractable * self, GESAsset * asset)
ges_uri_clip_asset_get_duration (uri_clip_asset));
ges_timeline_element_set_max_duration (GES_TIMELINE_ELEMENT (uriclip),
ges_uri_clip_asset_get_duration (uri_clip_asset));
ges_uri_clip_asset_get_max_duration (uri_clip_asset));
ges_uri_clip_set_is_image (uriclip,
ges_uri_clip_asset_is_image (uri_clip_asset));

View file

@ -113,6 +113,8 @@ ges_demux_class_init (GESDemuxClass * self_class)
GST_DEBUG_CATEGORY_INIT (gesdemux, "gesdemux", 0, "ges demux element");
gst_tag_register ("is-ges-timeline", GST_TAG_FLAG_META, G_TYPE_BOOLEAN,
"is-ges-timeline", "The stream is a ges timeline.", NULL);
gclass->get_property = ges_demux_get_property;
gclass->set_property = ges_demux_set_property;
@ -259,9 +261,14 @@ static gboolean
ges_demux_set_srcpad_probe (GstElement * element, GstPad * pad,
gpointer user_data)
{
GstTagList *tlist = gst_tag_list_new ("is-ges-timeline", TRUE, NULL);
gst_pad_add_probe (pad,
GST_PAD_PROBE_TYPE_EVENT_DOWNSTREAM | GST_PAD_PROBE_TYPE_QUERY_UPSTREAM,
(GstPadProbeCallback) ges_demux_src_probe, element, NULL);
gst_tag_list_set_scope (tlist, GST_TAG_SCOPE_GLOBAL);
gst_pad_push_event (pad, gst_event_new_tag (tlist));
return TRUE;
}