[PATCH 2/3] quartz/dsoundrender: Don't let writepos advance past playpos.

Anton Baskanov baskanov at gmail.com
Tue Apr 27 02:20:53 CDT 2021


On вторник, 27 апреля 2021 г. 06:23:58 +07 you wrote:
> On 4/25/21 9:51 PM, Anton Baskanov wrote:
> > Fixes audio stuttering during video playback in multiple games (e.g.
> > Commandos 2, Alien Nations, Dino Crisis Demo).
> 
> Can you please provide a +quartz,+strmbase,+gstreamer log that
> demonstrates the problem?

I've attached the log of the Commandos 2 (GOG version) first intro video 
playback. The relevant part is:

0154:trace:quartz:DSoundRender_SendSampleData Wrote 75500 bytes at 17108, next 
at 4408 - (75500/88200)
0154:trace:quartz:SystemClockImpl_GetTime clock 002D8440, time 03FBFC20, 
returning 1569156.542.
0154:trace:quartz:DSoundRender_SendSampleData Wrote 12700 bytes at 4408, next 
at 17108 - (88196/12700)

First, DSoundRender_GetWritePos reports 75500 free bytes, so we write 75500 
bytes to the buffer. At this point, DSoundRender_GetWritePos must report 0 free 
bytes, since the buffer is full, but it reports 88196 instead, so we write 
another 12700 bytes, overrunning playpos.

Some time after that an underrun happens when dsound write cursor advances 
past our write position:

0154:fixme:quartz:DSoundRender_UpdatePositions Underrun of data occurred!

To reproduce this issue there has to be enough data to fill the buffer, i.e. the 
samples must be at least 1s in length.

> 
> > Signed-off-by: Anton Baskanov <baskanov at gmail.com>
> > ---
> > 
> >   dlls/quartz/dsoundrender.c       | 5 +----
> >   dlls/quartz/tests/dsoundrender.c | 2 +-
> >   2 files changed, 2 insertions(+), 5 deletions(-)
> > 
> > diff --git a/dlls/quartz/dsoundrender.c b/dlls/quartz/dsoundrender.c
> > index 6c6732e468a..f7f0255d4ab 100644
> > --- a/dlls/quartz/dsoundrender.c
> > +++ b/dlls/quartz/dsoundrender.c
> > @@ -149,7 +149,6 @@ static void DSoundRender_UpdatePositions(struct
> > dsound_render *This, DWORD *seqw> 
> >   static HRESULT DSoundRender_GetWritePos(struct dsound_render *This,
> >   
> >           DWORD *ret_writepos, REFERENCE_TIME write_at, DWORD *pfree,
> >           DWORD *skip)
> >   
> >   {
> > 
> > -    WAVEFORMATEX *wfx = (WAVEFORMATEX *)This->sink.pin.mt.pbFormat;
> > 
> >       DWORD writepos, min_writepos, playpos;
> >       REFERENCE_TIME max_lag = 50 * 10000;
> >       REFERENCE_TIME cur, writepos_t, delta_t;
> > 
> > @@ -212,10 +211,8 @@ static HRESULT DSoundRender_GetWritePos(struct
> > dsound_render *This,> 
> >           *ret_writepos = (min_writepos + aheadbytes) % This->buf_size;
> >       
> >       }
> >   
> >   end:
> > -    if (playpos > *ret_writepos)
> > +    if (playpos >= *ret_writepos)
> > 
> >           *pfree = playpos - *ret_writepos;
> > 
> > -    else if (playpos == *ret_writepos)
> > -        *pfree = This->buf_size - wfx->nBlockAlign;
> > 
> >       else
> >       
> >           *pfree = This->buf_size + playpos - *ret_writepos;
> >       
> >       if (time_from_pos(This, This->buf_size - *pfree) >=
> >       DSoundRenderer_Max_Fill) {> 
> > diff --git a/dlls/quartz/tests/dsoundrender.c
> > b/dlls/quartz/tests/dsoundrender.c index c33c074d93d..e591e1832d5 100644
> > --- a/dlls/quartz/tests/dsoundrender.c
> > +++ b/dlls/quartz/tests/dsoundrender.c
> > @@ -737,7 +737,7 @@ static HRESULT send_frame(IMemInputPin *sink)
> > 
> >       params->sink = sink;
> >       params->sample = sample;
> >       thread = CreateThread(NULL, 0, frame_thread, params, 0, NULL);
> > 
> > -    ret = WaitForSingleObject(thread, 500);
> > +    ret = WaitForSingleObject(thread, 2000);
> > 
> >       todo_wine_if (ret) ok(!ret, "Wait failed.\n");
> >       GetExitCodeThread(thread, &ret);
> >       CloseHandle(thread);

-------------- next part --------------
A non-text attachment was scrubbed...
Name: commandos2.txt.gz
Type: application/gzip
Size: 81241 bytes
Desc: not available
URL: <http://www.winehq.org/pipermail/wine-devel/attachments/20210427/3543e985/attachment-0001.gz>


More information about the wine-devel mailing list