Signed-off-by: Nikolay Sivov nsivov@codeweavers.com --- dlls/mf/session.c | 195 +++++++++++++++++++++++++++++++++++++++------- 1 file changed, 168 insertions(+), 27 deletions(-)
diff --git a/dlls/mf/session.c b/dlls/mf/session.c index 02e24a2305..d007202b1f 100644 --- a/dlls/mf/session.c +++ b/dlls/mf/session.c @@ -75,6 +75,19 @@ enum session_state SESSION_STATE_SHUT_DOWN, };
+struct media_stream +{ + struct list entry; + IMFMediaStream *stream; +}; + +struct media_source +{ + struct list entry; + IMFMediaSource *source; + struct list streams; +}; + struct media_session { IMFMediaSession IMFMediaSession_iface; @@ -89,7 +102,11 @@ struct media_session IMFRateControl *clock_rate_control; IMFTopoLoader *topo_loader; IMFQualityManager *quality_manager; - IMFTopology *current_topology; + struct + { + IMFTopology *current_topology; + struct list sources; + } presentation; struct list topologies; enum session_state state; CRITICAL_SECTION cs; @@ -395,19 +412,48 @@ static IMFTopology *session_get_next_topology(struct media_session *session) { struct queued_topology *queued;
- if (!session->current_topology) + if (!session->presentation.current_topology) { struct list *head = list_head(&session->topologies); if (!head) return NULL;
queued = LIST_ENTRY(head, struct queued_topology, entry); - session->current_topology = queued->topology; + session->presentation.current_topology = queued->topology; list_remove(&queued->entry); heap_free(queued); }
- return session->current_topology; + return session->presentation.current_topology; +} + +static void session_clear_presentation(struct media_session *session) +{ + struct media_source *source, *source2; + struct media_stream *stream, *stream2; + + if (session->presentation.current_topology) + { + IMFTopology_Release(session->presentation.current_topology); + session->presentation.current_topology = NULL; + } + + LIST_FOR_EACH_ENTRY_SAFE(source, source2, &session->presentation.sources, struct media_source, entry) + { + list_remove(&source->entry); + + LIST_FOR_EACH_ENTRY_SAFE(stream, stream2, &source->streams, struct media_stream, entry) + { + list_remove(&stream->entry); + if (stream->stream) + IMFMediaStream_Release(stream->stream); + heap_free(stream); + } + + if (source->source) + IMFMediaSource_Release(source->source); + heap_free(source); + } }
static void session_start(struct media_session *session, const GUID *time_format, const PROPVARIANT *start_position) @@ -433,13 +479,17 @@ static void session_start(struct media_session *session, const GUID *time_format
for (i = 0; i < count; ++i) { - if (SUCCEEDED(IMFCollection_GetElement(nodes, i, (IUnknown **)&node))) + if (SUCCEEDED(hr = IMFCollection_GetElement(nodes, i, (IUnknown **)&node))) { IMFPresentationDescriptor *pd = NULL; - IMFMediaSource *source = NULL; + struct media_source *source;
- hr = IMFTopologyNode_GetUnknown(node, &MF_TOPONODE_SOURCE, &IID_IMFMediaSource, - (void **)&source); + if (!(source = heap_alloc_zero(sizeof(*source)))) + hr = E_OUTOFMEMORY; + + if (SUCCEEDED(hr)) + hr = IMFTopologyNode_GetUnknown(node, &MF_TOPONODE_SOURCE, &IID_IMFMediaSource, + (void **)&source->source);
if (SUCCEEDED(hr)) hr = IMFTopologyNode_GetUnknown(node, &MF_TOPONODE_PRESENTATION_DESCRIPTOR, @@ -447,17 +497,26 @@ static void session_start(struct media_session *session, const GUID *time_format
/* Subscribe to source events, start it. */ if (SUCCEEDED(hr)) - hr = IMFMediaSource_BeginGetEvent(source, &session->events_callback, NULL); + hr = IMFMediaSource_BeginGetEvent(source->source, &session->events_callback, + (IUnknown *)source->source);
if (SUCCEEDED(hr)) - hr = IMFMediaSource_Start(source, pd, time_format, start_position); - - if (source) - IMFMediaSource_Release(source); + hr = IMFMediaSource_Start(source->source, pd, time_format, start_position);
if (pd) IMFPresentationDescriptor_Release(pd);
+ if (SUCCEEDED(hr)) + { + list_add_tail(&session->presentation.sources, &source->entry); + } + else if (source) + { + if (source->source) + IMFMediaSource_Release(source->source); + heap_free(source); + } + IMFTopologyNode_Release(node); } } @@ -523,8 +582,7 @@ static ULONG WINAPI mfsession_Release(IMFMediaSession *iface) if (!refcount) { session_clear_topologies(session); - if (session->current_topology) - IMFTopology_Release(session->current_topology); + session_clear_presentation(session); if (session->event_queue) IMFMediaEventQueue_Release(session->event_queue); if (session->clock) @@ -863,14 +921,10 @@ static HRESULT WINAPI session_commands_callback_Invoke(IMFAsyncCallback *iface, if (flags & MFSESSION_SETTOPOLOGY_CLEAR_CURRENT) { EnterCriticalSection(&session->cs); - if ((topology && topology == session->current_topology) || !topology) + if ((topology && topology == session->presentation.current_topology) || !topology) { /* FIXME: stop current topology, queue next one. */ - if (session->current_topology) - { - IMFTopology_Release(session->current_topology); - session->current_topology = NULL; - } + session_clear_presentation(session); } else status = S_FALSE; @@ -907,11 +961,7 @@ static HRESULT WINAPI session_commands_callback_Invoke(IMFAsyncCallback *iface, if (flags & MFSESSION_SETTOPOLOGY_IMMEDIATE) { session_clear_topologies(session); - if (session->current_topology) - { - IMFTopology_Release(session->current_topology); - session->current_topology = NULL; - } + session_clear_presentation(session); }
queued_topology->topology = topology; @@ -1010,11 +1060,101 @@ static HRESULT WINAPI session_events_callback_GetParameters(IMFAsyncCallback *if return E_NOTIMPL; }
-static HRESULT WINAPI session_events_callback_Invoke(IMFAsyncCallback *iface, IMFAsyncResult *result) +static HRESULT session_add_media_stream(struct media_source *source, IMFMediaStream *stream) { + struct media_stream *media_stream; + + if (!(media_stream = heap_alloc_zero(sizeof(*media_stream)))) + return E_OUTOFMEMORY; + + media_stream->stream = stream; + IMFMediaStream_AddRef(media_stream->stream); + + list_add_tail(&source->streams, &media_stream->entry); + return S_OK; }
+static HRESULT WINAPI session_events_callback_Invoke(IMFAsyncCallback *iface, IMFAsyncResult *result) +{ + struct media_session *session = impl_from_events_callback_IMFAsyncCallback(iface); + IMFMediaEventGenerator *event_source; + IMFMediaEvent *event = NULL; + MediaEventType event_type; + struct media_source *cur; + IMFMediaSource *source; + IMFMediaStream *stream; + PROPVARIANT value; + HRESULT hr; + + if (FAILED(hr = IMFAsyncResult_GetState(result, (IUnknown **)&event_source))) + return hr; + + if (FAILED(hr = IMFMediaEventGenerator_EndGetEvent(event_source, result, &event))) + { + WARN("Failed to get event from %p, hr %#x.\n", event_source, hr); + goto failed; + } + + if (FAILED(hr = IMFMediaEvent_GetType(event, &event_type))) + { + WARN("Failed to get event type, hr %#x.\n", hr); + goto failed; + } + + value.vt = VT_EMPTY; + if (FAILED(hr = IMFMediaEvent_GetValue(event, &value))) + { + WARN("Failed to get event value, hr %#x.\n", hr); + goto failed; + } + + switch (event_type) + { + case MENewStream: + stream = (IMFMediaStream *)value.punkVal; + + if (value.vt != VT_UNKNOWN || !stream) + { + WARN("Unexpected event value.\n"); + break; + } + + if (FAILED(hr = IMFMediaStream_GetMediaSource(stream, &source))) + break; + + EnterCriticalSection(&session->cs); + + LIST_FOR_EACH_ENTRY(cur, &session->presentation.sources, struct media_source, entry) + { + if (source == cur->source) + { + hr = session_add_media_stream(cur, stream); + + if (SUCCEEDED(hr)) + hr = IMFMediaStream_BeginGetEvent(stream, &session->events_callback, (IUnknown *)stream); + + break; + } + } + + LeaveCriticalSection(&session->cs); + + break; + default: + ; + } + + PropVariantClear(&value); + +failed: + if (event) + IMFMediaEvent_Release(event); + IMFMediaEventGenerator_Release(event_source); + + return hr; +} + static const IMFAsyncCallbackVtbl session_events_callback_vtbl = { session_events_callback_QueryInterface, @@ -1142,6 +1282,7 @@ HRESULT WINAPI MFCreateMediaSession(IMFAttributes *config, IMFMediaSession **ses object->events_callback.lpVtbl = &session_events_callback_vtbl; object->refcount = 1; list_init(&object->topologies); + list_init(&object->presentation.sources); InitializeCriticalSection(&object->cs);
if (FAILED(hr = MFCreateEventQueue(&object->event_queue)))
Signed-off-by: Nikolay Sivov nsivov@codeweavers.com --- dlls/mfplat/main.c | 64 ++++++++++++++++++++++++---------------------- 1 file changed, 33 insertions(+), 31 deletions(-)
diff --git a/dlls/mfplat/main.c b/dlls/mfplat/main.c index 30810daa44..6be9a194d4 100644 --- a/dlls/mfplat/main.c +++ b/dlls/mfplat/main.c @@ -5585,7 +5585,7 @@ HRESULT WINAPI MFCreateSourceResolver(IMFSourceResolver **resolver) return S_OK; }
-typedef struct media_event +struct media_event { struct attributes attributes; IMFMediaEvent IMFMediaEvent_iface; @@ -5594,28 +5594,28 @@ typedef struct media_event GUID extended_type; HRESULT status; PROPVARIANT value; -} mfmediaevent; +};
-static inline mfmediaevent *impl_from_IMFMediaEvent(IMFMediaEvent *iface) +static inline struct media_event *impl_from_IMFMediaEvent(IMFMediaEvent *iface) { - return CONTAINING_RECORD(iface, mfmediaevent, IMFMediaEvent_iface); + return CONTAINING_RECORD(iface, struct media_event, IMFMediaEvent_iface); }
static HRESULT WINAPI mfmediaevent_QueryInterface(IMFMediaEvent *iface, REFIID riid, void **out) { - mfmediaevent *This = impl_from_IMFMediaEvent(iface); + struct media_event *event = impl_from_IMFMediaEvent(iface);
- TRACE("(%p)->(%s %p)\n", This, debugstr_guid(riid), out); + TRACE("%p, %s, %p.\n", iface, debugstr_guid(riid), out);
if(IsEqualGUID(riid, &IID_IUnknown) || IsEqualGUID(riid, &IID_IMFAttributes) || IsEqualGUID(riid, &IID_IMFMediaEvent)) { - *out = &This->IMFMediaEvent_iface; + *out = &event->IMFMediaEvent_iface; } else { - FIXME("(%s, %p)\n", debugstr_guid(riid), out); + FIXME("%s, %p.\n", debugstr_guid(riid), out); *out = NULL; return E_NOINTERFACE; } @@ -5626,29 +5626,29 @@ static HRESULT WINAPI mfmediaevent_QueryInterface(IMFMediaEvent *iface, REFIID r
static ULONG WINAPI mfmediaevent_AddRef(IMFMediaEvent *iface) { - mfmediaevent *This = impl_from_IMFMediaEvent(iface); - ULONG ref = InterlockedIncrement(&This->attributes.ref); + struct media_event *event = impl_from_IMFMediaEvent(iface); + ULONG refcount = InterlockedIncrement(&event->attributes.ref);
- TRACE("(%p) ref=%u\n", This, ref); + TRACE("%p, refcount %u.\n", iface, refcount);
- return ref; + return refcount; }
static ULONG WINAPI mfmediaevent_Release(IMFMediaEvent *iface) { struct media_event *event = impl_from_IMFMediaEvent(iface); - ULONG ref = InterlockedDecrement(&event->attributes.ref); + ULONG refcount = InterlockedDecrement(&event->attributes.ref);
- TRACE("(%p) ref=%u\n", iface, ref); + TRACE("%p, refcount %u.\n", iface, refcount);
- if (!ref) + if (!refcount) { clear_attributes_object(&event->attributes); PropVariantClear(&event->value); heap_free(event); }
- return ref; + return refcount; }
static HRESULT WINAPI mfmediaevent_GetItem(IMFMediaEvent *iface, REFGUID key, PROPVARIANT *value) @@ -5927,42 +5927,44 @@ static HRESULT WINAPI mfmediaevent_CopyAllItems(IMFMediaEvent *iface, IMFAttribu
static HRESULT WINAPI mfmediaevent_GetType(IMFMediaEvent *iface, MediaEventType *type) { - mfmediaevent *This = impl_from_IMFMediaEvent(iface); + struct media_event *event = impl_from_IMFMediaEvent(iface);
- TRACE("%p, %p\n", This, type); + TRACE("%p, %p.\n", iface, type);
- *type = This->type; + *type = event->type;
return S_OK; }
static HRESULT WINAPI mfmediaevent_GetExtendedType(IMFMediaEvent *iface, GUID *extended_type) { - mfmediaevent *This = impl_from_IMFMediaEvent(iface); + struct media_event *event = impl_from_IMFMediaEvent(iface);
- TRACE("%p, %p\n", This, extended_type); + TRACE("%p, %p.\n", iface, extended_type);
- *extended_type = This->extended_type; + *extended_type = event->extended_type;
return S_OK; }
static HRESULT WINAPI mfmediaevent_GetStatus(IMFMediaEvent *iface, HRESULT *status) { - mfmediaevent *This = impl_from_IMFMediaEvent(iface); + struct media_event *event = impl_from_IMFMediaEvent(iface);
- TRACE("%p, %p\n", This, status); + TRACE("%p, %p.\n", iface, status);
- *status = This->status; + *status = event->status;
return S_OK; }
static HRESULT WINAPI mfmediaevent_GetValue(IMFMediaEvent *iface, PROPVARIANT *value) { - mfmediaevent *This = impl_from_IMFMediaEvent(iface); + struct media_event *event = impl_from_IMFMediaEvent(iface); + + TRACE("%p, %p.\n", iface, value);
- PropVariantCopy(value, &This->value); + PropVariantCopy(value, &event->value);
return S_OK; } @@ -6014,14 +6016,14 @@ static const IMFMediaEventVtbl mfmediaevent_vtbl = HRESULT WINAPI MFCreateMediaEvent(MediaEventType type, REFGUID extended_type, HRESULT status, const PROPVARIANT *value, IMFMediaEvent **event) { - mfmediaevent *object; + struct media_event *object; HRESULT hr;
- TRACE("%s, %s, %08x, %s, %p\n", debugstr_eventid(type), debugstr_guid(extended_type), status, + TRACE("%s, %s, %#x, %s, %p.\n", debugstr_eventid(type), debugstr_guid(extended_type), status, debugstr_propvar(value), event);
- object = HeapAlloc( GetProcessHeap(), 0, sizeof(*object) ); - if(!object) + object = heap_alloc(sizeof(*object)); + if (!object) return E_OUTOFMEMORY;
if (FAILED(hr = init_attributes_object(&object->attributes, 0)))
Signed-off-by: Nikolay Sivov nsivov@codeweavers.com --- dlls/mfplat/main.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-)
diff --git a/dlls/mfplat/main.c b/dlls/mfplat/main.c index 6be9a194d4..19178d9d51 100644 --- a/dlls/mfplat/main.c +++ b/dlls/mfplat/main.c @@ -4763,7 +4763,7 @@ struct resolver_cancel_object enum resolved_object_origin origin; };
-typedef struct source_resolver +struct source_resolver { IMFSourceResolver IMFSourceResolver_iface; LONG refcount; @@ -4771,7 +4771,7 @@ typedef struct source_resolver IMFAsyncCallback url_callback; CRITICAL_SECTION cs; struct list pending; -} mfsourceresolver; +};
static struct source_resolver *impl_from_IMFSourceResolver(IMFSourceResolver *iface) { @@ -5272,14 +5272,14 @@ static HRESULT resolver_end_create_object(struct source_resolver *resolver, enum
static HRESULT WINAPI source_resolver_QueryInterface(IMFSourceResolver *iface, REFIID riid, void **obj) { - mfsourceresolver *This = impl_from_IMFSourceResolver(iface); + struct source_resolver *resolver = impl_from_IMFSourceResolver(iface);
- TRACE("(%p->(%s, %p)\n", This, debugstr_guid(riid), obj); + TRACE("%p, %s, %p.\n", iface, debugstr_guid(riid), obj);
if (IsEqualIID(riid, &IID_IMFSourceResolver) || IsEqualIID(riid, &IID_IUnknown)) { - *obj = &This->IMFSourceResolver_iface; + *obj = &resolver->IMFSourceResolver_iface; } else { @@ -5335,7 +5335,7 @@ static HRESULT WINAPI source_resolver_CreateObjectFromURL(IMFSourceResolver *ifa MFASYNCRESULT *data; HRESULT hr;
- TRACE("%p, %s, %#x, %p, %p, %p\n", iface, debugstr_w(url), flags, props, obj_type, object); + TRACE("%p, %s, %#x, %p, %p, %p.\n", iface, debugstr_w(url), flags, props, obj_type, object);
if (!url || !obj_type || !object) return E_POINTER;
Signed-off-by: Nikolay Sivov nsivov@codeweavers.com --- dlls/mfreadwrite/main.c | 28 ++++++++++++++-------------- 1 file changed, 14 insertions(+), 14 deletions(-)
diff --git a/dlls/mfreadwrite/main.c b/dlls/mfreadwrite/main.c index 3637d2f5ed..6859af8d53 100644 --- a/dlls/mfreadwrite/main.c +++ b/dlls/mfreadwrite/main.c @@ -95,7 +95,7 @@ struct media_stream enum media_stream_state state; };
-typedef struct source_reader +struct source_reader { IMFSourceReader IMFSourceReader_iface; IMFAsyncCallback source_events_callback; @@ -110,7 +110,7 @@ typedef struct source_reader struct media_stream *streams; DWORD stream_count; CRITICAL_SECTION cs; -} srcreader; +};
struct sink_writer { @@ -118,9 +118,9 @@ struct sink_writer LONG refcount; };
-static inline srcreader *impl_from_IMFSourceReader(IMFSourceReader *iface) +static inline struct source_reader *impl_from_IMFSourceReader(IMFSourceReader *iface) { - return CONTAINING_RECORD(iface, srcreader, IMFSourceReader_iface); + return CONTAINING_RECORD(iface, struct source_reader, IMFSourceReader_iface); }
static struct source_reader *impl_from_source_callback_IMFAsyncCallback(IMFAsyncCallback *iface) @@ -481,14 +481,14 @@ static const IMFAsyncCallbackVtbl stream_events_callback_vtbl =
static HRESULT WINAPI src_reader_QueryInterface(IMFSourceReader *iface, REFIID riid, void **out) { - srcreader *This = impl_from_IMFSourceReader(iface); + struct source_reader *reader = impl_from_IMFSourceReader(iface);
- TRACE("(%p)->(%s %p)\n", This, debugstr_guid(riid), out); + TRACE("%p, %s, %p.\n", iface, debugstr_guid(riid), out);
if(IsEqualGUID(riid, &IID_IUnknown) || IsEqualGUID(riid, &IID_IMFSourceReader)) { - *out = &This->IMFSourceReader_iface; + *out = &reader->IMFSourceReader_iface; } else { @@ -503,12 +503,12 @@ static HRESULT WINAPI src_reader_QueryInterface(IMFSourceReader *iface, REFIID r
static ULONG WINAPI src_reader_AddRef(IMFSourceReader *iface) { - srcreader *This = impl_from_IMFSourceReader(iface); - ULONG ref = InterlockedIncrement(&This->refcount); + struct source_reader *reader = impl_from_IMFSourceReader(iface); + ULONG refcount = InterlockedIncrement(&reader->refcount);
- TRACE("(%p) ref=%u\n", This, ref); + TRACE("%p, refcount %u.\n", iface, refcount);
- return ref; + return refcount; }
static ULONG WINAPI src_reader_Release(IMFSourceReader *iface) @@ -517,7 +517,7 @@ static ULONG WINAPI src_reader_Release(IMFSourceReader *iface) ULONG refcount = InterlockedDecrement(&reader->refcount); unsigned int i;
- TRACE("%p, refcount %d.\n", iface, refcount); + TRACE("%p, refcount %u.\n", iface, refcount);
if (!refcount) { @@ -868,8 +868,8 @@ static HRESULT WINAPI src_reader_ReadSample(IMFSourceReader *iface, DWORD index,
static HRESULT WINAPI src_reader_Flush(IMFSourceReader *iface, DWORD index) { - srcreader *This = impl_from_IMFSourceReader(iface); - FIXME("%p, 0x%08x\n", This, index); + FIXME("%p, %#x.\n", iface, index); + return E_NOTIMPL; }
Signed-off-by: Nikolay Sivov nsivov@codeweavers.com --- dlls/mf/session.c | 37 +++++++++++++++++++++++++++++++++++++ 1 file changed, 37 insertions(+)
diff --git a/dlls/mf/session.c b/dlls/mf/session.c index d007202b1f..169ba7403b 100644 --- a/dlls/mf/session.c +++ b/dlls/mf/session.c @@ -81,10 +81,18 @@ struct media_stream IMFMediaStream *stream; };
+enum source_state +{ + SOURCE_STATE_STOPPED = 0, + SOURCE_STATE_STARTED, + SOURCE_STATE_PAUSED, +}; + struct media_source { struct list entry; IMFMediaSource *source; + enum source_state state; struct list streams; };
@@ -1075,10 +1083,25 @@ static HRESULT session_add_media_stream(struct media_source *source, IMFMediaStr return S_OK; }
+static void session_set_source_state(struct media_session *session, IMFMediaSource *source, enum source_state state) +{ + struct media_source *cur; + + LIST_FOR_EACH_ENTRY(cur, &session->presentation.sources, struct media_source, entry) + { + if (source == cur->source) + { + cur->state = state; + break; + } + } +} + static HRESULT WINAPI session_events_callback_Invoke(IMFAsyncCallback *iface, IMFAsyncResult *result) { struct media_session *session = impl_from_events_callback_IMFAsyncCallback(iface); IMFMediaEventGenerator *event_source; + enum source_state source_state; IMFMediaEvent *event = NULL; MediaEventType event_type; struct media_source *cur; @@ -1111,6 +1134,20 @@ static HRESULT WINAPI session_events_callback_Invoke(IMFAsyncCallback *iface, IM
switch (event_type) { + case MESourceStarted: + case MESourcePaused: + case MESourceStopped: + if (event_type == MESourceStarted) + source_state = SOURCE_STATE_STARTED; + else if (event_type == MESourcePaused) + source_state = SOURCE_STATE_PAUSED; + else + source_state = SOURCE_STATE_STOPPED; + + EnterCriticalSection(&session->cs); + session_set_source_state(session, (IMFMediaSource *)event_source, source_state); + LeaveCriticalSection(&session->cs); + break; case MENewStream: stream = (IMFMediaStream *)value.punkVal;