[PATCH 2/9] mf: Use single list for topology nodes in current presentation.
Nikolay Sivov
nsivov at codeweavers.com
Fri Mar 13 07:34:31 CDT 2020
Signed-off-by: Nikolay Sivov <nsivov at codeweavers.com>
---
dlls/mf/session.c | 325 ++++++++++++++++++++++------------------------
1 file changed, 155 insertions(+), 170 deletions(-)
diff --git a/dlls/mf/session.c b/dlls/mf/session.c
index cc014f548a..9c3288da34 100644
--- a/dlls/mf/session.c
+++ b/dlls/mf/session.c
@@ -102,15 +102,6 @@ struct media_source
enum object_state state;
};
-struct source_node
-{
- struct list entry;
- IMFMediaStream *stream;
- IMFMediaSource *source;
- DWORD stream_id;
- enum object_state state;
-};
-
struct media_sink
{
struct list entry;
@@ -119,11 +110,28 @@ struct media_sink
BOOL finalized;
};
-struct output_node
+struct topo_node
{
struct list entry;
- IMFStreamSink *stream;
+ MF_TOPOLOGY_TYPE type;
+ TOPOID node_id;
enum object_state state;
+ union
+ {
+ IMFMediaStream *source_stream;
+ IMFStreamSink *sink_stream;
+ IMFTransform *transform;
+ IUnknown *object;
+ } object;
+
+ union
+ {
+ struct
+ {
+ IMFMediaSource *source;
+ DWORD stream_id;
+ } source;
+ } u;
};
enum presentation_flags
@@ -154,9 +162,8 @@ struct media_session
IMFTopology *current_topology;
MF_TOPOSTATUS topo_status;
struct list sources;
- struct list source_nodes;
struct list sinks;
- struct list output_nodes;
+ struct list nodes;
DWORD flags;
/* Latest Start() arguments. */
@@ -603,11 +610,28 @@ static void session_set_caps(struct media_session *session, DWORD caps)
IMFMediaEvent_Release(event);
}
+static void release_topo_node(struct topo_node *node)
+{
+ switch (node->type)
+ {
+ case MF_TOPOLOGY_SOURCESTREAM_NODE:
+ if (node->u.source.source)
+ IMFMediaSource_Release(node->u.source.source);
+ break;
+ default:
+ ;
+ }
+
+ if (node->object.object)
+ IUnknown_Release(node->object.object);
+ heap_free(node);
+}
+
static void session_clear_presentation(struct media_session *session)
{
- struct source_node *src_node, *src_node2;
struct media_source *source, *source2;
struct media_sink *sink, *sink2;
+ struct topo_node *node, *node2;
IMFTopology_Clear(session->presentation.current_topology);
session->presentation.topo_status = MF_TOPOSTATUS_INVALID;
@@ -622,12 +646,10 @@ static void session_clear_presentation(struct media_session *session)
heap_free(source);
}
- LIST_FOR_EACH_ENTRY_SAFE(src_node, src_node2, &session->presentation.source_nodes, struct source_node, entry)
+ LIST_FOR_EACH_ENTRY_SAFE(node, node2, &session->presentation.nodes, struct topo_node, entry)
{
- list_remove(&src_node->entry);
- if (src_node->stream)
- IMFMediaStream_Release(src_node->stream);
- heap_free(src_node);
+ list_remove(&node->entry);
+ release_topo_node(node);
}
LIST_FOR_EACH_ENTRY_SAFE(sink, sink2, &session->presentation.sinks, struct media_sink, entry)
@@ -861,84 +883,6 @@ static HRESULT session_add_media_source(struct media_session *session, IMFTopolo
return hr;
}
-static HRESULT session_add_source_node(struct media_session *session, IMFTopologyNode *node, IMFMediaSource *source)
-{
- struct source_node *source_node;
- IMFStreamDescriptor *sd;
- DWORD stream_id;
- HRESULT hr;
-
- if (FAILED(hr = IMFTopologyNode_GetUnknown(node, &MF_TOPONODE_STREAM_DESCRIPTOR, &IID_IMFStreamDescriptor,
- (void **)&sd)))
- {
- WARN("Missing MF_TOPONODE_STREAM_DESCRIPTOR, hr %#x.\n", hr);
- return hr;
- }
-
- hr = IMFStreamDescriptor_GetStreamIdentifier(sd, &stream_id);
- IMFStreamDescriptor_Release(sd);
- if (FAILED(hr))
- return hr;
-
- if (!(source_node = heap_alloc_zero(sizeof(*source_node))))
- return E_OUTOFMEMORY;
-
- source_node->source = source;
- IMFMediaSource_AddRef(source_node->source);
-
- list_add_tail(&session->presentation.source_nodes, &source_node->entry);
-
- return hr;
-}
-
-static void session_collect_source_nodes(struct media_session *session)
-{
- IMFTopology *topology;
- IMFTopologyNode *node;
- IMFCollection *nodes;
- DWORD count, i;
- HRESULT hr;
-
- if (!list_empty(&session->presentation.source_nodes))
- return;
-
- topology = session->presentation.current_topology;
-
- if (!topology || FAILED(IMFTopology_GetSourceNodeCollection(topology, &nodes)))
- return;
-
- if (FAILED(IMFCollection_GetElementCount(nodes, &count)))
- return;
-
- /* Create list of distinct sources, and whole list of source nodes. */
- for (i = 0; i < count; ++i)
- {
- if (SUCCEEDED(hr = IMFCollection_GetElement(nodes, i, (IUnknown **)&node)))
- {
- IMFMediaSource *source;
-
- if (FAILED(IMFTopologyNode_GetUnknown(node, &MF_TOPONODE_SOURCE, &IID_IMFMediaSource, (void **)&source)))
- {
- WARN("Missing MF_TOPONODE_SOURCE, hr %#x.\n", hr);
- IMFTopologyNode_Release(node);
- continue;
- }
-
- hr = session_add_media_source(session, node, source);
- IMFMediaSource_Release(source);
-
- if (SUCCEEDED(hr))
- {
- if (FAILED(hr = session_add_source_node(session, node, source)))
- WARN("Failed to add source node, hr %#x.\n", hr);
- }
-
- IMFMediaSource_Release(source);
- IMFTopologyNode_Release(node);
- }
- }
-}
-
static void session_raise_topology_set(struct media_session *session, IMFTopology *topology, HRESULT status)
{
PROPVARIANT param;
@@ -994,66 +938,105 @@ static HRESULT session_add_media_sink(struct media_session *session, IMFTopology
return S_OK;
}
-static HRESULT session_collect_output_nodes(struct media_session *session)
+static HRESULT session_append_node(struct media_session *session, IMFTopologyNode *node)
{
- IMFTopology *topology = session->presentation.current_topology;
- IMFTopologyNode *topo_node;
- struct output_node *node;
- IMFCollection *nodes;
- DWORD count, i;
- HRESULT hr;
+ struct topo_node *topo_node;
+ IMFMediaSink *media_sink;
+ IMFStreamDescriptor *sd;
+ HRESULT hr = S_OK;
+ IUnknown *object;
- if (!list_empty(&session->presentation.output_nodes))
- return S_OK;
+ if (!(topo_node = heap_alloc_zero(sizeof(*topo_node))))
+ return E_OUTOFMEMORY;
- if (FAILED(hr = IMFTopology_GetOutputNodeCollection(topology, &nodes)))
- return hr;
+ IMFTopologyNode_GetNodeType(node, &topo_node->type);
+ IMFTopologyNode_GetTopoNodeID(node, &topo_node->node_id);
- if (FAILED(hr = IMFCollection_GetElementCount(nodes, &count)))
+ switch (topo_node->type)
{
- IMFCollection_Release(nodes);
- return hr;
- }
+ case MF_TOPOLOGY_OUTPUT_NODE:
+ if (FAILED(hr = IMFTopologyNode_GetObject(node, &object)))
+ {
+ WARN("Node %s does not have associated object.\n", wine_dbgstr_longlong(topo_node->node_id));
+ break;
+ }
+ hr = IUnknown_QueryInterface(object, &IID_IMFStreamSink, (void **)&topo_node->object.object);
+ IUnknown_Release(object);
+ if (FAILED(hr))
+ break;
- for (i = 0; i < count; ++i)
- {
- IMFMediaSink *media_sink = NULL;
+ if (FAILED(hr = IMFStreamSink_GetMediaSink(topo_node->object.sink_stream, &media_sink)))
+ break;
+
+ hr = session_add_media_sink(session, node, media_sink);
+ IMFMediaSink_Release(media_sink);
- if (FAILED(hr = IMFCollection_GetElement(nodes, i, (IUnknown **)&topo_node)))
break;
+ case MF_TOPOLOGY_SOURCESTREAM_NODE:
+ if (FAILED(IMFTopologyNode_GetUnknown(node, &MF_TOPONODE_SOURCE, &IID_IMFMediaSource,
+ (void **)&topo_node->u.source.source)))
+ {
+ WARN("Missing MF_TOPONODE_SOURCE, hr %#x.\n", hr);
+ break;
+ }
- if (!(node = heap_alloc_zero(sizeof(*node))))
- hr = E_OUTOFMEMORY;
+ if (FAILED(hr = session_add_media_source(session, node, topo_node->u.source.source)))
+ break;
- if (SUCCEEDED(hr))
- hr = IMFTopologyNode_GetObject(topo_node, (IUnknown **)&node->stream);
+ if (FAILED(hr = IMFTopologyNode_GetUnknown(node, &MF_TOPONODE_STREAM_DESCRIPTOR,
+ &IID_IMFStreamDescriptor, (void **)&sd)))
+ {
+ WARN("Missing MF_TOPONODE_STREAM_DESCRIPTOR, hr %#x.\n", hr);
+ break;
+ }
- if (SUCCEEDED(hr))
- hr = IMFStreamSink_GetMediaSink(node->stream, &media_sink);
+ hr = IMFStreamDescriptor_GetStreamIdentifier(sd, &topo_node->u.source.stream_id);
+ IMFStreamDescriptor_Release(sd);
- if (SUCCEEDED(hr))
- hr = session_add_media_sink(session, topo_node, media_sink);
+ break;
+ case MF_TOPOLOGY_TRANSFORM_NODE:
+ case MF_TOPOLOGY_TEE_NODE:
+ FIXME("Unsupported node type %d.\n", topo_node->type);
- if (media_sink)
- IMFMediaSink_Release(media_sink);
+ break;
+ default:
+ ;
+ }
- if (SUCCEEDED(hr))
- {
- list_add_tail(&session->presentation.output_nodes, &node->entry);
- }
- else if (node)
+ if (SUCCEEDED(hr))
+ list_add_tail(&session->presentation.nodes, &topo_node->entry);
+ else
+ release_topo_node(topo_node);
+
+ return hr;
+}
+
+static HRESULT session_collect_nodes(struct media_session *session)
+{
+ IMFTopology *topology = session->presentation.current_topology;
+ IMFTopologyNode *node;
+ WORD i, count = 0;
+
+ if (!list_empty(&session->presentation.nodes))
+ return S_OK;
+
+ IMFTopology_GetNodeCount(topology, &count);
+
+ for (i = 0; i < count; ++i)
+ {
+ if (FAILED(IMFTopology_GetNode(topology, i, &node)))
{
- if (node->stream)
- IMFStreamSink_Release(node->stream);
- heap_free(node);
+ WARN("Failed to get node %u.\n", i);
+ continue;
}
- IMFTopologyNode_Release(topo_node);
- }
+ if (FAILED(session_append_node(session, node)))
+ WARN("Failed to add node %u.\n", i);
- IMFCollection_Release(nodes);
+ IMFTopologyNode_Release(node);
+ }
- return hr;
+ return S_OK;
}
static void session_set_current_topology(struct media_session *session, IMFTopology *topology)
@@ -1070,8 +1053,7 @@ static void session_set_current_topology(struct media_session *session, IMFTopol
return;
}
- session_collect_source_nodes(session);
- session_collect_output_nodes(session);
+ session_collect_nodes(session);
/* FIXME: attributes are all zero for now */
if (SUCCEEDED(MFCreateMediaEvent(MESessionNotifyPresentationTime, &GUID_NULL, S_OK, NULL, &event)))
@@ -1714,7 +1696,7 @@ static HRESULT WINAPI session_events_callback_GetParameters(IMFAsyncCallback *if
static HRESULT session_add_media_stream(struct media_session *session, IMFMediaSource *source, IMFMediaStream *stream)
{
- struct source_node *node;
+ struct topo_node *node;
IMFStreamDescriptor *sd;
DWORD stream_id = 0;
HRESULT hr;
@@ -1727,18 +1709,19 @@ static HRESULT session_add_media_stream(struct media_session *session, IMFMediaS
if (FAILED(hr))
return hr;
- LIST_FOR_EACH_ENTRY(node, &session->presentation.source_nodes, struct source_node, entry)
+ LIST_FOR_EACH_ENTRY(node, &session->presentation.nodes, struct topo_node, entry)
{
- if (node->source == source && node->stream_id == stream_id)
+ if (node->type == MF_TOPOLOGY_SOURCESTREAM_NODE && node->u.source.source == source
+ && node->u.source.stream_id == stream_id)
{
- if (node->stream)
+ if (node->object.source_stream)
{
- WARN("Source node already has stream set.\n");
+ WARN("Node already has stream set.\n");
return S_FALSE;
}
- node->stream = stream;
- IMFMediaStream_AddRef(node->stream);
+ node->object.source_stream = stream;
+ IMFMediaStream_AddRef(node->object.source_stream);
break;
}
}
@@ -1749,7 +1732,7 @@ static HRESULT session_add_media_stream(struct media_session *session, IMFMediaS
static BOOL session_is_source_nodes_state(struct media_session *session, enum object_state state)
{
struct media_source *source;
- struct source_node *node;
+ struct topo_node *node;
LIST_FOR_EACH_ENTRY(source, &session->presentation.sources, struct media_source, entry)
{
@@ -1757,9 +1740,9 @@ static BOOL session_is_source_nodes_state(struct media_session *session, enum ob
return FALSE;
}
- LIST_FOR_EACH_ENTRY(node, &session->presentation.source_nodes, struct source_node, entry)
+ LIST_FOR_EACH_ENTRY(node, &session->presentation.nodes, struct topo_node, entry)
{
- if (node->state != state)
+ if (node->type == MF_TOPOLOGY_SOURCESTREAM_NODE && node->state != state)
return FALSE;
}
@@ -1768,11 +1751,11 @@ static BOOL session_is_source_nodes_state(struct media_session *session, enum ob
static BOOL session_is_output_nodes_state(struct media_session *session, enum object_state state)
{
- struct output_node *node;
+ struct topo_node *node;
- LIST_FOR_EACH_ENTRY(node, &session->presentation.output_nodes, struct output_node, entry)
+ LIST_FOR_EACH_ENTRY(node, &session->presentation.nodes, struct topo_node, entry)
{
- if (node->state != state)
+ if (node->type == MF_TOPOLOGY_OUTPUT_NODE && node->state != state)
return FALSE;
}
@@ -1804,8 +1787,8 @@ static HRESULT session_start_clock(struct media_session *session)
{
IMFPresentationTimeSource *time_source = NULL;
LONGLONG start_offset = 0;
- struct output_node *node;
struct media_sink *sink;
+ struct topo_node *node;
HRESULT hr;
if (!(session->presentation.flags & SESSION_FLAG_SINKS_SUBSCRIBED))
@@ -1828,10 +1811,13 @@ static HRESULT session_start_clock(struct media_session *session)
if (FAILED(hr))
WARN("Failed to set time source, hr %#x.\n", hr);
- LIST_FOR_EACH_ENTRY(node, &session->presentation.output_nodes, struct output_node, entry)
+ LIST_FOR_EACH_ENTRY(node, &session->presentation.nodes, struct topo_node, entry)
{
- if (FAILED(hr = IMFStreamSink_BeginGetEvent(node->stream, &session->events_callback,
- (IUnknown *)node->stream)))
+ if (node->type != MF_TOPOLOGY_OUTPUT_NODE)
+ continue;
+
+ if (FAILED(hr = IMFStreamSink_BeginGetEvent(node->object.sink_stream, &session->events_callback,
+ node->object.object)))
{
WARN("Failed to subscribe to stream sink events, hr %#x.\n", hr);
}
@@ -1874,10 +1860,9 @@ static HRESULT session_start_clock(struct media_session *session)
static void session_set_source_object_state(struct media_session *session, IUnknown *object,
MediaEventType event_type)
{
- struct source_node *src_node;
- struct output_node *out_node;
struct media_source *src;
enum object_state state;
+ struct topo_node *node;
BOOL changed = FALSE;
if ((state = session_get_object_state_for_event(event_type)) == OBJ_STATE_INVALID)
@@ -1903,12 +1888,12 @@ static void session_set_source_object_state(struct media_session *session, IUnkn
case MEStreamPaused:
case MEStreamStopped:
- LIST_FOR_EACH_ENTRY(src_node, &session->presentation.source_nodes, struct source_node, entry)
+ LIST_FOR_EACH_ENTRY(node, &session->presentation.nodes, struct topo_node, entry)
{
- if (object == (IUnknown *)src_node->stream)
+ if (node->type == MF_TOPOLOGY_SOURCESTREAM_NODE && object == node->object.object)
{
- changed = src_node->state != state;
- src_node->state = state;
+ changed = node->state != state;
+ node->state = state;
break;
}
}
@@ -1945,9 +1930,10 @@ static void session_set_source_object_state(struct media_session *session, IUnkn
if (!session_is_source_nodes_state(session, OBJ_STATE_STOPPED))
break;
- LIST_FOR_EACH_ENTRY(out_node, &session->presentation.output_nodes, struct output_node, entry)
+ LIST_FOR_EACH_ENTRY(node, &session->presentation.nodes, struct topo_node, entry)
{
- IMFStreamSink_Flush(out_node->stream);
+ if (node->type == MF_TOPOLOGY_OUTPUT_NODE)
+ IMFStreamSink_Flush(node->object.sink_stream);
}
session_set_caps(session, session->caps & ~MFSESSIONCAP_PAUSE);
@@ -1972,7 +1958,7 @@ static void session_set_sink_stream_state(struct media_session *session, IMFStre
MediaEventType event_type)
{
struct media_source *source;
- struct output_node *node;
+ struct topo_node *node;
enum object_state state;
BOOL changed = FALSE;
IMFMediaEvent *event;
@@ -1982,9 +1968,9 @@ static void session_set_sink_stream_state(struct media_session *session, IMFStre
if ((state = session_get_object_state_for_event(event_type)) == OBJ_STATE_INVALID)
return;
- LIST_FOR_EACH_ENTRY(node, &session->presentation.output_nodes, struct output_node, entry)
+ LIST_FOR_EACH_ENTRY(node, &session->presentation.nodes, struct topo_node, entry)
{
- if (stream == node->stream)
+ if (node->type == MF_TOPOLOGY_OUTPUT_NODE && stream == node->object.sink_stream)
{
changed = node->state != state;
node->state = state;
@@ -2438,9 +2424,8 @@ HRESULT WINAPI MFCreateMediaSession(IMFAttributes *config, IMFMediaSession **ses
object->refcount = 1;
list_init(&object->topologies);
list_init(&object->presentation.sources);
- list_init(&object->presentation.source_nodes);
list_init(&object->presentation.sinks);
- list_init(&object->presentation.output_nodes);
+ list_init(&object->presentation.nodes);
InitializeCriticalSection(&object->cs);
if (FAILED(hr = MFCreateTopology(&object->presentation.current_topology)))
--
2.25.1
More information about the wine-devel
mailing list