https://bugs.winehq.org/show_bug.cgi?id=53475
--- Comment #12 from ilkka.prusi@gmail.com --- (In reply to Zeb Figura from comment #11)
(In reply to ilkka.prusi from comment #9)
Created attachment 72847 [details] Simplify end of stream and flush event handling
Flush event handling has bogus error message: it is normal that WaitForSingleObject() returns 0 when event has been signalled. Also at that point it is expected that code will stop blocking so expedited return would be preferred instead of continuing in SendSampleData(). This has a case-check in the patch.
The problem with this diff is that under normal operation we really shouldn't be getting there in the first place. If flush_event is signaled then the sink should be flushing or stopped. In either case the upstream filter that's driving the graph (i.e. the parser) should have waited for the streaming thread to finish before un-flushing or restarting the graph.
The code is awful and doesn't make this clear, of course.
So the filter state and event state can end in a conflicting situation if I understood this correctly?
Looking at the code more it might be attempting to write out rest of the sample after flushing was signalled
In dsound_render_sink_eos(), when stream is finished resetting should buffer have no meaningful purpose: a) buffer will be destroyed and sample no longer matters b) buffer could be reused and rewritten with new sample Zeroing serves no purpose in either case and is removed in the patch.
The buffer may not be destroyed or refilled immediately; it may take an arbitrary amount of time, during which time dsound will continue to loop over it. If we don't zero the buffer the user will hear the last second of audio repeat.
Additionally, in dsound_render_sink_eos() there is a waiting loop which seems to have no purpose and causes bogus "underrun" message when sample playing is supposed to end already. Code does other things that seem to have no useful meaning when stream is ending. The lines that may have use are lifter up the call chain in the patch.
It's waiting for the buffer to finish playing, so that the aforementioned zeroing won't overwrite data that hasn't been written out to the audio device yet.
So end of stream happens earlier than actually stopping playback? But a couple of lines earlier there's IMediaEventSink_Release() already so it is supposed to end? Is it only relying on actual object destroying happening at a later time?
Maybe that function should just call IDirectSoundBuffer_Stop() to ensure it is ending cleanly? Or is there something conceptually different about end of stream rather than end of sample playback?