This should fix some spurious test failure in `test_media_session_Close`, as sometimes the source shutdown happens quickly enough and changes the session state to SESSION_STATE_STOPPED, causing the later Close command to succeed when it consistently returns E_SHUTDOWN on Windows.
From: Rémi Bernon rbernon@codeweavers.com
Until the topology is set again. --- dlls/mf/session.c | 27 +++++++++++++++++++++------ 1 file changed, 21 insertions(+), 6 deletions(-)
diff --git a/dlls/mf/session.c b/dlls/mf/session.c index 47760cc44a7..e6f37146221 100644 --- a/dlls/mf/session.c +++ b/dlls/mf/session.c @@ -103,6 +103,7 @@ enum session_state SESSION_STATE_STOPPING_SINKS, SESSION_STATE_STOPPING_SOURCES, SESSION_STATE_FINALIZING_SINKS, + SESSION_STATE_SOURCE_SHUTDOWN, SESSION_STATE_CLOSED, SESSION_STATE_SHUT_DOWN, }; @@ -1051,7 +1052,7 @@ static void session_reset(struct media_session *session) { /* Media sessions in native Windows are not consistently usable after a * forced source shutdown, but we try to clean up as well as possible. */ - session->state = SESSION_STATE_STOPPED; + session->state = SESSION_STATE_SOURCE_SHUTDOWN; session_clear_presentation(session); session_purge_pending_commands(session); session_command_complete(session); @@ -1061,7 +1062,7 @@ static void session_handle_start_error(struct media_session *session, HRESULT hr { if (hr == MF_E_SHUTDOWN) { - session_reset(session); + session_source_shutdown(session); hr = MF_E_INVALIDREQUEST; } session_command_complete_with_event(session, MESessionStarted, hr, NULL); @@ -1155,6 +1156,9 @@ static void session_start(struct media_session *session, const GUID *time_format /* SESSION_STATE_STARTED -> SESSION_STATE_RESTARTING_SOURCES -> SESSION_STATE_STARTED */ session->state = SESSION_STATE_RESTARTING_SOURCES; break; + case SESSION_STATE_SOURCE_SHUTDOWN: + session_command_complete_with_event(session, MESessionStarted, MF_E_SHUTDOWN, NULL); + break; default: session_command_complete_with_event(session, MESessionStarted, MF_E_INVALIDREQUEST, NULL); break; @@ -1233,6 +1237,9 @@ static void session_pause(struct media_session *session) case SESSION_STATE_STOPPED: hr = MF_E_SESSION_PAUSEWHILESTOPPED; break; + case SESSION_STATE_SOURCE_SHUTDOWN: + hr = MF_E_SHUTDOWN; + break; default: hr = MF_E_INVALIDREQUEST; } @@ -1294,10 +1301,13 @@ static void session_stop(struct media_session *session)
break; case SESSION_STATE_STOPPED: - hr = S_OK; - /* fallthrough */ + session_command_complete_with_event(session, MESessionStopped, S_OK, NULL); + break; + case SESSION_STATE_SOURCE_SHUTDOWN: + session_command_complete_with_event(session, MESessionStopped, MF_E_SHUTDOWN, NULL); + break; default: - session_command_complete_with_event(session, MESessionStopped, hr, NULL); + session_command_complete_with_event(session, MESessionStopped, MF_E_INVALIDREQUEST, NULL); break; } } @@ -1349,6 +1359,9 @@ static void session_close(struct media_session *session) if (SUCCEEDED(hr = IMFPresentationClock_Stop(session->clock))) session->state = SESSION_STATE_STOPPING_SINKS; break; + case SESSION_STATE_SOURCE_SHUTDOWN: + hr = MF_E_SHUTDOWN; + break; default: hr = MF_E_INVALIDREQUEST; break; @@ -2012,6 +2025,8 @@ static HRESULT session_set_current_topology(struct media_session *session, IMFTo }
session->source_shutdown_handled = FALSE; + if (session->state == SESSION_STATE_SOURCE_SHUTDOWN) + session->state = SESSION_STATE_STOPPED;
session_collect_nodes(session);
@@ -2960,7 +2975,7 @@ static void session_handle_source_shutdown(struct media_session *session) if (finalize_sinks) session_finalize_sinks(session); else - session_reset(session); + session_source_shutdown(session); }
LeaveCriticalSection(&session->cs);
From: Rémi Bernon rbernon@codeweavers.com
--- dlls/mf/session.c | 25 +------------------------ 1 file changed, 1 insertion(+), 24 deletions(-)
diff --git a/dlls/mf/session.c b/dlls/mf/session.c index e6f37146221..0645313c79c 100644 --- a/dlls/mf/session.c +++ b/dlls/mf/session.c @@ -1026,35 +1026,12 @@ static void session_flush_nodes(struct media_session *session) } }
-static void session_purge_pending_commands(struct media_session *session) -{ - struct session_op *op, *op2; - - /* Purge all commands which are no longer valid after a forced source shutdown. - * Calling Stop() in this case is not required in native Windows. */ - LIST_FOR_EACH_ENTRY_SAFE(op, op2, &session->commands, struct session_op, entry) - { - if (op->command == SESSION_CMD_SET_TOPOLOGY) - break; - if (op->command == SESSION_CMD_CLEAR_TOPOLOGIES || op->command == SESSION_CMD_CLOSE - || op->command == SESSION_CMD_SHUTDOWN) - continue; - /* Once a command is submitted, the callback becomes responsible - * for removal from the list and release of the ref. */ - if (op->submitted) - continue; - list_remove(&op->entry); - IUnknown_Release(&op->IUnknown_iface); - } -} - -static void session_reset(struct media_session *session) +static void session_source_shutdown(struct media_session *session) { /* Media sessions in native Windows are not consistently usable after a * forced source shutdown, but we try to clean up as well as possible. */ session->state = SESSION_STATE_SOURCE_SHUTDOWN; session_clear_presentation(session); - session_purge_pending_commands(session); session_command_complete(session); }