[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