[Bug 750694] New: alsasink: Brief gap after unpause if audio clock is not the pipeline clock
GStreamer (GNOME Bugzilla)
bugzilla at gnome.org
Wed Jun 10 04:07:21 PDT 2015
https://bugzilla.gnome.org/show_bug.cgi?id=750694
Bug ID: 750694
Summary: alsasink: Brief gap after unpause if audio clock is
not the pipeline clock
Classification: Platform
Product: GStreamer
Version: git master
OS: Linux
Status: NEW
Severity: normal
Priority: Normal
Component: gst-plugins-base
Assignee: gstreamer-bugs at lists.freedesktop.org
Reporter: dv at pseudoterminal.org
QA Contact: gstreamer-bugs at lists.freedesktop.org
GNOME version: ---
Created attachment 304947
--> https://bugzilla.gnome.org/attachment.cgi?id=304947&action=edit
gst-play patch , do not commit! Just for testing purposes
If playback is paused, later unpaused, and the audio clock is not the pipeline
clock, then after unpause, a short audio sequence can be heard, then a brief
gap, then audio continues. This is 100% reproducible, even with gst-play, if
the attached gst-play-alsasink-test.patch is used. Patch gstreamer core with
this, rebuild, and then play an audio file and pause&unpause a few times.
The problem can be fixed/cirumvented by using snd_pcm_drain() instead of
snd_pcm_drop() in the gst_alsasink_reset() definition. (snd_pcm_nonblock() has
to be used before and after calling snd_pcm_drain(), since draining in nonblock
mode won't work properly.)
There are two open questions. First, it is unclear if draining instead of
dropping is a viable option. Draining will introduce a small delay (since it
blocks until draining is complete).
Second, it is not fully known *why* this error occurs, and why draining helps.
I can only speculate:
Draining essentially instructs ALSA to block until the playback pointer catches
up with the write pointer. Drop just stops playback immediately. Therefore, if
drop is called, all pending writes are discarded, but the *current* one is
finished (in case a write is happening concurrently in the background). The
write pointer inside ALSA is moved forward, but the playback pointer isn't,
since drop stopped playback. Then, after unpause, the sink resynchronizes
itself, which leads to nullsamples being inserted prior to the actual audio
data. These nullsamples are what cause the gap. The problem then boils down to
the fact that ALSA's internal write pointer is moved forward, but the playback
pointer isn't: the playback pointer is still in front of the old samples that
were written *before* the pause. In other words, after unpause, ALSA plays a
few "old" samples that were written earlier.
I see no way to tell ALSA to drop and *not* move forward the write pointer. So,
draining really seems to be the only simple choice. Another, nontrivial option
would be mmap, since it might be possible then to do a manual memset() after
dropping, which would clear out any of these "old" samples.
Ideas? Thoughts?
--
You are receiving this mail because:
You are the QA Contact for the bug.
You are the assignee for the bug.
More information about the gstreamer-bugs
mailing list