mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer.git
synced 2025-04-26 04:26:14 +00:00
ges: Handle trimming in groups
This was broken, clips where moving all around, make it behave properly.
This commit is contained in:
parent
c74aee5fdc
commit
c4c26f8748
6 changed files with 109 additions and 23 deletions
|
@ -1395,6 +1395,8 @@ _trim (GESTimelineElement * element, GstClockTime start)
|
||||||
GESTrackElement *track_element =
|
GESTrackElement *track_element =
|
||||||
GES_TRACK_ELEMENT (GES_CONTAINER_CHILDREN (element)->data);
|
GES_TRACK_ELEMENT (GES_CONTAINER_CHILDREN (element)->data);
|
||||||
|
|
||||||
|
GST_DEBUG_OBJECT (element, "Trimming child: %" GST_PTR_FORMAT,
|
||||||
|
track_element);
|
||||||
ret = timeline_trim_object (timeline, track_element, NULL, GES_EDGE_START,
|
ret = timeline_trim_object (timeline, track_element, NULL, GES_EDGE_START,
|
||||||
start);
|
start);
|
||||||
}
|
}
|
||||||
|
|
|
@ -315,26 +315,46 @@ _child_start_changed_cb (GESTimelineElement * child,
|
||||||
GParamSpec * arg G_GNUC_UNUSED, GESContainer * container)
|
GParamSpec * arg G_GNUC_UNUSED, GESContainer * container)
|
||||||
{
|
{
|
||||||
ChildMapping *map;
|
ChildMapping *map;
|
||||||
|
GstClockTime start;
|
||||||
|
|
||||||
GESContainerPrivate *priv = container->priv;
|
GESContainerPrivate *priv = container->priv;
|
||||||
GESTimelineElement *element = GES_TIMELINE_ELEMENT (container);
|
GESTimelineElement *element = GES_TIMELINE_ELEMENT (container);
|
||||||
|
|
||||||
if (container->children_control_mode == GES_CHILDREN_IGNORE_NOTIFIES)
|
|
||||||
return;
|
|
||||||
|
|
||||||
map = g_hash_table_lookup (priv->mappings, child);
|
map = g_hash_table_lookup (priv->mappings, child);
|
||||||
g_assert (map);
|
g_assert (map);
|
||||||
|
|
||||||
if (container->children_control_mode == GES_CHILDREN_UPDATE_OFFSETS) {
|
switch (container->children_control_mode) {
|
||||||
map->start_offset = _START (container) - _START (child);
|
case GES_CHILDREN_IGNORE_NOTIFIES:
|
||||||
|
return;
|
||||||
|
case GES_CHILDREN_UPDATE_ALL_VALUES:
|
||||||
|
_ges_container_sort_children (container);
|
||||||
|
start = container->children ?
|
||||||
|
_START (container->children->data) : _START (container);
|
||||||
|
|
||||||
return;
|
if (start != _START (container)) {
|
||||||
|
_DURATION (container) = _END (container) - start;
|
||||||
|
_START (container) = start;
|
||||||
|
|
||||||
|
GST_DEBUG_OBJECT (container, "Child move made us "
|
||||||
|
"move to %" GST_TIME_FORMAT, GST_TIME_ARGS (_START (container)));
|
||||||
|
|
||||||
|
g_object_notify (G_OBJECT (container), "start");
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Falltrough! */
|
||||||
|
case GES_CHILDREN_UPDATE_OFFSETS:
|
||||||
|
map->start_offset = _START (container) - _START (child);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case GES_CHILDREN_UPDATE:
|
||||||
|
/* We update all the children calling our set_start method */
|
||||||
|
container->initiated_move = child;
|
||||||
|
_set_start0 (element, _START (child) + map->start_offset);
|
||||||
|
container->initiated_move = NULL;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* We update all the children calling our set_start method */
|
|
||||||
container->initiated_move = child;
|
|
||||||
_set_start0 (element, _START (child) + map->start_offset);
|
|
||||||
container->initiated_move = NULL;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
|
@ -370,6 +390,8 @@ _child_duration_changed_cb (GESTimelineElement * child,
|
||||||
{
|
{
|
||||||
ChildMapping *map;
|
ChildMapping *map;
|
||||||
|
|
||||||
|
GList *tmp;
|
||||||
|
GstClockTime end = 0;
|
||||||
GESContainerPrivate *priv = container->priv;
|
GESContainerPrivate *priv = container->priv;
|
||||||
GESTimelineElement *element = GES_TIMELINE_ELEMENT (container);
|
GESTimelineElement *element = GES_TIMELINE_ELEMENT (container);
|
||||||
|
|
||||||
|
@ -379,16 +401,32 @@ _child_duration_changed_cb (GESTimelineElement * child,
|
||||||
map = g_hash_table_lookup (priv->mappings, child);
|
map = g_hash_table_lookup (priv->mappings, child);
|
||||||
g_assert (map);
|
g_assert (map);
|
||||||
|
|
||||||
if (container->children_control_mode == GES_CHILDREN_UPDATE_OFFSETS) {
|
switch (container->children_control_mode) {
|
||||||
map->inpoint_offset = _START (container) - _START (child);
|
case GES_CHILDREN_IGNORE_NOTIFIES:
|
||||||
|
break;
|
||||||
|
case GES_CHILDREN_UPDATE_ALL_VALUES:
|
||||||
|
_ges_container_sort_children_by_end (container);
|
||||||
|
|
||||||
return;
|
for (tmp = container->children; tmp; tmp = tmp->next)
|
||||||
|
end = MAX (end, _END (tmp->data));
|
||||||
|
|
||||||
|
if (end != _END (container)) {
|
||||||
|
_DURATION (container) = end - _START (container);
|
||||||
|
g_object_notify (G_OBJECT (container), "duration");
|
||||||
|
}
|
||||||
|
/* Falltrough */
|
||||||
|
case GES_CHILDREN_UPDATE_OFFSETS:
|
||||||
|
map->inpoint_offset = _START (container) - _START (child);
|
||||||
|
break;
|
||||||
|
case GES_CHILDREN_UPDATE:
|
||||||
|
/* We update all the children calling our set_duration method */
|
||||||
|
container->initiated_move = child;
|
||||||
|
_set_duration0 (element, _DURATION (child) + map->duration_offset);
|
||||||
|
container->initiated_move = NULL;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* We update all the children calling our set_duration method */
|
|
||||||
container->initiated_move = child;
|
|
||||||
_set_duration0 (element, _DURATION (child) + map->duration_offset);
|
|
||||||
container->initiated_move = NULL;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/****************************************************
|
/****************************************************
|
||||||
|
|
|
@ -44,6 +44,7 @@ typedef enum
|
||||||
GES_CHILDREN_UPDATE,
|
GES_CHILDREN_UPDATE,
|
||||||
GES_CHILDREN_IGNORE_NOTIFIES,
|
GES_CHILDREN_IGNORE_NOTIFIES,
|
||||||
GES_CHILDREN_UPDATE_OFFSETS,
|
GES_CHILDREN_UPDATE_OFFSETS,
|
||||||
|
GES_CHILDREN_UPDATE_ALL_VALUES,
|
||||||
GES_CHILDREN_LAST
|
GES_CHILDREN_LAST
|
||||||
} GESChildrenControlMode;
|
} GESChildrenControlMode;
|
||||||
|
|
||||||
|
|
|
@ -185,7 +185,7 @@ static gboolean
|
||||||
_trim (GESTimelineElement * group, GstClockTime start)
|
_trim (GESTimelineElement * group, GstClockTime start)
|
||||||
{
|
{
|
||||||
GList *tmp;
|
GList *tmp;
|
||||||
GstClockTime last_child_end = 0;
|
GstClockTime last_child_end = 0, oldstart = _START (group);
|
||||||
GESContainer *container = GES_CONTAINER (group);
|
GESContainer *container = GES_CONTAINER (group);
|
||||||
GESTimeline *timeline = GES_TIMELINE_ELEMENT_TIMELINE (group);
|
GESTimeline *timeline = GES_TIMELINE_ELEMENT_TIMELINE (group);
|
||||||
gboolean ret = TRUE, expending = (start < _START (group));
|
gboolean ret = TRUE, expending = (start < _START (group));
|
||||||
|
@ -201,10 +201,12 @@ _trim (GESTimelineElement * group, GstClockTime start)
|
||||||
GESTimelineElement *child = tmp->data;
|
GESTimelineElement *child = tmp->data;
|
||||||
|
|
||||||
if (expending) {
|
if (expending) {
|
||||||
/* If the start if bigger, we do not touch it (in case we are expending)
|
/* If the start is bigger, we do not touch it (in case we are expending) */
|
||||||
*/
|
if (_START (child) > oldstart) {
|
||||||
if (_START (child) > _START (group))
|
GST_DEBUG_OBJECT (child, "Skipping as not at begining of the group");
|
||||||
continue;
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
ret &= ges_timeline_element_trim (child, start);
|
ret &= ges_timeline_element_trim (child, start);
|
||||||
} else {
|
} else {
|
||||||
if (start > _END (child))
|
if (start > _END (child))
|
||||||
|
|
|
@ -1363,6 +1363,28 @@ ges_timeline_trim_object_simple (GESTimeline * timeline,
|
||||||
|
|
||||||
switch (edge) {
|
switch (edge) {
|
||||||
case GES_EDGE_START:
|
case GES_EDGE_START:
|
||||||
|
{
|
||||||
|
GESTimelineElement *toplevel;
|
||||||
|
GESChildrenControlMode old_mode;
|
||||||
|
toplevel = ges_timeline_element_get_toplevel_parent (element);
|
||||||
|
|
||||||
|
if (position < _START (toplevel) && _START (toplevel) < _START (element)) {
|
||||||
|
GST_DEBUG_OBJECT (toplevel, "Not trimming %p as not at begining "
|
||||||
|
"of the container", element);
|
||||||
|
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
old_mode = GES_CONTAINER (toplevel)->children_control_mode;
|
||||||
|
if (GES_IS_GROUP (toplevel) && old_mode == GES_CHILDREN_UPDATE) {
|
||||||
|
GST_DEBUG_OBJECT (toplevel, "Setting children udpate mode to"
|
||||||
|
" UPDDATE_ALL_VALUES so we can trim without moving the contained");
|
||||||
|
/* The container will update its values itself according to new
|
||||||
|
* values of the children */
|
||||||
|
GES_CONTAINER (toplevel)->children_control_mode =
|
||||||
|
GES_CHILDREN_UPDATE_ALL_VALUES;
|
||||||
|
}
|
||||||
|
|
||||||
inpoint = _INPOINT (track_element);
|
inpoint = _INPOINT (track_element);
|
||||||
duration = _DURATION (track_element);
|
duration = _DURATION (track_element);
|
||||||
|
|
||||||
|
@ -1393,7 +1415,12 @@ ges_timeline_trim_object_simple (GESTimeline * timeline,
|
||||||
timeline->priv->needs_transitions_update = TRUE;
|
timeline->priv->needs_transitions_update = TRUE;
|
||||||
|
|
||||||
_set_duration0 (GES_TIMELINE_ELEMENT (track_element), duration);
|
_set_duration0 (GES_TIMELINE_ELEMENT (track_element), duration);
|
||||||
|
if (GES_IS_GROUP (toplevel))
|
||||||
|
GES_CONTAINER (toplevel)->children_control_mode = old_mode;
|
||||||
|
|
||||||
|
gst_object_unref (toplevel);
|
||||||
break;
|
break;
|
||||||
|
}
|
||||||
case GES_EDGE_END:
|
case GES_EDGE_END:
|
||||||
{
|
{
|
||||||
cur = g_hash_table_lookup (timeline->priv->by_end, track_element);
|
cur = g_hash_table_lookup (timeline->priv->by_end, track_element);
|
||||||
|
|
|
@ -1150,6 +1150,22 @@ GST_START_TEST (test_groups)
|
||||||
check_layer (c4, 1);
|
check_layer (c4, 1);
|
||||||
check_layer (c5, 2);
|
check_layer (c5, 2);
|
||||||
|
|
||||||
|
fail_unless (ges_container_edit (GES_CONTAINER (c), NULL, 0,
|
||||||
|
GES_EDIT_MODE_TRIM, GES_EDGE_START, 5) == TRUE);
|
||||||
|
CHECK_OBJECT_PROPS (c, 5, 5, 5);
|
||||||
|
CHECK_OBJECT_PROPS (c1, 10, 0, 10);
|
||||||
|
CHECK_OBJECT_PROPS (c2, 20, 0, 20);
|
||||||
|
CHECK_OBJECT_PROPS (c3, 40, 10, 10);
|
||||||
|
CHECK_OBJECT_PROPS (c4, 40, 0, 20);
|
||||||
|
CHECK_OBJECT_PROPS (c5, 50, 0, 20);
|
||||||
|
CHECK_OBJECT_PROPS (group, 5, 0, 35);
|
||||||
|
check_layer (c, 0);
|
||||||
|
check_layer (c1, 1);
|
||||||
|
check_layer (c2, 1);
|
||||||
|
check_layer (c3, 0);
|
||||||
|
check_layer (c4, 1);
|
||||||
|
check_layer (c5, 2);
|
||||||
|
|
||||||
gst_object_unref (timeline);
|
gst_object_unref (timeline);
|
||||||
gst_object_unref (asset);
|
gst_object_unref (asset);
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue