Commit 82f03261 authored by Nikolay Sivov's avatar Nikolay Sivov Committed by Alexandre Julliard

mf: Rearrange topology queueing logic to simplify status notifications.

parent 7c5fcfff
...@@ -66,6 +66,7 @@ struct queued_topology ...@@ -66,6 +66,7 @@ struct queued_topology
{ {
struct list entry; struct list entry;
IMFTopology *topology; IMFTopology *topology;
MF_TOPOSTATUS status;
}; };
enum session_state enum session_state
...@@ -114,7 +115,7 @@ struct media_session ...@@ -114,7 +115,7 @@ struct media_session
IMFQualityManager *quality_manager; IMFQualityManager *quality_manager;
struct struct
{ {
IMFTopology *current_topology; struct queued_topology current_topology;
struct list sources; struct list sources;
} presentation; } presentation;
struct list topologies; struct list topologies;
...@@ -356,6 +357,31 @@ static void session_clear_topologies(struct media_session *session) ...@@ -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, &param, &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) static HRESULT session_bind_output_nodes(IMFTopology *topology)
{ {
MF_TOPOLOGY_TYPE node_type; MF_TOPOLOGY_TYPE node_type;
...@@ -422,19 +448,19 @@ static IMFTopology *session_get_next_topology(struct media_session *session) ...@@ -422,19 +448,19 @@ static IMFTopology *session_get_next_topology(struct media_session *session)
{ {
struct queued_topology *queued; struct queued_topology *queued;
if (!session->presentation.current_topology) if (!session->presentation.current_topology.topology)
{ {
struct list *head = list_head(&session->topologies); struct list *head = list_head(&session->topologies);
if (!head) if (!head)
return NULL; return NULL;
queued = LIST_ENTRY(head, struct queued_topology, entry); queued = LIST_ENTRY(head, struct queued_topology, entry);
session->presentation.current_topology = queued->topology; session->presentation.current_topology = *queued;
list_remove(&queued->entry); list_remove(&queued->entry);
heap_free(queued); heap_free(queued);
} }
return session->presentation.current_topology; return session->presentation.current_topology.topology;
} }
static void session_clear_presentation(struct media_session *session) static void session_clear_presentation(struct media_session *session)
...@@ -442,10 +468,10 @@ 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_source *source, *source2;
struct media_stream *stream, *stream2; struct media_stream *stream, *stream2;
if (session->presentation.current_topology) if (session->presentation.current_topology.topology)
{ {
IMFTopology_Release(session->presentation.current_topology); IMFTopology_Release(session->presentation.current_topology.topology);
session->presentation.current_topology = NULL; session->presentation.current_topology.topology = NULL;
} }
LIST_FOR_EACH_ENTRY_SAFE(source, source2, &session->presentation.sources, struct media_source, entry) 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 * ...@@ -924,6 +950,16 @@ static HRESULT WINAPI session_commands_callback_GetParameters(IMFAsyncCallback *
return E_NOTIMPL; 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, &param);
}
static HRESULT WINAPI session_commands_callback_Invoke(IMFAsyncCallback *iface, IMFAsyncResult *result) static HRESULT WINAPI session_commands_callback_Invoke(IMFAsyncCallback *iface, IMFAsyncResult *result)
{ {
struct session_op *op = impl_op_from_IUnknown(IMFAsyncResult_GetStateNoAddRef(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, ...@@ -944,26 +980,12 @@ static HRESULT WINAPI session_commands_callback_Invoke(IMFAsyncCallback *iface,
{ {
IMFTopology *topology = op->u.set_topology.topology; IMFTopology *topology = op->u.set_topology.topology;
MF_TOPOSTATUS topo_status = MF_TOPOSTATUS_INVALID; 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; DWORD flags = op->u.set_topology.flags;
PROPVARIANT param;
if (flags & MFSESSION_SETTOPOLOGY_CLEAR_CURRENT) /* Resolve unless claimed to be full. */
{ if (!(flags & MFSESSION_SETTOPOLOGY_CLEAR_CURRENT) && topology)
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_NORESOLUTION)) if (!(flags & MFSESSION_SETTOPOLOGY_NORESOLUTION))
{ {
IMFTopology *resolved_topology = NULL; IMFTopology *resolved_topology = NULL;
...@@ -984,47 +1006,45 @@ static HRESULT WINAPI session_commands_callback_Invoke(IMFAsyncCallback *iface, ...@@ -984,47 +1006,45 @@ static HRESULT WINAPI session_commands_callback_Invoke(IMFAsyncCallback *iface,
{ {
if (!(queued_topology = heap_alloc_zero(sizeof(*queued_topology)))) if (!(queued_topology = heap_alloc_zero(sizeof(*queued_topology))))
status = E_OUTOFMEMORY; 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; if ((topology && topology == session->presentation.current_topology.topology) || !topology)
param.punkVal = (IUnknown *)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 else if (queued_topology)
param.vt = VT_EMPTY;
IMFMediaEventQueue_QueueEventParamVar(session->event_queue, MESessionTopologySet, &GUID_NULL,
status, &param);
if (topo_status != MF_TOPOSTATUS_INVALID)
{ {
IMFMediaEvent *event; if (flags & MFSESSION_SETTOPOLOGY_IMMEDIATE)
if (SUCCEEDED(MFCreateMediaEvent(MESessionTopologyStatus, &GUID_NULL, status, &param, &event)))
{ {
IMFMediaEvent_SetUINT32(event, &MF_EVENT_TOPOLOGY_STATUS, topo_status); session_clear_topologies(session);
IMFMediaEventQueue_QueueEvent(session->event_queue, event); session_clear_presentation(session);
IMFMediaEvent_Release(event);
} }
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; break;
} }
case SESSION_CMD_START: case SESSION_CMD_START:
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment