[PATCH 4/7] mf: Rearrange topology queueing logic to simplify status notifications.
Nikolay Sivov
nsivov at codeweavers.com
Fri Oct 4 06:42:46 CDT 2019
Signed-off-by: Nikolay Sivov <nsivov at codeweavers.com>
---
dlls/mf/session.c | 128 +++++++++++++++++++++++++++-------------------
1 file changed, 74 insertions(+), 54 deletions(-)
diff --git a/dlls/mf/session.c b/dlls/mf/session.c
index 9c0b80e340..e23481d5c9 100644
--- a/dlls/mf/session.c
+++ b/dlls/mf/session.c
@@ -66,6 +66,7 @@ struct queued_topology
{
struct list entry;
IMFTopology *topology;
+ MF_TOPOSTATUS status;
};
enum session_state
@@ -114,7 +115,7 @@ struct media_session
IMFQualityManager *quality_manager;
struct
{
- IMFTopology *current_topology;
+ struct queued_topology current_topology;
struct list sources;
} presentation;
struct list topologies;
@@ -356,6 +357,31 @@ 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,
+ MF_TOPOSTATUS topo_status)
+{
+ IMFMediaEvent *event;
+ PROPVARIANT param;
+
+ if (topo_status == MF_TOPOSTATUS_INVALID)
+ return;
+
+ if (topo_status > topology->status)
+ {
+ param.vt = topology ? VT_UNKNOWN : VT_EMPTY;
+ param.punkVal = topology ? (IUnknown *)topology->topology : NULL;
+
+ if (FAILED(MFCreateMediaEvent(MESessionTopologyStatus, &GUID_NULL, status, ¶m, &event)))
+ return;
+
+ IMFMediaEvent_SetUINT32(event, &MF_EVENT_TOPOLOGY_STATUS, topo_status);
+ topology->status = topo_status;
+ IMFMediaEventQueue_QueueEvent(session->event_queue, event);
+ }
+
+ IMFMediaEvent_Release(event);
+}
+
static HRESULT session_bind_output_nodes(IMFTopology *topology)
{
MF_TOPOLOGY_TYPE node_type;
@@ -422,19 +448,19 @@ static IMFTopology *session_get_next_topology(struct media_session *session)
{
struct queued_topology *queued;
- if (!session->presentation.current_topology)
+ 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->topology;
+ session->presentation.current_topology = *queued;
list_remove(&queued->entry);
heap_free(queued);
}
- return session->presentation.current_topology;
+ return session->presentation.current_topology.topology;
}
static void session_clear_presentation(struct media_session *session)
@@ -442,10 +468,10 @@ static void session_clear_presentation(struct media_session *session)
struct media_source *source, *source2;
struct media_stream *stream, *stream2;
- if (session->presentation.current_topology)
+ if (session->presentation.current_topology.topology)
{
- IMFTopology_Release(session->presentation.current_topology);
- session->presentation.current_topology = NULL;
+ IMFTopology_Release(session->presentation.current_topology.topology);
+ session->presentation.current_topology.topology = NULL;
}
LIST_FOR_EACH_ENTRY_SAFE(source, source2, &session->presentation.sources, struct media_source, entry)
@@ -924,6 +950,16 @@ 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));
@@ -944,26 +980,12 @@ static HRESULT WINAPI session_commands_callback_Invoke(IMFAsyncCallback *iface,
{
IMFTopology *topology = op->u.set_topology.topology;
MF_TOPOSTATUS topo_status = MF_TOPOSTATUS_INVALID;
- struct queued_topology *queued_topology;
+ struct queued_topology *queued_topology = NULL;
DWORD flags = op->u.set_topology.flags;
- PROPVARIANT param;
- if (flags & MFSESSION_SETTOPOLOGY_CLEAR_CURRENT)
- {
- EnterCriticalSection(&session->cs);
- if ((topology && topology == session->presentation.current_topology) || !topology)
- {
- /* FIXME: stop current topology, queue next one. */
- session_clear_presentation(session);
- }
- else
- status = S_FALSE;
- topo_status = MF_TOPOSTATUS_READY;
- LeaveCriticalSection(&session->cs);
- }
- else if (topology)
+ /* Resolve unless claimed to be full. */
+ if (!(flags & MFSESSION_SETTOPOLOGY_CLEAR_CURRENT) && topology)
{
- /* Resolve unless claimed to be full. */
if (!(flags & MFSESSION_SETTOPOLOGY_NORESOLUTION))
{
IMFTopology *resolved_topology = NULL;
@@ -984,47 +1006,45 @@ static HRESULT WINAPI session_commands_callback_Invoke(IMFAsyncCallback *iface,
{
if (!(queued_topology = heap_alloc_zero(sizeof(*queued_topology))))
status = E_OUTOFMEMORY;
- else
- {
- EnterCriticalSection(&session->cs);
-
- if (flags & MFSESSION_SETTOPOLOGY_IMMEDIATE)
- {
- session_clear_topologies(session);
- session_clear_presentation(session);
- }
-
- queued_topology->topology = topology;
- IMFTopology_AddRef(queued_topology->topology);
- list_add_tail(&session->topologies, &queued_topology->entry);
+ }
- LeaveCriticalSection(&session->cs);
- }
+ if (SUCCEEDED(status))
+ {
+ queued_topology->topology = topology;
+ IMFTopology_AddRef(queued_topology->topology);
}
}
- if (topology)
+ EnterCriticalSection(&session->cs);
+
+ if (flags & MFSESSION_SETTOPOLOGY_CLEAR_CURRENT)
{
- param.vt = VT_UNKNOWN;
- param.punkVal = (IUnknown *)topology;
+ 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
- param.vt = VT_EMPTY;
-
- IMFMediaEventQueue_QueueEventParamVar(session->event_queue, MESessionTopologySet, &GUID_NULL,
- status, ¶m);
- if (topo_status != MF_TOPOSTATUS_INVALID)
+ else if (queued_topology)
{
- IMFMediaEvent *event;
-
- if (SUCCEEDED(MFCreateMediaEvent(MESessionTopologyStatus, &GUID_NULL, status, ¶m, &event)))
+ if (flags & MFSESSION_SETTOPOLOGY_IMMEDIATE)
{
- IMFMediaEvent_SetUINT32(event, &MF_EVENT_TOPOLOGY_STATUS, topo_status);
- IMFMediaEventQueue_QueueEvent(session->event_queue, event);
- IMFMediaEvent_Release(event);
+ 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);
+
break;
}
case SESSION_CMD_START:
--
2.23.0
More information about the wine-devel
mailing list