Nikolay Sivov : mf: Add support for async commands for media session.

Alexandre Julliard julliard at winehq.org
Mon May 13 16:24:16 CDT 2019


Module: wine
Branch: master
Commit: a005e250f0598a44afd482be5a00445878853dbd
URL:    https://source.winehq.org/git/wine.git/?a=commit;h=a005e250f0598a44afd482be5a00445878853dbd

Author: Nikolay Sivov <nsivov at codeweavers.com>
Date:   Fri May 10 18:44:34 2019 +0300

mf: Add support for async commands for media session.

Signed-off-by: Nikolay Sivov <nsivov at codeweavers.com>
Signed-off-by: Alexandre Julliard <julliard at winehq.org>

---

 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 ecedea6..d9c85c4 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 a433a30..7923581 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 e10bc8b..1d72d8b 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 702434a..5db737e 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),




More information about the wine-cvs mailing list