mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer.git
synced 2024-11-26 03:31:05 +00:00
timeline-tree: also trim non-core track elements
Also trim the in-point of non-core children of clips to ensure that their content will appear in the timeline at the same position. Part-of: <https://gitlab.freedesktop.org/gstreamer/gst-editing-services/-/merge_requests/169>
This commit is contained in:
parent
faa9d3990b
commit
b00c01ded7
2 changed files with 153 additions and 16 deletions
|
@ -869,9 +869,64 @@ set_edit_move_values (GESTimelineElement * element, EditData * data)
|
|||
return set_layer_priority (element, data);
|
||||
}
|
||||
|
||||
static gboolean
|
||||
set_edit_trim_start_inpoint_value (GESTimelineElement * element,
|
||||
EditData * data)
|
||||
{
|
||||
GstClockTime new_inpoint = _clock_time_minus_diff (element->inpoint,
|
||||
data->offset, NULL);
|
||||
if (!GST_CLOCK_TIME_IS_VALID (new_inpoint)) {
|
||||
GST_INFO_OBJECT (element, "Cannot trim start of %" GES_FORMAT
|
||||
" with offset %" G_GINT64_FORMAT " because it would result in an "
|
||||
"invalid in-point", GES_ARGS (element), data->offset);
|
||||
return FALSE;
|
||||
}
|
||||
data->inpoint = new_inpoint;
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
set_edit_trim_start_non_core_children (GESTimelineElement * clip,
|
||||
GstClockTimeDiff offset, GHashTable * edit_table)
|
||||
{
|
||||
GList *tmp;
|
||||
GESTimelineElement *child;
|
||||
GESTrackElement *el;
|
||||
EditData *data;
|
||||
|
||||
/* need to set in-point of active non-core children to keep their
|
||||
* internal content at the same timeline position. This also ensures
|
||||
* the duration-limit will not be broken */
|
||||
for (tmp = GES_CONTAINER_CHILDREN (clip); tmp; tmp = tmp->next) {
|
||||
child = tmp->data;
|
||||
el = tmp->data;
|
||||
if (ges_track_element_has_internal_source (el)
|
||||
&& ges_track_element_is_active (el)
|
||||
&& !GES_TRACK_ELEMENT_IS_CORE (child)) {
|
||||
|
||||
GST_INFO_OBJECT (child, "Setting track element %s to trim in-point "
|
||||
"with offset %" G_GINT64_FORMAT " since the parent clip %"
|
||||
GES_FORMAT " is being trimmed at its start", child->name, offset,
|
||||
GES_ARGS (clip));
|
||||
|
||||
if (g_hash_table_contains (edit_table, child)) {
|
||||
GST_ERROR_OBJECT (child, "Already set to be edited");
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
data = new_edit_data (EDIT_TRIM_START, offset, 0);
|
||||
g_hash_table_insert (edit_table, child, data);
|
||||
if (!set_edit_trim_start_inpoint_value (child, data))
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/* trim the start of a clip or a track element */
|
||||
static gboolean
|
||||
set_edit_trim_start_values (GESTimelineElement * element, EditData * data)
|
||||
set_edit_trim_start_values (GESTimelineElement * element, EditData * data,
|
||||
GHashTable * edit_table)
|
||||
{
|
||||
GstClockTime new_start =
|
||||
_clock_time_minus_diff (element->start, data->offset, NULL);
|
||||
|
@ -892,18 +947,16 @@ set_edit_trim_start_values (GESTimelineElement * element, EditData * data)
|
|||
}
|
||||
_CHECK_END (element, new_start, new_duration);
|
||||
|
||||
if (!GES_IS_TRACK_ELEMENT (element)
|
||||
|| ges_track_element_has_internal_source (GES_TRACK_ELEMENT (element))) {
|
||||
GstClockTime new_inpoint =
|
||||
_clock_time_minus_diff (element->inpoint, data->offset, NULL);
|
||||
if (!GST_CLOCK_TIME_IS_VALID (new_inpoint)) {
|
||||
GST_INFO_OBJECT (element, "Cannot trim start of %" GES_FORMAT
|
||||
" with offset %" G_GINT64_FORMAT " because it would result in an "
|
||||
"invalid in-point", GES_ARGS (element), data->offset);
|
||||
if (GES_IS_CLIP (element)) {
|
||||
if (!set_edit_trim_start_inpoint_value (element, data))
|
||||
return FALSE;
|
||||
if (!set_edit_trim_start_non_core_children (element, data->offset,
|
||||
edit_table))
|
||||
return FALSE;
|
||||
} else if (GES_IS_TRACK_ELEMENT (element)
|
||||
&& ges_track_element_has_internal_source (GES_TRACK_ELEMENT (element))) {
|
||||
if (!set_edit_trim_start_inpoint_value (element, data))
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
data->inpoint = new_inpoint;
|
||||
}
|
||||
data->start = new_start;
|
||||
data->duration = new_duration;
|
||||
|
@ -955,13 +1008,14 @@ set_edit_trim_end_values (GESTimelineElement * element, EditData * data)
|
|||
|
||||
/* handles clips and track elements with no parents */
|
||||
static gboolean
|
||||
set_clip_edit_values (GESTimelineElement * element, EditData * data)
|
||||
set_clip_edit_values (GESTimelineElement * element, EditData * data,
|
||||
GHashTable * edit_table)
|
||||
{
|
||||
switch (data->mode) {
|
||||
case EDIT_MOVE:
|
||||
return set_edit_move_values (element, data);
|
||||
case EDIT_TRIM_START:
|
||||
return set_edit_trim_start_values (element, data);
|
||||
return set_edit_trim_start_values (element, data, edit_table);
|
||||
case EDIT_TRIM_END:
|
||||
return set_edit_trim_end_values (element, data);
|
||||
}
|
||||
|
@ -1094,7 +1148,7 @@ replace_group_with_clip_edits (GNode * root, GESTimelineElement * group,
|
|||
}
|
||||
clip_data = new_edit_data (clip_mode, offset, layer_offset);
|
||||
g_hash_table_insert (edit_table, clip, clip_data);
|
||||
if (!set_clip_edit_values (clip, clip_data))
|
||||
if (!set_clip_edit_values (clip, clip_data, edit_table))
|
||||
goto error;
|
||||
}
|
||||
}
|
||||
|
@ -1131,7 +1185,7 @@ timeline_tree_set_element_edit_values (GNode * root, GHashTable * edits)
|
|||
if (GES_IS_GROUP (element))
|
||||
res = replace_group_with_clip_edits (root, element, edits);
|
||||
else
|
||||
res = set_clip_edit_values (element, edit_data);
|
||||
res = set_clip_edit_values (element, edit_data, edits);
|
||||
if (!res)
|
||||
goto error;
|
||||
}
|
||||
|
|
|
@ -522,6 +522,89 @@ class TestEditing(common.GESSimpleTimelineTest):
|
|||
]
|
||||
])
|
||||
|
||||
def test_trim_non_core(self):
|
||||
clip = self.append_clip()
|
||||
self.assertTrue(clip.set_inpoint(12))
|
||||
self.assertTrue(clip.set_max_duration(30))
|
||||
self.assertEqual(clip.get_duration_limit(), 18)
|
||||
for child in clip.get_children(False):
|
||||
self.assertEqual(child.get_inpoint(), 12)
|
||||
self.assertEqual(child.get_max_duration(), 30)
|
||||
|
||||
effect0 = GES.Effect.new("textoverlay")
|
||||
effect0.set_has_internal_source(True)
|
||||
self.assertTrue(effect0.set_inpoint(5))
|
||||
self.assertTrue(effect0.set_max_duration(20))
|
||||
self.assertTrue(clip.add(effect0))
|
||||
self.assertEqual(clip.get_duration_limit(), 15)
|
||||
|
||||
effect1 = GES.Effect.new("agingtv")
|
||||
effect1.set_has_internal_source(False)
|
||||
self.assertTrue(clip.add(effect1))
|
||||
|
||||
effect2 = GES.Effect.new("textoverlay")
|
||||
effect2.set_has_internal_source(True)
|
||||
self.assertTrue(effect2.set_inpoint(8))
|
||||
self.assertTrue(effect2.set_max_duration(18))
|
||||
self.assertTrue(clip.add(effect2))
|
||||
self.assertEqual(clip.get_duration_limit(), 10)
|
||||
|
||||
effect3 = GES.Effect.new("textoverlay")
|
||||
effect3.set_has_internal_source(True)
|
||||
self.assertTrue(effect3.set_inpoint(20))
|
||||
self.assertTrue(effect3.set_max_duration(22))
|
||||
self.assertTrue(effect3.set_active(False))
|
||||
self.assertTrue(clip.add(effect3))
|
||||
self.assertEqual(clip.get_duration_limit(), 10)
|
||||
|
||||
self.assertTrue(clip.set_start(10))
|
||||
self.assertTrue(clip.set_duration(10))
|
||||
|
||||
# cannot trim to a 0 because effect0 would have a negative in-point
|
||||
self.assertFalse(
|
||||
clip.edit([], -1, GES.EditMode.EDIT_TRIM, GES.Edge.EDGE_START, 0))
|
||||
|
||||
self.assertEqual(clip.start, 10)
|
||||
self.assertEqual(clip.inpoint, 12)
|
||||
self.assertEqual(effect0.inpoint, 5)
|
||||
self.assertEqual(effect1.inpoint, 0)
|
||||
self.assertEqual(effect2.inpoint, 8)
|
||||
self.assertEqual(effect3.inpoint, 20)
|
||||
|
||||
self.assertTrue(
|
||||
clip.edit([], -1, GES.EditMode.EDIT_TRIM, GES.Edge.EDGE_START, 5))
|
||||
|
||||
self.assertEqual(clip.start, 5)
|
||||
self.assertEqual(clip.duration, 15)
|
||||
self.assertEqual(clip.get_duration_limit(), 15)
|
||||
|
||||
for child in clip.get_children(False):
|
||||
self.assertEqual(child.start, 5)
|
||||
self.assertEqual(child.duration, 15)
|
||||
|
||||
self.assertEqual(clip.inpoint, 7)
|
||||
self.assertEqual(effect0.inpoint, 0)
|
||||
self.assertEqual(effect1.inpoint, 0)
|
||||
self.assertEqual(effect2.inpoint, 3)
|
||||
self.assertEqual(effect3.inpoint, 20)
|
||||
|
||||
self.assertTrue(
|
||||
clip.edit([], -1, GES.EditMode.EDIT_TRIM, GES.Edge.EDGE_START, 15))
|
||||
|
||||
self.assertEqual(clip.start, 15)
|
||||
self.assertEqual(clip.duration, 5)
|
||||
self.assertEqual(clip.get_duration_limit(), 5)
|
||||
|
||||
for child in clip.get_children(False):
|
||||
self.assertEqual(child.start, 15)
|
||||
self.assertEqual(child.duration, 5)
|
||||
|
||||
self.assertEqual(clip.inpoint, 17)
|
||||
self.assertEqual(effect0.inpoint, 10)
|
||||
self.assertEqual(effect1.inpoint, 0)
|
||||
self.assertEqual(effect2.inpoint, 13)
|
||||
self.assertEqual(effect3.inpoint, 20)
|
||||
|
||||
def test_ripple_end(self):
|
||||
clip = self.append_clip()
|
||||
clip.set_max_duration(20)
|
||||
|
|
Loading…
Reference in a new issue