clip: use time translation for split

The new in-point should be the media position corresponding to the media
position. media_duration_factor is no longer needed.

Part-of: <https://gitlab.freedesktop.org/gstreamer/gst-editing-services/-/merge_requests/177>
This commit is contained in:
Henry Wilkes 2020-05-15 14:41:58 +01:00
parent e36e99e1ce
commit 364c112d66
4 changed files with 33 additions and 55 deletions

View file

@ -2957,8 +2957,9 @@ ges_clip_split_full (GESClip * clip, guint64 position, GError ** error)
{ {
GList *tmp, *transitions = NULL; GList *tmp, *transitions = NULL;
GESClip *new_object; GESClip *new_object;
GstClockTime start, inpoint, duration, old_duration, new_duration; gboolean no_core = FALSE;
gdouble media_duration_factor; GstClockTime start, inpoint, duration, old_duration, new_duration,
new_inpoint;
GESTimelineElement *element; GESTimelineElement *element;
GESTimeline *timeline; GESTimeline *timeline;
GHashTable *track_for_copy; GHashTable *track_for_copy;
@ -2985,6 +2986,18 @@ ges_clip_split_full (GESClip * clip, guint64 position, GError ** error)
layer_prio = ges_timeline_element_get_layer_priority (element); layer_prio = ges_timeline_element_get_layer_priority (element);
old_duration = position - start; old_duration = position - start;
new_duration = duration + start - position;
/* convert the split position into an internal core time */
new_inpoint = _convert_core_time (clip, position, FALSE, &no_core, error);
/* if the split clip does not contain any active core elements with
* an internal source, just set the in-point to 0 for the new_object */
if (no_core)
new_inpoint = 0;
if (!GST_CLOCK_TIME_IS_VALID (new_inpoint))
return NULL;
if (timeline if (timeline
&& !timeline_tree_can_move_element (timeline_get_tree (timeline), element, && !timeline_tree_can_move_element (timeline_get_tree (timeline), element,
layer_prio, start, old_duration, error)) { layer_prio, start, old_duration, error)) {
@ -2995,7 +3008,6 @@ ges_clip_split_full (GESClip * clip, guint64 position, GError ** error)
return NULL; return NULL;
} }
new_duration = duration + start - position;
if (timeline if (timeline
&& !timeline_tree_can_move_element (timeline_get_tree (timeline), element, && !timeline_tree_can_move_element (timeline_get_tree (timeline), element,
layer_prio, position, new_duration, error)) { layer_prio, position, new_duration, error)) {
@ -3011,16 +3023,27 @@ ges_clip_split_full (GESClip * clip, guint64 position, GError ** error)
/* Create the new Clip */ /* Create the new Clip */
new_object = GES_CLIP (ges_timeline_element_copy (element, FALSE)); new_object = GES_CLIP (ges_timeline_element_copy (element, FALSE));
new_object->priv->prevent_duration_limit_update = TRUE;
GST_DEBUG_OBJECT (new_object, "New 'splitted' clip"); GST_DEBUG_OBJECT (new_object, "New 'splitted' clip");
/* Set new timing properties on the Clip */ /* Set new timing properties on the Clip */
media_duration_factor =
ges_timeline_element_get_media_duration_factor (element);
_set_start0 (GES_TIMELINE_ELEMENT (new_object), position); _set_start0 (GES_TIMELINE_ELEMENT (new_object), position);
_set_inpoint0 (GES_TIMELINE_ELEMENT (new_object), _set_inpoint0 (GES_TIMELINE_ELEMENT (new_object), new_inpoint);
inpoint + old_duration * media_duration_factor);
_set_duration0 (GES_TIMELINE_ELEMENT (new_object), new_duration); _set_duration0 (GES_TIMELINE_ELEMENT (new_object), new_duration);
/* NOTE: it is technically possible that the new_object may shrink
* later on in this method if the clip contains any non-linear time
* effects, which cause the duration-limit to drop. However, this
* should be safe since we have already checked with timeline-tree
* that the split position is not in the middle of an overlap. This
* means that the new_object should only be overlapping another
* element on its end, which makes shrinking safe.
*
* The original clip, however, should not shrink if the time effects
* obey the property that they do not depend on how much data they
* receive, which should be true for the time effects supported by GES.
*/
/* split binding before duration changes since shrinking can destroy /* split binding before duration changes since shrinking can destroy
* binding values */ * binding values */
track_for_copy = g_hash_table_new_full (NULL, NULL, track_for_copy = g_hash_table_new_full (NULL, NULL,
@ -3088,6 +3111,9 @@ ges_clip_split_full (GESClip * clip, guint64 position, GError ** error)
g_hash_table_unref (track_for_copy); g_hash_table_unref (track_for_copy);
g_list_free_full (transitions, gst_object_unref); g_list_free_full (transitions, gst_object_unref);
new_object->priv->prevent_duration_limit_update = FALSE;
_update_duration_limit (new_object);
return new_object; return new_object;
} }

View file

@ -491,7 +491,6 @@ typedef enum
} GESTimelineElementFlags; } GESTimelineElementFlags;
G_GNUC_INTERNAL GESTimelineElement * ges_timeline_element_peak_toplevel (GESTimelineElement * self); G_GNUC_INTERNAL GESTimelineElement * ges_timeline_element_peak_toplevel (GESTimelineElement * self);
G_GNUC_INTERNAL gdouble ges_timeline_element_get_media_duration_factor(GESTimelineElement *self);
G_GNUC_INTERNAL GESTimelineElement * ges_timeline_element_get_copied_from (GESTimelineElement *self); G_GNUC_INTERNAL GESTimelineElement * ges_timeline_element_get_copied_from (GESTimelineElement *self);
G_GNUC_INTERNAL GESTimelineElementFlags ges_timeline_element_flags (GESTimelineElement *self); G_GNUC_INTERNAL GESTimelineElementFlags ges_timeline_element_flags (GESTimelineElement *self);
G_GNUC_INTERNAL void ges_timeline_element_set_flags (GESTimelineElement *self, GESTimelineElementFlags flags); G_GNUC_INTERNAL void ges_timeline_element_set_flags (GESTimelineElement *self, GESTimelineElementFlags flags);

View file

@ -726,49 +726,6 @@ ges_timeline_element_peak_toplevel (GESTimelineElement * self)
return toplevel; return toplevel;
} }
gdouble
ges_timeline_element_get_media_duration_factor (GESTimelineElement * self)
{
gdouble media_duration_factor;
GESEffectClass *class;
GList *props;
media_duration_factor = 1.0;
class = GES_EFFECT_CLASS (g_type_class_ref (GES_TYPE_EFFECT));
for (props = class->rate_properties; props != NULL; props = props->next) {
GObject *child;
GParamSpec *pspec;
if (ges_timeline_element_lookup_child (self, props->data, &child, &pspec)) {
if (G_PARAM_SPEC_VALUE_TYPE (pspec) == G_TYPE_FLOAT) {
gfloat rate_change;
g_object_get (child, pspec->name, &rate_change, NULL);
media_duration_factor *= rate_change;
} else if (G_PARAM_SPEC_VALUE_TYPE (pspec) == G_TYPE_DOUBLE) {
gdouble rate_change;
g_object_get (child, pspec->name, &rate_change, NULL);
media_duration_factor *= rate_change;
} else {
GST_WARNING_OBJECT (self,
"Rate property %s in child %" GST_PTR_FORMAT
" is of unsupported type %s", pspec->name, child,
G_VALUE_TYPE_NAME (pspec->value_type));
}
gst_object_unref (child);
g_param_spec_unref (pspec);
GST_DEBUG_OBJECT (self,
"Added rate changing property %s, set to value %lf",
(const char *) props->data, media_duration_factor);
}
}
g_type_class_unref (class);
return media_duration_factor;
}
GESTimelineElement * GESTimelineElement *
ges_timeline_element_get_copied_from (GESTimelineElement * self) ges_timeline_element_get_copied_from (GESTimelineElement * self)
{ {

View file

@ -76,10 +76,6 @@ GST_START_TEST (test_tempochange)
fail_unless_equals_int64 (_INPOINT (clip3), 7.5 * GST_SECOND); fail_unless_equals_int64 (_INPOINT (clip3), 7.5 * GST_SECOND);
fail_unless_equals_int64 (_DURATION (clip3), 3 * GST_SECOND); fail_unless_equals_int64 (_DURATION (clip3), 3 * GST_SECOND);
ges_layer_remove_clip (layer, (GESClip *) clip);
ges_layer_remove_clip (layer, clip2);
ges_layer_remove_clip (layer, clip3);
gst_object_unref (timeline); gst_object_unref (timeline);
ges_deinit (); ges_deinit ();