track-element: Add is_core method to API

Open up the method to the user, since they may need the information.
Also added more documentation on what a core track element is to a clip
and how they are treated.

Part-of: <https://gitlab.freedesktop.org/gstreamer/gst-editing-services/-/merge_requests/169>
This commit is contained in:
Henry Wilkes 2020-05-13 12:11:32 +01:00
parent 9161c2efcb
commit e89411527a
7 changed files with 90 additions and 33 deletions

View file

@ -41,28 +41,49 @@
* interact with #GESClip-s directly, which will take care of creating and
* organising the elements of the timeline's tracks.
*
* Most subclassed clips will be associated with some *core*
* #GESTrackElement-s. When such a clip is added to a layer in a timeline,
* it will create these children and they will be added to the timeline's
* tracks. You can connect to the #GESContainer::child-added signal to be
* notified of their creation. If a clip will produce several core
* elements of the same #GESTrackElement:track-type but they are destined
* for separate tracks, you should connect to the timeline's
* #GESTimeline::select-tracks-for-object signal to coordinate which
* tracks each element should land in.
* ## Core Children
*
* Note, no two core children within a clip can share the same #GESTrack.
* Therefore, if you use #GESTimeline::select-tracks-for-object, you
* should ensure that each core #GESTrackElement is destined for
* different #GESTrack-s per clip (or no track).
* In more detail, clips will usually have some *core* #GESTrackElement
* children, which are created by the clip when it is added to a layer in
* a timeline. The type and form of these core children will depend on the
* clip's subclass. You can use ges_track_element_is_core() to determine
* whether a track element is considered such a core track element. Note,
* if a core track element is part of a clip, it will always be treated as
* a core *child* of the clip. You can connect to the
* #GESContainer::child-added signal to be notified of their creation.
*
* When a child is added to a clip, the timeline will select its tracks
* using #GESTimeline::select-tracks-for-object. Note that it may be the
* case that the child will still have no set #GESTrackElement:track
* after this process. For example, if the timeline does not have a track
* of the corresponding #GESTrack:track-type. A clip can safely contain
* such children, which may have their track set later, although they will
* play no functioning role in the timeline in the meantime.
*
* If a clip may create track elements with various
* #GESTrackElement:track-type(s), such as a #GESUriClip, but you only
* want it to create a subset of these types, you should set the
* #GESClip:supported-formats of the clip to the subset of types. This
* should be done *before* adding the clip to a layer.
*
* If a clip will produce several core elements of the same
* #GESTrackElement:track-type, you should connect to the timeline's
* #GESTimeline::select-tracks-for-object signal to coordinate which
* tracks each element should land in. Note, no two core children within a
* clip can share the same #GESTrack, so you should not select the same
* track for two separate core children. Provided you stick to this rule,
* it is still safe to select several tracks for the same core child, the
* core child will be copied into the additional tracks. You can manually
* add the child to more tracks later using ges_clip_add_child_to_track().
* If you do not wish to use a core child, you can always select no track.
*
* The #GESTimelineElement:in-point of the clip will control the
* #GESTimelineElement:in-point of these core elements to be the same
* #GESTimelineElement:in-point of its core children to be the same
* value if their #GESTrackElement:has-internal-source is set to %TRUE.
*
* The #GESTimelineElement:max-duration of the clip is the minimum
* #GESTimelineElement:max-duration of its children. If you set its value
* to anything other than its current value, this will also set the
* #GESTimelineElement:max-duration of its core children. If you set its
* value to anything other than its current value, this will also set the
* #GESTimelineElement:max-duration of all its core children to the same
* value if their #GESTrackElement:has-internal-source is set to %TRUE.
* As a special case, whilst a clip does not yet have any core children,
@ -82,12 +103,16 @@
* effects. You can change the ordering of effects using
* ges_clip_set_top_effect_index().
*
* Note, since an effect must be applied on top of a core child, if you
* use #GESTimeline::select-tracks-for-object, you should ensure that the
* Tracks are selected for top effects in the same way as core children.
* If you add a top effect to a clip before it is part of a timeline, and
* later add the clip to a timeline, the track selection for the top
* effects will occur just after the track selection for the core
* children. If you add a top effect to a clip that is already part of a
* timeline, the track selection will occur immediately. Since a top
* effect must be applied on top of a core child, if you use
* #GESTimeline::select-tracks-for-object, you should ensure that the
* added effects are destined for a #GESTrack that already contains a core
* child (note that #GESTimeline::select-tracks-for-object will be called
* for the core children before the added effects, so their tracks will be
* selected before the effects).
* child.
*
* In addition, if the core child in the track is not
* #GESTrackElement:active, then neither can any of its effects be
@ -173,7 +198,8 @@ G_DEFINE_ABSTRACT_TYPE_WITH_CODE (GESClip, ges_clip,
* *
****************************************************/
#define _IS_CORE_CHILD(child) GES_TRACK_ELEMENT_IS_CORE(child)
#define _IS_CORE_CHILD(child) \
ges_track_element_is_core (GES_TRACK_ELEMENT (child))
#define _IS_TOP_EFFECT(child) \
(!_IS_CORE_CHILD (child) && GES_IS_BASE_EFFECT (child))

View file

@ -83,9 +83,6 @@ GstDebugCategory * _ges_debug (void);
#define GES_FORMAT GES_TIMELINE_ELEMENT_FORMAT
#define GES_ARGS GES_TIMELINE_ELEMENT_ARGS
#define GES_TRACK_ELEMENT_IS_CORE(child) \
(ges_track_element_get_creator_asset (GES_TRACK_ELEMENT (child)) != NULL)
#define GES_TIMELINE_ELEMENT_SET_BEING_EDITED(element) \
ELEMENT_SET_FLAG ( \
ges_timeline_element_peak_toplevel (GES_TIMELINE_ELEMENT (element)), \

View file

@ -902,7 +902,7 @@ set_edit_trim_start_non_core_children (GESTimelineElement * clip,
el = tmp->data;
if (ges_track_element_has_internal_source (el)
&& ges_track_element_is_active (el)
&& !GES_TRACK_ELEMENT_IS_CORE (child)) {
&& !ges_track_element_is_core (el)) {
GST_INFO_OBJECT (child, "Setting track element %s to trim in-point "
"with offset %" G_GINT64_FORMAT " since the parent clip %"

View file

@ -1308,8 +1308,9 @@ _core_in_track (GESTrack * track, GESClip * clip)
{
GList *tmp;
for (tmp = GES_CONTAINER_CHILDREN (clip); tmp; tmp = tmp->next) {
if (GES_TRACK_ELEMENT_IS_CORE (tmp->data)
&& ges_track_element_get_track (tmp->data) == track) {
GESTrackElement *el = tmp->data;
if (ges_track_element_is_core (el)
&& ges_track_element_get_track (el) == track) {
return tmp->data;
}
}
@ -1331,7 +1332,7 @@ select_tracks_for_object_default (GESTimeline * timeline,
GESTrack *track = GES_TRACK (tmp->data);
if ((track->type & ges_track_element_get_track_type (tr_object))) {
if (GES_TRACK_ELEMENT_IS_CORE (tr_object)) {
if (ges_track_element_is_core (tr_object)) {
core = _core_in_track (track, clip);
if (core) {
GST_WARNING_OBJECT (timeline, "The clip '%s' contains multiple "
@ -1546,7 +1547,7 @@ clip_track_element_removed_cb (GESClip * clip,
/* if we have non-core elements in the same track, they should be
* removed from them to preserve the rule that a non-core can only be
* in the same track as a core element from the same clip */
if (GES_TRACK_ELEMENT_IS_CORE (track_element))
if (ges_track_element_is_core (track_element))
ges_clip_empty_from_track (clip, track);
ges_track_remove_element (track, track_element);
}
@ -1573,7 +1574,7 @@ _add_clip_children_to_tracks (GESTimeline * timeline, GESClip * clip,
children = ges_container_get_children (GES_CONTAINER (clip), FALSE);
for (tmp = children; tmp; tmp = tmp->next) {
GESTrackElement *el = tmp->data;
if (GES_TRACK_ELEMENT_IS_CORE (el) != add_core)
if (ges_track_element_is_core (el) != add_core)
continue;
if (g_list_find (blacklist, el))
continue;

View file

@ -1826,3 +1826,33 @@ ges_track_element_get_control_binding (GESTrackElement * object,
property_name);
return binding;
}
/**
* ges_track_element_is_core:
* @object: A #GESTrackElement
*
* Get whether the given track element is a core track element. That is,
* it was created by the @create_track_elements #GESClipClass method for
* some #GESClip.
*
* Note that such a track element can only be added to a clip that shares
* the same #GESAsset as the clip that created it. For example, you are
* allowed to move core children between clips that resulted from
* ges_container_ungroup(), but you could not move the core child from a
* #GESUriClip to a #GESTitleClip or another #GESUriClip with a different
* #GESUriClip:uri.
*
* Moreover, if a core track element is added to a clip, it will always be
* added as a core child. Therefore, if this returns %TRUE, then @element
* will be a core child of its parent clip.
*
* Returns: %TRUE if @element is a core track element.
*/
gboolean
ges_track_element_is_core (GESTrackElement * object)
{
g_return_val_if_fail (GES_IS_TRACK_ELEMENT (object), FALSE);
return (ges_track_element_get_creator_asset (object) != NULL);
}

View file

@ -133,6 +133,9 @@ GstElement * ges_track_element_get_nleobject (GESTrackElement * object);
GES_API
GstElement * ges_track_element_get_element (GESTrackElement * object);
GES_API
gboolean ges_track_element_is_core (GESTrackElement * object);
GES_API
gboolean ges_track_element_set_active (GESTrackElement * object,
gboolean active);

View file

@ -278,7 +278,7 @@ extractable_set_asset (GESExtractable * self, GESAsset * asset)
GESTrackElement *child = tmp->data;
GESTrack *track = ges_track_element_get_track (child);
/* remove our core children */
if (GES_TRACK_ELEMENT_IS_CORE (child)) {
if (ges_track_element_is_core (child)) {
if (track)
g_hash_table_insert (source_by_track, gst_object_ref (track),
gst_object_ref (child));
@ -306,7 +306,7 @@ extractable_set_asset (GESExtractable * self, GESAsset * asset)
* the same source! */
for (tmp = GES_CONTAINER_CHILDREN (clip); tmp; tmp = tmp->next) {
GESTrackElement *child = tmp->data;
if (GES_TRACK_ELEMENT_IS_CORE (child)) {
if (ges_track_element_is_core (child)) {
GESTrackElement *orig_source = g_hash_table_lookup (source_by_track,
ges_track_element_get_track (child));
contains_core = TRUE;