baseaudiosink: make discont-wait configurable
authorFelipe Contreras <felipe.contreras@gmail.com>
Mon, 2 May 2011 10:05:28 +0000 (13:05 +0300)
committerWim Taymans <wim.taymans@collabora.co.uk>
Mon, 7 Nov 2011 10:58:46 +0000 (11:58 +0100)
Now we can configure how much time to wait before deciding that a
discont has happened.

Also, adds getter and setter to allow derived implementations to set
this value upon construction.

Suggestions and several improvements by Havard Graff.

Signed-off-by: Felipe Contreras <felipe.contreras@gmail.com>
gst-libs/gst/audio/gstbaseaudiosink.c
gst-libs/gst/audio/gstbaseaudiosink.h

index dd531c919040c18e18d445dc6b604d3732fa71bd..eb4a0a3a4c670cf13abdf5c5a50fadf55951b935 100644 (file)
@@ -62,12 +62,15 @@ struct _GstBaseAudioSinkPrivate
    * before resyncing */
   guint64 drift_tolerance;
 
-  /* time of the previous detected discont candidate */
-  GstClockTime discont_time;
-
   /* number of nanoseconds we allow timestamps to drift
    * before resyncing */
   GstClockTime alignment_threshold;
+
+  /* time of the previous detected discont candidate */
+  GstClockTime discont_time;
+
+  /* number of nanoseconds to wait until creating a discontinuity */
+  GstClockTime discont_wait;
 };
 
 /* BaseAudioSink signals and args */
@@ -86,13 +89,17 @@ enum
 /* FIXME, enable pull mode when clock slaving and trick modes are figured out */
 #define DEFAULT_CAN_ACTIVATE_PULL FALSE
 
+/* when timestamps drift for more than 40ms we resync. This should
+ * be anough to compensate for timestamp rounding errors. */
+#define DEFAULT_ALIGNMENT_THRESHOLD   (40 * GST_MSECOND)
+
 /* when clock slaving drift for more than 40ms we resync. This is
  * a reasonable default */
 #define DEFAULT_DRIFT_TOLERANCE   ((40 * GST_MSECOND) / GST_USECOND)
 
-/* when timestamps drift for more than 40ms we resync. This should
- * be anough to compensate for timestamp rounding errors. */
-#define DEFAULT_ALIGNMENT_THRESHOLD   (40 * GST_MSECOND)
+/* allow for one second before resyncing to see if the timestamps drift will
+ * fix itself, or is a permanent offset */
+#define DEFAULT_DISCONT_WAIT        (1 * GST_SECOND)
 
 enum
 {
@@ -103,8 +110,9 @@ enum
   PROP_PROVIDE_CLOCK,
   PROP_SLAVE_METHOD,
   PROP_CAN_ACTIVATE_PULL,
-  PROP_DRIFT_TOLERANCE,
   PROP_ALIGNMENT_THRESHOLD,
+  PROP_DRIFT_TOLERANCE,
+  PROP_DISCONT_WAIT,
 
   PROP_LAST
 };
@@ -252,6 +260,19 @@ gst_base_audio_sink_class_init (GstBaseAudioSinkClass * klass)
           G_MAXINT64, DEFAULT_ALIGNMENT_THRESHOLD,
           G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
 
+  /**
+   * GstBaseAudioSink:discont-wait
+   *
+   * A window of time in nanoseconds to wait before creating a discontinuity as
+   * a result of breaching the drift-tolerance.
+   */
+  g_object_class_install_property (gobject_class, PROP_DISCONT_WAIT,
+      g_param_spec_int64 ("discont-wait", "Discont Wait",
+          "Window of time in nanoseconds to wait before "
+          "creating a discontinuity", 0,
+          G_MAXINT64, DEFAULT_DISCONT_WAIT,
+          G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
+
   gstelement_class->change_state =
       GST_DEBUG_FUNCPTR (gst_base_audio_sink_change_state);
   gstelement_class->provide_clock =
@@ -292,6 +313,7 @@ gst_base_audio_sink_init (GstBaseAudioSink * baseaudiosink,
   baseaudiosink->priv->slave_method = DEFAULT_SLAVE_METHOD;
   baseaudiosink->priv->drift_tolerance = DEFAULT_DRIFT_TOLERANCE;
   baseaudiosink->priv->alignment_threshold = DEFAULT_ALIGNMENT_THRESHOLD;
+  baseaudiosink->priv->discont_wait = DEFAULT_DISCONT_WAIT;
 
   baseaudiosink->provided_clock = gst_audio_clock_new ("GstAudioSinkClock",
       (GstAudioClockGetTimeFunc) gst_base_audio_sink_get_time, baseaudiosink);
@@ -729,6 +751,50 @@ gst_base_audio_sink_get_alignment_threshold (GstBaseAudioSink * sink)
   return result;
 }
 
+/**
+ * gst_base_audio_sink_set_discont_wait:
+ * @sink: a #GstBaseAudioSink
+ * @discont_wait: the new discont wait in nanoseconds
+ *
+ * Controls how long the sink will wait before creating a discontinuity.
+ *
+ * Since: 0.10.31
+ */
+void
+gst_base_audio_sink_set_discont_wait (GstBaseAudioSink * sink,
+    GstClockTime discont_wait)
+{
+  g_return_if_fail (GST_IS_BASE_AUDIO_SINK (sink));
+
+  GST_OBJECT_LOCK (sink);
+  sink->priv->discont_wait = discont_wait;
+  GST_OBJECT_UNLOCK (sink);
+}
+
+/**
+ * gst_base_audio_sink_get_discont_wait
+ * @sink: a #GstBaseAudioSink
+ *
+ * Get the current discont wait, in nanoseconds, used by @sink.
+ *
+ * Returns: The current discont wait used by @sink.
+ *
+ * Since: 0.10.31
+ */
+GstClockTime
+gst_base_audio_sink_get_discont_wait (GstBaseAudioSink * sink)
+{
+  GstClockTime result;
+
+  g_return_val_if_fail (GST_IS_BASE_AUDIO_SINK (sink), -1);
+
+  GST_OBJECT_LOCK (sink);
+  result = sink->priv->discont_wait;
+  GST_OBJECT_UNLOCK (sink);
+
+  return result;
+}
+
 static void
 gst_base_audio_sink_set_property (GObject * object, guint prop_id,
     const GValue * value, GParamSpec * pspec)
@@ -760,6 +826,9 @@ gst_base_audio_sink_set_property (GObject * object, guint prop_id,
       gst_base_audio_sink_set_alignment_threshold (sink,
           g_value_get_uint64 (value));
       break;
+    case PROP_DISCONT_WAIT:
+      gst_base_audio_sink_set_discont_wait (sink, g_value_get_uint64 (value));
+      break;
     default:
       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
       break;
@@ -797,6 +866,9 @@ gst_base_audio_sink_get_property (GObject * object, guint prop_id,
       g_value_set_uint64 (value,
           gst_base_audio_sink_get_alignment_threshold (sink));
       break;
+    case PROP_DISCONT_WAIT:
+      g_value_set_uint64 (value, gst_base_audio_sink_get_discont_wait (sink));
+      break;
     default:
       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
       break;
@@ -1443,17 +1515,21 @@ gst_base_audio_sink_get_alignment (GstBaseAudioSink * sink,
   if (sample_diff > headroom && align < 0)
     allow_align = FALSE;
 
-  /* wait before deciding to make a discontinuity */
   if (G_UNLIKELY (sample_diff >= max_sample_diff)) {
-    GstClockTime time = gst_util_uint64_scale_int (sample_offset,
-        GST_SECOND, ringbuf->spec.rate);
-    if (sink->priv->discont_time == -1) {
-      /* discont candidate */
-      sink->priv->discont_time = time;
-    } else if (time - sink->priv->discont_time >= GST_SECOND) {
-      /* one second passed, discontinuity detected */
+    /* wait before deciding to make a discontinuity */
+    if (sink->priv->discont_wait > 0) {
+      GstClockTime time = gst_util_uint64_scale_int (sample_offset,
+          GST_SECOND, ringbuf->spec.rate);
+      if (sink->priv->discont_time == -1) {
+        /* discont candidate */
+        sink->priv->discont_time = time;
+      } else if (time - sink->priv->discont_time >= sink->priv->discont_wait) {
+        /* discont_wait expired, discontinuity detected */
+        discont = TRUE;
+        sink->priv->discont_time = -1;
+      }
+    } else {
       discont = TRUE;
-      sink->priv->discont_time = -1;
     }
   } else if (G_UNLIKELY (sink->priv->discont_time != -1)) {
     /* we have had a discont, but are now back on track! */
index 0da0a15c1faa1d7b818bb2835ce69a1595231256..e41a46a500b62547687fac682b336779e3f2ba20 100644 (file)
@@ -185,6 +185,11 @@ void       gst_base_audio_sink_set_alignment_threshold (GstBaseAudioSink * sink,
 GstClockTime
            gst_base_audio_sink_get_alignment_threshold (GstBaseAudioSink * sink);
 
+void       gst_base_audio_sink_set_discont_wait       (GstBaseAudioSink * sink,
+                                                       GstClockTime discont_wait);
+GstClockTime
+           gst_base_audio_sink_get_discont_wait       (GstBaseAudioSink * sink);
+
 G_END_DECLS
 
 #endif /* __GST_BASE_AUDIO_SINK_H__ */