Signed-off-by: Nikolay Sivov nsivov@codeweavers.com --- dlls/mf/Makefile.in | 2 +- dlls/mf/session.c | 208 +++++++++++++++++++++++++++++++++++++++++++- dlls/mf/topology.c | 4 - include/mfidl.idl | 12 +++ 4 files changed, 217 insertions(+), 9 deletions(-)
diff --git a/dlls/mf/Makefile.in b/dlls/mf/Makefile.in index ecedea65c1..d9c85c435f 100644 --- a/dlls/mf/Makefile.in +++ b/dlls/mf/Makefile.in @@ -1,6 +1,6 @@ MODULE = mf.dll IMPORTLIB = mf -IMPORTS = mfplat mfuuid +IMPORTS = mfplat uuid mfuuid
C_SRCS = \ main.c \ diff --git a/dlls/mf/session.c b/dlls/mf/session.c index a433a300ee..7923581f13 100644 --- a/dlls/mf/session.c +++ b/dlls/mf/session.c @@ -33,12 +33,33 @@
WINE_DEFAULT_DEBUG_CHANNEL(mfplat);
+enum session_command +{ + SESSION_CLEAR_TOPOLOGIES, +}; + +struct session_op +{ + IUnknown IUnknown_iface; + LONG refcount; + enum session_command command; +}; + +struct queued_topology +{ + struct list entry; + IMFTopology *topology; +}; + struct media_session { IMFMediaSession IMFMediaSession_iface; IMFGetService IMFGetService_iface; + IMFAsyncCallback commands_callback; LONG refcount; IMFMediaEventQueue *event_queue; + struct list topologies; + CRITICAL_SECTION cs; };
struct clock_sink @@ -93,11 +114,21 @@ static inline struct media_session *impl_from_IMFMediaSession(IMFMediaSession *i return CONTAINING_RECORD(iface, struct media_session, IMFMediaSession_iface); }
+static struct media_session *impl_from_commands_callback_IMFAsyncCallback(IMFAsyncCallback *iface) +{ + return CONTAINING_RECORD(iface, struct media_session, commands_callback); +} + static struct media_session *impl_from_IMFGetService(IMFGetService *iface) { return CONTAINING_RECORD(iface, struct media_session, IMFGetService_iface); }
+static struct session_op *impl_op_from_IUnknown(IUnknown *iface) +{ + return CONTAINING_RECORD(iface, struct session_op, IUnknown_iface); +} + static struct presentation_clock *impl_from_IMFPresentationClock(IMFPresentationClock *iface) { return CONTAINING_RECORD(iface, struct presentation_clock, IMFPresentationClock_iface); @@ -128,6 +159,79 @@ static struct sink_notification *impl_from_IUnknown(IUnknown *iface) return CONTAINING_RECORD(iface, struct sink_notification, IUnknown_iface); }
+static HRESULT WINAPI session_op_QueryInterface(IUnknown *iface, REFIID riid, void **obj) +{ + if (IsEqualIID(riid, &IID_IUnknown)) + { + *obj = iface; + IUnknown_AddRef(iface); + return S_OK; + } + + *obj = NULL; + return E_NOINTERFACE; +} + +static ULONG WINAPI session_op_AddRef(IUnknown *iface) +{ + struct session_op *op = impl_op_from_IUnknown(iface); + ULONG refcount = InterlockedIncrement(&op->refcount); + + TRACE("%p, refcount %u.\n", iface, refcount); + + return refcount; +} + +static ULONG WINAPI session_op_Release(IUnknown *iface) +{ + struct session_op *op = impl_op_from_IUnknown(iface); + ULONG refcount = InterlockedDecrement(&op->refcount); + + TRACE("%p, refcount %u.\n", iface, refcount); + + if (!refcount) + { + heap_free(op); + } + + return refcount; +} + +static IUnknownVtbl session_op_vtbl = +{ + session_op_QueryInterface, + session_op_AddRef, + session_op_Release, +}; + +static HRESULT create_session_op(enum session_command command, IUnknown **ret) +{ + struct session_op *op; + + if (!(op = heap_alloc(sizeof(*op)))) + return E_OUTOFMEMORY; + + op->IUnknown_iface.lpVtbl = &session_op_vtbl; + op->refcount = 1; + op->command = command; + + *ret = &op->IUnknown_iface; + + return S_OK; +} + +static void session_clear_topologies(struct media_session *session) +{ + struct queued_topology *ptr, *next; + + LIST_FOR_EACH_ENTRY_SAFE(ptr, next, &session->topologies, struct queued_topology, entry) + { + list_remove(&ptr->entry); + IMFTopology_Release(ptr->topology); + heap_free(ptr); + } +} + static HRESULT WINAPI mfsession_QueryInterface(IMFMediaSession *iface, REFIID riid, void **out) { struct media_session *session = impl_from_IMFMediaSession(iface); @@ -173,8 +277,10 @@ static ULONG WINAPI mfsession_Release(IMFMediaSession *iface)
if (!refcount) { + session_clear_topologies(session); if (session->event_queue) IMFMediaEventQueue_Release(session->event_queue); + DeleteCriticalSection(&session->cs); heap_free(session); }
@@ -220,16 +326,44 @@ static HRESULT WINAPI mfsession_QueueEvent(IMFMediaSession *iface, MediaEventTyp
static HRESULT WINAPI mfsession_SetTopology(IMFMediaSession *iface, DWORD flags, IMFTopology *topology) { - FIXME("(%p)->(%#x, %p)\n", iface, flags, topology); + struct media_session *session = impl_from_IMFMediaSession(iface); + struct queued_topology *queued_topology;
- return E_NOTIMPL; + FIXME("%p, %#x, %p.\n", iface, flags, topology); + + if (!(queued_topology = heap_alloc(sizeof(*queued_topology)))) + return E_OUTOFMEMORY; + + queued_topology->topology = topology; + IMFTopology_AddRef(queued_topology->topology); + + EnterCriticalSection(&session->cs); + list_add_tail(&session->topologies, &queued_topology->entry); + LeaveCriticalSection(&session->cs); + + return S_OK; +} + +static HRESULT session_submit_command(struct media_session *session, IUnknown *op) +{ + return MFPutWorkItem(MFASYNC_CALLBACK_QUEUE_STANDARD, &session->commands_callback, op); }
static HRESULT WINAPI mfsession_ClearTopologies(IMFMediaSession *iface) { - FIXME("(%p)\n", iface); + struct media_session *session = impl_from_IMFMediaSession(iface); + IUnknown *op; + HRESULT hr;
- return E_NOTIMPL; + TRACE("%p.\n", iface); + + if (FAILED(hr = create_session_op(SESSION_CLEAR_TOPOLOGIES, &op))) + return hr; + + hr = session_submit_command(session, op); + IUnknown_Release(op); + + return hr; }
static HRESULT WINAPI mfsession_Start(IMFMediaSession *iface, const GUID *format, const PROPVARIANT *start) @@ -346,6 +480,69 @@ static const IMFGetServiceVtbl session_get_service_vtbl = session_get_service_GetService, };
+static HRESULT WINAPI session_commands_callback_QueryInterface(IMFAsyncCallback *iface, REFIID riid, void **obj) +{ + if (IsEqualIID(riid, &IID_IMFAsyncCallback) || + IsEqualIID(riid, &IID_IUnknown)) + { + *obj = iface; + IMFAsyncCallback_AddRef(iface); + return S_OK; + } + + WARN("Unsupported %s.\n", debugstr_guid(riid)); + *obj = NULL; + return E_NOINTERFACE; +} + +static ULONG WINAPI session_commands_callback_AddRef(IMFAsyncCallback *iface) +{ + struct media_session *session = impl_from_commands_callback_IMFAsyncCallback(iface); + return IMFMediaSession_AddRef(&session->IMFMediaSession_iface); +} + +static ULONG WINAPI session_commands_callback_Release(IMFAsyncCallback *iface) +{ + struct media_session *session = impl_from_commands_callback_IMFAsyncCallback(iface); + return IMFMediaSession_Release(&session->IMFMediaSession_iface); +} + +static HRESULT WINAPI session_commands_callback_GetParameters(IMFAsyncCallback *iface, DWORD *flags, DWORD *queue) +{ + return E_NOTIMPL; +} + +static HRESULT WINAPI session_commands_callback_Invoke(IMFAsyncCallback *iface, IMFAsyncResult *result) +{ + struct session_op *op = impl_op_from_IUnknown(IMFAsyncResult_GetStateNoAddRef(result)); + struct media_session *session = impl_from_commands_callback_IMFAsyncCallback(iface); + + switch (op->command) + { + case SESSION_CLEAR_TOPOLOGIES: + EnterCriticalSection(&session->cs); + session_clear_topologies(session); + LeaveCriticalSection(&session->cs); + + IMFMediaEventQueue_QueueEventParamVar(session->event_queue, MESessionTopologiesCleared, &GUID_NULL, + S_OK, NULL); + break; + default: + ; + } + + return S_OK; +} + +static const IMFAsyncCallbackVtbl session_commands_callback_vtbl = +{ + session_commands_callback_QueryInterface, + session_commands_callback_AddRef, + session_commands_callback_Release, + session_commands_callback_GetParameters, + session_commands_callback_Invoke, +}; + /*********************************************************************** * MFCreateMediaSession (mf.@) */ @@ -365,12 +562,15 @@ HRESULT WINAPI MFCreateMediaSession(IMFAttributes *config, IMFMediaSession **ses
object->IMFMediaSession_iface.lpVtbl = &mfmediasessionvtbl; object->IMFGetService_iface.lpVtbl = &session_get_service_vtbl; + object->commands_callback.lpVtbl = &session_commands_callback_vtbl; object->refcount = 1; if (FAILED(hr = MFCreateEventQueue(&object->event_queue))) { IMFMediaSession_Release(&object->IMFMediaSession_iface); return hr; } + list_init(&object->topologies); + InitializeCriticalSection(&object->cs);
*session = &object->IMFMediaSession_iface;
diff --git a/dlls/mf/topology.c b/dlls/mf/topology.c index e10bc8b07d..1d72d8bb68 100644 --- a/dlls/mf/topology.c +++ b/dlls/mf/topology.c @@ -26,10 +26,6 @@ #include "windef.h" #include "winbase.h"
-#include "initguid.h" -#include "ole2.h" -#include "ocidl.h" - #undef INITGUID #include <guiddef.h> #include "mfapi.h" diff --git a/include/mfidl.idl b/include/mfidl.idl index 702434aa2d..5db737e68d 100644 --- a/include/mfidl.idl +++ b/include/mfidl.idl @@ -64,6 +64,18 @@ typedef enum _MFCLOCK_CHARACTERISTICS_FLAGS MFCLOCK_CHARACTERISTICS_FLAG_IS_SYSTEM_CLOCK = 0x00000008, } MFCLOCK_CHARACTERISTICS_FLAGS;
+typedef enum MFSESSION_SETTOPOLOGY_FLAGS +{ + MFSESSION_SETTOPOLOGY_IMMEDIATE = 0x00000001, + MFSESSION_SETTOPOLOGY_NORESOLUTION = 0x00000002, + MFSESSION_SETTOPOLOGY_CLEAR_CURRENT = 0x00000004, +} MFSESSION_SETTOPOLOGY_FLAGS; + +typedef enum MFSESSION_GETFULLTOPOLOGY_FLAGS +{ + MFSESSION_GETFULLTOPOLOGY_CURRENT = 0x00000001, +} MFSESSION_GETFULLTOPOLOGY_FLAGS; + [ object, uuid(2eb1e945-18b8-4139-9b1a-d5d584818530),