From: Zhiyi Zhang zzhang@codeweavers.com
--- dlls/mf/session.c | 49 +++++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 47 insertions(+), 2 deletions(-)
diff --git a/dlls/mf/session.c b/dlls/mf/session.c index ca5e367ec44..42459d1cc5c 100644 --- a/dlls/mf/session.c +++ b/dlls/mf/session.c @@ -91,6 +91,7 @@ enum session_state { SESSION_STATE_STOPPED = 0, SESSION_STATE_STARTING_SOURCES, + SESSION_STATE_SEEKING_SOURCES, SESSION_STATE_PREROLLING_SINKS, SESSION_STATE_STARTING_SINKS, SESSION_STATE_STARTED, @@ -110,6 +111,7 @@ enum object_state OBJ_STATE_STARTED, OBJ_STATE_PAUSED, OBJ_STATE_PREROLLED, + OBJ_STATE_SEEKING, OBJ_STATE_INVALID, };
@@ -929,6 +931,7 @@ static void session_start(struct media_session *session, const GUID *time_format { struct media_source *source; struct topo_node *topo_node; + MFTIME duration; HRESULT hr; UINT i;
@@ -981,8 +984,42 @@ static void session_start(struct media_session *session, const GUID *time_format session->state = SESSION_STATE_STARTING_SOURCES; break; case SESSION_STATE_STARTED: - FIXME("Seeking is not implemented.\n"); - session_command_complete(session); + session->presentation.time_format = *time_format; + session->presentation.start_position.vt = VT_EMPTY; + PropVariantCopy(&session->presentation.start_position, start_position); + + LIST_FOR_EACH_ENTRY(source, &session->presentation.sources, struct media_source, entry) + { + hr = IMFPresentationDescriptor_GetUINT64(source->pd, &MF_PD_DURATION, (UINT64 *)&duration); + if (SUCCEEDED(hr) && IsEqualGUID(time_format, &GUID_NULL) + && start_position->vt == VT_I8 && start_position->hVal.QuadPart > duration) + { + WARN("Start position %s out of range, hr %#lx.\n", wine_dbgstr_longlong(start_position->hVal.QuadPart), hr); + session_command_complete_with_event(session, MESessionStarted, MF_E_INVALID_POSITION, NULL); + return; + } + + if (FAILED(hr = IMFMediaSource_Stop(source->source))) + { + WARN("Failed to stop media source %p, hr %#lx.\n", source->source, hr); + session_command_complete_with_event(session, MESessionStarted, hr, NULL); + return; + } + + if (FAILED(hr = IMFMediaSource_Start(source->source, source->pd, &GUID_NULL, start_position))) + { + WARN("Failed to start media source %p, hr %#lx.\n", source->source, hr); + session_command_complete_with_event(session, MESessionStarted, hr, NULL); + return; + } + } + + session_flush_nodes(session); + LIST_FOR_EACH_ENTRY(source, &session->presentation.sources, struct media_source, entry) + { + source->state = OBJ_STATE_SEEKING; + } + session->state = SESSION_STATE_SEEKING_SOURCES; break; default: session_command_complete_with_event(session, MESessionStarted, MF_E_INVALIDREQUEST, NULL); @@ -2976,6 +3013,14 @@ static void session_set_source_object_state(struct media_session *session, IUnkn else if (SUCCEEDED(session_start_clock(session))) session->state = SESSION_STATE_STARTING_SINKS;
+ break; + case SESSION_STATE_SEEKING_SOURCES: + if (!session_is_source_nodes_state(session, OBJ_STATE_STARTED)) + break; + + if (SUCCEEDED(session_start_clock(session))) + session_set_started(session); + break; case SESSION_STATE_PAUSING_SOURCES: if (!session_is_source_nodes_state(session, OBJ_STATE_PAUSED))