From: Torge Matthies openglfreak@googlemail.com
--- dlls/mf/session.c | 84 +++++++++++++++++++++++++++++++---------------- 1 file changed, 55 insertions(+), 29 deletions(-)
diff --git a/dlls/mf/session.c b/dlls/mf/session.c index e0ea5f911bf..11d6282aa26 100644 --- a/dlls/mf/session.c +++ b/dlls/mf/session.c @@ -219,6 +219,7 @@ enum presentation_flags SESSION_FLAG_END_OF_PRESENTATION = 0x10, SESSION_FLAG_PENDING_RATE_CHANGE = 0x20, SESSION_FLAG_PENDING_COMMAND = 0x40, + SESSION_FLAG_QUEUED_COMMAND = 0x80, };
struct media_session @@ -454,6 +455,33 @@ static HRESULT session_is_shut_down(struct media_session *session) return session->state == SESSION_STATE_SHUT_DOWN ? MF_E_SHUTDOWN : S_OK; }
+static void session_schedule_command(struct media_session *session) +{ + struct session_op *op; + struct list *e; + + if (session->presentation.flags & (SESSION_FLAG_PENDING_COMMAND | SESSION_FLAG_QUEUED_COMMAND)) + { + TRACE("not queueing: flags %x\n", session->presentation.flags); + return; + } + + if (session->state != SESSION_STATE_STOPPED && session->state != SESSION_STATE_STARTED && + session->state != SESSION_STATE_PAUSED && session->state != SESSION_STATE_CLOSED && + session->state != SESSION_STATE_SHUT_DOWN) + { + TRACE("not queueing: state %x\n", session->state); + return; + } + + if ((e = list_head(&session->commands))) + { + op = LIST_ENTRY(e, struct session_op, entry); + MFPutWorkItem(MFASYNC_CALLBACK_QUEUE_STANDARD, &session->commands_callback, &op->IUnknown_iface); + session->presentation.flags |= SESSION_FLAG_QUEUED_COMMAND; + } +} + static HRESULT session_submit_command(struct media_session *session, struct session_op *op) { HRESULT hr; @@ -463,13 +491,12 @@ static HRESULT session_submit_command(struct media_session *session, struct sess EnterCriticalSection(&session->cs); if (SUCCEEDED(hr = session_is_shut_down(session))) { - if (list_empty(&session->commands) && !(session->presentation.flags & SESSION_FLAG_PENDING_COMMAND)) - hr = MFPutWorkItem(MFASYNC_CALLBACK_QUEUE_STANDARD, &session->commands_callback, &op->IUnknown_iface); if (op->command == SESSION_CMD_SHUTDOWN) list_add_head(&session->commands, &op->entry); else list_add_tail(&session->commands, &op->entry); IUnknown_AddRef(&op->IUnknown_iface); + session_schedule_command(session); } LeaveCriticalSection(&session->cs);
@@ -946,17 +973,9 @@ static struct topo_node *session_get_topo_node_output(const struct media_session
static void session_command_complete(struct media_session *session) { - struct session_op *op; - struct list *e; - - session->presentation.flags &= ~SESSION_FLAG_PENDING_COMMAND; - + session->presentation.flags &= ~(SESSION_FLAG_PENDING_COMMAND | SESSION_FLAG_QUEUED_COMMAND); /* Submit next command. */ - if ((e = list_head(&session->commands))) - { - op = LIST_ENTRY(e, struct session_op, entry); - MFPutWorkItem(MFASYNC_CALLBACK_QUEUE_STANDARD, &session->commands_callback, &op->IUnknown_iface); - } + session_schedule_command(session); }
static void session_command_complete_with_event(struct media_session *session, MediaEventType event, @@ -1001,6 +1020,13 @@ static void session_flush_nodes(struct media_session *session) } }
+static void session_set_state(struct media_session *session, enum session_state new_state) +{ + TRACE("setting state to %d\n", new_state); + session->state = new_state; + session_schedule_command(session); +} + static void session_start(struct media_session *session, const GUID *time_format, const PROPVARIANT *start_position) { struct media_source *source; @@ -1055,7 +1081,7 @@ static void session_start(struct media_session *session, const GUID *time_format } }
- session->state = SESSION_STATE_STARTING_SOURCES; + session_set_state(session, SESSION_STATE_STARTING_SOURCES); break; case SESSION_STATE_STARTED: /* Check for invalid positions */ @@ -1087,7 +1113,7 @@ static void session_start(struct media_session *session, const GUID *time_format PropVariantCopy(&session->presentation.start_position, start_position);
/* SESSION_STATE_STARTED -> SESSION_STATE_RESTARTING_SOURCES -> SESSION_STATE_STARTED */ - session->state = SESSION_STATE_RESTARTING_SOURCES; + session_set_state(session, SESSION_STATE_RESTARTING_SOURCES); break; default: session_command_complete_with_event(session, MESessionStarted, MF_E_INVALIDREQUEST, NULL); @@ -1102,7 +1128,7 @@ static void session_set_started(struct media_session *session) unsigned int caps; DWORD flags;
- session->state = SESSION_STATE_STARTED; + session_set_state(session, SESSION_STATE_STARTED);
caps = session->caps | MFSESSIONCAP_PAUSE;
@@ -1134,7 +1160,7 @@ static void session_set_paused(struct media_session *session, unsigned int state /* 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; + if (state != ~0u) session_set_state(session, state); if (SUCCEEDED(status)) session_set_caps(session, session->caps & ~MFSESSIONCAP_PAUSE); session_command_complete_with_event(session, MESessionPaused, status, NULL); @@ -1142,7 +1168,7 @@ static void session_set_paused(struct media_session *session, unsigned int state
static void session_set_closed(struct media_session *session, HRESULT status) { - session->state = SESSION_STATE_CLOSED; + session_set_state(session, SESSION_STATE_CLOSED); if (SUCCEEDED(status)) session_set_caps(session, session->caps & ~(MFSESSIONCAP_START | MFSESSIONCAP_SEEK)); session_command_complete_with_event(session, MESessionClosed, status, NULL); @@ -1159,7 +1185,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_set_state(session, SESSION_STATE_PAUSING_SINKS); state = SESSION_STATE_PAUSED;
break; @@ -1197,7 +1223,7 @@ static void session_set_stopped(struct media_session *session, HRESULT status) MediaEventType event_type; IMFMediaEvent *event;
- session->state = SESSION_STATE_STOPPED; + session_set_state(session, SESSION_STATE_STOPPED); event_type = session->presentation.flags & SESSION_FLAG_END_OF_PRESENTATION ? MESessionEnded : MESessionStopped;
if (SUCCEEDED(MFCreateMediaEvent(event_type, &GUID_NULL, status, NULL, &event))) @@ -1217,7 +1243,7 @@ static void session_do_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_set_state(session, SESSION_STATE_STOPPING_SINKS); else session_set_stopped(session, hr); } @@ -1249,7 +1275,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_set_state(session, SESSION_STATE_FINALIZING_SINKS);
LIST_FOR_EACH_ENTRY(sink, &session->presentation.sinks, struct media_sink, entry) { @@ -1286,7 +1312,7 @@ 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_set_state(session, SESSION_STATE_STOPPING_SINKS); break; default: hr = MF_E_INVALIDREQUEST; @@ -2395,7 +2421,7 @@ static HRESULT WINAPI mfsession_Shutdown(IMFMediaSession *iface) EnterCriticalSection(&session->cs); if (SUCCEEDED(hr = session_is_shut_down(session))) { - session->state = SESSION_STATE_SHUT_DOWN; + session_set_state(session, SESSION_STATE_SHUT_DOWN); IMFMediaEventQueue_Shutdown(session->event_queue); if (session->quality_manager) IMFQualityManager_Shutdown(session->quality_manager); @@ -3107,10 +3133,10 @@ static void session_set_source_object_state(struct media_session *session, IUnkn } } } - session->state = SESSION_STATE_PREROLLING_SINKS; + session_set_state(session, SESSION_STATE_PREROLLING_SINKS); } else if (SUCCEEDED(session_start_clock(session))) - session->state = SESSION_STATE_STARTING_SINKS; + session_set_state(session, SESSION_STATE_STARTING_SINKS);
break; case SESSION_STATE_RESTARTING_SOURCES: @@ -3131,7 +3157,7 @@ static void session_set_source_object_state(struct media_session *session, IUnkn return; } } - session->state = SESSION_STATE_STARTING_SOURCES; + session_set_state(session, SESSION_STATE_STARTING_SOURCES); break; case SESSION_STATE_PAUSING_SOURCES: if (!session_is_source_nodes_state(session, OBJ_STATE_PAUSED)) @@ -3178,7 +3204,7 @@ static void session_set_sink_stream_state(struct media_session *session, IMFStre break;
if (SUCCEEDED(session_start_clock(session))) - session->state = SESSION_STATE_STARTING_SINKS; + session_set_state(session, SESSION_STATE_STARTING_SINKS); break; case SESSION_STATE_STARTING_SINKS: if (!session_is_output_nodes_state(session, OBJ_STATE_STARTED)) @@ -3190,7 +3216,7 @@ static void session_set_sink_stream_state(struct media_session *session, IMFStre if (!session_is_output_nodes_state(session, OBJ_STATE_PAUSED)) break;
- session->state = SESSION_STATE_PAUSING_SOURCES; + session_set_state(session, SESSION_STATE_PAUSING_SOURCES);
LIST_FOR_EACH_ENTRY(source, &session->presentation.sources, struct media_source, entry) { @@ -3206,7 +3232,7 @@ static void session_set_sink_stream_state(struct media_session *session, IMFStre if (!session_is_output_nodes_state(session, OBJ_STATE_STOPPED)) break;
- session->state = SESSION_STATE_STOPPING_SOURCES; + session_set_state(session, SESSION_STATE_STOPPING_SOURCES);
LIST_FOR_EACH_ENTRY(source, &session->presentation.sources, struct media_source, entry) {