mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer.git
synced 2024-11-26 11:41:09 +00:00
formatter: Fix saving/loading project with clip speed rate control
We need to ensure that clips duration is set after time effects are added and we now need to serialize effects inpoints and max duration. Part-of: <https://gitlab.freedesktop.org/gstreamer/gst-editing-services/-/merge_requests/177>
This commit is contained in:
parent
e142f49177
commit
db5c62ad4c
5 changed files with 56 additions and 16 deletions
|
@ -94,6 +94,7 @@ struct _GESBaseXmlFormatterPrivate
|
|||
GESTrackElement *current_track_element;
|
||||
|
||||
GESClip *current_clip;
|
||||
GstClockTime current_clip_duration;
|
||||
|
||||
gboolean timeline_auto_transition;
|
||||
|
||||
|
@ -416,6 +417,7 @@ ges_base_xml_formatter_init (GESBaseXmlFormatter * self)
|
|||
g_direct_equal, NULL, (GDestroyNotify) _free_layer_entry);
|
||||
priv->current_track_element = NULL;
|
||||
priv->current_clip = NULL;
|
||||
priv->current_clip_duration = GST_CLOCK_TIME_NONE;
|
||||
priv->timeline_auto_transition = FALSE;
|
||||
}
|
||||
|
||||
|
@ -636,8 +638,16 @@ _add_track_element (GESFormatter * self, GESClip * clip,
|
|||
(GstStructureForeachFunc) _set_child_property, trackelement);
|
||||
|
||||
if (properties) {
|
||||
gboolean has_internal_source;
|
||||
/* We do not serialize the priority anymore, and we should never have. */
|
||||
gst_structure_remove_field (properties, "priority");
|
||||
|
||||
/* Ensure that has-internal-source is set before inpoint as otherwise
|
||||
* the inpoint will be ignored */
|
||||
if (gst_structure_get_boolean (properties, "has-internal-source",
|
||||
&has_internal_source) && has_internal_source)
|
||||
g_object_set (trackelement, "has-internal-source", has_internal_source,
|
||||
NULL);
|
||||
gst_structure_foreach (properties,
|
||||
(GstStructureForeachFunc) set_property_foreach, trackelement);
|
||||
}
|
||||
|
@ -915,6 +925,7 @@ ges_base_xml_formatter_add_clip (GESBaseXmlFormatter * self,
|
|||
if (!nclip)
|
||||
return;
|
||||
|
||||
priv->current_clip_duration = duration;
|
||||
priv->current_clip = nclip;
|
||||
}
|
||||
|
||||
|
@ -1335,3 +1346,24 @@ ges_base_xml_formatter_last_group_add_child (GESBaseXmlFormatter * self,
|
|||
GST_DEBUG_OBJECT (self, "Adding %s to %s", child_id,
|
||||
GES_TIMELINE_ELEMENT_NAME (((PendingGroup *) priv->groups->data)->group));
|
||||
}
|
||||
|
||||
void
|
||||
ges_base_xml_formatter_end_current_clip (GESBaseXmlFormatter * self)
|
||||
{
|
||||
GESBaseXmlFormatterPrivate *priv = _GET_PRIV (self);
|
||||
|
||||
if (priv->state != STATE_LOADING_CLIPS) {
|
||||
GST_DEBUG_OBJECT (self, "Not ending clip in %s state.",
|
||||
loading_state_name (priv->state));
|
||||
return;
|
||||
}
|
||||
|
||||
g_return_if_fail (priv->current_clip);
|
||||
|
||||
if (_DURATION (priv->current_clip) != priv->current_clip_duration)
|
||||
_set_duration0 (GES_TIMELINE_ELEMENT (priv->current_clip),
|
||||
priv->current_clip_duration);
|
||||
|
||||
priv->current_clip = NULL;
|
||||
priv->current_clip_duration = GST_CLOCK_TIME_NONE;
|
||||
}
|
||||
|
|
|
@ -377,7 +377,10 @@ G_GNUC_INTERNAL void ges_base_xml_formatter_set_timeline_properties(GESBaseXmlFo
|
|||
GESTimeline *timeline,
|
||||
const gchar *properties,
|
||||
const gchar *metadatas);
|
||||
G_GNUC_INTERNAL void ges_xml_formatter_deinit (void);
|
||||
|
||||
G_GNUC_INTERNAL void ges_base_xml_formatter_end_current_clip (GESBaseXmlFormatter *self);
|
||||
|
||||
G_GNUC_INTERNAL void ges_xml_formatter_deinit (void);
|
||||
|
||||
G_GNUC_INTERNAL gboolean set_property_foreach (GQuark field_id,
|
||||
const GValue * value,
|
||||
|
|
|
@ -1021,6 +1021,9 @@ _parse_element_end (GMarkupParseContext * context,
|
|||
if (!priv->subproject_depth) {
|
||||
g_clear_pointer (&priv->subproject, g_free);
|
||||
}
|
||||
} else if (!g_strcmp0 (element_name, "clip")) {
|
||||
if (!priv->subproject)
|
||||
ges_base_xml_formatter_end_current_clip (GES_BASE_XML_FORMATTER (self));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1553,8 +1556,7 @@ _save_effect (GString * str, guint clip_id, GESTrackElement * trackelement,
|
|||
g_list_free_full (tracks, gst_object_unref);
|
||||
|
||||
properties = _serialize_properties (G_OBJECT (trackelement), NULL, "start",
|
||||
"in-point", "duration", "locked", "max-duration", "name", "priority",
|
||||
NULL);
|
||||
"duration", "locked", "name", "priority", NULL);
|
||||
metas =
|
||||
ges_meta_container_metas_to_string (GES_META_CONTAINER (trackelement));
|
||||
extractable_id = ges_extractable_get_id (GES_EXTRACTABLE (trackelement));
|
||||
|
|
|
@ -213,11 +213,11 @@ class GESSimpleTimelineTest(GESTest):
|
|||
|
||||
return clip
|
||||
|
||||
def append_clip(self, layer=0, asset_type=GES.TestClip):
|
||||
def append_clip(self, layer=0, asset_type=GES.TestClip, asset_id=None):
|
||||
while len(self.timeline.get_layers()) < layer + 1:
|
||||
self.timeline.append_layer()
|
||||
layer = self.timeline.get_layers()[layer]
|
||||
clip = GES.Asset.request(asset_type, None).extract()
|
||||
clip = GES.Asset.request(asset_type, asset_id).extract()
|
||||
clip.props.start = layer.get_duration()
|
||||
clip.props.duration = 10
|
||||
self.assertTrue(layer.add_clip(clip))
|
||||
|
@ -231,16 +231,16 @@ class GESSimpleTimelineTest(GESTest):
|
|||
and not GObject.type_is_a(p.value_type, GObject.Object)]
|
||||
for p in props:
|
||||
pname = p.name
|
||||
v0 = GObject.Value()
|
||||
v0.init(p.value_type)
|
||||
v0.set_value(ref.get_property(pname))
|
||||
refval = GObject.Value()
|
||||
refval.init(p.value_type)
|
||||
refval.set_value(ref.get_property(pname))
|
||||
|
||||
v1 = GObject.Value()
|
||||
v1.init(p.value_type)
|
||||
v1.set_value(element.get_property(pname))
|
||||
value = GObject.Value()
|
||||
value.init(p.value_type)
|
||||
value.set_value(element.get_property(pname))
|
||||
|
||||
self.assertTrue(Gst.value_compare(v0, v1) == Gst.VALUE_EQUAL,
|
||||
"%s are not equal: %s != %s" % (pname, v0, v1))
|
||||
self.assertTrue(Gst.value_compare(refval, value) == Gst.VALUE_EQUAL,
|
||||
"%s are not equal: %s != %s\n %s != %s" % (pname, value, refval, element, ref))
|
||||
|
||||
if isinstance(ref, GES.TrackElement):
|
||||
self.assertElementAreEqual(ref.get_nleobject(), element.get_nleobject())
|
||||
|
@ -275,7 +275,7 @@ class GESSimpleTimelineTest(GESTest):
|
|||
if not isinstance(ref_child, GES.Effect):
|
||||
child = tmpchild
|
||||
break
|
||||
elif ref_child.props.bin_description == child.props.bin_description:
|
||||
elif ref_child.props.bin_description == tmpchild.props.bin_description:
|
||||
child = tmpchild
|
||||
break
|
||||
|
||||
|
|
|
@ -613,9 +613,8 @@ class TestEditing(common.GESSimpleTimelineTest):
|
|||
def test_trim_time_effects(self):
|
||||
self.track_types = [GES.TrackType.VIDEO]
|
||||
super().setUp()
|
||||
clip = self.append_clip()
|
||||
clip = self.append_clip(asset_id="max-duration=30")
|
||||
self.assertTrue(clip.set_inpoint(12))
|
||||
self.assertTrue(clip.set_max_duration(30))
|
||||
self.assertEqual(clip.get_duration_limit(), 18)
|
||||
|
||||
children = clip.get_children(False)
|
||||
|
@ -646,6 +645,7 @@ class TestEditing(common.GESSimpleTimelineTest):
|
|||
self.assertEqual(clip.get_duration_limit(), 36)
|
||||
self.assertTrue(clip.set_start(40))
|
||||
self.assertTrue(clip.set_duration(10))
|
||||
self.check_reload_timeline()
|
||||
|
||||
# cannot trim to a 16 because overlay would have a negative in-point
|
||||
error = None
|
||||
|
@ -662,6 +662,8 @@ class TestEditing(common.GESSimpleTimelineTest):
|
|||
self.assertEqual(overlay.get_inpoint(), 5)
|
||||
self.assertEqual(overlay.get_max_duration(), 16)
|
||||
|
||||
self.check_reload_timeline()
|
||||
|
||||
# trim backwards to 20
|
||||
self.assertTrue(
|
||||
clip.edit_full(-1, GES.EditMode.EDIT_TRIM, GES.Edge.EDGE_START, 20))
|
||||
|
@ -686,6 +688,7 @@ class TestEditing(common.GESSimpleTimelineTest):
|
|||
# increased by 2
|
||||
self.assertEqual(overlay.get_inpoint(), 2)
|
||||
self.assertEqual(overlay.get_max_duration(), 16)
|
||||
self.check_reload_timeline()
|
||||
|
||||
def test_ripple_end(self):
|
||||
clip = self.append_clip()
|
||||
|
|
Loading…
Reference in a new issue