From: Rémi Bernon rbernon@codeweavers.com
--- dlls/mf/session.c | 124 ++++++++++++++++++++++++---------------------- 1 file changed, 66 insertions(+), 58 deletions(-)
diff --git a/dlls/mf/session.c b/dlls/mf/session.c index bff858854ca..dc7fe9c9b93 100644 --- a/dlls/mf/session.c +++ b/dlls/mf/session.c @@ -97,20 +97,24 @@ enum session_state SESSION_STATE_PAUSED, SESSION_STATE_CLOSED, SESSION_STATE_SHUT_DOWN, +};
+enum command_state +{ + COMMAND_STATE_COMPLETE = 0, /* STOPPED | PAUSED | STARTED -> STARTED transition */ - SESSION_STATE_RESTARTING_SOURCES, /* -> SESSION_STATE_STARTING_SOURCES */ - SESSION_STATE_STARTING_SOURCES, /* -> SESSION_STATE_PREROLLING_SINKS | SESSION_STATE_STARTING_SINKS */ - SESSION_STATE_PREROLLING_SINKS, /* -> SESSION_STATE_STARTING_SINKS */ - SESSION_STATE_STARTING_SINKS, /* -> SESSION_STATE_STARTED */ + COMMAND_STATE_RESTARTING_SOURCES, /* -> COMMAND_STATE_STARTING_SOURCES */ + COMMAND_STATE_STARTING_SOURCES, /* -> COMMAND_STATE_PREROLLING_SINKS | COMMAND_STATE_STARTING_SINKS */ + COMMAND_STATE_PREROLLING_SINKS, /* -> COMMAND_STATE_STARTING_SINKS */ + COMMAND_STATE_STARTING_SINKS, /* -> SESSION_STATE_STARTED */ /* STARTED -> PAUSED transition */ - SESSION_STATE_PAUSING_SINKS, /* -> SESSION_STATE_PAUSING_SOURCES */ - SESSION_STATE_PAUSING_SOURCES, /* -> SESSION_STATE_PAUSED */ + COMMAND_STATE_PAUSING_SINKS, /* -> COMMAND_STATE_PAUSING_SOURCES */ + COMMAND_STATE_PAUSING_SOURCES, /* -> SESSION_STATE_PAUSED */ /* STARTED | PAUSED -> STOPPED transition */ - SESSION_STATE_STOPPING_SINKS, /* -> SESSION_STATE_STOPPING_SOURCES */ - SESSION_STATE_STOPPING_SOURCES, /* -> SESSION_STATE_STOPPED */ + COMMAND_STATE_STOPPING_SINKS, /* -> COMMAND_STATE_STOPPING_SOURCES */ + COMMAND_STATE_STOPPING_SOURCES, /* -> SESSION_STATE_STOPPED */ /* STARTED | PAUSED | STOPPED -> CLOSED transition */ - SESSION_STATE_FINALIZING_SINKS, + COMMAND_STATE_FINALIZING_SINKS, /* -> SESSION_STATE_CLOSED */ };
enum object_state @@ -270,6 +274,7 @@ struct media_session struct list topologies; struct list commands; enum session_state state; + enum command_state command_state; DWORD caps; CRITICAL_SECTION cs; }; @@ -972,6 +977,7 @@ static void session_command_complete(struct media_session *session) struct list *e; HRESULT hr;
+ session->command_state = COMMAND_STATE_COMPLETE; session->presentation.flags &= ~SESSION_FLAG_PENDING_COMMAND;
/* Submit next command. */ @@ -1127,7 +1133,7 @@ static void session_start(struct media_session *session, const GUID *time_format } }
- session->state = SESSION_STATE_STARTING_SOURCES; + session->command_state = COMMAND_STATE_STARTING_SOURCES; break; case SESSION_STATE_STARTED: /* Check for invalid positions */ @@ -1158,15 +1164,12 @@ static void session_start(struct media_session *session, const GUID *time_format session->presentation.start_position.vt = VT_EMPTY; PropVariantCopy(&session->presentation.start_position, start_position);
- session->state = SESSION_STATE_RESTARTING_SOURCES; + session->command_state = COMMAND_STATE_RESTARTING_SOURCES; break; case SESSION_STATE_CLOSED: case SESSION_STATE_SHUT_DOWN: session_command_complete_with_event(session, MESessionStarted, MF_E_INVALIDREQUEST, NULL); break; - default: - assert(0); - break; } }
@@ -1234,7 +1237,7 @@ static void session_pause(struct media_session *session)
/* Transition in two steps - pause the clock, wait for sinks, then pause sources. */ if (SUCCEEDED(hr = IMFPresentationClock_Pause(session->clock))) - session->state = SESSION_STATE_PAUSING_SINKS; + session->command_state = COMMAND_STATE_PAUSING_SINKS; state = SESSION_STATE_PAUSED;
break; @@ -1247,9 +1250,6 @@ static void session_pause(struct media_session *session) case SESSION_STATE_SHUT_DOWN: hr = MF_E_INVALIDREQUEST; break; - default: - assert(0); - break; }
if (FAILED(hr)) @@ -1303,7 +1303,7 @@ static void session_stop(struct media_session *session) /* Transition in two steps - stop the clock, wait for sinks, then stop sources. */ IMFPresentationClock_GetTime(session->clock, &session->presentation.clock_stop_time); if (SUCCEEDED(hr = IMFPresentationClock_Stop(session->clock))) - session->state = SESSION_STATE_STOPPING_SINKS; + session->command_state = COMMAND_STATE_STOPPING_SINKS; else session_set_stopped(session, hr);
@@ -1315,9 +1315,6 @@ static void session_stop(struct media_session *session) case SESSION_STATE_SHUT_DOWN: session_command_complete_with_event(session, MESessionStopped, hr, NULL); break; - default: - assert(0); - break; } }
@@ -1329,7 +1326,7 @@ static HRESULT session_finalize_sinks(struct media_session *session) HRESULT hr = S_OK;
session->presentation.flags &= ~SESSION_FLAG_FINALIZE_SINKS; - session->state = SESSION_STATE_FINALIZING_SINKS; + session->command_state = COMMAND_STATE_FINALIZING_SINKS;
LIST_FOR_EACH_ENTRY(sink, &session->presentation.sinks, struct media_sink, entry) { @@ -1365,15 +1362,12 @@ static void session_close(struct media_session *session) case SESSION_STATE_PAUSED: session->presentation.flags |= SESSION_FLAG_FINALIZE_SINKS; if (SUCCEEDED(hr = IMFPresentationClock_Stop(session->clock))) - session->state = SESSION_STATE_STOPPING_SINKS; + session->command_state = COMMAND_STATE_STOPPING_SINKS; break; case SESSION_STATE_CLOSED: case SESSION_STATE_SHUT_DOWN: hr = MF_E_INVALIDREQUEST; break; - default: - assert(0); - break; }
session_clear_queued_topologies(session); @@ -2825,8 +2819,6 @@ static HRESULT WINAPI session_commands_callback_Invoke(IMFAsyncCallback *iface, LeaveCriticalSection(&session->cs); return S_OK; } - assert( session->state <= SESSION_STATE_SHUT_DOWN ); - list_remove(&op->entry); session->presentation.flags |= SESSION_FLAG_PENDING_COMMAND;
@@ -2959,26 +2951,30 @@ static void session_handle_source_shutdown(struct media_session *session)
/* When stopping the session, MESessionStopped is sent without waiting * for MESourceStopped, so we need do nothing in that case. */ - switch (session->state) + switch (session->command_state) { - case SESSION_STATE_STARTING_SOURCES: - case SESSION_STATE_RESTARTING_SOURCES: - case SESSION_STATE_PREROLLING_SINKS: - case SESSION_STATE_STARTING_SINKS: + case COMMAND_STATE_STARTING_SOURCES: + case COMMAND_STATE_RESTARTING_SOURCES: + case COMMAND_STATE_PREROLLING_SINKS: + case COMMAND_STATE_STARTING_SINKS: IMFMediaEventQueue_QueueEventParamVar(session->event_queue, MESessionStarted, &GUID_NULL, MF_E_INVALIDREQUEST, NULL); break; - case SESSION_STATE_STOPPING_SINKS: - case SESSION_STATE_STOPPING_SOURCES: + case COMMAND_STATE_STOPPING_SINKS: + case COMMAND_STATE_STOPPING_SOURCES: if (!finalize_sinks) IMFMediaEventQueue_QueueEventParamVar(session->event_queue, MESessionStopped, &GUID_NULL, MF_E_INVALIDREQUEST, NULL); break; - default: + case COMMAND_STATE_PAUSING_SINKS: + case COMMAND_STATE_PAUSING_SOURCES: + case COMMAND_STATE_FINALIZING_SINKS: + case COMMAND_STATE_COMPLETE: + WARN("Ignoring source shutdown in command state %#x\n", session->command_state); break; }
- if (session->state != SESSION_STATE_CLOSED) + if (session->state != SESSION_STATE_CLOSED || session->command_state != COMMAND_STATE_COMPLETE) { if (finalize_sinks) session_finalize_sinks(session); @@ -3264,9 +3260,9 @@ static void session_set_source_object_state(struct media_session *session, IUnkn if (!changed) return;
- switch (session->state) + switch (session->command_state) { - case SESSION_STATE_STARTING_SOURCES: + case COMMAND_STATE_STARTING_SOURCES: if (!session_is_source_nodes_state(session, OBJ_STATE_STARTED)) break;
@@ -3315,13 +3311,13 @@ static void session_set_source_object_state(struct media_session *session, IUnkn } } } - session->state = SESSION_STATE_PREROLLING_SINKS; + session->command_state = COMMAND_STATE_PREROLLING_SINKS; } else if (SUCCEEDED(session_start_clock(session))) - session->state = SESSION_STATE_STARTING_SINKS; + session->command_state = COMMAND_STATE_STARTING_SINKS;
break; - case SESSION_STATE_RESTARTING_SOURCES: + case COMMAND_STATE_RESTARTING_SOURCES: if (!session_is_source_nodes_state(session, OBJ_STATE_STOPPED)) break;
@@ -3339,15 +3335,15 @@ static void session_set_source_object_state(struct media_session *session, IUnkn return; } } - session->state = SESSION_STATE_STARTING_SOURCES; + session->command_state = COMMAND_STATE_STARTING_SOURCES; break; - case SESSION_STATE_PAUSING_SOURCES: + case COMMAND_STATE_PAUSING_SOURCES: if (!session_is_source_nodes_state(session, OBJ_STATE_PAUSED)) break;
session_set_paused(session, SESSION_STATE_PAUSED, S_OK); break; - case SESSION_STATE_STOPPING_SOURCES: + case COMMAND_STATE_STOPPING_SOURCES: if (!session_is_source_nodes_state(session, OBJ_STATE_STOPPED)) break;
@@ -3360,8 +3356,14 @@ static void session_set_source_object_state(struct media_session *session, IUnkn session_set_stopped(session, S_OK);
break; - default: - ; + case COMMAND_STATE_COMPLETE: + case COMMAND_STATE_PREROLLING_SINKS: + case COMMAND_STATE_STARTING_SINKS: + case COMMAND_STATE_PAUSING_SINKS: + case COMMAND_STATE_STOPPING_SINKS: + case COMMAND_STATE_FINALIZING_SINKS: + WARN("Ignoring source state change in command state %#x\n", session->command_state); + break; } }
@@ -3379,26 +3381,26 @@ static void session_set_sink_stream_state(struct media_session *session, IMFStre if (!(changed = session_set_node_object_state(session, (IUnknown *)stream, MF_TOPOLOGY_OUTPUT_NODE, state))) return;
- switch (session->state) + switch (session->command_state) { - case SESSION_STATE_PREROLLING_SINKS: + case COMMAND_STATE_PREROLLING_SINKS: if (!session_is_output_nodes_state(session, OBJ_STATE_PREROLLED)) break;
if (SUCCEEDED(session_start_clock(session))) - session->state = SESSION_STATE_STARTING_SINKS; + session->command_state = COMMAND_STATE_STARTING_SINKS; break; - case SESSION_STATE_STARTING_SINKS: + case COMMAND_STATE_STARTING_SINKS: if (!session_is_output_nodes_state(session, OBJ_STATE_STARTED)) break;
session_set_started(session); break; - case SESSION_STATE_PAUSING_SINKS: + case COMMAND_STATE_PAUSING_SINKS: if (!session_is_output_nodes_state(session, OBJ_STATE_PAUSED)) break;
- session->state = SESSION_STATE_PAUSING_SOURCES; + session->command_state = COMMAND_STATE_PAUSING_SOURCES;
LIST_FOR_EACH_ENTRY(source, &session->presentation.sources, struct media_source, entry) { @@ -3410,11 +3412,11 @@ static void session_set_sink_stream_state(struct media_session *session, IMFStre session_set_paused(session, SESSION_STATE_PAUSED, hr);
break; - case SESSION_STATE_STOPPING_SINKS: + case COMMAND_STATE_STOPPING_SINKS: if (!session_is_output_nodes_state(session, OBJ_STATE_STOPPED)) break;
- session->state = SESSION_STATE_STOPPING_SOURCES; + session->command_state = COMMAND_STATE_STOPPING_SOURCES;
LIST_FOR_EACH_ENTRY(source, &session->presentation.sources, struct media_source, entry) { @@ -3435,8 +3437,14 @@ static void session_set_sink_stream_state(struct media_session *session, IMFStre }
break; - default: - ; + case COMMAND_STATE_COMPLETE: + case COMMAND_STATE_RESTARTING_SOURCES: + case COMMAND_STATE_STARTING_SOURCES: + case COMMAND_STATE_PAUSING_SOURCES: + case COMMAND_STATE_STOPPING_SOURCES: + case COMMAND_STATE_FINALIZING_SINKS: + WARN("Ignoring sink state change in command state %#x\n", session->command_state); + break; } }