[Bug 30118] New: Sound occasionally stalls past underrun, bypassing our lead-in writer

wine-bugs at winehq.org wine-bugs at winehq.org
Fri Mar 9 07:03:59 CST 2012


http://bugs.winehq.org/show_bug.cgi?id=30118

             Bug #: 30118
           Summary: Sound occasionally stalls past underrun, bypassing our
                    lead-in writer
           Product: Wine
           Version: 1.4-rc5
          Platform: x86
        OS/Version: Linux
            Status: NEW
          Severity: normal
          Priority: P2
         Component: winealsa.drv
        AssignedTo: wine-bugs at winehq.org
        ReportedBy: hoehle at users.sourceforge.net
    Classification: Unclassified


Attachment #39217 to bug #29294 contains a log where Civilization 5 audio
stalls after an underrun.

99% of the time, an underrun happens while the mmdevapi render callback sleeps.
snd_pcm_avail is then the first to detect it, recovers, writes the lead-in and
audio is running again.  This happened 266 times in the log:
 62.063:alsa_write_data XRun state avail 12689, recovering

In rare cases, the underrun did not yet occur when snd_pcm_avail was called
rather than a few µs later in snd_pcm_write.
 62.190:alsa_write_data pad: 4245
 62.190:alsa_write_best_effort writei failed, recovering: -32 (Broken pipe)
ALSA lib pcm.c:7316:(snd_pcm_recover) underrun occurred

Following that, ALSA has a little data
 62.201:alsa_write_data pad: 512
 62.211:alsa:alsa_write_data pad: 5120
but somehow DSound stops feeding it.

Now bug #29294 involves Jack whose precise behaviour I don't know, but here's
what would happen when using plain plug:dmix or hw:0:  Our lead-in writer does
not trigger because it sits before snd_pcm_write.  The key issue is that ALSA
has less than one period of data, so it doesn't start!  That is known behaviour
from both dmix and hw:x,y devices.

 23.054:AudioClient_Initialize ALSA period: 5512 frames
 23.055:AudioClient_Initialize ALSA buffer: 16537 frames
 23.055:AudioClient_Initialize MMDevice period: 441 frames
 23.055:AudioClient_Initialize MMDevice buffer: 5120 frames

As a result, position does not increase.  The little data prevents writing the
lead-in upon subsequent callback invocations.  Unfortunately, DSound is
presumably waiting for a particular position to be reached to continue feeding
data.

Position would increase and bump to max = release_frames - held_frames if it
would hit another underun -- if ALSA had managed to start.

So this is partly a bug in DSound which I've already blamed for using
GetPosition instead of GetCurrentPadding when feeding data, witness comment
#21, bug #29472, comment #17 or bug #29497, comment #1.  However the subject of
this bug report shall be winealsa's incomplete underrun recovery.

Also note another issue here: mmdevapi's buffer of 5120 frames is smaller than
ALSA's period!  Thanks to the lead-in, that nevertheless works at start. 
Perhaps DSound would not have stalled had that buffer been larger; it might
have written more frames.

Months ago I conducted many tests with different buffer and period sizes in
exclusive mode but have not finalized that work about the minimum and maximum
buffer sizes and when to return E_INVALID_DEVICE_PERIOD or
AUDCLNT_E_BUFFER_SIZE_ERROR etc.  That's still a TODO on my list.  That work
has been very revealing about the relationship between mmdevapi and alsa buffer
and period sizes.  Presumably, mmdevapi must create a buffer at least as large
as ALSA's period.

-- 
Configure bugmail: http://bugs.winehq.org/userprefs.cgi?tab=email
Do not reply to this email, post in Bugzilla using the
above URL to reply.
------- You are receiving this mail because: -------
You are watching all bug changes.


More information about the wine-bugs mailing list