After an evaluation, GNOME has moved from Bugzilla to GitLab. Learn more about GitLab.
No new issues can be reported in GNOME Bugzilla anymore.
To report an issue in a GNOME project, go to GNOME GitLab.
Do not go to GNOME Gitlab for: Bluefish, Doxygen, GnuCash, GStreamer, java-gnome, LDTP, NetworkManager, Tomboy.
Bug 732908 - audioresample: skips samples unless input buffers have correct size
audioresample: skips samples unless input buffers have correct size
Status: RESOLVED FIXED
Product: GStreamer
Classification: Platform
Component: gst-plugins-base
unspecified
Other Linux
: Normal major
: 1.4.2
Assigned To: GStreamer Maintainers
GStreamer Maintainers
Depends on:
Blocks:
 
 
Reported: 2014-07-08 16:57 UTC by Kipp
Modified: 2015-01-19 18:36 UTC
See Also:
GNOME target: ---
GNOME version: ---


Attachments
fix dropping of input samples when downsampling (1.88 KB, patch)
2014-07-08 16:57 UTC, Kipp
committed Details | Review
before the patch, F64LE format (47.02 KB, application/pdf)
2014-07-08 16:58 UTC, Kipp
  Details
before the patch, S32LE format (46.40 KB, application/pdf)
2014-07-08 16:58 UTC, Kipp
  Details
after the patch, F64LE format (46.39 KB, application/pdf)
2014-07-08 16:58 UTC, Kipp
  Details
after the patch, S32LE format (45.75 KB, application/pdf)
2014-07-08 16:59 UTC, Kipp
  Details
add sample count check (1.45 KB, patch)
2014-07-08 21:37 UTC, Kipp
rejected Details | Review
proposed patch (1.56 KB, patch)
2015-01-14 08:47 UTC, Jan Alexander Steffens (heftig)
committed Details | Review

Description Kipp 2014-07-08 16:57:14 UTC
Created attachment 280172 [details] [review]
fix dropping of input samples when downsampling

when the resampler is fed buffers with an unlucky number of samples in them, it drops samples from the input stream causing a phase (= timestamp) drift in its output.  I think this might be the cause of a number of userspace audio problems I have experienced involving stuttering.  this is actually a very serious bug for the work we're doing so I have taken the liberty of putting the severity at major.

the bug is easily seen with the following

$ gst-launch-1.0 \
	audiotestsrc freq=16 wave=sine samplesperbuffer=170 num-buffers=24 \
	! audio/x-raw, format=F64LE, channels=1, rate=4096 \
	! tee name=input \
	! audioresample quality=1 \
	! audio/x-raw, rate=64 \
	! tsvenc ! filesink location="dump.out" sync=false async=false \
	input. ! tsvenc ! filesink location="dump.in" sync=false async=false \

to run that you will need to apply the tsvenc patch to the debugutilsbad plugin to get the time series dumps in ascii, otherwise you can do whatever you want to look at the streams.

a patch is attached that fixes it, and I have also attached plots of the output of the pipeline above before and after applying the patch.
Comment 1 Kipp 2014-07-08 16:58:07 UTC
Created attachment 280173 [details]
before the patch, F64LE format
Comment 2 Kipp 2014-07-08 16:58:34 UTC
Created attachment 280174 [details]
before the patch, S32LE format
Comment 3 Kipp 2014-07-08 16:58:55 UTC
Created attachment 280175 [details]
after the patch, F64LE format
Comment 4 Kipp 2014-07-08 16:59:18 UTC
Created attachment 280176 [details]
after the patch, S32LE format
Comment 5 Tim-Philipp Müller 2014-07-08 21:00:57 UTC
Thanks for the patch and the bug report. What would be superb is a unit test for this in tests/check/elements/audioresample.c - how difficult would you think this would be to do?
Comment 6 Kipp 2014-07-08 21:37:41 UTC
Created attachment 280192 [details] [review]
add sample count check

I don't know how to define a unit test to detect the problem fixed in this bug report, but this patch here at least adds a safety check that detects a mismatch between the input and output sample counts (accounting for latency and sample rate conversion).  there's no check that the contents of the samples are correct, but any dropping of input samples or double-counting of input samples will be detected by this.
Comment 7 Kipp 2014-07-10 16:21:16 UTC
(In reply to comment #6)
> Created an attachment (id=280192) [details] [review]
> add sample count check
> 
> I don't know how to define a unit test to detect the problem fixed in this bug
> report, but this patch here at least adds a safety check that detects a
> mismatch between the input and output sample counts (accounting for latency and
> sample rate conversion).  there's no check that the contents of the samples are
> correct, but any dropping of input samples or double-counting of input samples
> will be detected by this.

So ... thinking about this some more, I'd be concerned that this check will fail if the quality is changed mid stream.  Increasing the quality will increase the latency and, eventually, this test will pass again but there might be an intermediate period when the output appears to have generated more samples than there should have been (because they were generated using the earlier, shorter, kernel).

The problem with a unit test approach is that special buffer sizes are needed to trigger the failure, so the test would have to involve "all" (however that gets defined) buffer sizes.  Leaving an assert in the code to be tripped in the wild is a more certain way to detect problems like this --- crowd-source the unit test --- but it seems that even getting that right is difficult.
Comment 8 Kipp 2014-09-04 20:10:29 UTC
Ping.  Any word on getting this patch included upstream?  Thanks.
Comment 9 Sebastian Dröge (slomo) 2014-09-05 08:15:38 UTC
You could write a unit test that just feeds audioresample with randomly sized buffers manually, instead of creating a pipeline that feeds it from audiotestsrc. That should allow to trigger the bug
Comment 10 Sebastian Dröge (slomo) 2014-09-05 08:16:14 UTC
Comment on attachment 280192 [details] [review]
add sample count check

Rejected as this will cause problems when the quality changes mid-stream
Comment 11 Sebastian Dröge (slomo) 2014-09-05 08:21:29 UTC
Pushed but it would be good if you could provide a unit test to prevent that we introduce changes later that break it again :) Keeping this bug open for now.


commit 684cf44ee3c8ccdbcc2f5711f050ba57d9909183
Author: Kipp Cannon <kipp.cannon@ligo.org>
Date:   Tue Jul 8 12:37:41 2014 -0400

    audioresample: don't skip input samples
    
    when downsampling, the output buffer can be filled before all the input
    samples are consumed.  this is correct:  when downsampling, several input
    samples are needed for each output sample, so when only a small number of
    input samples are available the number of output samples produced can be 0.
    
    the resampler, however, was discarding those extra input samples instead of
    clocking them into its filter history for the next iteration.  this patch
    fixes this by removing the check that the output buffer is full.  the code
    now always loops until all input samples are consumed, and relies on the
    calling code to have provided a suitably sized location for the output.
    note that there are already other checks in place in the calling code to
    ensure that this is the case.
    
    https://bugzilla.gnome.org/show_bug.cgi?id=732908
Comment 12 Jan Alexander Steffens (heftig) 2015-01-13 14:50:30 UTC
This has now caused the resampler to lock up during draining here because it wasn't able to consume one last input sample.

All output samples were written, so *ochunk = olen = 0, but one last input sample remained, so *ichunk = ilen = 0.

speex_resampler_process_native reduced *ichunk to 0, so the while(ilen) never terminated.
Comment 13 Jan Alexander Steffens (heftig) 2015-01-13 14:51:13 UTC
(In reply to comment #12)
Ah, ilen = 1, of course.
Comment 14 Jan Alexander Steffens (heftig) 2015-01-14 08:47:25 UTC
Created attachment 294495 [details] [review]
proposed patch

How about this?

audioresample: Try to prevent endless looping
   
Speex may decide not to consume any samples because it can't write any. I've seen a hang during draining caused by the resample loop never terminating. In that case, resampling happened as normal until olen was 0 but ilen was still 1. _process_native then reduced ichunk to 0, so ilen never decreased below 1 and the loop never terminated.
    
Instead of reverting 684cf44 ({audioresample: don't skip input samples), break only if all output samples have been produced and speex refuses to consume any more input samples.
Comment 15 Sebastian Dröge (slomo) 2015-01-14 10:28:32 UTC
Kipp, can you check if that patch still works with your use case?
Comment 16 Kipp 2015-01-19 18:28:59 UTC
(In reply to comment #15)
> Kipp, can you check if that patch still works with your use case?

Hi,

Re-ran my tests with the proposed patch applied and it looks OK to me.  Thanks.
Comment 17 Sebastian Dröge (slomo) 2015-01-19 18:36:46 UTC
Thanks for testing! :)

commit a636c39638e7d667d71ec5a1070c3e468cf45a73
Author: Jan Alexander Steffens (heftig) <jsteffens@make.tv>
Date:   Tue Jan 13 16:07:06 2015 +0100

    audioresample: Try to prevent endless looping
    
    Speex may decide not to consume any samples because it can't write any. I've
    seen a hang during draining caused by the resample loop never terminating.
    In that case, resampling happened as normal until olen was 0 but ilen was
    still 1. _process_native then reduced ichunk to 0, so ilen never decreased
    below 1 and the loop never terminated.
    
    Instead of reverting 684cf44 ({audioresample: don't skip input samples),
    break only if all output samples have been produced and speex refuses
    to consume any more input samples.
    
    https://bugzilla.gnome.org/show_bug.cgi?id=732908