gst/audioresample/gstaudioresample.c: Don't trigger discontinuities for very small imperfections; a filter flush will...

Original commit message from CVS:
* gst/audioresample/gstaudioresample.c:
(audioresample_check_discont), (audioresample_transform):
Don't trigger discontinuities for very small imperfections; a filter
flush will sound bad, and many plugins have rounding errors leading
to these.
This commit is contained in:
Michael Smith 2007-03-15 10:52:21 +00:00
parent b6d7f65463
commit 4ab2d699fd
2 changed files with 42 additions and 16 deletions

View file

@ -1,3 +1,11 @@
2007-03-15 Michael Smith <msmith@fluendo.com>
* gst/audioresample/gstaudioresample.c:
(audioresample_check_discont), (audioresample_transform):
Don't trigger discontinuities for very small imperfections; a filter
flush will sound bad, and many plugins have rounding errors leading
to these.
2007-03-14 Philippe Kalaf <philippe.kalaf@collabora.co.uk> 2007-03-14 Philippe Kalaf <philippe.kalaf@collabora.co.uk>
* gst-libs/gst/rtp/gstbasertpaudiopayload.c: * gst-libs/gst/rtp/gstbasertpaudiopayload.c:

View file

@ -575,6 +575,33 @@ audioresample_do_output (GstAudioresample * audioresample, GstBuffer * outbuf)
return GST_FLOW_OK; return GST_FLOW_OK;
} }
/* llabs() is C99, so we might not have it; just use a simple macro... */
#define LLABS(x) ((x>0)?x:-x)
static gboolean
audioresample_check_discont (GstAudioresample * audioresample,
GstClockTime timestamp)
{
if (timestamp != GST_CLOCK_TIME_NONE &&
audioresample->prev_ts != GST_CLOCK_TIME_NONE &&
audioresample->prev_duration != GST_CLOCK_TIME_NONE &&
timestamp != audioresample->prev_ts + audioresample->prev_duration) {
/* Potentially a discontinuous buffer. However, it turns out that many
* elements generate imperfect streams due to rounding errors, so we permit
* a small error (up to one sample) without triggering a filter
* flush/restart (if triggered incorrectly, this will be audible) */
GstClockTimeDiff diff = timestamp -
(audioresample->prev_ts + audioresample->prev_duration);
if (LLABS (diff) > GST_SECOND / audioresample->i_rate) {
GST_WARNING_OBJECT (audioresample,
"encountered timestamp discontinuity of %" G_GINT64_FORMAT, diff);
return TRUE;
}
}
return FALSE;
}
static GstFlowReturn static GstFlowReturn
audioresample_transform (GstBaseTransform * base, GstBuffer * inbuf, audioresample_transform (GstBaseTransform * base, GstBuffer * inbuf,
GstBuffer * outbuf) GstBuffer * outbuf)
@ -600,22 +627,13 @@ audioresample_transform (GstBaseTransform * base, GstBuffer * inbuf,
GST_BUFFER_OFFSET (inbuf), GST_BUFFER_OFFSET_END (inbuf)); GST_BUFFER_OFFSET (inbuf), GST_BUFFER_OFFSET_END (inbuf));
/* check for timestamp discontinuities and flush/reset if needed */ /* check for timestamp discontinuities and flush/reset if needed */
if (GST_CLOCK_TIME_IS_VALID (audioresample->prev_ts) && if (G_UNLIKELY (audioresample_check_discont (audioresample, timestamp))) {
GST_CLOCK_TIME_IS_VALID (audioresample->prev_duration)) { /* Flush internal samples */
GstClockTime ts_expected = audioresample->prev_ts + audioresample_pushthrough (audioresample);
audioresample->prev_duration; /* Inform downstream element about discontinuity */
GstClockTimeDiff ts_diff = GST_CLOCK_DIFF (ts_expected, timestamp); audioresample->need_discont = TRUE;
/* We want to recalculate the offset */
if (G_UNLIKELY (ts_diff != 0)) { audioresample->ts_offset = -1;
GST_WARNING_OBJECT (audioresample,
"encountered timestamp discontinuity of %" G_GINT64_FORMAT, ts_diff);
/* Flush internal samples */
audioresample_pushthrough (audioresample);
/* Inform downstream element about discontinuity */
audioresample->need_discont = TRUE;
/* We want to recalculate the offset */
audioresample->ts_offset = -1;
}
} }
if (audioresample->ts_offset == -1) { if (audioresample->ts_offset == -1) {