auto-transition: select track directly

By-pass the select-tracks-for-object signal for auto-transitions since
their track element must land in the same track as the elements it is
the auto-transition for.
This commit is contained in:
Henry Wilkes 2020-04-06 12:16:11 +01:00
parent 269c2d1dc0
commit 067304a05f
2 changed files with 97 additions and 15 deletions

View file

@ -150,6 +150,8 @@ struct _GESTimelinePrivate
* and %FALSE otherwize */
gboolean needs_transitions_update;
GESTrack *auto_transition_track;
/* While we are creating and adding the TrackElements for a clip, we need to
* ignore the child-added signal */
gboolean track_elements_moving;
@ -344,6 +346,8 @@ ges_timeline_dispose (GObject * object)
g_hash_table_unref (priv->all_elements);
gst_object_unref (priv->stream_collection);
gst_clear_object (&priv->auto_transition_track);
G_OBJECT_CLASS (ges_timeline_parent_class)->dispose (object);
}
@ -897,25 +901,46 @@ ges_timeline_create_transition (GESTimeline * timeline,
GESTrackElement * previous, GESTrackElement * next, GESClip * transition,
GESLayer * layer, guint64 start, guint64 duration)
{
GESAsset *asset;
GESAutoTransition *auto_transition;
GESTrackElement *child;
/* track should not be NULL */
GESTrack *track = ges_track_element_get_track (next);
if (transition == NULL) {
/* TODO make it possible to specify a Transition asset in the API */
GESAsset *asset;
LOCK_DYN (timeline);
timeline->priv->auto_transition_track = gst_object_ref (track);
UNLOCK_DYN (timeline);
asset = ges_asset_request (GES_TYPE_TRANSITION_CLIP, "crossfade", NULL);
transition =
ges_layer_add_asset (layer, asset, start, 0, duration,
transition = ges_layer_add_asset (layer, asset, start, 0, duration,
ges_track_element_get_track_type (next));
g_object_unref (asset);
gst_object_unref (asset);
LOCK_DYN (timeline);
/* should have been set to NULL, but clear just in case */
gst_clear_object (&timeline->priv->auto_transition_track);
UNLOCK_DYN (timeline);
} else {
GST_DEBUG_OBJECT (timeline,
"Reusing already existing transition: %" GST_PTR_FORMAT, transition);
}
g_return_val_if_fail (transition, NULL);
g_return_val_if_fail (g_list_length (GES_CONTAINER_CHILDREN (transition)) ==
1, NULL);
child = GES_CONTAINER_CHILDREN (transition)->data;
if (ges_track_element_get_track (child) != track) {
GST_ERROR_OBJECT (timeline, "The auto transition element %"
GES_FORMAT " for elements %" GES_FORMAT " and %" GES_FORMAT
" is not in the same track %" GST_PTR_FORMAT,
GES_ARGS (child), GES_ARGS (previous), GES_ARGS (next), track);
return NULL;
}
/* We know there is only 1 TrackElement */
auto_transition =
ges_auto_transition_new (GES_CONTAINER_CHILDREN (transition)->data,
previous, next);
auto_transition = ges_auto_transition_new (child, previous, next);
g_signal_connect (auto_transition, "destroy-me",
G_CALLBACK (_destroy_auto_transition_cb), timeline);
@ -1515,6 +1540,7 @@ static void
clip_track_element_added_cb (GESClip * clip,
GESTrackElement * track_element, GESTimeline * timeline)
{
GESTrack *auto_trans_track;
gboolean error = FALSE;
if (timeline->priv->track_elements_moving) {
@ -1531,8 +1557,23 @@ clip_track_element_added_cb (GESClip * clip,
return;
}
if (!_add_track_element_to_tracks (timeline, clip, track_element))
error = TRUE;
LOCK_DYN (timeline);
/* take ownership of auto_transition_track. For auto-transitions, this
* should be used exactly once! */
auto_trans_track = timeline->priv->auto_transition_track;
timeline->priv->auto_transition_track = NULL;
UNLOCK_DYN (timeline);
if (auto_trans_track) {
/* don't use track-selection */
if (!ges_clip_add_child_to_track (clip, track_element, auto_trans_track,
NULL))
error = TRUE;
gst_object_unref (auto_trans_track);
} else {
if (!_add_track_element_to_tracks (timeline, clip, track_element))
error = TRUE;
}
if (error)
_set_track_selection_error (timeline, TRUE);

View file

@ -536,7 +536,7 @@ GST_START_TEST (test_ges_timeline_multiple_tracks)
GESTimeline *timeline;
GESLayer *layer;
GESTrack *track1, *track2;
GESClip *s1, *s2, *s3, *s4;
GESClip *s1, *s2, *s3, *s4, *transition;
GESTrackElement *e1, *e2, *e3, *el, *el2, *e_copy;
gboolean found_e1 = FALSE, found_e2 = FALSE, found_e3 = FALSE;
GList *trackelements, *tmp, *layers;
@ -549,6 +549,7 @@ GST_START_TEST (test_ges_timeline_multiple_tracks)
GST_DEBUG ("Create a timeline");
timeline = ges_timeline_new ();
fail_unless (timeline != NULL);
ges_timeline_set_auto_transition (timeline, TRUE);
GST_DEBUG ("Create a layer");
layer = ges_layer_new ();
@ -578,7 +579,7 @@ GST_START_TEST (test_ges_timeline_multiple_tracks)
/* s1 and s3 can overlap since they are destined for different tracks */
/* s2 will overlap both */
/* s4 destined for no track */
_CREATE_SOURCE (layer, s1, 0, 10);
_CREATE_SOURCE (layer, s1, 0, 12);
_CREATE_SOURCE (layer, s2, 5, 10);
_CREATE_SOURCE (layer, s3, 0, 10);
_CREATE_SOURCE (layer, s4, 0, 20);
@ -648,6 +649,8 @@ GST_START_TEST (test_ges_timeline_multiple_tracks)
fail_unless (g_list_find (layers, layer) != NULL);
g_list_free_full (layers, gst_object_unref);
fail_unless (ges_layer_get_auto_transition (layer));
assert_equals_int (st_data.num_unrecognised, 0);
/* Make sure the associated TrackElements are in the Track */
@ -756,11 +759,49 @@ GST_START_TEST (test_ges_timeline_multiple_tracks)
/* called once for source (where no track was selected) */
assert_equals_int (st_data.num_calls[0], 1);
/* 2 sources + 2 effects */
assert_num_in_track (track1, 4);
assert_num_in_track (track2, 4);
/* 2 sources + 1 transition + 2 effects */
assert_num_in_track (track1, 5);
assert_num_in_track (track2, 5);
el = NULL;
trackelements = ges_track_get_elements (track1);
for (tmp = trackelements; tmp; tmp = tmp->next) {
if (GES_IS_VIDEO_TRANSITION (tmp->data)) {
fail_if (el);
el = tmp->data;
}
}
g_list_free_full (trackelements, gst_object_unref);
fail_unless (GES_IS_CLIP (GES_TIMELINE_ELEMENT_PARENT (el)));
transition = GES_CLIP (GES_TIMELINE_ELEMENT_PARENT (el));
assert_layer (transition, layer);
CHECK_OBJECT_PROPS (transition, 5, 0, 7);
CHECK_OBJECT_PROPS (el, 5, 0, 7);
fail_unless (ges_track_element_get_track (el) == track1);
/* make sure we can change the transition type */
fail_unless (ges_video_transition_set_transition_type (GES_VIDEO_TRANSITION
(el), GES_VIDEO_STANDARD_TRANSITION_TYPE_BARNDOOR_H));
el = NULL;
trackelements = ges_track_get_elements (track2);
for (tmp = trackelements; tmp; tmp = tmp->next) {
if (GES_IS_VIDEO_TRANSITION (tmp->data)) {
fail_if (el);
el = tmp->data;
}
}
g_list_free_full (trackelements, gst_object_unref);
fail_unless (GES_IS_CLIP (GES_TIMELINE_ELEMENT_PARENT (el)));
transition = GES_CLIP (GES_TIMELINE_ELEMENT_PARENT (el));
assert_layer (transition, layer);
CHECK_OBJECT_PROPS (transition, 5, 0, 5);
CHECK_OBJECT_PROPS (el, 5, 0, 5);
fail_unless (ges_track_element_get_track (el) == track2);
/* make sure we can change the transition type */
fail_unless (ges_video_transition_set_transition_type (GES_VIDEO_TRANSITION
(el), GES_VIDEO_STANDARD_TRANSITION_TYPE_BARNDOOR_H));
gst_object_unref (timeline);