http://bugs.winehq.org/show_bug.cgi?id=30147
Bug #: 30147 Summary: mmdevapi: incorrect capture overrun handling Product: Wine Version: 1.3.25 Platform: x86 OS/Version: Linux Status: NEW Severity: normal Priority: P2 Component: mmdevapi AssignedTo: wine-bugs@winehq.org ReportedBy: hoehle@users.sourceforge.net CC: m.b.lankhorst@gmail.com Classification: Unclassified
Created attachment 39320 --> http://bugs.winehq.org/attachment.cgi?id=39320 mmdevapi capture test from native w7 machine
Most wineXYZ audio drivers do not handle mmdevapi capture overrun correctly. In particular, the ALSA & OSS drivers randomly overwrite old with new data, depending on the read pointer within the capture buffer.
Native roughly supports, with some quirks, a scenario like: Initialize(duration=Xms); Start; Sleep(X+Yms); /* Y extra spare time */ Stop; /* optional, buffer is full now */ repeat GetBuffer/ReleaseBuffer until (hr != S_OK); The goal is to obtain one buffer (~Xms) full of data.
The attached log from a w7 machine shows what packet gets recorded at what time by tracing GetBuffer's performance counter output parameter (qpc). The key data points are:
capture.c:544: rate: 48000 capture.c:293: GetBufferSize 23941 period size 480 capture.c:248: Sleep.1 position 480 pad 16800 flags 0, frames locked: 480 capture.c:250: sleep qpc=67335132 capture.c:293: GetBufferSize 23941 period size 480 capture.c:303: Overrun position 1440 pad 23941 flags 1, frames locked: 480 capture.c:305: overrun qpc=67355139
This position and qpc jump of exactly one period I don't understand.
capture.c:331: Cont'ed position 1920 pad 23461 flags 0, frames locked: 480 capture.c:333: cont'ed qpc=67365133 qpc=67375139 0 position 2400 pad 22981 flags 0, next 480, frames locked: 480 qpc=67385135 1 position 2880 pad 22501 flags 0, next 480, frames locked: 480
Note how position correlates with 10ms increments of qpc (in µs).
qpc=67795152 42 position 22560 pad 3301 flags 0, next 480, frames locked: 480 qpc=67805153 43 position 23040 pad 2821 flags 0, next 480, frames locked: 480 qpc=67815148 44 position 23520 pad 2341 flags 0, next 421, frames locked: 421 qpc=67823919 45 position 23520 pad 1920 flags 0, next 59, frames locked: 59 qpc=67825154 46 position 24000 pad 1861 flags 0, next 480, frames locked: 480 qpc=67835147 47 position 24480 pad 1381 flags 1, next 421, frames locked: 421 qpc=68085155 48 position 36480 pad 960 flags 1, next 480, frames locked: 480 capture.c:352: Test failed: Valid IAudioCaptureClient_GetBuffer: 08890001 qpc=68085155 49 position -1 pad 480 flags 1, next 0, frames locked: 0
qpc indicates that old packets are being delivered until iteration <48, where another position jump occurs.
Summary:
- I don't know where native's 23941 frames buffer comes from. It's neither a multiple of the period size nor of 1024.
- Upon underrun, a DISCONTINUITY is immediately signaled and one packet is skipped. The latter is weird. (I'm wondering whether native overwrites one packet within the circular buffer as an overrun detector, then skips it?).
+ Then, almost a full buffer of old packets can be retrieved with GetBuffer.
- While the full buffer is 49 * 480 + 421, only 48 * 480 + 421 frames can be retrieved with a qpc indicating pre-overrun times.
- The last old packet is flagged with DISCONTINUITY too (iteration 47). I'd have expected solely the following one to bear this mark.
+ When there's room again in the buffer, GetBuffer yields new packets (iteration 48). Both position and qpc reflect the overrun gap that appears to have last for 250ms. DISCONTINUITY is set too.
- There's some strange packet splitting at iterations 44-45 that may correspond to a wrap-around of native's buffer. I wonder why native does not limit buffer to multiples of period size.
- Note that the position 23520 of the 59 frames fragment rest is the same as that of the previous 421 frames packet. A bug in native? The qpc is different and looks ok.
+ GetNextPacket exactly matches the following GetBuffer, even when it yields less than one packet, e.g. 421/59/480.
- GetCurrentPadding >= period size does not imply a successful GetBuffer, see iteration 49. Only GetNextPacket correlates fine. A bug in native?