mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer.git
synced 2025-04-26 04:36:20 +00:00
track: Use a GSequence to keep the sorted list of TrackObject-s
Use a GSequence instead of a GList to optimise the process. Conflicts: ges/ges-track.c
This commit is contained in:
parent
171bf8e627
commit
c2bedb182e
1 changed files with 86 additions and 51 deletions
137
ges/ges-track.c
137
ges/ges-track.c
|
@ -40,7 +40,7 @@ struct _GESTrackPrivate
|
||||||
{
|
{
|
||||||
/*< private > */
|
/*< private > */
|
||||||
GESTimeline *timeline;
|
GESTimeline *timeline;
|
||||||
GList *trackobjects;
|
GSequence *tckobjs_by_start;
|
||||||
guint64 duration;
|
guint64 duration;
|
||||||
|
|
||||||
GstCaps *caps;
|
GstCaps *caps;
|
||||||
|
@ -119,18 +119,77 @@ ges_track_set_property (GObject * object, guint property_id,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
add_trackobj_to_list_foreach (GESTrackObject * trackobj, GList ** list)
|
||||||
|
{
|
||||||
|
g_object_ref (trackobj);
|
||||||
|
*list = g_list_prepend (*list, trackobj);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Remove @object from @track, but keeps it in the sequence this is needed
|
||||||
|
* when finalizing as we can not change a GSequence at the same time we are
|
||||||
|
* accessing it
|
||||||
|
*/
|
||||||
|
static gboolean
|
||||||
|
remove_object_internal (GESTrack * track, GESTrackObject * object)
|
||||||
|
{
|
||||||
|
GESTrackPrivate *priv;
|
||||||
|
GstElement *gnlobject;
|
||||||
|
|
||||||
|
GST_DEBUG ("track:%p, object:%p", track, object);
|
||||||
|
|
||||||
|
priv = track->priv;
|
||||||
|
|
||||||
|
if (G_UNLIKELY (ges_track_object_get_track (object) != track)) {
|
||||||
|
GST_WARNING ("Object belongs to another track");
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((gnlobject = ges_track_object_get_gnlobject (object))) {
|
||||||
|
GST_DEBUG ("Removing GnlObject '%s' from composition '%s'",
|
||||||
|
GST_ELEMENT_NAME (gnlobject), GST_ELEMENT_NAME (priv->composition));
|
||||||
|
|
||||||
|
if (!gst_bin_remove (GST_BIN (priv->composition), gnlobject)) {
|
||||||
|
GST_WARNING ("Failed to remove gnlobject from composition");
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
gst_element_set_state (gnlobject, GST_STATE_NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
g_signal_handlers_disconnect_by_func (object, sort_track_objects_cb, NULL);
|
||||||
|
|
||||||
|
ges_track_object_set_track (object, NULL);
|
||||||
|
|
||||||
|
g_signal_emit (track, ges_track_signals[TRACK_OBJECT_REMOVED], 0,
|
||||||
|
GES_TRACK_OBJECT (object));
|
||||||
|
|
||||||
|
g_object_unref (object);
|
||||||
|
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
dispose_tckobjs_foreach (GESTrackObject * tckobj, GESTrack * track)
|
||||||
|
{
|
||||||
|
GESTimelineObject *tlobj;
|
||||||
|
|
||||||
|
tlobj = ges_track_object_get_timeline_object (tckobj);
|
||||||
|
|
||||||
|
remove_object_internal (track, tckobj);
|
||||||
|
ges_timeline_object_release_track_object (tlobj, tckobj);
|
||||||
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
ges_track_dispose (GObject * object)
|
ges_track_dispose (GObject * object)
|
||||||
{
|
{
|
||||||
GESTrack *track = (GESTrack *) object;
|
GESTrack *track = (GESTrack *) object;
|
||||||
GESTrackPrivate *priv = track->priv;
|
GESTrackPrivate *priv = track->priv;
|
||||||
|
|
||||||
while (priv->trackobjects) {
|
/* Remove all TrackObjects and drop our reference */
|
||||||
GESTrackObject *trobj = GES_TRACK_OBJECT (priv->trackobjects->data);
|
g_sequence_foreach (track->priv->tckobjs_by_start,
|
||||||
ges_track_remove_object (track, trobj);
|
(GFunc) dispose_tckobjs_foreach, track);
|
||||||
ges_timeline_object_release_track_object ((GESTimelineObject *)
|
g_sequence_free (priv->tckobjs_by_start);
|
||||||
ges_track_object_get_timeline_object (trobj), trobj);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (priv->composition) {
|
if (priv->composition) {
|
||||||
gst_bin_remove (GST_BIN (object), priv->composition);
|
gst_bin_remove (GST_BIN (object), priv->composition);
|
||||||
|
@ -287,6 +346,7 @@ ges_track_init (GESTrack * self)
|
||||||
|
|
||||||
self->priv->composition = gst_element_factory_make ("gnlcomposition", NULL);
|
self->priv->composition = gst_element_factory_make ("gnlcomposition", NULL);
|
||||||
self->priv->updating = TRUE;
|
self->priv->updating = TRUE;
|
||||||
|
self->priv->tckobjs_by_start = g_sequence_new (NULL);
|
||||||
|
|
||||||
g_signal_connect (G_OBJECT (self->priv->composition), "notify::duration",
|
g_signal_connect (G_OBJECT (self->priv->composition), "notify::duration",
|
||||||
G_CALLBACK (composition_duration_cb), self);
|
G_CALLBACK (composition_duration_cb), self);
|
||||||
|
@ -414,8 +474,10 @@ ges_track_set_caps (GESTrack * track, const GstCaps * caps)
|
||||||
/* FIXME : put the compare function in the utils */
|
/* FIXME : put the compare function in the utils */
|
||||||
|
|
||||||
static gint
|
static gint
|
||||||
objects_start_compare (GESTrackObject * a, GESTrackObject * b)
|
objects_start_compare (GESTrackObject * a, GESTrackObject * b,
|
||||||
|
gpointer user_data)
|
||||||
{
|
{
|
||||||
|
|
||||||
if (a->start == b->start) {
|
if (a->start == b->start) {
|
||||||
if (a->priority < b->priority)
|
if (a->priority < b->priority)
|
||||||
return -1;
|
return -1;
|
||||||
|
@ -472,9 +534,8 @@ ges_track_add_object (GESTrack * track, GESTrackObject * object)
|
||||||
}
|
}
|
||||||
|
|
||||||
g_object_ref_sink (object);
|
g_object_ref_sink (object);
|
||||||
track->priv->trackobjects =
|
g_sequence_insert_sorted (track->priv->tckobjs_by_start, object,
|
||||||
g_list_insert_sorted (track->priv->trackobjects, object,
|
(GCompareDataFunc) objects_start_compare, NULL);
|
||||||
(GCompareFunc) objects_start_compare);
|
|
||||||
|
|
||||||
g_signal_emit (track, ges_track_signals[TRACK_OBJECT_ADDED], 0,
|
g_signal_emit (track, ges_track_signals[TRACK_OBJECT_ADDED], 0,
|
||||||
GES_TRACK_OBJECT (object));
|
GES_TRACK_OBJECT (object));
|
||||||
|
@ -482,6 +543,9 @@ ges_track_add_object (GESTrack * track, GESTrackObject * object)
|
||||||
g_signal_connect (GES_TRACK_OBJECT (object), "notify::start",
|
g_signal_connect (GES_TRACK_OBJECT (object), "notify::start",
|
||||||
G_CALLBACK (sort_track_objects_cb), track);
|
G_CALLBACK (sort_track_objects_cb), track);
|
||||||
|
|
||||||
|
g_signal_connect (GES_TRACK_OBJECT (object), "notify::duration",
|
||||||
|
G_CALLBACK (sort_track_objects_cb), track);
|
||||||
|
|
||||||
g_signal_connect (GES_TRACK_OBJECT (object), "notify::priority",
|
g_signal_connect (GES_TRACK_OBJECT (object), "notify::priority",
|
||||||
G_CALLBACK (sort_track_objects_cb), track);
|
G_CALLBACK (sort_track_objects_cb), track);
|
||||||
|
|
||||||
|
@ -501,14 +565,11 @@ GList *
|
||||||
ges_track_get_objects (GESTrack * track)
|
ges_track_get_objects (GESTrack * track)
|
||||||
{
|
{
|
||||||
GList *ret = NULL;
|
GList *ret = NULL;
|
||||||
GList *tmp;
|
|
||||||
|
|
||||||
g_return_val_if_fail (GES_IS_TRACK (track), NULL);
|
g_return_val_if_fail (GES_IS_TRACK (track), NULL);
|
||||||
|
|
||||||
for (tmp = track->priv->trackobjects; tmp; tmp = tmp->next) {
|
g_sequence_foreach (track->priv->tckobjs_by_start,
|
||||||
ret = g_list_prepend (ret, tmp->data);
|
(GFunc) add_trackobj_to_list_foreach, &ret);
|
||||||
g_object_ref (tmp->data);
|
|
||||||
}
|
|
||||||
|
|
||||||
ret = g_list_reverse (ret);
|
ret = g_list_reverse (ret);
|
||||||
return ret;
|
return ret;
|
||||||
|
@ -530,45 +591,20 @@ ges_track_get_objects (GESTrack * track)
|
||||||
gboolean
|
gboolean
|
||||||
ges_track_remove_object (GESTrack * track, GESTrackObject * object)
|
ges_track_remove_object (GESTrack * track, GESTrackObject * object)
|
||||||
{
|
{
|
||||||
GESTrackPrivate *priv;
|
GSequenceIter *it;
|
||||||
GstElement *gnlobject;
|
|
||||||
|
|
||||||
g_return_val_if_fail (GES_IS_TRACK (track), FALSE);
|
g_return_val_if_fail (GES_IS_TRACK (track), FALSE);
|
||||||
g_return_val_if_fail (GES_IS_TRACK_OBJECT (object), FALSE);
|
g_return_val_if_fail (GES_IS_TRACK_OBJECT (object), FALSE);
|
||||||
|
|
||||||
GST_DEBUG ("track:%p, object:%p", track, object);
|
if (remove_object_internal (track, object) == TRUE) {
|
||||||
|
it = g_sequence_lookup (track->priv->tckobjs_by_start, object,
|
||||||
|
(GCompareDataFunc) objects_start_compare, NULL);
|
||||||
|
g_sequence_remove (it);
|
||||||
|
|
||||||
priv = track->priv;
|
return TRUE;
|
||||||
|
|
||||||
if (G_UNLIKELY (ges_track_object_get_track (object) != track)) {
|
|
||||||
GST_WARNING ("Object belongs to another track");
|
|
||||||
return FALSE;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((gnlobject = ges_track_object_get_gnlobject (object))) {
|
return FALSE;
|
||||||
GST_DEBUG ("Removing GnlObject '%s' from composition '%s'",
|
|
||||||
GST_ELEMENT_NAME (gnlobject), GST_ELEMENT_NAME (priv->composition));
|
|
||||||
|
|
||||||
if (!gst_bin_remove (GST_BIN (priv->composition), gnlobject)) {
|
|
||||||
GST_WARNING ("Failed to remove gnlobject from composition");
|
|
||||||
return FALSE;
|
|
||||||
}
|
|
||||||
|
|
||||||
gst_element_set_state (gnlobject, GST_STATE_NULL);
|
|
||||||
}
|
|
||||||
|
|
||||||
g_signal_handlers_disconnect_by_func (object, sort_track_objects_cb, NULL);
|
|
||||||
|
|
||||||
ges_track_object_set_track (object, NULL);
|
|
||||||
|
|
||||||
g_signal_emit (track, ges_track_signals[TRACK_OBJECT_REMOVED], 0,
|
|
||||||
GES_TRACK_OBJECT (object));
|
|
||||||
|
|
||||||
priv->trackobjects = g_list_remove (priv->trackobjects, object);
|
|
||||||
|
|
||||||
g_object_unref (object);
|
|
||||||
|
|
||||||
return TRUE;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
|
@ -628,9 +664,8 @@ static void
|
||||||
sort_track_objects_cb (GESTrackObject * child,
|
sort_track_objects_cb (GESTrackObject * child,
|
||||||
GParamSpec * arg G_GNUC_UNUSED, GESTrack * track)
|
GParamSpec * arg G_GNUC_UNUSED, GESTrack * track)
|
||||||
{
|
{
|
||||||
track->priv->trackobjects =
|
g_sequence_sort (track->priv->tckobjs_by_start,
|
||||||
g_list_sort (track->priv->trackobjects,
|
(GCompareDataFunc) objects_start_compare, NULL);
|
||||||
(GCompareFunc) objects_start_compare);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
|
|
Loading…
Reference in a new issue