From: Rémi Bernon rbernon@codeweavers.com
--- dlls/mf/session.c | 147 ++++++++++++++++++++++++---------------------- 1 file changed, 76 insertions(+), 71 deletions(-)
diff --git a/dlls/mf/session.c b/dlls/mf/session.c index bff858854ca..e864dab7336 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; } }
@@ -1204,12 +1207,12 @@ static void session_set_started(struct media_session *session) session_command_complete(session); }
-static void session_set_paused(struct media_session *session, unsigned int state, HRESULT status) +static void session_set_paused(struct media_session *session, HRESULT status) { /* Failed event status could indicate a failure during normal transition to paused state, or an attempt to pause from invalid initial state. To finalize failed transition in the former case, state is still forced to PAUSED, otherwise previous state is retained. */ - if (state != ~0u) session->state = state; + session->state = SESSION_STATE_PAUSED; if (SUCCEEDED(status)) session_set_caps(session, session->caps & ~MFSESSIONCAP_PAUSE); session_command_complete_with_event(session, MESessionPaused, status, NULL); @@ -1225,7 +1228,6 @@ static void session_set_closed(struct media_session *session, HRESULT status)
static void session_pause(struct media_session *session) { - unsigned int state = ~0u; HRESULT hr;
switch (session->state) @@ -1233,27 +1235,22 @@ static void session_pause(struct media_session *session) case SESSION_STATE_STARTED:
/* 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; - state = SESSION_STATE_PAUSED; + session->command_state = COMMAND_STATE_PAUSING_SINKS; + hr = IMFPresentationClock_Pause(session->clock);
- break; + if (FAILED(hr)) + session_set_paused(session, hr);
+ break; case SESSION_STATE_STOPPED: - hr = MF_E_SESSION_PAUSEWHILESTOPPED; + session_command_complete_with_event(session, MESessionPaused, MF_E_SESSION_PAUSEWHILESTOPPED, NULL); break; case SESSION_STATE_PAUSED: case SESSION_STATE_CLOSED: case SESSION_STATE_SHUT_DOWN: - hr = MF_E_INVALIDREQUEST; - break; - default: - assert(0); + session_command_complete_with_event(session, MESessionPaused, MF_E_INVALIDREQUEST, NULL); break; } - - if (FAILED(hr)) - session_set_paused(session, state, hr); }
static void session_clear_end_of_presentation(struct media_session *session) @@ -1303,7 +1300,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 +1312,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 +1323,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 +1359,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 +2816,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 +2948,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 +3257,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 +3308,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 +3332,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); + session_set_paused(session, 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 +3353,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 +3378,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) { @@ -3407,14 +3406,14 @@ static void session_set_sink_stream_state(struct media_session *session, IMFStre }
if (FAILED(hr)) - session_set_paused(session, SESSION_STATE_PAUSED, hr); + session_set_paused(session, 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 +3434,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; } }