mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer.git
synced 2024-11-26 03:31:05 +00:00
ges: Add API to disable timeline coherence checks
There are cases where user might want to be in full control of the timeline and not be limited by the checks that are being done by GES to go from one timeline layout to another, this should be doable as it is a valid use case. Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/3501>
This commit is contained in:
parent
ac6b3e9a45
commit
712bda84db
4 changed files with 98 additions and 1 deletions
|
@ -929,6 +929,11 @@ timeline_tree_can_move_elements (GNode * root, GHashTable * moving,
|
||||||
GError ** error)
|
GError ** error)
|
||||||
{
|
{
|
||||||
TreeIterationData data = tree_iteration_data_init;
|
TreeIterationData data = tree_iteration_data_init;
|
||||||
|
|
||||||
|
if (ges_timeline_get_edit_apis_disabled (root->data)) {
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
data.moving = moving;
|
data.moving = moving;
|
||||||
data.root = root;
|
data.root = root;
|
||||||
data.res = TRUE;
|
data.res = TRUE;
|
||||||
|
@ -1703,6 +1708,10 @@ timeline_tree_can_move_element (GNode * root,
|
||||||
GHashTableIter iter;
|
GHashTableIter iter;
|
||||||
gpointer key, value;
|
gpointer key, value;
|
||||||
|
|
||||||
|
if (ges_timeline_get_edit_apis_disabled (root->data)) {
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
if (layer_prio == GES_TIMELINE_ELEMENT_NO_LAYER_PRIORITY
|
if (layer_prio == GES_TIMELINE_ELEMENT_NO_LAYER_PRIORITY
|
||||||
&& priority != layer_prio) {
|
&& priority != layer_prio) {
|
||||||
GST_INFO_OBJECT (element, "Cannot move to a layer when no layer "
|
GST_INFO_OBJECT (element, "Cannot move to a layer when no layer "
|
||||||
|
|
|
@ -115,6 +115,10 @@
|
||||||
* transition object will be kept, but with its timing and layer adjusted
|
* transition object will be kept, but with its timing and layer adjusted
|
||||||
* accordingly.
|
* accordingly.
|
||||||
*
|
*
|
||||||
|
* NOTE: if you know what you are doing and want to be in full control of the
|
||||||
|
* timeline layout, you can disable the edit APIs with
|
||||||
|
* #ges_timeline_disable_edit_apis.
|
||||||
|
*
|
||||||
* ## Saving
|
* ## Saving
|
||||||
*
|
*
|
||||||
* To save/load a timeline, you can use the ges_timeline_load_from_uri()
|
* To save/load a timeline, you can use the ges_timeline_load_from_uri()
|
||||||
|
@ -234,6 +238,7 @@ struct _GESTimelinePrivate
|
||||||
GstStreamCollection *stream_collection;
|
GstStreamCollection *stream_collection;
|
||||||
|
|
||||||
gboolean rendering_smartly;
|
gboolean rendering_smartly;
|
||||||
|
gboolean disable_edit_apis;
|
||||||
};
|
};
|
||||||
|
|
||||||
/* private structure to contain our track-related information */
|
/* private structure to contain our track-related information */
|
||||||
|
@ -2947,7 +2952,7 @@ ges_timeline_commit_sync (GESTimeline * timeline)
|
||||||
* Freezes the timeline from being committed. This is usually needed while the
|
* Freezes the timeline from being committed. This is usually needed while the
|
||||||
* timeline is being rendered to ensure that not change to the timeline are
|
* timeline is being rendered to ensure that not change to the timeline are
|
||||||
* taken into account during that moment. Once the rendering is done, you
|
* taken into account during that moment. Once the rendering is done, you
|
||||||
* should call #ges_timeline_thaw_commit so that comiting becomes possible
|
* should call #ges_timeline_thaw_commit so that committing becomes possible
|
||||||
* again and any call to `commit()` that happened during the rendering is
|
* again and any call to `commit()` that happened during the rendering is
|
||||||
* actually taken into account.
|
* actually taken into account.
|
||||||
*
|
*
|
||||||
|
@ -3038,6 +3043,7 @@ ges_timeline_set_auto_transition (GESTimeline * timeline,
|
||||||
GESLayer *layer;
|
GESLayer *layer;
|
||||||
|
|
||||||
g_return_if_fail (GES_IS_TIMELINE (timeline));
|
g_return_if_fail (GES_IS_TIMELINE (timeline));
|
||||||
|
g_return_if_fail (!timeline->priv->disable_edit_apis);
|
||||||
CHECK_THREAD (timeline);
|
CHECK_THREAD (timeline);
|
||||||
|
|
||||||
timeline->priv->auto_transition = auto_transition;
|
timeline->priv->auto_transition = auto_transition;
|
||||||
|
@ -3387,3 +3393,64 @@ ges_timeline_get_frame_at (GESTimeline * self, GstClockTime timestamp)
|
||||||
|
|
||||||
return gst_util_uint64_scale (timestamp, fps_n, fps_d * GST_SECOND);
|
return gst_util_uint64_scale (timestamp, fps_n, fps_d * GST_SECOND);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* ges_timeline_disable_edit_apis:
|
||||||
|
* @self: A #GESTimeline
|
||||||
|
* @disable_edit_apis: %TRUE to disable all the edit APIs so the user is in full
|
||||||
|
* control of ensuring timeline state validity %FALSE otherwise.
|
||||||
|
*
|
||||||
|
* WARNING: When using that mode, GES won't guarantee the coherence of the
|
||||||
|
* timeline. You need to ensure that the rules described in the [Overlaps and
|
||||||
|
* auto transitions](#overlaps-and-autotransitions) section are respected any time
|
||||||
|
* the timeline is [commited](ges_timeline_commit) (otherwise playback will most
|
||||||
|
* probably fail in different ways).
|
||||||
|
*
|
||||||
|
* When disabling editing APIs, GES won't be able to enforce the rules that
|
||||||
|
* makes the timeline overall state to be valid but some feature won't be
|
||||||
|
* usable:
|
||||||
|
* * #GESTimeline:snapping-distance
|
||||||
|
* * #GESTimeline:auto-transition
|
||||||
|
*
|
||||||
|
* Since: 1.22
|
||||||
|
*/
|
||||||
|
void
|
||||||
|
ges_timeline_disable_edit_apis (GESTimeline * self, gboolean disable_edit_apis)
|
||||||
|
{
|
||||||
|
CHECK_THREAD (self);
|
||||||
|
g_return_if_fail (GES_IS_TIMELINE (self));
|
||||||
|
|
||||||
|
if (disable_edit_apis) {
|
||||||
|
if (self->priv->snapping_distance > 0) {
|
||||||
|
GST_INFO_OBJECT (self,
|
||||||
|
"Disabling snapping as we are disabling edit APIs");
|
||||||
|
|
||||||
|
ges_timeline_set_snapping_distance (self, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (self->priv->auto_transition || self->priv->auto_transitions) {
|
||||||
|
GST_INFO_OBJECT (self,
|
||||||
|
"Disabling auto transitions as we are disabling auto edit APIs");
|
||||||
|
ges_timeline_set_auto_transition (self, FALSE);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
self->priv->disable_edit_apis = disable_edit_apis;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* ges_timeline_get_edit_apis_disabled:
|
||||||
|
* @self: A #GESTimeline
|
||||||
|
*
|
||||||
|
* Returns: %TRUE if edit APIs are disabled, %FALSE otherwise.
|
||||||
|
*
|
||||||
|
* Since: 1.22
|
||||||
|
*/
|
||||||
|
gboolean
|
||||||
|
ges_timeline_get_edit_apis_disabled (GESTimeline * self)
|
||||||
|
{
|
||||||
|
CHECK_THREAD (self);
|
||||||
|
g_return_val_if_fail (GES_IS_TIMELINE (self), FALSE);
|
||||||
|
|
||||||
|
return self->priv->disable_edit_apis;
|
||||||
|
}
|
||||||
|
|
|
@ -160,4 +160,9 @@ GES_API
|
||||||
GESFrameNumber ges_timeline_get_frame_at (GESTimeline *self,
|
GESFrameNumber ges_timeline_get_frame_at (GESTimeline *self,
|
||||||
GstClockTime timestamp);
|
GstClockTime timestamp);
|
||||||
|
|
||||||
|
GES_API
|
||||||
|
void ges_timeline_disable_edit_apis (GESTimeline * self, gboolean disable_edit_apis);
|
||||||
|
GES_API
|
||||||
|
gboolean ges_timeline_get_edit_apis_disabled (GESTimeline * self);
|
||||||
|
|
||||||
G_END_DECLS
|
G_END_DECLS
|
||||||
|
|
|
@ -3651,6 +3651,22 @@ class TestComplexEditing(common.GESTimelineConfigTest):
|
||||||
c0, 0, GES.EditMode.EDIT_NORMAL, GES.Edge.EDGE_NONE, 10, 30,
|
c0, 0, GES.EditMode.EDIT_NORMAL, GES.Edge.EDGE_NONE, 10, 30,
|
||||||
[c0], [c1], {c0 : {"start": 27}}, [], [])
|
[c0], [c1], {c0 : {"start": 27}}, [], [])
|
||||||
|
|
||||||
|
def test_disable_timeline_editing_apis(self):
|
||||||
|
track = self.add_video_track()
|
||||||
|
self.assertEqual(self.timeline.props.auto_transition, True)
|
||||||
|
self.timeline.disable_edit_apis(True)
|
||||||
|
self.assertEqual(self.timeline.props.auto_transition, False)
|
||||||
|
|
||||||
|
c0 = self.add_clip("c0", 0, [track], 0, 10)
|
||||||
|
# Without disabling edit API adding clip would fail
|
||||||
|
c1 = self.add_clip("c1", 0, [track], 0, 10)
|
||||||
|
self.assertTimelineConfig()
|
||||||
|
|
||||||
|
c1.set_start(1)
|
||||||
|
c1.set_duration(1)
|
||||||
|
self.assertEqual(c1.get_start(), 1)
|
||||||
|
self.assertEqual(c1.get_duration(), 1)
|
||||||
|
|
||||||
|
|
||||||
class TestTransitions(common.GESSimpleTimelineTest):
|
class TestTransitions(common.GESSimpleTimelineTest):
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue