From: Yuxuan Shui <yshui@codeweavers.com> Previously the SEEKING flag is only set when the ASYNC_SEEK operation is executed. This is too late because of this race condition: - Application calls SetCurrentPosition, which queues the ASYNC_SEEK operation but does not set SEEKING. - Application calls ReadSample. Since the SEEKING flag hasn't been set, it proceeds without waiting and queues an ASYNC_READ operation. - ASYNC_SEEK operation starts its execution, but hasn't reached IMFMediaSource_Start yet. - ASYNC_READ operation starts its execution, and calls IMFMediaStream_RequestSample. Media source queues a request sample job. reader->streams[i]->requests++. ASYNC_READ finishes. - ASYNC_SEEK operation calls IMFMediaSource_Start, the request sample job queued by the media source gets dropped. At this point, there is no request sample job running, but the stream->requests counter is still positive. From this point on the source reader will not request anymore samples, future ReadSample will never complete. Setting the SEEKING flag early, then source reader will always wait in ReadSample so this kind of ordering cannot happen. --- dlls/mfreadwrite/reader.c | 7 ++++--- dlls/mfreadwrite/tests/mfplat.c | 2 +- 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/dlls/mfreadwrite/reader.c b/dlls/mfreadwrite/reader.c index fdbc40fc2ba..30fef71e26b 100644 --- a/dlls/mfreadwrite/reader.c +++ b/dlls/mfreadwrite/reader.c @@ -1562,10 +1562,10 @@ static HRESULT WINAPI source_reader_async_commands_callback_Invoke(IMFAsyncCallb case SOURCE_READER_ASYNC_SEEK: EnterCriticalSection(&reader->cs); - if (SUCCEEDED(IMFMediaSource_Start(reader->source, reader->descriptor, &command->u.seek.format, + if (FAILED(IMFMediaSource_Start(reader->source, reader->descriptor, &command->u.seek.format, &command->u.seek.position))) { - reader->flags |= SOURCE_READER_SEEKING; + reader->flags &= ~SOURCE_READER_SEEKING; } LeaveCriticalSection(&reader->cs); @@ -2358,6 +2358,8 @@ static HRESULT WINAPI src_reader_SetCurrentPosition(IMFSourceReaderEx *iface, RE if (SUCCEEDED(hr)) { + reader->flags |= SOURCE_READER_SEEKING; + for (i = 0; i < reader->stream_count; ++i) { reader->streams[i].last_sample_ts = 0; @@ -2378,7 +2380,6 @@ static HRESULT WINAPI src_reader_SetCurrentPosition(IMFSourceReaderEx *iface, RE { if (SUCCEEDED(IMFMediaSource_Start(reader->source, reader->descriptor, format, position))) { - reader->flags |= SOURCE_READER_SEEKING; while (reader->flags & SOURCE_READER_SEEKING) { SleepConditionVariableCS(&reader->state_event, &reader->cs, INFINITE); diff --git a/dlls/mfreadwrite/tests/mfplat.c b/dlls/mfreadwrite/tests/mfplat.c index 763aecc6908..2cbc946847c 100644 --- a/dlls/mfreadwrite/tests/mfplat.c +++ b/dlls/mfreadwrite/tests/mfplat.c @@ -1356,7 +1356,7 @@ static void test_async_source_reader(void) if (res) break; } - todo_wine ok(!res, "ReadSample didn't finish\n"); + ok(!res, "ReadSample didn't finish\n"); IMFSourceReaderCallback_Release(&callback->IMFSourceReaderCallback_iface); IMFSourceReader_Release(reader); -- GitLab https://gitlab.winehq.org/wine/wine/-/merge_requests/11174