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 635256 - alsasrc: suggestion for improvement of timestamping accuracy for alsa (and others) sound
alsasrc: suggestion for improvement of timestamping accuracy for alsa (and ot...
Status: RESOLVED FIXED
Product: GStreamer
Classification: Platform
Component: gst-plugins-base
0.10.x
Other Linux
: Normal normal
: 0.11.x
Assigned To: GStreamer Maintainers
GStreamer Maintainers
Depends on:
Blocks: 660170
 
 
Reported: 2010-11-19 10:35 UTC by Pontus Oldberg
Modified: 2012-09-10 09:35 UTC
See Also:
GNOME target: ---
GNOME version: ---


Attachments
Basic patch implementing driver fetched time stamps (16.32 KB, patch)
2010-11-19 10:35 UTC, Pontus Oldberg
none Details | Review
New patch based on discussions and new suggestions on implementation. (5.88 KB, patch)
2011-01-14 10:56 UTC, Pontus Oldberg
rejected Details | Review
make sure we have increasing timestamps (1.64 KB, patch)
2011-07-27 09:39 UTC, Stefan Sauer (gstreamer, gtkdoc dev)
rejected Details | Review
Suggestion on having a single thread to solve the timestamp issues. (28.27 KB, patch)
2012-01-02 13:07 UTC, Pontus Oldberg
none Details | Review
Using a return path for timestamps to the ringbuffer. (12.68 KB, patch)
2012-01-19 15:24 UTC, Pontus Oldberg
none Details | Review
Updated version...... (20.55 KB, patch)
2012-01-24 12:55 UTC, Pontus Oldberg
none Details | Review
New patch for 0.11 (15.40 KB, patch)
2012-05-04 14:37 UTC, Pontus Oldberg
none Details | Review
Updated patch from Wim's commetns. (16.48 KB, patch)
2012-06-14 09:43 UTC, Pontus Oldberg
none Details | Review
Another updated patch with fixes to comments from Wim. (18.94 KB, patch)
2012-06-20 12:04 UTC, Pontus Oldberg
none Details | Review

Description Pontus Oldberg 2010-11-19 10:35:35 UTC
Created attachment 174833 [details] [review]
Basic patch implementing driver fetched time stamps

We needed to improve the accuracy of the timestamps applied on the buffers in gstbaseaudiosrc by actually fetching the timestamp data from the driver. I have implemented the basic functionality for this (see patch) and need comments to get it in a shape that it can be pushed to GStreamer repos.

/Pontus
Comment 1 Wim Taymans 2010-11-19 10:58:22 UTC
This will need more explanation.

It seems like you want to use a monotonic clock for the pipeline and then try to avoid the clock slaving because you know that the alsa API also uses the monotonic clock for the timestamps.
Comment 2 Wim Taymans 2010-11-19 11:02:35 UTC
for example, what is the problem?

Is the problem that there is an undefined delay between getting the pipeline clock timestamp and the alsa device delay?
Comment 3 Pontus Oldberg 2010-11-19 11:14:33 UTC
This is exactly the problem that we want to resolve. No matter what target we are running our firmware on, or the load of the system we want to have consistent timestamps in the pipeline. This is important for us in order to have perfectly synchronized audio and video. This method is also used by us to timestamp the video pipeline from our video source element.
Comment 4 Stefan Sauer (gstreamer, gtkdoc dev) 2010-11-19 15:37:24 UTC
Just for the record, we should do something similar on v4l2src. The v4l2 kernel side switched to monotonic clock as well and we currently introduce quite some timestamp jitter by setting a timestamp when user-space is scheduled instead of taking the timestamp from kernelspace. If we want to do that configurable by a gobject-property, I would call it "use-driver-timestamps" or something similar.

Although I have not understood yet, why the patch is modifying basesrc.
Comment 5 Wim Taymans 2010-11-19 15:46:13 UTC
The problem is that these kernel timestamps may or may not have anything to do with the pipeline clock. 

The usual thing to do is to take a snapshot of the pipeline clock and the same monotonic clock and then subtract the monotonic clock diff from the pipeline clock timestamp.
Comment 6 Patrick Radizi 2010-11-22 10:07:44 UTC
Since our application must stream synchronized video/audio for weeks or months without interruptions we can't use two clocks because of the clock drift between these.

To have the best synchronization and the least amount of jitter we want to
1) Use the same clock to time stamp audio and video and 'drive' the pipeline
2) Take the audio and video buffer time stamps as close to the hardware as possible.
Comment 7 Stefan Sauer (gstreamer, gtkdoc dev) 2010-11-22 12:11:41 UTC
Patrick, Wims comment is all that we need to do. If you ensure that all components use the smae clock, the delta is constant and there is no drift. Its just so that we can't make assumptions on the gstreamer level.
Comment 8 Pontus Oldberg 2010-11-24 09:30:21 UTC
Stefan, your comment is very true if drift was all we needed to address. Unfortunately, in a heavily loaded system it is possible that our user space gstreamer application is scheduled so that large delays are introduced before being able to serve timestamps. Thus introducing either a constant audio delay or a jitter depending on implementation.

With the suggested architectural changes we stand a better chance of getting an accurate timestamp in these situations.
Comment 9 Sebastian Dröge (slomo) 2010-12-12 15:42:18 UTC
So is there still anything that needs to be done here?
Comment 10 Jonas Holmberg 2010-12-13 09:22:01 UTC
I think there are at least two other ways of doing it, without adding new properties:

1. alsasrc always use driver timestamps and provides a clock which is an instance of GstSystemClock that uses the monotonic clock. Does this ensure that the src element will always timestamp correctly according to the pipeline clock?

2. alsasrc checks if the pipeline (element) clock is an instance of GstSystemClock with clock-type set to monotonic clock and in that case uses driver timestamps, otherwise it will do what it does in the current implementation. The application will have to make sure the pipeline uses monotonic clock or the alsasrc will work exactly as before.

Would any of those two alternatives work without problems in an arbitrary pipeline?
Comment 11 Patrick Radizi 2010-12-15 09:53:34 UTC
Continuing with the ideas from Jonas for doing this automatically, (combining 1 and 2), I think the following should work.

* alsasrc always provides a clock, the monotonic clock
* when alsasrc changes state from PAUSED to PLAYING it checks the pipeline clock. If it's the monotonic clock it uses alsa driver time stamps. If it's a different clock it uses that clock to time stamp the buffers.

So, as long as a different clock isn't chosen for the pipeline alsa driver time stamps will always be used. And if a different clock is chosen, that clock will be used and everything will still work (as it does today)


The only side effect of this that I can think of is that it changes the clock that is used today when alsasrc is the clock provider. From time stamps based on the number of samples played to alsa driver samples. But I would think that driver time stamps always are to be preferred, or?
Comment 12 Patrick Radizi 2010-12-15 16:11:41 UTC
Conclusion after IRC discussion with Wim

- alsasrc should continue to provide the sample based clock as default clock (this clock is more accurate).

- when alsasrc changes state from PAUSED to PLAYING it checks the pipeline
clock. If it's the monotonic clock it uses alsa driver time stamps. If it's a
different clock it uses that clock to time stamp the buffers.

- to enable alsa driver time stamping it's up to the application controlling the pipeline to set the monotonic clock on the pipeline.

No extra properties are thus needed and alsasrc will work like it does today unless you set the monotonic clock on the pipeline, in which case you will get more accurate monotonic timestamps since they are taken from the driver.
Comment 13 Pontus Oldberg 2011-01-14 10:56:03 UTC
Created attachment 178307 [details] [review]
New patch based on discussions and new suggestions on implementation.

This new patch removes the need for an element property to control the timestamp behavior. The clock is examined when the pipeline changes state from paused to playing and depending on what clock is used, driver timestamps or the normal sample clock timestamps are used.
Comment 14 Wim Taymans 2011-01-14 12:13:30 UTC
Yes, looks good now.
Comment 15 Tobias Mueller 2011-04-15 17:56:57 UTC
So I guess there is no open question left. Hence I am reopening. There is a patch attached, so it'd be nice if anybody could review that :)
Comment 16 Pontus Oldberg 2011-04-26 07:37:22 UTC
Indeed, is there anything more that i can do to speed up the process ?
Comment 17 Wim Taymans 2011-05-09 09:41:01 UTC
I will commit this after the freeze.
Comment 18 Sebastian Dröge (slomo) 2011-05-14 09:56:11 UTC
commit 2b84f5bd74ddb50f7832917ea8b4dd38d005631b
Author: Sebastian Dröge <sebastian.droege@collabora.co.uk>
Date:   Mon May 9 12:56:14 2011 +0200

    alsasrc: Fix some compilation errors

commit 0b774e0b7cf7a8ef1780fb6100228ca6e8ca8bcf
Author: Pontus Oldberg <pontus.oldberg@invector.se>
Date:   Mon May 9 11:50:05 2011 +0200

    alsasrc: Improve timestamp accuracy
    
    Fixes bug #635256.
Comment 19 Tim-Philipp Müller 2011-05-16 15:32:23 UTC
This seems to break one of the unit tests:

tpm@zingle:~/gst/clean/gst-plugins-base/tests/check$ make pipelines/basetime.check
Running suite(s): baseaudiosrc
0%: Checks: 1, Failures: 1, Errors: 0
pipelines/basetime.c:49:F:general:test_basetime_calculation:0: Two buffers had same timestamp
Running suite(s): baseaudiosrc
0:00:00.074727869  1872      0x257eb70 WARN                     bin gstbin.c:2395:gst_bin_do_latency_func:<pipeline0> did not really configure latency of 0:00:00.000000000
0:00:02.083683685  1872      0x24cf300 WARN                     bin gstbin.c:2395:gst_bin_do_latency_func:<pipeline0> did not really configure latency of 0:00:00.000000000
0%: Checks: 1, Failures: 1, Errors: 0
pipelines/basetime.c:49:F:general:test_basetime_calculation:0: Two buffers had same timestamp
make: *** [pipelines/basetime.check] Error 1

(Have not investigated further)
Comment 20 Pontus Oldberg 2011-05-20 07:56:02 UTC
I'm looking into it right now.
Comment 21 Tim-Philipp Müller 2011-05-28 15:18:45 UTC
Pontus, are you still looking into this?
Comment 22 Pontus Oldberg 2011-05-30 07:29:49 UTC
Yes I am. At the moment it looks like the problem is not in the patch itself, instead it looks like the alsa library is simply returning 0 in the timestamps. I have not been able yet to determine why but I am still looking in to it.
/Pontus
Comment 23 Stefan Sauer (gstreamer, gtkdoc dev) 2011-07-26 12:20:53 UTC
I was also noticing the failing test, but not aware of the bug and thus change the test:
commit 7ca9c4ec407d44bad934ba3bd9f7aec550b17cf8
Author: Stefan Sauer <ensonic@google.com>
Date:   Tue Jul 26 13:51:31 2011 +0200

    basetime: fix failing test
    
    Always use audiotestsrc as it seems to have been the intention according to the
    comment header. The test does not work with live-audiosources.

This could be reverted if we figure out a solution. For me the test was running on alsasrc and got 1 ts, another ts that was larger and then the same ts again.

Pontus, any news?
Comment 24 Tim-Philipp Müller 2011-07-26 12:28:04 UTC
Someone will need to look at this before the next release and understand what's happening, so we can determine if the test is wrong or the new behaviour is wrong.

Otherwise we'll have to revert the patch.
Comment 25 Stefan Sauer (gstreamer, gtkdoc dev) 2011-07-27 09:23:22 UTC
This is what happens for alsasrc:

Running suite(s): baseaudiosrc
pipelines/basetime.c:60:test_basetime_calculation: test start
gstbin.c:2395:gst_bin_do_latency_func:<pipeline0> did not really configure latency of 0:00:00.000000000
gstbin.c:2395:gst_bin_do_latency_func:<pipeline0> did not really configure latency of 0:00:00.000000000
pipelines/basetime.c:49:buffer_probe_cb: ts = 5124095:34:33.682703544
pipelines/basetime.c:49:buffer_probe_cb: ts = 5124095:34:33.677624179
pipelines/basetime.c:49:buffer_probe_cb: ts = 5124095:34:33.677624179
0%: Checks: 1, Failures: 1, Errors: 0
pipelines/basetime.c:53:F:general:test_basetime_calculation:0: Two buffers had same timestamp: 5124095:34:33.677624179

for audiotestsrc is-live{true,false} and pulsesrc we get e.g.:

Running suite(s): baseaudiosrc
pipelines/basetime.c:60:test_basetime_calculation: test start
pulsemixerctrl.c:365:gst_pulsemixer_ctrl_open:<pulsesrc0> Failed to get source info: Invalid argument
gstbin.c:2395:gst_bin_do_latency_func:<pipeline0> did not really configure latency of 0:00:00.000000000
gstbin.c:2395:gst_bin_do_latency_func:<pipeline0> did not really configure latency of 0:00:00.000000000
pipelines/basetime.c:49:buffer_probe_cb: ts = 0:00:02.039831769
gstbin.c:2395:gst_bin_do_latency_func:<pipeline0> did not really configure latency of 0:00:00.000000000
pipelines/basetime.c:49:buffer_probe_cb: ts = 0:00:02.065818163
pipelines/basetime.c:49:buffer_probe_cb: ts = 0:00:02.091804558
pipelines/basetime.c:49:buffer_probe_cb: ts = 0:00:02.117790952
pipelines/basetime.c:49:buffer_probe_cb: ts = 0:00:02.143777347
pipelines/basetime.c:49:buffer_probe_cb: ts = 0:00:02.169763741
...
pipelines/basetime.c:49:buffer_probe_cb: ts = 0:00:03.988811360
gstaudiosrc.c:237:audioringbuffer_thread_func:<pulsesrc0> error reading data -1 (reason: Success), skipping segment
pipelines/basetime.c:124:test_basetime_calculation: cleaning up tasks
100%: Checks: 1, Failures: 0, Errors: 0

If I don't make the test fail, but just print a warning, we can see that the timestamps for alsasrc are never increasing.
Comment 26 Stefan Sauer (gstreamer, gtkdoc dev) 2011-07-27 09:39:54 UTC
Created attachment 192740 [details] [review]
make sure we have increasing timestamps

This makes the test work. Not sure if that's the right thing to do though.
Comment 27 Stefan Sauer (gstreamer, gtkdoc dev) 2011-07-27 09:42:31 UTC
There has been alsa bugs, but those I found are supposed to be fixed:
http://www.spinics.net/lists/alsa-devel/msg10789.html
Comment 28 Pontus Oldberg 2011-08-24 14:33:14 UTC
I have had no luck in recreating this error. I have built master on gstreamer and gst-plugins-base as well as version 1.0.24.1 of alsa-lib. Stefans's rewrite of the testcase (test_basetime_calculation) to use audiotestsrc instead of alsasrc as an audio source works as expected, BUT I also tried to change the test back to using alsasrc as an audio source and it still works fine here for me with a good monotonic clock source being reported.

Having a fallback clock source is not a good solution for this since we've explicitly told the pipeline to use/expect the monotonic clock.

I'm not sure how to proceed, but if someone can verify my findings I'd appreciate it.
Comment 29 Tim-Philipp Müller 2011-09-26 22:59:03 UTC
For more breakage, see bug #660170.

I am going to revert this if no one looks into it and sees if it's fixable.
Comment 30 Brian G. Marete 2011-09-26 23:20:14 UTC
Hello,

The patch that came out of this report: 0b774e0b7cf7a8ef1780fb610022 (in -base) broke time-stamping in the simple pipeline: `gst-launch alsasrc ! audiorate ! filesink=/dev/null'. See Bug #660170 which I filed earlier today. Reverting that patch fixes that bug.

Thanks!
Comment 31 Vincent Penquerc'h 2011-09-26 23:29:05 UTC
Fixable (just ignore those timestamps if ALSA returns a 0 timestamp).
Patch on the other bug.
Comment 32 Pontus Oldberg 2011-09-27 14:59:53 UTC
I'll have a go at this again.
Comment 33 Brian G. Marete 2011-09-29 18:01:36 UTC
Pontus, Vincent's latest patch on the other bug (#660170) fixes this.
Comment 34 Sebastian Dröge (slomo) 2011-10-03 09:29:52 UTC
(In reply to comment #26)
> Created an attachment (id=192740) [details] [review]
> make sure we have increasing timestamps
> 
> This makes the test work. Not sure if that's the right thing to do though.

Is this patch still valid? IMHO checking if the driver supports timestamps first makes sense
Comment 35 Stefan Sauer (gstreamer, gtkdoc dev) 2011-11-28 08:08:07 UTC
I think its a good idea. I retested the pipelines in Bug 660170 with my patch applied and run the tests. No regression, will push the patch.
Comment 36 Pontus Oldberg 2011-11-28 12:26:26 UTC
I hate to be the bringer of bad news, but in this case I have to.
My patch is seriously flawed and should really be pulled from the repo, and I'll attempt to explain why.

Basically, create and read are executed in separate threads which can (and will) cause a situation where create and read are not synchronized. In our application this has caused the framework to generate two consecutive equal timestamps (i.e. create is executed twice before a read operation is performed). This situation is more likely to appear in a loaded system, at least this is where we have seen the problems. There is also another problem with some alsa pcm drivers, where the avail parameter is not correctly exposed to the alsa-lib. This also need to be taken into consideration in a new implementation.

I am working on a completely new solution to obtain perfectly synchronized timestamps but it is not anywhere near ready yet.
Comment 37 Tim-Philipp Müller 2011-11-30 23:20:02 UTC
Reverted these for the release:

commit e88e47cd247e6e573485093cd82e40de087a8193
Author: Tim-Philipp Müller <tim.muller@collabora.co.uk>
Date:   Wed Nov 30 23:15:35 2011 +0000

    Revert "alsasrc: Improve timestamp accuracy"
    
    This reverts commit 0b774e0b7cf7a8ef1780fb6100228ca6e8ca8bcf.

commit e5ae5538500d1f243b5edbd92e0531933e10e4aa
Author: Tim-Philipp Müller <tim.muller@collabora.co.uk>
Date:   Wed Nov 30 23:15:22 2011 +0000

    Revert "alsasrc: Fix some compilation errors"
    
    This reverts commit 2b84f5bd74ddb50f7832917ea8b4dd38d005631b.

commit 4cc8920db4ee742dc5476079fadfe493dcadf028
Author: Tim-Philipp Müller <tim.muller@collabora.co.uk>
Date:   Wed Nov 30 23:15:12 2011 +0000

    Revert "alsa: Remove unused but set variable"
    
    This reverts commit e9aed7f31c7e9e415f733e147140ce3ef2f57a61.

commit 1290f7de0e2bdd493fd70b5715863e118383b4cb
Author: Tim-Philipp Müller <tim.muller@collabora.co.uk>
Date:   Wed Nov 30 23:15:03 2011 +0000

    Revert "alsasrc: fail gracefully when ALSA does not give timestamps"
    
    This reverts commit c7282a5718c7f31f84fb31b2c38fab0f9a38e2b0.

commit d11849114c6a068c4382402d82f26086ded4427d
Author: Tim-Philipp Müller <tim.muller@collabora.co.uk>
Date:   Wed Nov 30 23:14:54 2011 +0000

    Revert "alsasrc: handle the case where the drivers don't supply timestamps"
    
    This reverts commit 8154b69112cdc4830cd6002ec6c1f2917d30437b.

commit 6d167abdfa77108f3c98aae98b04e0225f570b85
Author: Stefan Sauer <ensonic@google.com>
Date:   Mon Nov 28 10:55:39 2011 +0100

    Revert "alsasrc: style fix"
    
    This reverts commit f70ca6d4cbfd2b672dcc7215814bf6b39ce2c3f8.
Comment 38 Pontus Oldberg 2012-01-02 13:07:03 UTC
Created attachment 204448 [details] [review]
Suggestion on having a single thread to solve the timestamp issues.
Comment 39 Pontus Oldberg 2012-01-02 13:07:40 UTC
I have spent some time looking into this the past weeks and have come up with a fix that is a bit more extensive than the previous one.

Note, that it still is a experimental version, but I thought it would be good to have it here for further discussion.

Basically this suggestion introduces a new property (in the audiosrc element) that tells the system to run the alsasrc in a single thread instead of having a separate read thread and the pipeline thread. Time stamps are now taken in the same thread as data is read which solves the problem of having reads and taking the timestamps unsynchronized.

As I understand it, having a separate read thread solves the problem were poorly written alsa drivers would loose data if not served instantly when new data is available. This is why the read thread wasn't removed completely.

This implementation starts up with dual threaded alsasrc as default, and by setting the "single-thread" property to true it goes into a single-thread mode of operation. Driver timestamping is also disabled in dual thread mode since it does not work properly, as discussed before.

Comments, suggestions anyone ?
Comment 40 Pontus Oldberg 2012-01-02 13:13:32 UTC
Oh, I should probably point out that this patch is based on 0.10.35 as this is the version that we currently are using internally.
Comment 41 Pontus Oldberg 2012-01-19 15:24:21 UTC
Created attachment 205626 [details] [review]
Using a return path for timestamps to the ringbuffer.

After comments from Wim I tried the attached solution instead. It does not have the advantage of eliminating the read thread but it is much simpler.
Comment 42 Pontus Oldberg 2012-01-24 12:55:54 UTC
Created attachment 205970 [details] [review]
Updated version......

Here's a new version using an array for holding a timestamp for each entry in the ringbuffer.
Comment 43 Pontus Oldberg 2012-05-04 14:37:45 UTC
Created attachment 213444 [details] [review]
New patch for 0.11

I have created a new patch file for the 0.11 branch. It would be great if someone could have a look at it so that I can make any changes needed. Thank you.
Comment 44 Wim Taymans 2012-05-24 12:57:30 UTC
It is too broken:

* 0.10 version breaks ABI
* 0.11 missing audiobasesrc code.
* 0.11 version should simply add the *timestamp to existing read methods.
* In gst_audio_base_src_create() the base_time is not taken into account.
* gst_audio_ring_buffer_read() can read over multiple segments, it seems the 
  timestamp of the last segment is used, not the first (which should be closer to
  the real value). You might want to adjust the timestamp with the amount of
  bytes relative to the segment.
* the ringbuffer timestamp array is leaked
* a timestamp of -1 (instead of 0) should be used when the subclass doesn't
  provide a timestamp. This is because 0 can be a valid clock time.
Comment 45 Pontus Oldberg 2012-06-14 09:43:17 UTC
Created attachment 216398 [details] [review]
Updated patch from Wim's commetns.

This a new patch that solves most of Wim's comments above. Some of you comments need some more discussions on the board.
Comment 46 Wim Taymans 2012-06-19 07:22:07 UTC
Giving up again.. still broken
Comment 47 Pontus Oldberg 2012-06-19 07:26:52 UTC
Wim, Any pointers as to what you feel is broken ?
Comment 48 Wim Taymans 2012-06-19 13:34:07 UTC
* In gst_audio_base_src_create() the base_time is not taken into account.
* gst_audio_ring_buffer_read() can read over multiple segments, it seems the 
  timestamp of the last segment is used, not the first (which should be closer
to
  the real value). You might want to adjust the timestamp with the amount of
  bytes relative to the segment.
* a timestamp of -1 (instead of 0) should be used when the subclass doesn't
  provide a timestamp. This is because 0 can be a valid clock time.
Comment 49 Pontus Oldberg 2012-06-20 12:04:06 UTC
Created attachment 216823 [details] [review]
Another updated patch with fixes to comments from Wim.

Here's another go at fixing the comments made by Wim. Hopefully this one will make it =)
Comment 50 Wim Taymans 2012-09-10 09:35:32 UTC
* fixed some places where 0 was used as invalid timestamp
* fixed possible crasher in alsa when allocation failed.
* ported -good plugins

commit a2f8ec4f5a79eccef129f73053903c63e787ca2e
Author: Pontus Oldberg <pontus.oldberg at invector.se>
Date:   Mon Sep 10 11:26:38 2012 +0200

    ringbuffer: add support for timestamps
    
    Make it possible for subclasses to provide the timestamp (as an absolute time
    against the pipeline clock) of the last read data.
    Fix up alsa to provide the timestamp received from alsa. Because the alsa
    timestamps are in monotonic time, we can only do this when the monotonic clock
    has been selected as the pipeline clock.
    
    Fixes https://bugzilla.gnome.org/show_bug.cgi?id=635256