From: Zhiyi Zhang zzhang@codeweavers.com
--- dlls/mf/session.c | 53 ++++++++++++++++++++++++++++++++++++++++------- 1 file changed, 45 insertions(+), 8 deletions(-)
diff --git a/dlls/mf/session.c b/dlls/mf/session.c index b9b77415f61..c48e11f5910 100644 --- a/dlls/mf/session.c +++ b/dlls/mf/session.c @@ -110,6 +110,7 @@ enum object_state OBJ_STATE_STARTED, OBJ_STATE_PAUSED, OBJ_STATE_PREROLLED, + OBJ_STATE_SEEKING, OBJ_STATE_INVALID, };
@@ -902,9 +903,27 @@ static void session_flush_nodes(struct media_session *session) } }
+static void session_set_source_output_nodes_seeking(struct media_session *session) +{ + struct media_source *source; + struct topo_node *node; + + LIST_FOR_EACH_ENTRY(source, &session->presentation.sources, struct media_source, entry) + { + source->state = OBJ_STATE_SEEKING; + } + + LIST_FOR_EACH_ENTRY(node, &session->presentation.nodes, struct topo_node, entry) + { + if (node->type == MF_TOPOLOGY_SOURCESTREAM_NODE || node->type == MF_TOPOLOGY_OUTPUT_NODE) + node->state = OBJ_STATE_SEEKING; + } +} + static void session_start(struct media_session *session, const GUID *time_format, const PROPVARIANT *start_position) { struct media_source *source; + MFTIME duration; HRESULT hr;
switch (session->state) @@ -920,7 +939,7 @@ static void session_start(struct media_session *session, const GUID *time_format
/* fallthrough */ case SESSION_STATE_PAUSED: - + case SESSION_STATE_STARTED: session->presentation.time_format = *time_format; session->presentation.start_position.vt = VT_EMPTY; PropVariantCopy(&session->presentation.start_position, start_position); @@ -931,9 +950,32 @@ static void session_start(struct media_session *session, const GUID *time_format return; }
+ if (session->state != SESSION_STATE_STOPPED) + { + LIST_FOR_EACH_ENTRY(source, &session->presentation.sources, struct media_source, entry) + { + 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; + } + } + } + session_flush_nodes(session); + LIST_FOR_EACH_ENTRY(source, &session->presentation.sources, struct media_source, entry) { - if (FAILED(hr = IMFMediaSource_Start(source->source, source->pd, &GUID_NULL, start_position))) + 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_Start(source->source, source->pd, time_format, start_position))) { WARN("Failed to start media source %p, hr %#lx.\n", source->source, hr); session_command_complete_with_event(session, MESessionStarted, hr, NULL); @@ -941,12 +983,9 @@ static void session_start(struct media_session *session, const GUID *time_format } }
+ session_set_source_output_nodes_seeking(session); session->state = SESSION_STATE_STARTING_SOURCES; break; - case SESSION_STATE_STARTED: - FIXME("Seeking is not implemented.\n"); - session_command_complete(session); - break; default: session_command_complete_with_event(session, MESessionStarted, MF_E_INVALIDREQUEST, NULL); break; @@ -3653,8 +3692,6 @@ static HRESULT WINAPI session_events_callback_Invoke(IMFAsyncCallback *iface, IM { case MESourceSeeked: case MEStreamSeeked: - FIXME("Source/stream seeking, semi-stub!\n"); - /* fallthrough */ case MESourceStarted: case MESourcePaused: case MESourceStopped: