summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorStéphane Cerveau <scerveau@collabora.com>2021-08-03 11:31:07 +0200
committerGStreamer Marge Bot <gitlab-merge-bot@gstreamer-foundation.org>2021-08-06 13:42:45 +0000
commit20c6668f5a7ce50eeae8b71230d0646ffdefedd9 (patch)
treeb9297021a0f1a11caca60533a3d9e11044f5bc57
parent2bb2ff380e4bc0fa33db026178e546c267d9292d (diff)
ges: freeze commit during render
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>
-rw-r--r--ges/ges-pipeline.c4
-rw-r--r--ges/ges-timeline.c53
-rw-r--r--ges/ges-timeline.h4
3 files changed, 60 insertions, 1 deletions
diff --git a/ges/ges-pipeline.c b/ges/ges-pipeline.c
index 4988aec0..9934059a 100644
--- a/ges/ges-pipeline.c
+++ b/ges/ges-pipeline.c
@@ -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;
diff --git a/ges/ges-timeline.c b/ges/ges-timeline.c
index ac60f23e..6fe3f21a 100644
--- a/ges/ges-timeline.c
+++ b/ges/ges-timeline.c
@@ -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
*
diff --git a/ges/ges-timeline.h b/ges/ges-timeline.h
index 16a800b2..00947d8b 100644
--- a/ges/ges-timeline.h
+++ b/ges/ges-timeline.h
@@ -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);