clip: use time translation for split
authorHenry Wilkes <hwilkes@igalia.com>
Fri, 15 May 2020 13:41:58 +0000 (14:41 +0100)
committerHenry Wilkes <hwilkes@igalia.com>
Mon, 25 May 2020 10:20:38 +0000 (11:20 +0100)
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>

ges/ges-clip.c
ges/ges-internal.h
ges/ges-timeline-element.c
tests/check/ges/tempochange.c

index 2e74ff0795fa2b7c3761e0a5ee2531d6159fa00a..5b31b823e59124c9e66bf501d989095fe49bc0f2 100644 (file)
@@ -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;
 }
 
index 84911ff5d08d3b6a79ecb119448f3a4096d3dab9..5d5721c307d3a51296512b7d31f76a0223e56c82 100644 (file)
@@ -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);
index aa9e3856fafb160251da60449d91b18c7cc74575..e4a606305524bfc54deaf37db0eb56dcc225c1a9 100644 (file)
@@ -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)
 {
index ba38e122dfef3489968f770103d56ef905033bed..4cc776e5583c4c329a57afafba0ea60716a6e313 100644 (file)
@@ -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 ();