timeline-tree: fix overlap check

Previously, the code was not able to detect that an element overlaps on
its end, nor could it detect that an element overlaps two elements that
already overlap.
This commit is contained in:
Henry Wilkes 2020-04-01 21:34:48 +01:00
parent f698408176
commit eec9c90a8c
2 changed files with 103 additions and 2 deletions

View file

@ -64,6 +64,8 @@ struct _TreeIterationData
/* Elements overlaping on the start/end of @element */
GESTimelineElement *overlaping_on_start;
GESTimelineElement *overlaping_on_end;
GstClockTime overlap_start_final_time;
GstClockTime overlap_end_first_time;
/* Timestamp after which elements will be rippled */
GstClockTime ripple_time;
@ -90,6 +92,8 @@ struct _TreeIterationData
.movings = NULL,
.overlaping_on_start = NULL,
.overlaping_on_end = NULL,
.overlap_start_final_time = GST_CLOCK_TIME_NONE,
.overlap_end_first_time = GST_CLOCK_TIME_NONE,
.ripple_time = GST_CLOCK_TIME_NONE,
.snapping = NULL,
.edge = GES_EDGE_NONE,
@ -436,6 +440,7 @@ check_track_elements_overlaps_and_values (GNode * node,
}
if (moving_start < end && moving_start > start) {
/* moving_start is between the start and end of the node */
GST_LOG ("Overlap start: %s<%p> [%" G_GINT64_FORMAT "-%" G_GINT64_FORMAT
"] and %s<%p> [%" G_GINT64_FORMAT "-%" G_GINT64_FORMAT " (%"
G_GINT64_FORMAT ")]", e->name, e, start, end, data->element->name,
@ -445,9 +450,18 @@ check_track_elements_overlaps_and_values (GNode * node,
data->overlaping_on_start->name, e->name);
goto error;
}
if (GST_CLOCK_TIME_IS_VALID (data->overlap_end_first_time) &&
end > data->overlap_end_first_time) {
GST_INFO ("%s overlaps %s at start and %s at end, but they already "
"overlap each other", data->element->name, e->name,
data->overlaping_on_end->name);
goto error;
}
/* record the time at which the overlapped ends */
data->overlap_start_final_time = end;
data->overlaping_on_start = node->data;
} else if (moving_end > end && end > moving_start) {
} else if (moving_end < end && moving_end > start) {
/* moving_end is between the start and end of the node */
GST_LOG ("Overlap end: %s<%p> [%" G_GINT64_FORMAT "-%" G_GINT64_FORMAT
"] and %s<%p> [%" G_GINT64_FORMAT "-%" G_GINT64_FORMAT " (%"
G_GINT64_FORMAT ")]", e->name, e, start, end, data->element->name,
@ -458,6 +472,15 @@ check_track_elements_overlaps_and_values (GNode * node,
data->overlaping_on_end->name, e->name);
goto error;
}
if (GST_CLOCK_TIME_IS_VALID (data->overlap_start_final_time) &&
start < data->overlap_start_final_time) {
GST_INFO ("%s overlaps %s at end and %s at start, but they already "
"overlap each other", data->element->name, e->name,
data->overlaping_on_start->name);
goto error;
}
/* record the time at which the overlapped starts */
data->overlap_end_first_time = start;
data->overlaping_on_end = node->data;
}

View file

@ -1188,6 +1188,84 @@ class TestInvalidOverlaps(common.GESSimpleTimelineTest):
])
class TestConfigurationRules(common.GESSimpleTimelineTest):
def _try_add_clip(self, start, duration, layer=None):
if layer is None:
layer = self.layer
asset = GES.Asset.request(GES.TestClip, None)
# large inpoint to allow trims
return layer.add_asset (asset, start, 1000, duration,
GES.TrackType.UNKNOWN)
def test_full_overlap_add(self):
clip1 = self._try_add_clip(50, 50)
self.assertIsNotNone(clip1)
self.assertIsNone(self._try_add_clip(50, 50))
self.assertIsNone(self._try_add_clip(49, 51))
self.assertIsNone(self._try_add_clip(51, 49))
def test_triple_overlap_add(self):
clip1 = self._try_add_clip(0, 50)
self.assertIsNotNone(clip1)
clip2 = self._try_add_clip(40, 50)
self.assertIsNotNone(clip2)
self.assertIsNone(self._try_add_clip(40, 10))
self.assertIsNone(self._try_add_clip(30, 30))
self.assertIsNone(self._try_add_clip(1, 88))
def test_full_overlap_move(self):
clip1 = self._try_add_clip(0, 50)
self.assertIsNotNone(clip1)
clip2 = self._try_add_clip(50, 50)
self.assertIsNotNone(clip2)
self.assertFalse(clip2.set_start(0))
def test_triple_overlap_move(self):
clip1 = self._try_add_clip(0, 50)
self.assertIsNotNone(clip1)
clip2 = self._try_add_clip(40, 50)
self.assertIsNotNone(clip2)
clip3 = self._try_add_clip(100, 60)
self.assertIsNotNone(clip3)
self.assertFalse(clip3.set_start(30))
def test_full_overlap_move_into_layer(self):
clip1 = self._try_add_clip(0, 50)
self.assertIsNotNone(clip1)
layer2 = self.timeline.append_layer()
clip2 = self._try_add_clip(0, 50, layer2)
self.assertIsNotNone(clip2)
self.assertFalse(clip2.move_to_layer(self.layer))
def test_triple_overlap_move_into_layer(self):
clip1 = self._try_add_clip(0, 50)
self.assertIsNotNone(clip1)
clip2 = self._try_add_clip(40, 50)
self.assertIsNotNone(clip2)
layer2 = self.timeline.append_layer()
clip3 = self._try_add_clip(30, 30, layer2)
self.assertIsNotNone(clip3)
self.assertFalse(clip3.move_to_layer(self.layer))
def test_full_overlap_trim(self):
clip1 = self._try_add_clip(0, 50)
self.assertIsNotNone(clip1)
clip2 = self._try_add_clip(50, 50)
self.assertIsNotNone(clip2)
self.assertFalse(clip2.trim(0))
self.assertFalse(clip1.set_duration(100))
def test_triple_overlap_trim(self):
clip1 = self._try_add_clip(0, 20)
self.assertIsNotNone(clip1)
clip2 = self._try_add_clip(10, 30)
self.assertIsNotNone(clip2)
clip3 = self._try_add_clip(30, 20)
self.assertIsNotNone(clip3)
self.assertFalse(clip3.trim(19))
self.assertFalse(clip1.set_duration(31))
class TestSnapping(common.GESSimpleTimelineTest):
def test_snapping(self):