From: Zhiyi Zhang zzhang@codeweavers.com
--- dlls/mf/session.c | 57 ++++++++++++++++++++++++++++++++++++++++++----- 1 file changed, 51 insertions(+), 6 deletions(-)
diff --git a/dlls/mf/session.c b/dlls/mf/session.c index 8fe3260e9f0..7a628801310 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, };
@@ -889,9 +890,27 @@ static HRESULT session_subscribe_sources(struct media_session *session) return hr; }
+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) @@ -907,6 +926,13 @@ static void session_start(struct media_session *session, const GUID *time_format
/* fallthrough */ case SESSION_STATE_PAUSED: + case SESSION_STATE_STARTED: + if (session->state == SESSION_STATE_STARTED && !(session->caps & MFSESSIONCAP_SEEK)) + { + WARN("Seeking is not supported for this session.\n"); + session_command_complete(session); + return; + }
session->presentation.time_format = *time_format; session->presentation.start_position.vt = VT_EMPTY; @@ -920,6 +946,14 @@ static void session_start(struct media_session *session, const GUID *time_format
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) && 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, &GUID_NULL, start_position))) { WARN("Failed to start media source %p, hr %#lx.\n", source->source, hr); @@ -928,12 +962,22 @@ static void session_start(struct media_session *session, const GUID *time_format } }
+ if (session->state == SESSION_STATE_STARTED) + { + struct topo_node *node; + + LIST_FOR_EACH_ENTRY(node, &session->presentation.nodes, struct topo_node, entry) + { + if (node->type == MF_TOPOLOGY_OUTPUT_NODE) + IMFStreamSink_Flush(node->object.sink_stream); + else if (node->type == MF_TOPOLOGY_TRANSFORM_NODE) + IMFTransform_ProcessMessage(node->object.transform, MFT_MESSAGE_COMMAND_FLUSH, 0); + } + + 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; @@ -2167,6 +2211,9 @@ static HRESULT WINAPI mfsession_Start(IMFMediaSession *iface, const GUID *format if (!start_position) return E_POINTER;
+ if (FAILED(hr = session_is_shut_down(session))) + return hr; + if (FAILED(hr = create_session_op(SESSION_CMD_START, &op))) return hr;
@@ -3659,8 +3706,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: