Previously, the paused state was not handled.
-- v4: mf: Reset audio client on flush. mf: Update state and start clock for both paused and stopped.
From: Brendan McGrath bmcgrath@codeweavers.com
Previously, the paused state was not handled. --- dlls/mf/sar.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/dlls/mf/sar.c b/dlls/mf/sar.c index 84824f954dd..d908e2bb085 100644 --- a/dlls/mf/sar.c +++ b/dlls/mf/sar.c @@ -636,7 +636,7 @@ static HRESULT WINAPI audio_renderer_clock_sink_OnClockStart(IMFClockStateSink * EnterCriticalSection(&renderer->cs); if (renderer->audio_client) { - if (renderer->state == STREAM_STATE_STOPPED) + if (renderer->state != STREAM_STATE_RUNNING) { if (FAILED(hr = IAudioClient_Start(renderer->audio_client))) WARN("Failed to start audio client, hr %#lx.\n", hr);
From: Brendan McGrath bmcgrath@codeweavers.com
--- dlls/mf/sar.c | 2 ++ 1 file changed, 2 insertions(+)
diff --git a/dlls/mf/sar.c b/dlls/mf/sar.c index d908e2bb085..19e4eeda6b7 100644 --- a/dlls/mf/sar.c +++ b/dlls/mf/sar.c @@ -1458,6 +1458,8 @@ static HRESULT WINAPI audio_renderer_stream_Flush(IMFStreamSink *iface) } } renderer->queued_frames = 0; + if (FAILED(hr = IAudioClient_Reset(renderer->audio_client))) + WARN("Failed to reset audio client, hr %#lx.\n", hr); LeaveCriticalSection(&renderer->cs);
return hr;
On Wed Apr 23 04:33:22 2025 +0000, Brendan McGrath wrote:
changed this line in [version 4 of the diff](/wine/wine/-/merge_requests/7833/diffs?diff_id=172917&start_sha=10185656e89e1cd8f4d7c8638b294be794de9a6d#37de8fd303086366917ec7ce9239620f0961a3f0_1461_1461)
Done
On Wed Apr 23 01:13:31 2025 +0000, Brendan McGrath wrote:
Dropping buffers with PTS being too far behind would be SAR
functionality I think I haven't tested SAR when using an external clock. But I found that when it uses its own clock (it implements the `IMFPresentationTimeSource` interface), it never drops samples. It just updates its clock to reflect the sample PTS. I captured that in a test here: https://gitlab.winehq.org/redmcg/wine/-/commit/f940f12b3c7d562fb2fb00a68a3e7... In that test, I confirm the clock is `5510000`, then I get SAR to process a sample with PTS `20000000` and duration `100000`, sleep for 150ms (to allow time for SAR to process the sample) and then confirm the clock has magically jumped to `20100000` (which is a 1.5 second jump in a tenth of that time). I've found this matches the behavior of `IMFMediaEngine` too; thus it must use the `IMFPresentationTimeSource` provided by SAR. So audio is never out of sync, as it determines the presentation time. It's up to the video to pause or speed-up as necessary to keep audio and video in sync. I found I needed to implement this behavior to fix seek in VRChat (which uses `IMFMediaEngine`). I plan to raise an MR upstream soon (once I'm happy with it).
Yes, we have some tests for time source interface support in SAR, the session will always use this source, and we have generic support for that already in session_set_presentation_clock(). Currently it's using the very first time source it can get, I don't know if it's entirely correct but it will pick SAR as long as you stay with builtin sinks.
Just so I understand, SAR clock jumps to pts + <time it actually took to play this sample/time it would take according to sample rate> or it jumps blindly to pts + mf sample duration, ignoring actual playback time? I don't know how well sample duration is validated against actual buffer sizes.
In contrast, if I just restart without a seek (i.e. use current time) I get:
9198.091103|03596|source_mock_Start: MEUpdatedStream 9198.091297|15820|clock_sink_OnClockStart: .
Is this an artifact of your tracing or OnClockRestart() is actually never used?
This merge request was approved by Nikolay Sivov.