[PATCH 04/14] mf: Create separate topology object and use it as current.
Nikolay Sivov
nsivov at codeweavers.com
Fri Feb 28 06:00:54 CST 2020
Signed-off-by: Nikolay Sivov <nsivov at codeweavers.com>
---
dlls/mf/session.c | 243 ++++++++++++++++++++++++----------------------
1 file changed, 125 insertions(+), 118 deletions(-)
diff --git a/dlls/mf/session.c b/dlls/mf/session.c
index 6da495e3c1..0963bcb06e 100644
--- a/dlls/mf/session.c
+++ b/dlls/mf/session.c
@@ -122,7 +122,8 @@ struct media_session
IMFQualityManager *quality_manager;
struct
{
- struct queued_topology current_topology;
+ IMFTopology *current_topology;
+ MF_TOPOSTATUS topo_status;
struct list sources;
struct list sinks;
} presentation;
@@ -446,7 +447,7 @@ static void session_clear_topologies(struct media_session *session)
}
}
-static void session_set_topo_status(struct media_session *session, struct queued_topology *topology, HRESULT status,
+static void session_set_topo_status(struct media_session *session, HRESULT status,
MF_TOPOSTATUS topo_status)
{
IMFMediaEvent *event;
@@ -455,20 +456,20 @@ static void session_set_topo_status(struct media_session *session, struct queued
if (topo_status == MF_TOPOSTATUS_INVALID)
return;
- if (topo_status > topology->status)
+ if (topo_status > session->presentation.topo_status)
{
- param.vt = topology ? VT_UNKNOWN : VT_EMPTY;
- param.punkVal = topology ? (IUnknown *)topology->topology : NULL;
+ param.vt = VT_UNKNOWN;
+ param.punkVal = (IUnknown *)session->presentation.current_topology;
if (FAILED(MFCreateMediaEvent(MESessionTopologyStatus, &GUID_NULL, status, ¶m, &event)))
return;
+ session->presentation.topo_status = topo_status;
+
IMFMediaEvent_SetUINT32(event, &MF_EVENT_TOPOLOGY_STATUS, topo_status);
- topology->status = topo_status;
IMFMediaEventQueue_QueueEvent(session->event_queue, event);
+ IMFMediaEvent_Release(event);
}
-
- IMFMediaEvent_Release(event);
}
static HRESULT session_bind_output_nodes(IMFTopology *topology)
@@ -533,36 +534,14 @@ static HRESULT session_bind_output_nodes(IMFTopology *topology)
return hr;
}
-static IMFTopology *session_get_next_topology(struct media_session *session)
-{
- struct queued_topology *queued;
-
- if (!session->presentation.current_topology.topology)
- {
- struct list *head = list_head(&session->topologies);
- if (!head)
- return NULL;
-
- queued = LIST_ENTRY(head, struct queued_topology, entry);
- session->presentation.current_topology = *queued;
- list_remove(&queued->entry);
- heap_free(queued);
- }
-
- return session->presentation.current_topology.topology;
-}
-
static void session_clear_presentation(struct media_session *session)
{
struct media_source *source, *source2;
struct media_stream *stream, *stream2;
struct media_sink *sink, *sink2;
- if (session->presentation.current_topology.topology)
- {
- IMFTopology_Release(session->presentation.current_topology.topology);
- session->presentation.current_topology.topology = NULL;
- }
+ IMFTopology_Clear(session->presentation.current_topology);
+ session->presentation.topo_status = MF_TOPOSTATUS_INVALID;
LIST_FOR_EACH_ENTRY_SAFE(source, source2, &session->presentation.sources, struct media_source, entry)
{
@@ -594,7 +573,6 @@ static void session_clear_presentation(struct media_session *session)
static void session_start(struct media_session *session, const GUID *time_format, const PROPVARIANT *start_position)
{
IMFTopologyNode *node;
- IMFTopology *topology;
IMFCollection *nodes;
DWORD count, i;
HRESULT hr;
@@ -604,9 +582,8 @@ static void session_start(struct media_session *session, const GUID *time_format
switch (session->state)
{
case SESSION_STATE_STOPPED:
- topology = session_get_next_topology(session);
- if (!topology || FAILED(IMFTopology_GetSourceNodeCollection(topology, &nodes)))
+ if (FAILED(IMFTopology_GetSourceNodeCollection(session->presentation.current_topology, &nodes)))
break;
if (FAILED(IMFCollection_GetElementCount(nodes, &count)))
@@ -671,6 +648,111 @@ static void session_start(struct media_session *session, const GUID *time_format
LeaveCriticalSection(&session->cs);
}
+static void session_raise_topology_set(struct media_session *session, IMFTopology *topology, HRESULT status)
+{
+ PROPVARIANT param;
+
+ param.vt = topology ? VT_UNKNOWN : VT_EMPTY;
+ param.punkVal = (IUnknown *)topology;
+
+ IMFMediaEventQueue_QueueEventParamVar(session->event_queue, MESessionTopologySet, &GUID_NULL, status, ¶m);
+}
+
+static void session_set_current_topology(struct media_session *session, IMFTopology *topology)
+{
+ IMFMediaEvent *event;
+ HRESULT hr;
+
+ if (FAILED(hr = IMFTopology_CloneFrom(session->presentation.current_topology, topology)))
+ {
+ WARN("Failed to clone topology, hr %#x.\n", hr);
+ return;
+ }
+
+ /* FIXME: attributes are all zero for now */
+ if (SUCCEEDED(MFCreateMediaEvent(MESessionNotifyPresentationTime, &GUID_NULL, S_OK, NULL, &event)))
+ {
+ IMFMediaEvent_SetUINT64(event, &MF_EVENT_START_PRESENTATION_TIME, 0);
+ IMFMediaEvent_SetUINT64(event, &MF_EVENT_PRESENTATION_TIME_OFFSET, 0);
+ IMFMediaEvent_GetUINT64(event, &MF_EVENT_START_PRESENTATION_TIME_AT_OUTPUT, 0);
+
+ IMFMediaEventQueue_QueueEvent(session->event_queue, event);
+ IMFMediaEvent_Release(event);
+ }
+}
+
+static void session_set_topology(struct media_session *session, DWORD flags, IMFTopology *topology)
+{
+ HRESULT status = S_OK;
+
+ /* Resolve unless claimed to be full. */
+ if (!(flags & MFSESSION_SETTOPOLOGY_CLEAR_CURRENT) && topology)
+ {
+ if (!(flags & MFSESSION_SETTOPOLOGY_NORESOLUTION))
+ {
+ IMFTopology *resolved_topology = NULL;
+
+ status = session_bind_output_nodes(topology);
+
+ if (SUCCEEDED(status))
+ status = IMFTopoLoader_Load(session->topo_loader, topology, &resolved_topology, NULL /* FIXME? */);
+
+ if (SUCCEEDED(status))
+ {
+ topology = resolved_topology;
+ }
+ }
+ }
+
+ EnterCriticalSection(&session->cs);
+
+ if (flags & MFSESSION_SETTOPOLOGY_CLEAR_CURRENT)
+ {
+ if ((topology && topology == session->presentation.current_topology) || !topology)
+ {
+ /* FIXME: stop current topology, queue next one. */
+ session_clear_presentation(session);
+ }
+ else
+ status = S_FALSE;
+
+ topology = NULL;
+ }
+ else if (topology && flags & MFSESSION_SETTOPOLOGY_IMMEDIATE)
+ {
+ session_clear_topologies(session);
+ session_clear_presentation(session);
+ }
+
+ session_raise_topology_set(session, topology, status);
+
+ /* With no current topology set it right away, otherwise queue. */
+ if (topology)
+ {
+ if (session->presentation.topo_status == MF_TOPOSTATUS_INVALID)
+ {
+ session_set_current_topology(session, topology);
+ }
+ else
+ {
+ struct queued_topology *queued_topology;
+
+ if ((queued_topology = heap_alloc_zero(sizeof(*queued_topology))))
+ {
+ queued_topology->topology = topology;
+ IMFTopology_AddRef(queued_topology->topology);
+
+ list_add_tail(&session->topologies, &queued_topology->entry);
+ }
+ }
+ }
+
+ if (status == S_OK)
+ session_set_topo_status(session, S_OK, MF_TOPOSTATUS_READY);
+
+ LeaveCriticalSection(&session->cs);
+}
+
static HRESULT WINAPI mfsession_QueryInterface(IMFMediaSession *iface, REFIID riid, void **out)
{
struct media_session *session = impl_from_IMFMediaSession(iface);
@@ -718,6 +800,8 @@ static ULONG WINAPI mfsession_Release(IMFMediaSession *iface)
{
session_clear_topologies(session);
session_clear_presentation(session);
+ if (session->presentation.current_topology)
+ IMFTopology_Release(session->presentation.current_topology);
if (session->event_queue)
IMFMediaEventQueue_Release(session->event_queue);
if (session->clock)
@@ -1053,21 +1137,10 @@ static HRESULT WINAPI session_commands_callback_GetParameters(IMFAsyncCallback *
return E_NOTIMPL;
}
-static void session_raise_topology_set(struct media_session *session, IMFTopology *topology, HRESULT status)
-{
- PROPVARIANT param;
-
- param.vt = topology ? VT_UNKNOWN : VT_EMPTY;
- param.punkVal = (IUnknown *)topology;
-
- IMFMediaEventQueue_QueueEventParamVar(session->event_queue, MESessionTopologySet, &GUID_NULL, status, ¶m);
-}
-
static HRESULT WINAPI session_commands_callback_Invoke(IMFAsyncCallback *iface, IMFAsyncResult *result)
{
struct session_op *op = impl_op_from_IUnknown(IMFAsyncResult_GetStateNoAddRef(result));
struct media_session *session = impl_from_commands_callback_IMFAsyncCallback(iface);
- HRESULT status = S_OK;
switch (op->command)
{
@@ -1080,76 +1153,8 @@ static HRESULT WINAPI session_commands_callback_Invoke(IMFAsyncCallback *iface,
S_OK, NULL);
break;
case SESSION_CMD_SET_TOPOLOGY:
- {
- IMFTopology *topology = op->u.set_topology.topology;
- MF_TOPOSTATUS topo_status = MF_TOPOSTATUS_INVALID;
- struct queued_topology *queued_topology = NULL;
- DWORD flags = op->u.set_topology.flags;
-
- /* Resolve unless claimed to be full. */
- if (!(flags & MFSESSION_SETTOPOLOGY_CLEAR_CURRENT) && topology)
- {
- if (!(flags & MFSESSION_SETTOPOLOGY_NORESOLUTION))
- {
- IMFTopology *resolved_topology = NULL;
-
- status = session_bind_output_nodes(topology);
-
- if (SUCCEEDED(status))
- status = IMFTopoLoader_Load(session->topo_loader, topology, &resolved_topology, NULL /* FIXME? */);
-
- if (SUCCEEDED(status))
- {
- topology = resolved_topology;
- topo_status = MF_TOPOSTATUS_READY;
- }
- }
-
- if (SUCCEEDED(status))
- {
- if (!(queued_topology = heap_alloc_zero(sizeof(*queued_topology))))
- status = E_OUTOFMEMORY;
- }
-
- if (SUCCEEDED(status))
- {
- queued_topology->topology = topology;
- IMFTopology_AddRef(queued_topology->topology);
- }
- }
-
- EnterCriticalSection(&session->cs);
-
- if (flags & MFSESSION_SETTOPOLOGY_CLEAR_CURRENT)
- {
- if ((topology && topology == session->presentation.current_topology.topology) || !topology)
- {
- /* FIXME: stop current topology, queue next one. */
- session_clear_presentation(session);
- }
- else
- status = S_FALSE;
- topo_status = MF_TOPOSTATUS_READY;
- queued_topology = &session->presentation.current_topology;
- }
- else if (queued_topology)
- {
- if (flags & MFSESSION_SETTOPOLOGY_IMMEDIATE)
- {
- session_clear_topologies(session);
- session_clear_presentation(session);
- }
-
- list_add_tail(&session->topologies, &queued_topology->entry);
- }
-
- session_raise_topology_set(session, topology, status);
- session_set_topo_status(session, queued_topology, status, topo_status);
-
- LeaveCriticalSection(&session->cs);
-
+ session_set_topology(session, op->u.set_topology.flags, op->u.set_topology.topology);
break;
- }
case SESSION_CMD_START:
{
session_start(session, &op->u.start.time_format, &op->u.start.start_position);
@@ -1247,7 +1252,7 @@ static BOOL session_set_source_state(struct media_session *session, IMFMediaSour
static HRESULT session_set_sinks_clock(struct media_session *session)
{
- IMFTopology *topology = session->presentation.current_topology.topology;
+ IMFTopology *topology = session->presentation.current_topology;
IMFTopologyNode *node;
IMFCollection *nodes;
DWORD count, i;
@@ -1363,8 +1368,7 @@ static HRESULT WINAPI session_events_callback_Invoke(IMFAsyncCallback *iface, IM
ret = session_set_source_state(session, (IMFMediaSource *)event_source, source_state);
if (ret && event_type == MESourceStarted)
{
- session_set_topo_status(session, &session->presentation.current_topology, S_OK,
- MF_TOPOSTATUS_STARTED_SOURCE);
+ session_set_topo_status(session, S_OK, MF_TOPOSTATUS_STARTED_SOURCE);
if (session->state == SESSION_STATE_STARTING)
{
@@ -1609,6 +1613,9 @@ HRESULT WINAPI MFCreateMediaSession(IMFAttributes *config, IMFMediaSession **ses
list_init(&object->presentation.sinks);
InitializeCriticalSection(&object->cs);
+ if (FAILED(hr = MFCreateTopology(&object->presentation.current_topology)))
+ goto failed;
+
if (FAILED(hr = MFCreateEventQueue(&object->event_queue)))
goto failed;
--
2.25.0
More information about the wine-devel
mailing list