summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMark Nauwelaerts <mark.nauwelaerts@collabora.co.uk>2009-12-15 18:41:38 +0100
committerMark Nauwelaerts <mark.nauwelaerts@collabora.co.uk>2009-12-15 19:51:08 +0100
commit8b4f6dd43bf13d286f11f532033ac46aec33b13b (patch)
tree45c0268113abf94272c672c867203e40c9c432d8
parentb5fe63ed796db284e8757020c33a59f9e345ab0d (diff)
audiorate: add a tolerance property
It may not be uncommon for the input timestamps to experience some jitter around the 'perfect time'. As such, instead of regularly adding and dropping samples, optionally allow for some tolerance in a more relaxed approach. API: GstAudioRate:tolerance
-rw-r--r--gst/audiorate/gstaudiorate.c41
-rw-r--r--gst/audiorate/gstaudiorate.h1
2 files changed, 39 insertions, 3 deletions
diff --git a/gst/audiorate/gstaudiorate.c b/gst/audiorate/gstaudiorate.c
index fd39b662e..2fbd5f8e5 100644
--- a/gst/audiorate/gstaudiorate.c
+++ b/gst/audiorate/gstaudiorate.c
@@ -30,8 +30,9 @@
*
* The properties #GstAudioRate:in, #GstAudioRate:out, #GstAudioRate:add
* and #GstAudioRate:drop can be read to obtain information about number of
- * input samples, output samples, dropped samples (i.e. the number of unused input
- * samples) and inserted samples (i.e. the number of samples added to stream).
+ * input samples, output samples, dropped samples (i.e. the number of unused
+ * input samples) and inserted samples (i.e. the number of samples added to
+ * stream).
*
* When the #GstAudioRate:silent property is set to FALSE, a GObject property
* notification will be emitted whenever one of the #GstAudioRate:add or
@@ -40,6 +41,13 @@
* Note that property notification will happen from the streaming thread, so
* applications should be prepared for this.
*
+ * If the #GstAudioRate:tolerance property is non-zero, and an incoming buffer's
+ * timestamp deviates less than the property indicates from what would make a
+ * 'perfect time', then no samples will be added or dropped.
+ * Note that the output is still guaranteed to be a perfect stream, which means
+ * that the incoming data is then simply shifted (by less than the indicated
+ * tolerance) to a perfect time.
+ *
* <refsect2>
* <title>Example pipelines</title>
* |[
@@ -75,7 +83,8 @@ enum
LAST_SIGNAL
};
-#define DEFAULT_SILENT TRUE
+#define DEFAULT_SILENT TRUE
+#define DEFAULT_TOLERANCE 0
enum
{
@@ -85,6 +94,7 @@ enum
ARG_ADD,
ARG_DROP,
ARG_SILENT,
+ ARG_TOLERANCE,
/* FILL ME */
};
@@ -189,6 +199,11 @@ gst_audio_rate_class_init (GstAudioRateClass * klass)
g_param_spec_boolean ("silent", "silent",
"Don't emit notify for dropped and duplicated frames", DEFAULT_SILENT,
G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
+ g_object_class_install_property (object_class, ARG_TOLERANCE,
+ g_param_spec_uint64 ("tolerance", "tolerance",
+ "Only act if timestamp jitter/imperfection exceeds indicated tolerance (ns)",
+ 0, G_MAXUINT64, DEFAULT_TOLERANCE,
+ G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
element_class->change_state = gst_audio_rate_change_state;
}
@@ -277,6 +292,7 @@ gst_audio_rate_init (GstAudioRate * audiorate)
audiorate->drop = 0;
audiorate->add = 0;
audiorate->silent = DEFAULT_SILENT;
+ audiorate->tolerance = DEFAULT_TOLERANCE;
}
static void
@@ -479,6 +495,7 @@ gst_audio_rate_chain (GstPad * pad, GstBuffer * buf)
guint64 in_offset, in_offset_end, in_samples;
guint in_size;
GstFlowReturn ret = GST_FLOW_OK;
+ GstClockTimeDiff diff;
audiorate = GST_AUDIO_RATE (gst_pad_get_parent (pad));
@@ -536,6 +553,17 @@ gst_audio_rate_chain (GstPad * pad, GstBuffer * buf)
GST_TIME_ARGS (GST_FRAMES_TO_CLOCK_TIME (in_samples, audiorate->rate)),
in_size, in_offset, in_offset_end, audiorate->next_offset);
+ diff = in_time - audiorate->next_ts;
+ if (diff <= (GstClockTimeDiff) audiorate->tolerance &&
+ diff >= (GstClockTimeDiff) - audiorate->tolerance) {
+ /* buffer time close enough to expected time,
+ * so produce a perfect stream by simply 'shifting'
+ * it to next ts and offset and sending */
+ GST_LOG_OBJECT (audiorate, "within tolerance %" GST_TIME_FORMAT,
+ GST_TIME_ARGS (audiorate->tolerance));
+ goto send;
+ }
+
/* do we need to insert samples */
if (in_offset > audiorate->next_offset) {
GstBuffer *fill;
@@ -639,6 +667,7 @@ gst_audio_rate_chain (GstPad * pad, GstBuffer * buf)
if (GST_BUFFER_SIZE (buf) == 0)
goto beach;
+send:
/* Now calculate parameters for whichever buffer (either the original
* or truncated one) we're pushing. */
GST_BUFFER_OFFSET (buf) = audiorate->next_offset;
@@ -696,6 +725,9 @@ gst_audio_rate_set_property (GObject * object,
case ARG_SILENT:
audiorate->silent = g_value_get_boolean (value);
break;
+ case ARG_TOLERANCE:
+ audiorate->tolerance = g_value_get_uint64 (value);
+ break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
break;
@@ -724,6 +756,9 @@ gst_audio_rate_get_property (GObject * object,
case ARG_SILENT:
g_value_set_boolean (value, audiorate->silent);
break;
+ case ARG_TOLERANCE:
+ g_value_set_uint64 (value, audiorate->tolerance);
+ break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
break;
diff --git a/gst/audiorate/gstaudiorate.h b/gst/audiorate/gstaudiorate.h
index 84e3a9a58..bcc087bda 100644
--- a/gst/audiorate/gstaudiorate.h
+++ b/gst/audiorate/gstaudiorate.h
@@ -57,6 +57,7 @@ struct _GstAudioRate
/* stats */
guint64 in, out, add, drop;
gboolean silent;
+ guint64 tolerance;
/* audio state */
guint64 next_offset;