mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer.git
synced 2024-11-26 19:51:11 +00:00
container: Add a ges_container_group method
+ Add some basic unit tests API: GESContainer:group vmethod ges_container_group
This commit is contained in:
parent
ae80f08869
commit
f579a6a95c
5 changed files with 248 additions and 5 deletions
|
@ -364,6 +364,8 @@ GES_CONTAINER_HEIGHT
|
|||
ges_container_get_children
|
||||
ges_container_add
|
||||
ges_container_remove
|
||||
ges_container_ungroup
|
||||
ges_container_group
|
||||
<SUBSECTION Standard>
|
||||
GESContainerPrivate
|
||||
ges_container_get_type
|
||||
|
|
156
ges/ges-clip.c
156
ges/ges-clip.c
|
@ -68,6 +68,12 @@ struct _GESClipPrivate
|
|||
GESTrackType supportedformats;
|
||||
};
|
||||
|
||||
typedef struct _CheckTrack
|
||||
{
|
||||
GESTrack *track;
|
||||
GESTrackElement *source;
|
||||
} CheckTrack;
|
||||
|
||||
enum
|
||||
{
|
||||
PROP_0,
|
||||
|
@ -221,6 +227,155 @@ _ungroup (GESContainer * container, gboolean recursive)
|
|||
return ret;
|
||||
}
|
||||
|
||||
static GESContainer *
|
||||
_group (GList * containers)
|
||||
{
|
||||
CheckTrack *tracks = NULL;
|
||||
GESTimeline *timeline = NULL;
|
||||
GESTrackType supported_formats;
|
||||
GESTimelineLayer *layer = NULL;
|
||||
GList *tmp, *tmpclip, *tmpelement;
|
||||
GstClockTime start, inpoint, duration;
|
||||
|
||||
GESAsset *asset = NULL;
|
||||
GESContainer *ret = NULL;
|
||||
guint nb_tracks = 0, i = 0;
|
||||
|
||||
start = inpoint = duration = GST_CLOCK_TIME_NONE;
|
||||
|
||||
/* First check if all the containers are clips, if they
|
||||
* all have the same start/inpoint/duration and are in the same
|
||||
* layer.
|
||||
*
|
||||
* We also need to make sure that all source have been created by the
|
||||
* same asset, keep the information */
|
||||
for (tmp = containers; tmp; tmp = tmp->next) {
|
||||
GESClip *clip;
|
||||
GESTimeline *tmptimeline;
|
||||
GESContainer *tmpcontainer;
|
||||
GESTimelineElement *element;
|
||||
|
||||
tmpcontainer = GES_CONTAINER (tmp->data);
|
||||
element = GES_TIMELINE_ELEMENT (tmp->data);
|
||||
if (GES_IS_CLIP (element) == FALSE) {
|
||||
GST_DEBUG ("Can only work with clips");
|
||||
goto done;
|
||||
}
|
||||
clip = GES_CLIP (tmp->data);
|
||||
tmptimeline = ges_timeline_element_get_timeline (element);
|
||||
if (!timeline) {
|
||||
GList *tmptrack;
|
||||
|
||||
start = _START (tmpcontainer);
|
||||
inpoint = _INPOINT (tmpcontainer);
|
||||
duration = _DURATION (tmpcontainer);
|
||||
timeline = tmptimeline;
|
||||
layer = clip->priv->layer;
|
||||
nb_tracks = g_list_length (GES_TIMELINE_GET_TRACKS (timeline));
|
||||
tracks = g_new0 (CheckTrack, nb_tracks);
|
||||
|
||||
for (tmptrack = GES_TIMELINE_GET_TRACKS (timeline); tmptrack;
|
||||
tmptrack = tmptrack->next) {
|
||||
tracks[i].track = tmptrack->data;
|
||||
i++;
|
||||
}
|
||||
} else {
|
||||
if (start != _START (tmpcontainer) ||
|
||||
inpoint != _INPOINT (tmpcontainer) ||
|
||||
duration != _DURATION (tmpcontainer) || clip->priv->layer != layer) {
|
||||
GST_INFO ("All children must have the same start, inpoint, duration "
|
||||
" and be in the same layer");
|
||||
|
||||
goto done;
|
||||
} else {
|
||||
GList *tmp2;
|
||||
|
||||
for (tmp2 = GES_CONTAINER_CHILDREN (tmp->data); tmp2; tmp2 = tmp2->next) {
|
||||
GESTrackElement *track_element = GES_TRACK_ELEMENT (tmp2->data);
|
||||
|
||||
if (GES_IS_SOURCE (track_element)) {
|
||||
guint i;
|
||||
|
||||
for (i = 0; i < nb_tracks; i++) {
|
||||
if (tracks[i].track ==
|
||||
ges_track_element_get_track (track_element)) {
|
||||
if (tracks[i].source) {
|
||||
GST_INFO ("Can not link clips with various source for a "
|
||||
"same track");
|
||||
|
||||
goto done;
|
||||
}
|
||||
tracks[i].source = track_element;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* Then check that all sources have been created by the same asset,
|
||||
* otherwise we can not group */
|
||||
for (i = 0; i < nb_tracks; i++) {
|
||||
if (tracks[i].source == NULL) {
|
||||
GST_FIXME ("Check what to do here as we might end up having a mess");
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
/* FIXME Check what to do if we have source that have no assets */
|
||||
if (!asset) {
|
||||
asset =
|
||||
ges_extractable_get_asset (GES_EXTRACTABLE
|
||||
(ges_timeline_element_get_parent (GES_TIMELINE_ELEMENT (tracks
|
||||
[i].source))));
|
||||
continue;
|
||||
}
|
||||
if (asset !=
|
||||
ges_extractable_get_asset (GES_EXTRACTABLE
|
||||
(ges_timeline_element_get_parent (GES_TIMELINE_ELEMENT (tracks
|
||||
[i].source))))) {
|
||||
GST_INFO ("Can not link clips with source coming from different assets");
|
||||
|
||||
goto done;
|
||||
}
|
||||
}
|
||||
|
||||
/* And now pass all TrackElements to the first clip,
|
||||
* and remove others from the layer (updating the supported formats) */
|
||||
ret = containers->data;
|
||||
supported_formats = GES_CLIP (ret)->priv->supportedformats;
|
||||
for (tmpclip = containers->next; tmpclip; tmpclip = tmpclip->next) {
|
||||
GESClip *cclip = tmpclip->data;
|
||||
|
||||
for (tmpelement = GES_CONTAINER_CHILDREN (cclip); tmpelement;
|
||||
tmpelement = tmpelement->next) {
|
||||
GESTimelineElement *celement = GES_TIMELINE_ELEMENT (tmpelement->data);
|
||||
|
||||
ges_container_remove (GES_CONTAINER (cclip), celement);
|
||||
ges_container_add (ret, celement);
|
||||
|
||||
supported_formats = supported_formats |
|
||||
ges_track_element_get_track_type (GES_TRACK_ELEMENT (celement));
|
||||
}
|
||||
|
||||
ges_timeline_layer_remove_clip (layer, tmpclip->data);
|
||||
}
|
||||
|
||||
ges_clip_set_supported_formats (GES_CLIP (ret), supported_formats);
|
||||
|
||||
done:
|
||||
if (tracks)
|
||||
g_free (tracks);
|
||||
|
||||
|
||||
return ret;
|
||||
|
||||
}
|
||||
|
||||
|
||||
/****************************************************
|
||||
* *
|
||||
* GObject virtual methods implementation *
|
||||
|
@ -310,6 +465,7 @@ ges_clip_class_init (GESClipClass * klass)
|
|||
container_class->add_child = _add_child;
|
||||
container_class->remove_child = _remove_child;
|
||||
container_class->ungroup = _ungroup;
|
||||
container_class->group = _group;
|
||||
|
||||
klass->need_fill_track = TRUE;
|
||||
}
|
||||
|
|
|
@ -390,6 +390,7 @@ ges_container_class_init (GESContainerClass * klass)
|
|||
klass->remove_child = NULL;
|
||||
klass->add_child = NULL;
|
||||
klass->ungroup = NULL;
|
||||
klass->group = NULL;
|
||||
}
|
||||
|
||||
static void
|
||||
|
@ -672,13 +673,13 @@ ges_container_get_children (GESContainer * container)
|
|||
}
|
||||
|
||||
/**
|
||||
* ges_container_ungroup
|
||||
* 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.
|
||||
* apropriately.
|
||||
*
|
||||
* Returns: (transfer container) (element-type GESContainer): The list of
|
||||
* #GESContainer resulting from the ungrouping operation
|
||||
|
@ -703,3 +704,47 @@ ges_container_ungroup (GESContainer * container, gboolean recursive)
|
|||
|
||||
return klass->ungroup (container, recursive);
|
||||
}
|
||||
|
||||
/**
|
||||
* ges_container_group:
|
||||
* @containers: (transfer none)(element-type GESContainer): The
|
||||
* #GESContainer to group, they must all be in a same #GESTimeline
|
||||
*
|
||||
* Groups the #GESContainer-s provided in @containers. It creates a subclass
|
||||
* of #GESContainer, depending on the containers provided in @containers.
|
||||
* Basically, if all the containers in @containers should be contained in a same
|
||||
* clip (all the #GESTrackElement they contain have the exact same
|
||||
* start/inpoint/duration and are in the same layer), it will create a #GESClip
|
||||
* otherwise a #GESGroup will be created
|
||||
*
|
||||
* Returns: (transfer none): The #GESContainer (subclass) resulting of the
|
||||
* grouping
|
||||
*/
|
||||
GESContainer *
|
||||
ges_container_group (GList * containers)
|
||||
{
|
||||
GList *tmp;
|
||||
GESContainer *ret;
|
||||
GESTimeline *timeline;
|
||||
GESTimelineElement *element;
|
||||
GObjectClass *clip_class;
|
||||
|
||||
g_return_val_if_fail (containers, NULL);
|
||||
element = GES_TIMELINE_ELEMENT (containers->data);
|
||||
timeline = ges_timeline_element_get_timeline (element);
|
||||
g_return_val_if_fail (timeline, NULL);
|
||||
|
||||
if (g_list_length (containers) == 1)
|
||||
return containers->data;
|
||||
|
||||
for (tmp = containers; tmp; tmp = tmp->next) {
|
||||
g_return_val_if_fail (GES_IS_CONTAINER (tmp->data), NULL);
|
||||
g_return_val_if_fail (ges_timeline_element_get_timeline
|
||||
(GES_TIMELINE_ELEMENT (tmp->data)) == timeline, NULL);
|
||||
}
|
||||
|
||||
clip_class = g_type_class_peek (GES_TYPE_CLIP);
|
||||
ret = GES_CONTAINER_CLASS (clip_class)->group (containers);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
|
|
@ -90,6 +90,7 @@ struct _GESContainer
|
|||
* @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
|
||||
* @group: Groups the #GESContainers together
|
||||
* #GESContainer containing those #GESTimelineElement apropriately.
|
||||
*/
|
||||
struct _GESContainerClass
|
||||
|
@ -105,6 +106,7 @@ struct _GESContainerClass
|
|||
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);
|
||||
GESContainer * (*group) (GList *containers);
|
||||
|
||||
|
||||
/*< private >*/
|
||||
|
@ -119,6 +121,7 @@ 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);
|
||||
GESContainer *ges_container_group (GList *containers);
|
||||
|
||||
G_END_DECLS
|
||||
#endif /* _GES_CONTAINER */
|
||||
|
|
|
@ -177,13 +177,14 @@ GST_START_TEST (test_split_object)
|
|||
|
||||
GST_END_TEST;
|
||||
|
||||
GST_START_TEST (test_clip_ungroup)
|
||||
GST_START_TEST (test_clip_group_ungroup)
|
||||
{
|
||||
GESAsset *asset;
|
||||
GESTimeline *timeline;
|
||||
GESClip *clip, *clip2;
|
||||
GList *containers, *tmp;
|
||||
GESTimelineLayer *layer;
|
||||
GESContainer *regrouped_clip;
|
||||
GESTrack *audio_track, *video_track;
|
||||
|
||||
ges_init ();
|
||||
|
@ -224,7 +225,6 @@ GST_START_TEST (test_clip_ungroup)
|
|||
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);
|
||||
|
@ -255,6 +255,43 @@ GST_START_TEST (test_clip_ungroup)
|
|||
assert_equals_uint64 (_INPOINT (clip2), 0);
|
||||
assert_equals_uint64 (_DURATION (clip2), 10);
|
||||
|
||||
regrouped_clip = ges_container_group (containers);
|
||||
fail_unless (regrouped_clip == NULL);
|
||||
|
||||
ges_timeline_element_set_start (GES_TIMELINE_ELEMENT (clip), 0);
|
||||
regrouped_clip = ges_container_group (containers);
|
||||
assert_is_type (regrouped_clip, GES_TYPE_CLIP);
|
||||
assert_equals_int (g_list_length (GES_CONTAINER_CHILDREN (regrouped_clip)),
|
||||
2);
|
||||
assert_equals_int (ges_clip_get_supported_formats (GES_CLIP (regrouped_clip)),
|
||||
GES_TRACK_TYPE_VIDEO | GES_TRACK_TYPE_AUDIO);
|
||||
g_list_free_full (containers, gst_object_unref);
|
||||
|
||||
GST_DEBUG ("Check clips in the layer");
|
||||
tmp = ges_timeline_layer_get_clips (layer);
|
||||
assert_equals_int (g_list_length (tmp), 1);
|
||||
g_list_free_full (tmp, gst_object_unref);
|
||||
|
||||
GST_DEBUG ("Check TrackElement in audio track");
|
||||
tmp = ges_track_get_elements (audio_track);
|
||||
assert_equals_int (g_list_length (tmp), 1);
|
||||
assert_equals_int (ges_track_element_get_track_type (tmp->data),
|
||||
GES_TRACK_TYPE_AUDIO);
|
||||
fail_unless (GES_CONTAINER (ges_timeline_element_get_parent (tmp->data)) ==
|
||||
regrouped_clip);
|
||||
g_list_free_full (tmp, gst_object_unref);
|
||||
|
||||
GST_DEBUG ("Check TrackElement in video track");
|
||||
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);
|
||||
fail_unless (GES_CONTAINER (ges_timeline_element_get_parent (tmp->data)) ==
|
||||
regrouped_clip);
|
||||
g_list_free_full (tmp, gst_object_unref);
|
||||
|
||||
gst_object_unref (timeline);
|
||||
}
|
||||
|
||||
|
@ -270,7 +307,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);
|
||||
tcase_add_test (tc_chain, test_clip_group_ungroup);
|
||||
|
||||
return s;
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue