mf: Set presentation clock for sinks, subscribe to sink events.
Signed-off-by: Nikolay Sivov <nsivov@codeweavers.com> Signed-off-by: Alexandre Julliard <julliard@winehq.org>
This commit is contained in:
parent
01bab1876d
commit
3bd1e1edf7
|
@ -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)))
|
||||
|
|
Loading…
Reference in New Issue