mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer.git
synced 2024-11-26 19:51:11 +00:00
container: Add a way to ungroup a GESContainer into several GESContainers
+ Add simple unit test API: GESContainerClass::ungroup vmethod ges_container_ungroup
This commit is contained in:
parent
c72c14b398
commit
c73ced52f8
4 changed files with 191 additions and 0 deletions
|
@ -158,6 +158,74 @@ _remove_child (GESContainer * container, GESTimelineElement * element)
|
|||
return TRUE;
|
||||
}
|
||||
|
||||
static void
|
||||
add_tlobj_to_list (gpointer key, gpointer tlobj, GList ** list)
|
||||
{
|
||||
*list = g_list_prepend (*list, g_object_ref (tlobj));
|
||||
}
|
||||
|
||||
static GList *
|
||||
_ungroup (GESContainer * container, gboolean recursive)
|
||||
{
|
||||
GList *tmp, *ret = NULL;
|
||||
GESClip *tmpclip;
|
||||
GESTrackType track_type;
|
||||
GESTrackElement *track_element;
|
||||
|
||||
gboolean first_obj = TRUE;
|
||||
GESClip *clip = GES_CLIP (container);
|
||||
GESTimelineElement *element = GES_TIMELINE_ELEMENT (container);
|
||||
GESTimelineLayer *layer = clip->priv->layer;
|
||||
GHashTable *_tracktype_clip = g_hash_table_new (g_int_hash, g_int_equal);
|
||||
|
||||
/* If there is no TrackElement, just return @container in a list */
|
||||
if (GES_CONTAINER_CHILDREN (container) == NULL) {
|
||||
GST_DEBUG ("No TrackElement, simply returning");
|
||||
return g_list_prepend (ret, container);
|
||||
}
|
||||
|
||||
/* We need a copy of the current list of tracks */
|
||||
for (tmp = GES_CONTAINER_CHILDREN (container); tmp; tmp = tmp->next) {
|
||||
track_element = GES_TRACK_ELEMENT (tmp->data);
|
||||
track_type = ges_track_element_get_track_type (track_element);
|
||||
|
||||
tmpclip = g_hash_table_lookup (_tracktype_clip, &track_type);
|
||||
if (tmpclip == NULL) {
|
||||
if (G_UNLIKELY (first_obj == TRUE)) {
|
||||
tmpclip = clip;
|
||||
first_obj = FALSE;
|
||||
} else {
|
||||
tmpclip = GES_CLIP (ges_timeline_element_copy (element, FALSE));
|
||||
if (layer) {
|
||||
/* Add new container to the same layer as @container */
|
||||
ges_clip_set_moving_from_layer (tmpclip, TRUE);
|
||||
ges_timeline_layer_add_clip (layer, tmpclip);
|
||||
ges_clip_set_moving_from_layer (tmpclip, FALSE);
|
||||
}
|
||||
}
|
||||
|
||||
g_hash_table_insert (_tracktype_clip, &track_type, tmpclip);
|
||||
ges_clip_set_supported_formats (tmpclip, track_type);
|
||||
}
|
||||
|
||||
/* Move trackelement to the container it is supposed to land into */
|
||||
if (tmpclip != clip) {
|
||||
ges_container_remove (container, GES_TIMELINE_ELEMENT (track_element));
|
||||
ges_container_add (GES_CONTAINER (tmpclip),
|
||||
GES_TIMELINE_ELEMENT (track_element));
|
||||
}
|
||||
}
|
||||
g_hash_table_foreach (_tracktype_clip, (GHFunc) add_tlobj_to_list, &ret);
|
||||
g_hash_table_unref (_tracktype_clip);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/****************************************************
|
||||
* *
|
||||
* GObject virtual methods implementation *
|
||||
* *
|
||||
****************************************************/
|
||||
static void
|
||||
ges_clip_get_property (GObject * object, guint property_id,
|
||||
GValue * value, GParamSpec * pspec)
|
||||
|
@ -241,6 +309,7 @@ ges_clip_class_init (GESClipClass * klass)
|
|||
container_class->get_priorty_range = _get_priorty_range;
|
||||
container_class->add_child = _add_child;
|
||||
container_class->remove_child = _remove_child;
|
||||
container_class->ungroup = _ungroup;
|
||||
|
||||
klass->need_fill_track = TRUE;
|
||||
}
|
||||
|
|
|
@ -389,6 +389,7 @@ ges_container_class_init (GESContainerClass * klass)
|
|||
/* No default implementations */
|
||||
klass->remove_child = NULL;
|
||||
klass->add_child = NULL;
|
||||
klass->ungroup = NULL;
|
||||
}
|
||||
|
||||
static void
|
||||
|
@ -669,3 +670,36 @@ ges_container_get_children (GESContainer * container)
|
|||
return g_list_copy_deep (container->children, (GCopyFunc) gst_object_ref,
|
||||
NULL);
|
||||
}
|
||||
|
||||
/**
|
||||
* ges_container_ungroup
|
||||
* @container: (transfer full): The #GESContainer to ungroup
|
||||
* @recursive: Wether to recursively ungroup @container
|
||||
*
|
||||
* Ungroups the #GESTimelineElement contained in this GESContainer,
|
||||
* creating new #GESContainer containing those #GESTimelineElement
|
||||
* properly apropriately.
|
||||
*
|
||||
* Returns: (transfer container) (element-type GESContainer): The list of
|
||||
* #GESContainer resulting from the ungrouping operation
|
||||
* The user is responsible for unreffing the contained objects
|
||||
* and freeing the list.
|
||||
*/
|
||||
GList *
|
||||
ges_container_ungroup (GESContainer * container, gboolean recursive)
|
||||
{
|
||||
GESContainerClass *klass;
|
||||
|
||||
g_return_val_if_fail (GES_IS_CONTAINER (container), NULL);
|
||||
|
||||
GST_DEBUG_OBJECT (container, "Ungrouping container %s recursively",
|
||||
recursive ? "" : "not");
|
||||
|
||||
klass = GES_CONTAINER_GET_CLASS (container);
|
||||
if (klass->ungroup == NULL) {
|
||||
GST_INFO_OBJECT (container, "No ungoup virtual method, doint nothing");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return klass->ungroup (container, recursive);
|
||||
}
|
||||
|
|
|
@ -89,6 +89,8 @@ struct _GESContainer
|
|||
* @remove_child: Virtual method to remove a child
|
||||
* @add_child: Virtual method to add a child
|
||||
* @get_priorty_range: Returns the range of possible priority in which the children can be in.
|
||||
* @ungroup: Ungroups the #GESTimelineElement contained in this #GESContainer, creating new
|
||||
* #GESContainer containing those #GESTimelineElement apropriately.
|
||||
*/
|
||||
struct _GESContainerClass
|
||||
{
|
||||
|
@ -102,6 +104,7 @@ struct _GESContainerClass
|
|||
gboolean (*add_child) (GESContainer *container, GESTimelineElement *element);
|
||||
gboolean (*remove_child) (GESContainer *container, GESTimelineElement *element);
|
||||
void (*get_priorty_range) (GESContainer *container, guint32 *min_prio, guint32 *max_prio);
|
||||
GList* (*ungroup) (GESContainer *container, gboolean recursive);
|
||||
|
||||
|
||||
/*< private >*/
|
||||
|
@ -115,6 +118,7 @@ GType ges_container_get_type (void);
|
|||
GList* ges_container_get_children (GESContainer *container);
|
||||
gboolean ges_container_add (GESContainer *container, GESTimelineElement *child);
|
||||
gboolean ges_container_remove (GESContainer *container, GESTimelineElement *child);
|
||||
GList * ges_container_ungroup (GESContainer * container, gboolean recursive);
|
||||
|
||||
G_END_DECLS
|
||||
#endif /* _GES_CONTAINER */
|
||||
|
|
|
@ -177,6 +177,89 @@ GST_START_TEST (test_split_object)
|
|||
|
||||
GST_END_TEST;
|
||||
|
||||
GST_START_TEST (test_clip_ungroup)
|
||||
{
|
||||
GESAsset *asset;
|
||||
GESTimeline *timeline;
|
||||
GESClip *clip, *clip2;
|
||||
GList *containers, *tmp;
|
||||
GESTimelineLayer *layer;
|
||||
GESTrack *audio_track, *video_track;
|
||||
|
||||
ges_init ();
|
||||
|
||||
timeline = ges_timeline_new ();
|
||||
layer = ges_timeline_layer_new ();
|
||||
audio_track = ges_track_audio_raw_new ();
|
||||
video_track = ges_track_video_raw_new ();
|
||||
|
||||
fail_unless (ges_timeline_add_track (timeline, audio_track));
|
||||
fail_unless (ges_timeline_add_track (timeline, video_track));
|
||||
fail_unless (ges_timeline_add_layer (timeline, layer));
|
||||
|
||||
asset = ges_asset_request (GES_TYPE_TEST_CLIP, NULL, NULL);
|
||||
assert_is_type (asset, GES_TYPE_ASSET);
|
||||
|
||||
clip = ges_timeline_layer_add_asset (layer, asset, 0, 0, 10, 1,
|
||||
GES_TRACK_TYPE_UNKNOWN);
|
||||
ASSERT_OBJECT_REFCOUNT (clip, "1 layer", 1);
|
||||
assert_equals_uint64 (_START (clip), 0);
|
||||
assert_equals_uint64 (_INPOINT (clip), 0);
|
||||
assert_equals_uint64 (_DURATION (clip), 10);
|
||||
assert_equals_int (g_list_length (GES_CONTAINER_CHILDREN (clip)), 2);
|
||||
|
||||
containers = ges_container_ungroup (GES_CONTAINER (clip), FALSE);
|
||||
assert_equals_int (g_list_length (containers), 2);
|
||||
fail_unless (clip == containers->data);
|
||||
assert_equals_int (g_list_length (GES_CONTAINER_CHILDREN (clip)), 1);
|
||||
assert_equals_uint64 (_START (clip), 0);
|
||||
assert_equals_uint64 (_INPOINT (clip), 0);
|
||||
assert_equals_uint64 (_DURATION (clip), 10);
|
||||
ASSERT_OBJECT_REFCOUNT (clip, "1 for the layer + 1 in containers list", 2);
|
||||
|
||||
clip2 = containers->next->data;
|
||||
fail_if (clip2 == clip);
|
||||
assert_equals_int (g_list_length (GES_CONTAINER_CHILDREN (clip2)), 1);
|
||||
assert_equals_uint64 (_START (clip2), 0);
|
||||
assert_equals_uint64 (_INPOINT (clip2), 0);
|
||||
assert_equals_uint64 (_DURATION (clip2), 10);
|
||||
ASSERT_OBJECT_REFCOUNT (clip2, "1 for the layer + 1 in containers list", 2);
|
||||
g_list_free_full (containers, gst_object_unref);
|
||||
|
||||
tmp = ges_track_get_elements (audio_track);
|
||||
assert_equals_int (g_list_length (tmp), 1);
|
||||
ASSERT_OBJECT_REFCOUNT (tmp->data, "1 for the track + 1 for the container "
|
||||
"+ 1 for the timeline + 1 in tmp list", 4);
|
||||
assert_equals_int (ges_track_element_get_track_type (tmp->data),
|
||||
GES_TRACK_TYPE_AUDIO);
|
||||
assert_equals_int (ges_clip_get_supported_formats (GES_CLIP
|
||||
(ges_timeline_element_get_parent (tmp->data))), GES_TRACK_TYPE_AUDIO);
|
||||
g_list_free_full (tmp, gst_object_unref);
|
||||
tmp = ges_track_get_elements (video_track);
|
||||
assert_equals_int (g_list_length (tmp), 1);
|
||||
ASSERT_OBJECT_REFCOUNT (tmp->data, "1 for the track + 1 for the container "
|
||||
"+ 1 for the timeline + 1 in tmp list", 4);
|
||||
assert_equals_int (ges_track_element_get_track_type (tmp->data),
|
||||
GES_TRACK_TYPE_VIDEO);
|
||||
assert_equals_int (ges_clip_get_supported_formats (GES_CLIP
|
||||
(ges_timeline_element_get_parent (tmp->data))), GES_TRACK_TYPE_VIDEO);
|
||||
g_list_free_full (tmp, gst_object_unref);
|
||||
|
||||
ges_timeline_element_set_start (GES_TIMELINE_ELEMENT (clip), 10);
|
||||
assert_equals_int (g_list_length (GES_CONTAINER_CHILDREN (clip)), 1);
|
||||
assert_equals_uint64 (_START (clip), 10);
|
||||
assert_equals_uint64 (_INPOINT (clip), 0);
|
||||
assert_equals_uint64 (_DURATION (clip), 10);
|
||||
assert_equals_int (g_list_length (GES_CONTAINER_CHILDREN (clip2)), 1);
|
||||
assert_equals_uint64 (_START (clip2), 0);
|
||||
assert_equals_uint64 (_INPOINT (clip2), 0);
|
||||
assert_equals_uint64 (_DURATION (clip2), 10);
|
||||
|
||||
gst_object_unref (timeline);
|
||||
}
|
||||
|
||||
GST_END_TEST;
|
||||
|
||||
static Suite *
|
||||
ges_suite (void)
|
||||
{
|
||||
|
@ -187,6 +270,7 @@ ges_suite (void)
|
|||
|
||||
tcase_add_test (tc_chain, test_object_properties);
|
||||
tcase_add_test (tc_chain, test_split_object);
|
||||
tcase_add_test (tc_chain, test_clip_ungroup);
|
||||
|
||||
return s;
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue