diff --git a/ges/ges-clip.c b/ges/ges-clip.c index 2e74ff0795..5b31b823e5 100644 --- a/ges/ges-clip.c +++ b/ges/ges-clip.c @@ -2957,8 +2957,9 @@ ges_clip_split_full (GESClip * clip, guint64 position, GError ** error) { GList *tmp, *transitions = NULL; GESClip *new_object; - GstClockTime start, inpoint, duration, old_duration, new_duration; - gdouble media_duration_factor; + gboolean no_core = FALSE; + GstClockTime start, inpoint, duration, old_duration, new_duration, + new_inpoint; GESTimelineElement *element; GESTimeline *timeline; 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); 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 && !timeline_tree_can_move_element (timeline_get_tree (timeline), element, layer_prio, start, old_duration, error)) { @@ -2995,7 +3008,6 @@ ges_clip_split_full (GESClip * clip, guint64 position, GError ** error) return NULL; } - new_duration = duration + start - position; if (timeline && !timeline_tree_can_move_element (timeline_get_tree (timeline), element, layer_prio, position, new_duration, error)) { @@ -3011,16 +3023,27 @@ ges_clip_split_full (GESClip * clip, guint64 position, GError ** error) /* Create the new Clip */ 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"); /* 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_inpoint0 (GES_TIMELINE_ELEMENT (new_object), - inpoint + old_duration * media_duration_factor); + _set_inpoint0 (GES_TIMELINE_ELEMENT (new_object), new_inpoint); _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 * binding values */ 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_list_free_full (transitions, gst_object_unref); + new_object->priv->prevent_duration_limit_update = FALSE; + _update_duration_limit (new_object); + return new_object; } diff --git a/ges/ges-internal.h b/ges/ges-internal.h index 84911ff5d0..5d5721c307 100644 --- a/ges/ges-internal.h +++ b/ges/ges-internal.h @@ -491,7 +491,6 @@ typedef enum } GESTimelineElementFlags; 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 GESTimelineElementFlags ges_timeline_element_flags (GESTimelineElement *self); G_GNUC_INTERNAL void ges_timeline_element_set_flags (GESTimelineElement *self, GESTimelineElementFlags flags); diff --git a/ges/ges-timeline-element.c b/ges/ges-timeline-element.c index aa9e3856fa..e4a6063055 100644 --- a/ges/ges-timeline-element.c +++ b/ges/ges-timeline-element.c @@ -726,49 +726,6 @@ ges_timeline_element_peak_toplevel (GESTimelineElement * self) 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 * ges_timeline_element_get_copied_from (GESTimelineElement * self) { diff --git a/tests/check/ges/tempochange.c b/tests/check/ges/tempochange.c index ba38e122df..4cc776e558 100644 --- a/tests/check/ges/tempochange.c +++ b/tests/check/ges/tempochange.c @@ -76,10 +76,6 @@ GST_START_TEST (test_tempochange) fail_unless_equals_int64 (_INPOINT (clip3), 7.5 * 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); ges_deinit ();