container: change ownership when adding

Make sure we sink the child on adding, and keep it alive until the end
in case the method fails.

Also, since the child mappings hold a ref to the child, they should give
them up in their free method. This way, the ref will be given up on
disposing, even if ges_container_remove fails.

Also, reverse setting of the start of the container if adding fails.
This commit is contained in:
Henry Wilkes 2020-04-06 12:21:54 +01:00
parent 917eba54f7
commit 6e55a6556f
2 changed files with 18 additions and 7 deletions

View file

@ -123,8 +123,10 @@ _free_mapping (ChildMapping * mapping)
if (mapping->child_property_removed_notifyid) if (mapping->child_property_removed_notifyid)
g_signal_handler_disconnect (child, g_signal_handler_disconnect (child,
mapping->child_property_removed_notifyid); mapping->child_property_removed_notifyid);
if (child) {
ges_timeline_element_set_parent (child, NULL); ges_timeline_element_set_parent (child, NULL);
gst_object_unref (child);
}
g_slice_free (ChildMapping, mapping); g_slice_free (ChildMapping, mapping);
} }
@ -750,6 +752,7 @@ ges_container_add (GESContainer * container, GESTimelineElement * child)
GESContainerClass *class; GESContainerClass *class;
GList *current_children, *tmp; GList *current_children, *tmp;
GESContainerPrivate *priv; GESContainerPrivate *priv;
GstClockTime prev_start;
g_return_val_if_fail (GES_IS_CONTAINER (container), FALSE); g_return_val_if_fail (GES_IS_CONTAINER (container), FALSE);
g_return_val_if_fail (GES_IS_TIMELINE_ELEMENT (child), FALSE); g_return_val_if_fail (GES_IS_TIMELINE_ELEMENT (child), FALSE);
@ -770,6 +773,7 @@ ges_container_add (GESContainer * container, GESTimelineElement * child)
for (tmp = current_children; tmp; tmp = tmp->next) for (tmp = current_children; tmp; tmp = tmp->next)
g_object_freeze_notify (G_OBJECT (tmp->data)); g_object_freeze_notify (G_OBJECT (tmp->data));
g_object_freeze_notify (G_OBJECT (child)); g_object_freeze_notify (G_OBJECT (child));
gst_object_ref_sink (child);
if (class->add_child) { if (class->add_child) {
if (class->add_child (container, child) == FALSE) { if (class->add_child (container, child) == FALSE) {
@ -784,7 +788,8 @@ ges_container_add (GESContainer * container, GESTimelineElement * child)
* add_child. However, a user's custom container class may have a good * add_child. However, a user's custom container class may have a good
* reason to not want the container's start value to change when adding * reason to not want the container's start value to change when adding
* a new child */ * a new child */
if (_START (container) > _START (child)) { prev_start = _START (container);
if (prev_start > _START (child)) {
_START (container) = _START (child); _START (container) = _START (child);
g_hash_table_foreach (priv->mappings, (GHFunc) _resync_start_offsets, g_hash_table_foreach (priv->mappings, (GHFunc) _resync_start_offsets,
@ -798,7 +803,6 @@ ges_container_add (GESContainer * container, GESTimelineElement * child)
mapping->duration_offset = _DURATION (container) - _DURATION (child); mapping->duration_offset = _DURATION (container) - _DURATION (child);
g_hash_table_insert (priv->mappings, child, mapping); g_hash_table_insert (priv->mappings, child, mapping);
container->children = g_list_prepend (container->children, child); container->children = g_list_prepend (container->children, child);
_ges_container_sort_children (container); _ges_container_sort_children (container);
@ -818,6 +822,14 @@ ges_container_add (GESContainer * container, GESTimelineElement * child)
g_hash_table_remove (priv->mappings, child); g_hash_table_remove (priv->mappings, child);
container->children = g_list_remove (container->children, child); container->children = g_list_remove (container->children, child);
if (prev_start != _START (container)) {
_START (container) = prev_start;
g_hash_table_foreach (priv->mappings, (GHFunc) _resync_start_offsets,
container);
g_signal_stop_emission_by_name (container, "start");
}
_ges_container_sort_children (container); _ges_container_sort_children (container);
goto done; goto done;
@ -848,6 +860,7 @@ done:
g_object_thaw_notify (G_OBJECT (tmp->data)); g_object_thaw_notify (G_OBJECT (tmp->data));
g_object_thaw_notify (G_OBJECT (child)); g_object_thaw_notify (G_OBJECT (child));
g_list_free_full (current_children, gst_object_unref); g_list_free_full (current_children, gst_object_unref);
gst_object_unref (child);
container->children_control_mode = GES_CHILDREN_UPDATE; container->children_control_mode = GES_CHILDREN_UPDATE;
return ret; return ret;
} }
@ -903,7 +916,6 @@ ges_container_remove (GESContainer * container, GESTimelineElement * child)
} }
container->children = g_list_remove (container->children, child); container->children = g_list_remove (container->children, child);
/* Let it live removing from our mappings, also disconnects signals */
g_hash_table_remove (priv->mappings, child); g_hash_table_remove (priv->mappings, child);
_ges_container_remove_child_properties (container, child); _ges_container_remove_child_properties (container, child);
@ -921,7 +933,6 @@ ges_container_remove (GESContainer * container, GESTimelineElement * child)
"Not emitting 'child-removed' signal as child" "Not emitting 'child-removed' signal as child"
" removal happend during 'child-added' signal emission"); " removal happend during 'child-added' signal emission");
} }
gst_object_unref (child);
ret = TRUE; ret = TRUE;

View file

@ -528,7 +528,7 @@ static void
child_removed_cb (GESClip * clip, GESTimelineElement * effect, child_removed_cb (GESClip * clip, GESTimelineElement * effect,
gboolean * called) gboolean * called)
{ {
ASSERT_OBJECT_REFCOUNT (effect, "2 keeping alive ref + emission ref", 3); ASSERT_OBJECT_REFCOUNT (effect, "1 keeping alive ref + emission ref", 2);
*called = TRUE; *called = TRUE;
} }