From: Rémi Bernon rbernon@codeweavers.com
MR !607 was trying to fix an issue with Life Is Strange Remastered, but although it fixed some race conditions with presentation end, the issue it was trying to fix is still there.
The game calls IMFMediaSession_Stop while the presentation is ending, expects that command to quickly execute, interrupting the presentation end and emitting a MESessionStopped event instead of the MESessionEnded.
Delaying the Stop command and emitting the MESessionEnded event breaks the game assumptions and it crashes. --- dlls/mf/session.c | 12 +++++++++++- dlls/mf/tests/mf.c | 1 - 2 files changed, 11 insertions(+), 2 deletions(-)
diff --git a/dlls/mf/session.c b/dlls/mf/session.c index b2371763150..bee10cad746 100644 --- a/dlls/mf/session.c +++ b/dlls/mf/session.c @@ -2524,6 +2524,13 @@ static HRESULT WINAPI session_commands_callback_Invoke(IMFAsyncCallback *iface,
EnterCriticalSection(&session->cs);
+ if ((session->presentation.flags & SESSION_FLAG_END_OF_PRESENTATION) && op->command != SESSION_CMD_STOP) + { + WARN("session %p command is ending, waiting for it to complete.\n", session); + LeaveCriticalSection(&session->cs); + return S_OK; + } + if (session->presentation.flags & SESSION_FLAG_PENDING_COMMAND) { WARN("session %p command is in progress, waiting for it to complete.\n", session); @@ -2550,6 +2557,9 @@ static HRESULT WINAPI session_commands_callback_Invoke(IMFAsyncCallback *iface, session_pause(session); break; case SESSION_CMD_STOP: + if (session->presentation.flags & SESSION_FLAG_END_OF_PRESENTATION) + session_set_topo_status(session, S_OK, MF_TOPOSTATUS_ENDED); + session_clear_end_of_presentation(session); session_stop(session); break; case SESSION_CMD_CLOSE: @@ -3521,7 +3531,7 @@ static void session_raise_end_of_presentation(struct media_session *session) { if (session_nodes_is_mask_set(session, MF_TOPOLOGY_MAX, SOURCE_FLAG_END_OF_PRESENTATION)) { - session->presentation.flags |= SESSION_FLAG_END_OF_PRESENTATION | SESSION_FLAG_PENDING_COMMAND; + session->presentation.flags |= SESSION_FLAG_END_OF_PRESENTATION; IMFMediaEventQueue_QueueEventParamVar(session->event_queue, MEEndOfPresentation, &GUID_NULL, S_OK, NULL); } } diff --git a/dlls/mf/tests/mf.c b/dlls/mf/tests/mf.c index 76311029bcf..65dc407eecc 100644 --- a/dlls/mf/tests/mf.c +++ b/dlls/mf/tests/mf.c @@ -2624,7 +2624,6 @@ static void test_media_session_events(void) ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); } ok(IsEqualGUID(&guid, &GUID_NULL), "got guid %s\n", debugstr_guid(&guid)); - todo_wine ok(event_type == MESessionStopped, "got type %lu\n", event_type); ok(propvar.vt == VT_EMPTY, "got vt %u\n", propvar.vt);