Nikolay Sivov : mf: Set presentation clock for sinks, subscribe to sink events.
Alexandre Julliard
julliard at winehq.org
Fri Oct 4 16:34:05 CDT 2019
Module: wine
Branch: master
Commit: 3bd1e1edf7d8187f1e1902cd3900a22086bd6bbb
URL: https://source.winehq.org/git/wine.git/?a=commit;h=3bd1e1edf7d8187f1e1902cd3900a22086bd6bbb
Author: Nikolay Sivov <nsivov at codeweavers.com>
Date: Fri Oct 4 14:42:48 2019 +0300
mf: Set presentation clock for sinks, subscribe to sink events.
Signed-off-by: Nikolay Sivov <nsivov at codeweavers.com>
Signed-off-by: Alexandre Julliard <julliard at winehq.org>
---
dlls/mf/session.c | 93 +++++++++++++++++++++++++++++++++++++++++++++++++++++++
1 file changed, 93 insertions(+)
diff --git a/dlls/mf/session.c b/dlls/mf/session.c
index fa8d58ad9d..bf1e48aaf7 100644
--- a/dlls/mf/session.c
+++ b/dlls/mf/session.c
@@ -99,6 +99,12 @@ struct media_source
struct list streams;
};
+struct media_sink
+{
+ struct list entry;
+ IMFMediaSink *sink;
+};
+
struct media_session
{
IMFMediaSession IMFMediaSession_iface;
@@ -117,6 +123,7 @@ struct media_session
{
struct queued_topology current_topology;
struct list sources;
+ struct list sinks;
} presentation;
struct list topologies;
enum session_state state;
@@ -467,6 +474,7 @@ 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)
{
@@ -490,6 +498,15 @@ static void session_clear_presentation(struct media_session *session)
IMFMediaSource_Release(source->source);
heap_free(source);
}
+
+ LIST_FOR_EACH_ENTRY_SAFE(sink, sink2, &session->presentation.sinks, struct media_sink, entry)
+ {
+ list_remove(&sink->entry);
+
+ if (sink->sink)
+ IMFMediaSink_Release(sink->sink);
+ heap_free(sink);
+ }
}
static void session_start(struct media_session *session, const GUID *time_format, const PROPVARIANT *start_position)
@@ -1142,6 +1159,71 @@ static BOOL session_set_source_state(struct media_session *session, IMFMediaSour
return ret;
}
+static HRESULT session_set_sinks_clock(struct media_session *session)
+{
+ IMFTopology *topology = session->presentation.current_topology.topology;
+ IMFTopologyNode *node;
+ IMFCollection *nodes;
+ DWORD count, i;
+ HRESULT hr;
+
+ if (!list_empty(&session->presentation.sinks))
+ return S_OK;
+
+ if (FAILED(hr = IMFTopology_GetOutputNodeCollection(topology, &nodes)))
+ return hr;
+
+ if (FAILED(hr = IMFCollection_GetElementCount(nodes, &count)))
+ {
+ IMFCollection_Release(nodes);
+ return hr;
+ }
+
+ for (i = 0; i < count; ++i)
+ {
+ IMFStreamSink *stream_sink = NULL;
+ struct media_sink *sink;
+
+ if (FAILED(hr = IMFCollection_GetElement(nodes, i, (IUnknown **)&node)))
+ break;
+
+ if (!(sink = heap_alloc_zero(sizeof(*sink))))
+ hr = E_OUTOFMEMORY;
+
+ if (SUCCEEDED(hr))
+ hr = IMFTopologyNode_GetObject(node, (IUnknown **)&stream_sink);
+
+ if (SUCCEEDED(hr))
+ hr = IMFStreamSink_GetMediaSink(stream_sink, &sink->sink);
+
+ if (SUCCEEDED(hr))
+ hr = IMFMediaSink_SetPresentationClock(sink->sink, session->clock);
+
+ if (SUCCEEDED(hr))
+ hr = IMFStreamSink_BeginGetEvent(stream_sink, &session->events_callback, (IUnknown *)stream_sink);
+
+ if (stream_sink)
+ IMFStreamSink_Release(stream_sink);
+
+ if (SUCCEEDED(hr))
+ {
+ list_add_tail(&session->presentation.sinks, &sink->entry);
+ }
+ else if (sink)
+ {
+ if (sink->sink)
+ IMFMediaSink_Release(sink->sink);
+ heap_free(sink);
+ }
+
+ IMFTopologyNode_Release(node);
+ }
+
+ IMFCollection_Release(nodes);
+
+ return hr;
+}
+
static HRESULT WINAPI session_events_callback_Invoke(IMFAsyncCallback *iface, IMFAsyncResult *result)
{
struct media_session *session = impl_from_events_callback_IMFAsyncCallback(iface);
@@ -1194,9 +1276,19 @@ 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);
+ if (session->state == SESSION_STATE_STARTING)
+ {
+ if (SUCCEEDED(session_set_sinks_clock(session)))
+ {
+ session->state = SESSION_STATE_RUNNING;
+ }
+ }
+ }
+
LeaveCriticalSection(&session->cs);
break;
case MENewStream:
@@ -1371,6 +1463,7 @@ HRESULT WINAPI MFCreateMediaSession(IMFAttributes *config, IMFMediaSession **ses
object->refcount = 1;
list_init(&object->topologies);
list_init(&object->presentation.sources);
+ list_init(&object->presentation.sinks);
InitializeCriticalSection(&object->cs);
if (FAILED(hr = MFCreateEventQueue(&object->event_queue)))
More information about the wine-cvs
mailing list