From 9cbe7c1403de3d774dc25bc41fadcd1391de952e Mon Sep 17 00:00:00 2001 From: Monty Montgomery Date: Thu, 21 Jul 2011 17:16:26 -0400 Subject: [PATCH] vorbisenc: Relax overly-tight jitter tolerances in gstvobisenc vorbisenc currently reacts in a rater draconian fashion if input timestamps are more than 1/2 sample off what it considers ideal. If data is 'too late' it truncates buffers, if it is 'too soon' it completely shuts down encode and restarts it. This is causingvorbisenc to produce corrupt output when encoding data produced by sources with bugs that produce a smple or two of jitter (eg, flacdec) --- ext/vorbis/gstvorbisenc.c | 44 +++++++++++++++++++++++---------------- 1 file changed, 26 insertions(+), 18 deletions(-) diff --git a/ext/vorbis/gstvorbisenc.c b/ext/vorbis/gstvorbisenc.c index 9cdf484e15..85d47c3249 100644 --- a/ext/vorbis/gstvorbisenc.c +++ b/ext/vorbis/gstvorbisenc.c @@ -1012,12 +1012,12 @@ gst_vorbis_enc_buffer_check_discontinuous (GstVorbisEnc * vorbisenc, vorbisenc->expected_ts != GST_CLOCK_TIME_NONE && timestamp + duration != vorbisenc->expected_ts) { /* It turns out that a lot of elements don't generate perfect streams due - * to rounding errors. So, we permit small errors (< 1/2 a sample) without + * to rounding errors. So, we permit small errors (< 3 samples) without * causing a discont. */ - int halfsample = GST_SECOND / vorbisenc->frequency / 2; + int threesample = GST_SECOND / vorbisenc->frequency * 3; - if ((GstClockTimeDiff) (timestamp - vorbisenc->expected_ts) > halfsample) { + if ((GstClockTimeDiff) (timestamp - vorbisenc->expected_ts) > threesample) { GST_DEBUG_OBJECT (vorbisenc, "Expected TS %" GST_TIME_FORMAT ", buffer TS %" GST_TIME_FORMAT, GST_TIME_ARGS (vorbisenc->expected_ts), GST_TIME_ARGS (timestamp)); @@ -1135,28 +1135,36 @@ gst_vorbis_enc_chain (GstPad * pad, GstBuffer * buffer) if (vorbisenc->expected_ts != GST_CLOCK_TIME_NONE && timestamp < vorbisenc->expected_ts) { + int threesample = GST_SECOND / vorbisenc->frequency * 3; guint64 diff = vorbisenc->expected_ts - timestamp; guint64 diff_bytes; - GST_WARNING_OBJECT (vorbisenc, "Buffer is older than previous " - "timestamp + duration (%" GST_TIME_FORMAT "< %" GST_TIME_FORMAT - "), cannot handle. Clipping buffer.", - GST_TIME_ARGS (timestamp), GST_TIME_ARGS (vorbisenc->expected_ts)); + /* Don't freak out on tiny jitters; use the same < 3 sample + tolerance as in the discontinuous detection */ + if ((GstClockTimeDiff) (vorbisenc->expected_ts - timestamp) > threesample) { - diff_bytes = - GST_CLOCK_TIME_TO_FRAMES (diff, - vorbisenc->frequency) * vorbisenc->channels * sizeof (gfloat); - if (diff_bytes >= GST_BUFFER_SIZE (buffer)) { - gst_buffer_unref (buffer); - return GST_FLOW_OK; + GST_WARNING_OBJECT (vorbisenc, "Buffer is older than previous " + "timestamp + duration (%" GST_TIME_FORMAT "< %" GST_TIME_FORMAT + "), cannot handle. Clipping buffer.", + GST_TIME_ARGS (timestamp), GST_TIME_ARGS (vorbisenc->expected_ts)); + + diff_bytes = + GST_CLOCK_TIME_TO_FRAMES (diff, + vorbisenc->frequency) * vorbisenc->channels * sizeof (gfloat); + if (diff_bytes >= GST_BUFFER_SIZE (buffer)) { + gst_buffer_unref (buffer); + return GST_FLOW_OK; + } + buffer = gst_buffer_make_metadata_writable (buffer); + GST_BUFFER_DATA (buffer) += diff_bytes; + GST_BUFFER_SIZE (buffer) -= diff_bytes; + + if (GST_BUFFER_DURATION_IS_VALID (buffer)) + GST_BUFFER_DURATION (buffer) -= diff; } - buffer = gst_buffer_make_metadata_writable (buffer); - GST_BUFFER_DATA (buffer) += diff_bytes; - GST_BUFFER_SIZE (buffer) -= diff_bytes; + /* adjust the input timestamp in either case */ GST_BUFFER_TIMESTAMP (buffer) += diff; - if (GST_BUFFER_DURATION_IS_VALID (buffer)) - GST_BUFFER_DURATION (buffer) -= diff; } if (gst_vorbis_enc_buffer_check_discontinuous (vorbisenc, timestamp,