[PATCH 2/2] mf: Add support for async commands for media session.
Nikolay Sivov
nsivov at codeweavers.com
Fri May 10 10:44:34 CDT 2019
Signed-off-by: Nikolay Sivov <nsivov at 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),
--
2.20.1
More information about the wine-devel
mailing list