ges: freeze commit during render
authorStéphane Cerveau <scerveau@collabora.com>
Tue, 3 Aug 2021 09:31:07 +0000 (11:31 +0200)
committerGStreamer Marge Bot <gitlab-merge-bot@gstreamer-foundation.org>
Fri, 6 Aug 2021 13:42:45 +0000 (13:42 +0000)
In render mode, do not commit the timeline
as the position can be invalid and lead to
missing frames.

Fixes #136

Part-of: <https://gitlab.freedesktop.org/gstreamer/gst-editing-services/-/merge_requests/262>

ges/ges-pipeline.c
ges/ges-timeline.c
ges/ges-timeline.h

index 4988aec..9934059 100644 (file)
@@ -1228,6 +1228,7 @@ ges_pipeline_set_mode (GESPipeline * pipeline, GESPipelineFlags mode)
 
     /* Disable render bin */
     GST_DEBUG ("Disabling rendering bin");
+    ges_timeline_thaw_commit (pipeline->priv->timeline);
     gst_object_ref (pipeline->priv->encodebin);
     gst_object_ref (pipeline->priv->urisink);
     gst_bin_remove_many (GST_BIN_CAST (pipeline),
@@ -1249,7 +1250,8 @@ ges_pipeline_set_mode (GESPipeline * pipeline, GESPipelineFlags mode)
       (mode & (GES_PIPELINE_MODE_RENDER | GES_PIPELINE_MODE_SMART_RENDER))) {
     /* Adding render bin */
     GST_DEBUG ("Adding render bin");
-
+    /* in render mode the commit needs to be locked, see #136 */
+    ges_timeline_freeze_commit (pipeline->priv->timeline);
     if (G_UNLIKELY (pipeline->priv->urisink == NULL)) {
       GST_ERROR_OBJECT (pipeline, "Output URI not set !");
       return FALSE;
index ac60f23..6fe3f21 100644 (file)
@@ -225,6 +225,8 @@ struct _GESTimelinePrivate
   /* For ges_timeline_commit_sync */
   GMutex commited_lock;
   GCond commited_cond;
+  gboolean commit_frozen;
+  gboolean commit_delayed;
 
   GThread *valid_thread;
   gboolean disposed;
@@ -2784,6 +2786,12 @@ ges_timeline_commit_unlocked (GESTimeline * timeline)
   GList *tmp;
   gboolean res = TRUE;
 
+  if (timeline->priv->commit_frozen) {
+    GST_DEBUG_OBJECT (timeline, "commit locked");
+    timeline->priv->commit_delayed = TRUE;
+    return res;
+  }
+
   GST_DEBUG_OBJECT (timeline, "commiting changes");
 
   timeline_tree_create_transitions (timeline->priv->tree,
@@ -2933,6 +2941,51 @@ ges_timeline_commit_sync (GESTimeline * timeline)
 }
 
 /**
+ * ges_timeline_freeze_commit:
+ * @timeline: The #GESTimeline
+ *
+ * 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
+ * taken into account during that moment. Once the rendering is done, you
+ * should call #ges_timeline_thaw_commit so that comiting becomes possible
+ * again and any call to `commit()` that happened during the rendering is
+ * actually taken into account.
+ *
+ * Since: 1.20
+ *
+ */
+void
+ges_timeline_freeze_commit (GESTimeline * timeline)
+{
+  LOCK_DYN (timeline);
+  timeline->priv->commit_frozen = TRUE;
+  UNLOCK_DYN (timeline);
+}
+
+/**
+ * ges_timeline_thaw_commit:
+ * @timeline: The #GESTimeline
+ *
+ * Thaw the timeline so that comiting becomes possible
+ * again and any call to `commit()` that happened during the rendering is
+ * actually taken into account.
+ *
+ * Since: 1.20
+ *
+ */
+void
+ges_timeline_thaw_commit (GESTimeline * timeline)
+{
+  LOCK_DYN (timeline);
+  timeline->priv->commit_frozen = FALSE;
+  UNLOCK_DYN (timeline);
+  if (timeline->priv->commit_delayed) {
+    ges_timeline_commit (timeline);
+    timeline->priv->commit_delayed = FALSE;
+  }
+}
+
+/**
  * ges_timeline_get_duration:
  * @timeline: The #GESTimeline
  *
index 16a800b..00947d8 100644 (file)
@@ -126,6 +126,10 @@ GES_API
 gboolean ges_timeline_commit (GESTimeline * timeline);
 GES_API
 gboolean ges_timeline_commit_sync (GESTimeline * timeline);
+GES_API
+void ges_timeline_freeze_commit (GESTimeline * timeline);
+GES_API
+void ges_timeline_thaw_commit (GESTimeline * timeline);
 
 GES_API
 GstClockTime ges_timeline_get_duration (GESTimeline *timeline);