mmdevapi buffering

Joerg-Cyril.Hoehle at t-systems.com Joerg-Cyril.Hoehle at t-systems.com
Wed Jun 1 07:33:40 CDT 2011


Hi,

I have one big concern about MSDN's "Rendering a stream" (shared mode)
example w.r.t wrap-around of buffer pointers and how Wine implements it.
The example is at
http://msdn.microsoft.com/en-us/library/dd316756(v=vs.85).aspx

Suppose the write pointer is near the end of the buffer and the app is
a little late, so the HW read pointer is not far away.

|---------------------------------------------------^read------^write-----|

What is GetCurrentPadding going to return?
 - the tiny write-read portion, says MSDN AFAICT
 - 0, because there's a new fresh buffer waiting to be filled?

MSDN's example then computes avail = GetBufferSize() - GetCurrentPadding();
What is GetBuffer(avail) going to return?!?

 - If it's a pointer to the above buffer, it can only succeed if avail
   is tiny, otherwise there's a buffer overflow.
   However avail, as defined above and in MSDN's example, will be large.
  Wine tricks around that by returning a dynamic local tmp buffer larger than GetBufferSize
  (I wonder why a fixed one instead, twice GetBufferSize would not suffice?)
  Does native behave like that?
 - E_BUFFER_TOO_LARGE ?  The MSDN example would exit.
 - Could it be a pointer to the beginning of the buffer?
 - Or it's a pointer to another buffer!
   That's not compatible with Wine's current local_buffer implementation...
   Isn't Wine's mmdevapi going to produces glitches?

The problematic situation is when avail is small, as the following sleep for half a
buffer size in MSDN's example will inevitably produce an xrun.
So what actually is the buffer size and how does GetCurrentPadding behave?

I don't expect MSDN's example to be fundamentally flawed.  IMHO, they
designed their API such that it is the typical use case.
I believe that multiple buffers (of size GetBufferSize) are
involved (much like ALSA's periods) and that GetBuffer switches among
them -- exactly like they say about the exclusive mode ping pong.

I suppose native's mixer (in shared mode) would mix these possibly
incompletely filled buffers and everything is fine there.
No need to deal with wrap-around!

Why should Wine do something entirely different?

Regards,
 Jörg Höhle


More information about the wine-devel mailing list