[PATCH v2 11/11] mf: Introduce handler helper.
Derek Lesho
dlesho at codeweavers.com
Mon Feb 10 16:32:41 CST 2020
Signed-off-by: Derek Lesho <dlesho at codeweavers.com>
---
dlls/mf/Makefile.in | 1 +
dlls/mf/handler.c | 357 ++++++++++++++++++++++++++++
dlls/mf/handler.h | 29 +++
dlls/mf/main.c | 370 ++++--------------------------
dlls/winegstreamer/Makefile.in | 3 +-
dlls/winegstreamer/media_source.c | 332 ++-------------------------
6 files changed, 443 insertions(+), 649 deletions(-)
create mode 100644 dlls/mf/handler.c
create mode 100644 dlls/mf/handler.h
diff --git a/dlls/mf/Makefile.in b/dlls/mf/Makefile.in
index d23349c9cf..81872b17a5 100644
--- a/dlls/mf/Makefile.in
+++ b/dlls/mf/Makefile.in
@@ -5,6 +5,7 @@ IMPORTS = mfplat ole32 uuid mfuuid
EXTRADLLFLAGS = -mno-cygwin
C_SRCS = \
+ handler.c \
main.c \
samplegrabber.c \
sar.c \
diff --git a/dlls/mf/handler.c b/dlls/mf/handler.c
new file mode 100644
index 0000000000..db8783a7cd
--- /dev/null
+++ b/dlls/mf/handler.c
@@ -0,0 +1,357 @@
+#include <stdarg.h>
+
+#define COBJMACROS
+
+#include "windef.h"
+#include "winbase.h"
+#include "mfidl.h"
+
+#include "mfapi.h"
+#include "mferror.h"
+
+#include "handler.h"
+
+#include "wine/debug.h"
+#include "wine/heap.h"
+#include "wine/list.h"
+
+WINE_DEFAULT_DEBUG_CHANNEL(mfplat);
+
+struct create_object_context
+{
+ IUnknown IUnknown_iface;
+ LONG refcount;
+
+ IPropertyStore *props;
+ IMFByteStream *stream;
+ WCHAR *url;
+ DWORD flags;
+};
+
+struct handler_result
+{
+ struct list entry;
+ IMFAsyncResult *result;
+ MF_OBJECT_TYPE obj_type;
+ IUnknown *object;
+};
+
+static struct create_object_context *impl_from_IUnknown(IUnknown *iface)
+{
+ return CONTAINING_RECORD(iface, struct create_object_context, IUnknown_iface);
+}
+
+static HRESULT WINAPI create_object_context_QueryInterface(IUnknown *iface, REFIID riid, void **obj)
+{
+ TRACE("%p, %s, %p.\n", iface, debugstr_guid(riid), obj);
+
+ if (IsEqualIID(riid, &IID_IUnknown))
+ {
+ *obj = iface;
+ IUnknown_AddRef(iface);
+ return S_OK;
+ }
+
+ WARN("Unsupported %s.\n", debugstr_guid(riid));
+ *obj = NULL;
+ return E_NOINTERFACE;
+}
+
+static ULONG WINAPI create_object_context_AddRef(IUnknown *iface)
+{
+ struct create_object_context *context = impl_from_IUnknown(iface);
+ ULONG refcount = InterlockedIncrement(&context->refcount);
+
+ TRACE("%p, refcount %u.\n", iface, refcount);
+
+ return refcount;
+}
+
+static ULONG WINAPI create_object_context_Release(IUnknown *iface)
+{
+ struct create_object_context *context = impl_from_IUnknown(iface);
+ ULONG refcount = InterlockedDecrement(&context->refcount);
+
+ TRACE("%p, refcount %u.\n", iface, refcount);
+
+ if (!refcount)
+ {
+ if (context->props)
+ IPropertyStore_Release(context->props);
+ if (context->stream)
+ IMFByteStream_Release(context->stream);
+ if (context->url)
+ heap_free(context->url);
+ heap_free(context);
+ }
+
+ return refcount;
+}
+
+static const IUnknownVtbl create_object_context_vtbl =
+{
+ create_object_context_QueryInterface,
+ create_object_context_AddRef,
+ create_object_context_Release,
+};
+
+/* Start async methods */
+static struct handler *impl_from_IMFAsyncCallback(IMFAsyncCallback *iface)
+{
+ return CONTAINING_RECORD(iface, struct handler, IMFAsyncCallback_iface);
+}
+
+static HRESULT WINAPI handler_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;
+}
+
+/* lifetime not managed with COM */
+static ULONG WINAPI handler_callback_AddRef(IMFAsyncCallback *iface)
+{
+ return 2;
+}
+
+static ULONG WINAPI handler_callback_Release(IMFAsyncCallback *iface)
+{
+ return 1;
+}
+
+static HRESULT WINAPI handler_callback_GetParameters(IMFAsyncCallback *iface, DWORD *flags, DWORD *queue)
+{
+ return E_NOTIMPL;
+}
+
+static HRESULT WINAPI handler_callback_Invoke(IMFAsyncCallback *iface, IMFAsyncResult *result)
+{
+ struct handler *handler = impl_from_IMFAsyncCallback(iface);
+ struct handler_result *handler_result;
+ MF_OBJECT_TYPE obj_type = MF_OBJECT_INVALID;
+ IUnknown *object = NULL, *context_object;
+ struct create_object_context *context;
+ IMFAsyncResult *caller;
+ HRESULT hr;
+
+ caller = (IMFAsyncResult *)IMFAsyncResult_GetStateNoAddRef(result);
+
+ if (FAILED(hr = IMFAsyncResult_GetObject(result, &context_object)))
+ {
+ WARN("Expected context set for callee result.\n");
+ return hr;
+ }
+
+ context = impl_from_IUnknown(context_object);
+
+ hr = handler->create_object(handler, context->url, context->stream, context->flags, context->props, &object, &obj_type);
+
+ handler_result = heap_alloc(sizeof(*handler_result));
+ if (handler_result)
+ {
+ handler_result->result = caller;
+ IMFAsyncResult_AddRef(handler_result->result);
+ handler_result->obj_type = obj_type;
+ handler_result->object = object;
+
+ EnterCriticalSection(&handler->cs);
+ list_add_tail(&handler->results, &handler_result->entry);
+ LeaveCriticalSection(&handler->cs);
+ }
+ else
+ {
+ if (object)
+ IUnknown_Release(object);
+ hr = E_OUTOFMEMORY;
+ }
+
+ IUnknown_Release(&context->IUnknown_iface);
+
+ IMFAsyncResult_SetStatus(caller, hr);
+ MFInvokeCallback(caller);
+
+ return S_OK;
+}
+
+static const IMFAsyncCallbackVtbl handler_callback_vtbl =
+{
+ handler_callback_QueryInterface,
+ handler_callback_AddRef,
+ handler_callback_Release,
+ handler_callback_GetParameters,
+ handler_callback_Invoke,
+};
+
+/* Start handler helpers */
+
+static WCHAR *heap_strdupW(const WCHAR *str)
+{
+ WCHAR *ret = NULL;
+
+ if (str)
+ {
+ unsigned int size;
+
+ size = (lstrlenW(str) + 1) * sizeof(WCHAR);
+ ret = heap_alloc(size);
+ if (ret)
+ memcpy(ret, str, size);
+ }
+
+ return ret;
+}
+
+HRESULT handler_begin_create_object(struct handler *handler, IMFByteStream *stream,
+ const WCHAR *url, DWORD flags, IPropertyStore *props, IUnknown **cancel_cookie,
+ IMFAsyncCallback *callback, IUnknown *state)
+{
+ struct create_object_context *context;
+ IMFAsyncResult *caller, *item;
+ HRESULT hr;
+
+ if (cancel_cookie)
+ *cancel_cookie = NULL;
+
+ if (FAILED(hr = MFCreateAsyncResult(NULL, callback, state, &caller)))
+ return hr;
+
+ context = heap_alloc(sizeof(*context));
+ if (!context)
+ {
+ IMFAsyncResult_Release(caller);
+ return E_OUTOFMEMORY;
+ }
+
+ context->IUnknown_iface.lpVtbl = &create_object_context_vtbl;
+ context->refcount = 1;
+ context->props = props;
+ if (context->props)
+ IPropertyStore_AddRef(context->props);
+ context->flags = flags;
+ context->stream = stream;
+ if (context->stream)
+ IMFByteStream_AddRef(context->stream);
+ if (url)
+ context->url = heap_strdupW(url);
+ if (!context->url && !context->stream)
+ {
+ IMFAsyncResult_Release(caller);
+ IUnknown_Release(&context->IUnknown_iface);
+ return E_OUTOFMEMORY;
+ }
+
+ hr = MFCreateAsyncResult(&context->IUnknown_iface, &handler->IMFAsyncCallback_iface, (IUnknown *)caller, &item);
+ IUnknown_Release(&context->IUnknown_iface);
+ IMFAsyncResult_Release(caller);
+ if (SUCCEEDED(hr))
+ {
+ if (SUCCEEDED(hr = MFPutWorkItemEx(MFASYNC_CALLBACK_QUEUE_IO, item)))
+ {
+ if (cancel_cookie)
+ IMFAsyncResult_GetState(item, cancel_cookie);
+ }
+
+ IMFAsyncResult_Release(item);
+ }
+
+ return hr;
+}
+
+HRESULT handler_end_create_object(struct handler *handler, IMFAsyncResult *result,
+ MF_OBJECT_TYPE *obj_type, IUnknown **object)
+{
+ struct handler_result *found = NULL, *cur;
+ HRESULT hr;
+
+ EnterCriticalSection(&handler->cs);
+
+ LIST_FOR_EACH_ENTRY(cur, &handler->results, struct handler_result, entry)
+ {
+ if (result == cur->result)
+ {
+ list_remove(&cur->entry);
+ found = cur;
+ break;
+ }
+ }
+
+ LeaveCriticalSection(&handler->cs);
+
+ if (found)
+ {
+ *obj_type = found->obj_type;
+ *object = found->object;
+ hr = IMFAsyncResult_GetStatus(found->result);
+ IMFAsyncResult_Release(found->result);
+ heap_free(found);
+ }
+ else
+ {
+ *obj_type = MF_OBJECT_INVALID;
+ *object = NULL;
+ hr = MF_E_UNEXPECTED;
+ }
+
+ return hr;
+}
+
+HRESULT handler_cancel_object_creation(struct handler *handler, IUnknown *cancel_cookie)
+{
+ struct handler_result *found = NULL, *cur;
+
+ EnterCriticalSection(&handler->cs);
+
+ LIST_FOR_EACH_ENTRY(cur, &handler->results, struct handler_result, entry)
+ {
+ if (cancel_cookie == (IUnknown *)cur->result)
+ {
+ list_remove(&cur->entry);
+ found = cur;
+ break;
+ }
+ }
+
+ LeaveCriticalSection(&handler->cs);
+
+ if (found)
+ {
+ IMFAsyncResult_Release(found->result);
+ if (found->object)
+ IUnknown_Release(found->object);
+ heap_free(found);
+ }
+
+ return found ? S_OK : MF_E_UNEXPECTED;
+}
+
+void handler_construct(struct handler *handler, p_create_object_callback create_object_callback)
+{
+ handler->IMFAsyncCallback_iface.lpVtbl = &handler_callback_vtbl;
+ handler->create_object = create_object_callback;
+
+ list_init(&handler->results);
+ InitializeCriticalSection(&handler->cs);
+}
+
+void handler_destruct(struct handler *handler)
+{
+ struct handler_result *result, *next;
+
+ LIST_FOR_EACH_ENTRY_SAFE(result, next, &handler->results, struct handler_result, entry)
+ {
+ list_remove(&result->entry);
+ IMFAsyncResult_Release(result->result);
+ if (result->object)
+ IUnknown_Release(result->object);
+ heap_free(result);
+ }
+ DeleteCriticalSection(&handler->cs);
+}
\ No newline at end of file
diff --git a/dlls/mf/handler.h b/dlls/mf/handler.h
new file mode 100644
index 0000000000..14b110e1a7
--- /dev/null
+++ b/dlls/mf/handler.h
@@ -0,0 +1,29 @@
+#include "windef.h"
+
+#include "mfobjects.h"
+#include "mfapi.h"
+
+#include "wine/list.h"
+
+/* helper sub-object that handles ansyncronous nature of handlers */
+
+struct handler;
+typedef HRESULT (*p_create_object_callback)(struct handler *handler, WCHAR *url, IMFByteStream *stream, DWORD flags, IPropertyStore *props,
+ IUnknown **out_object, MF_OBJECT_TYPE *out_obj_type);
+
+struct handler
+{
+ IMFAsyncCallback IMFAsyncCallback_iface;
+ struct list results;
+ CRITICAL_SECTION cs;
+ p_create_object_callback create_object;
+};
+
+void handler_construct(struct handler *handler, p_create_object_callback create_object_callback);
+void handler_destruct(struct handler *handler);
+HRESULT handler_begin_create_object(struct handler *handler, IMFByteStream *stream,
+ const WCHAR *url, DWORD flags, IPropertyStore *props, IUnknown **cancel_cookie,
+ IMFAsyncCallback *callback, IUnknown *state);
+HRESULT handler_end_create_object(struct handler *handler, IMFAsyncResult *result,
+ MF_OBJECT_TYPE *obj_type, IUnknown **object);
+HRESULT handler_cancel_object_creation(struct handler *handler, IUnknown *cancel_cookie);
\ No newline at end of file
diff --git a/dlls/mf/main.c b/dlls/mf/main.c
index 251d59e1c0..5861560b60 100644
--- a/dlls/mf/main.c
+++ b/dlls/mf/main.c
@@ -35,6 +35,7 @@
#include "mferror.h"
#include "mf_private.h"
+#include "handler.h"
#include "wine/debug.h"
#include "wine/heap.h"
@@ -547,22 +548,12 @@ static const IClassFactoryVtbl class_factory_vtbl =
class_factory_LockServer,
};
-struct file_scheme_handler_result
-{
- struct list entry;
- IMFAsyncResult *result;
- MF_OBJECT_TYPE obj_type;
- IUnknown *object;
-};
-
struct file_scheme_handler
{
IMFSchemeHandler IMFSchemeHandler_iface;
- IMFAsyncCallback IMFAsyncCallback_iface;
LONG refcount;
IMFSourceResolver *resolver;
- struct list results;
- CRITICAL_SECTION cs;
+ struct handler handler;
};
static struct file_scheme_handler *impl_from_IMFSchemeHandler(IMFSchemeHandler *iface)
@@ -570,11 +561,6 @@ static struct file_scheme_handler *impl_from_IMFSchemeHandler(IMFSchemeHandler *
return CONTAINING_RECORD(iface, struct file_scheme_handler, IMFSchemeHandler_iface);
}
-static struct file_scheme_handler *impl_from_IMFAsyncCallback(IMFAsyncCallback *iface)
-{
- return CONTAINING_RECORD(iface, struct file_scheme_handler, IMFAsyncCallback_iface);
-}
-
static HRESULT WINAPI file_scheme_handler_QueryInterface(IMFSchemeHandler *iface, REFIID riid, void **obj)
{
TRACE("%p, %s, %p.\n", iface, debugstr_guid(riid), obj);
@@ -604,239 +590,45 @@ static ULONG WINAPI file_scheme_handler_AddRef(IMFSchemeHandler *iface)
static ULONG WINAPI file_scheme_handler_Release(IMFSchemeHandler *iface)
{
- struct file_scheme_handler *handler = impl_from_IMFSchemeHandler(iface);
- ULONG refcount = InterlockedDecrement(&handler->refcount);
- struct file_scheme_handler_result *result, *next;
-
- TRACE("%p, refcount %u.\n", iface, refcount);
-
- if (!refcount)
- {
- LIST_FOR_EACH_ENTRY_SAFE(result, next, &handler->results, struct file_scheme_handler_result, entry)
- {
- list_remove(&result->entry);
- IMFAsyncResult_Release(result->result);
- if (result->object)
- IUnknown_Release(result->object);
- heap_free(result);
- }
- DeleteCriticalSection(&handler->cs);
- if (handler->resolver)
- IMFSourceResolver_Release(handler->resolver);
- heap_free(handler);
- }
-
- return refcount;
-}
-
-struct create_object_context
-{
- IUnknown IUnknown_iface;
- LONG refcount;
-
- IPropertyStore *props;
- WCHAR *url;
- DWORD flags;
-};
-
-static struct create_object_context *impl_from_IUnknown(IUnknown *iface)
-{
- return CONTAINING_RECORD(iface, struct create_object_context, IUnknown_iface);
-}
-
-static HRESULT WINAPI create_object_context_QueryInterface(IUnknown *iface, REFIID riid, void **obj)
-{
- TRACE("%p, %s, %p.\n", iface, debugstr_guid(riid), obj);
-
- if (IsEqualIID(riid, &IID_IUnknown))
- {
- *obj = iface;
- IUnknown_AddRef(iface);
- return S_OK;
- }
-
- WARN("Unsupported %s.\n", debugstr_guid(riid));
- *obj = NULL;
- return E_NOINTERFACE;
-}
-
-static ULONG WINAPI create_object_context_AddRef(IUnknown *iface)
-{
- struct create_object_context *context = impl_from_IUnknown(iface);
- ULONG refcount = InterlockedIncrement(&context->refcount);
-
- TRACE("%p, refcount %u.\n", iface, refcount);
-
- return refcount;
-}
-
-static ULONG WINAPI create_object_context_Release(IUnknown *iface)
-{
- struct create_object_context *context = impl_from_IUnknown(iface);
- ULONG refcount = InterlockedDecrement(&context->refcount);
+ struct file_scheme_handler *this = impl_from_IMFSchemeHandler(iface);
+ ULONG refcount = InterlockedDecrement(&this->refcount);
TRACE("%p, refcount %u.\n", iface, refcount);
if (!refcount)
{
- if (context->props)
- IPropertyStore_Release(context->props);
- heap_free(context->url);
- heap_free(context);
+ if (this->resolver)
+ IMFSourceResolver_Release(this->resolver);
+ handler_destruct(&this->handler);
}
return refcount;
}
-static const IUnknownVtbl create_object_context_vtbl =
-{
- create_object_context_QueryInterface,
- create_object_context_AddRef,
- create_object_context_Release,
-};
-
-static WCHAR *heap_strdupW(const WCHAR *str)
-{
- WCHAR *ret = NULL;
-
- if (str)
- {
- unsigned int size;
-
- size = (lstrlenW(str) + 1) * sizeof(WCHAR);
- ret = heap_alloc(size);
- if (ret)
- memcpy(ret, str, size);
- }
-
- return ret;
-}
-
static HRESULT WINAPI file_scheme_handler_BeginCreateObject(IMFSchemeHandler *iface, const WCHAR *url, DWORD flags,
IPropertyStore *props, IUnknown **cancel_cookie, IMFAsyncCallback *callback, IUnknown *state)
{
- struct file_scheme_handler *handler = impl_from_IMFSchemeHandler(iface);
- struct create_object_context *context;
- IMFAsyncResult *caller, *item;
- HRESULT hr;
+ struct file_scheme_handler *this = impl_from_IMFSchemeHandler(iface);
TRACE("%p, %s, %#x, %p, %p, %p, %p.\n", iface, debugstr_w(url), flags, props, cancel_cookie, callback, state);
-
- if (cancel_cookie)
- *cancel_cookie = NULL;
-
- if (FAILED(hr = MFCreateAsyncResult(NULL, callback, state, &caller)))
- return hr;
-
- context = heap_alloc(sizeof(*context));
- if (!context)
- {
- IMFAsyncResult_Release(caller);
- return E_OUTOFMEMORY;
- }
-
- context->IUnknown_iface.lpVtbl = &create_object_context_vtbl;
- context->refcount = 1;
- context->props = props;
- if (context->props)
- IPropertyStore_AddRef(context->props);
- context->flags = flags;
- context->url = heap_strdupW(url);
- if (!context->url)
- {
- IMFAsyncResult_Release(caller);
- IUnknown_Release(&context->IUnknown_iface);
- return E_OUTOFMEMORY;
- }
-
- hr = MFCreateAsyncResult(&context->IUnknown_iface, &handler->IMFAsyncCallback_iface, (IUnknown *)caller, &item);
- IUnknown_Release(&context->IUnknown_iface);
- IMFAsyncResult_Release(caller);
- if (SUCCEEDED(hr))
- {
- if (SUCCEEDED(hr = MFPutWorkItemEx(MFASYNC_CALLBACK_QUEUE_IO, item)))
- {
- if (cancel_cookie)
- IMFAsyncResult_GetState(item, cancel_cookie);
- }
-
- IMFAsyncResult_Release(item);
- }
-
- return hr;
+ return handler_begin_create_object(&this->handler, NULL, url, flags, props, cancel_cookie, callback, state);
}
static HRESULT WINAPI file_scheme_handler_EndCreateObject(IMFSchemeHandler *iface, IMFAsyncResult *result,
MF_OBJECT_TYPE *obj_type, IUnknown **object)
{
- struct file_scheme_handler *handler = impl_from_IMFSchemeHandler(iface);
- struct file_scheme_handler_result *found = NULL, *cur;
- HRESULT hr;
+ struct file_scheme_handler *this = impl_from_IMFSchemeHandler(iface);
TRACE("%p, %p, %p, %p.\n", iface, result, obj_type, object);
-
- EnterCriticalSection(&handler->cs);
-
- LIST_FOR_EACH_ENTRY(cur, &handler->results, struct file_scheme_handler_result, entry)
- {
- if (result == cur->result)
- {
- list_remove(&cur->entry);
- found = cur;
- break;
- }
- }
-
- LeaveCriticalSection(&handler->cs);
-
- if (found)
- {
- *obj_type = found->obj_type;
- *object = found->object;
- hr = IMFAsyncResult_GetStatus(found->result);
- IMFAsyncResult_Release(found->result);
- heap_free(found);
- }
- else
- {
- *obj_type = MF_OBJECT_INVALID;
- *object = NULL;
- hr = MF_E_UNEXPECTED;
- }
-
- return hr;
+ return handler_end_create_object(&this->handler, result, obj_type, object);
}
static HRESULT WINAPI file_scheme_handler_CancelObjectCreation(IMFSchemeHandler *iface, IUnknown *cancel_cookie)
{
- struct file_scheme_handler *handler = impl_from_IMFSchemeHandler(iface);
- struct file_scheme_handler_result *found = NULL, *cur;
+ struct file_scheme_handler *this = impl_from_IMFSchemeHandler(iface);
TRACE("%p, %p.\n", iface, cancel_cookie);
-
- EnterCriticalSection(&handler->cs);
-
- LIST_FOR_EACH_ENTRY(cur, &handler->results, struct file_scheme_handler_result, entry)
- {
- if (cancel_cookie == (IUnknown *)cur->result)
- {
- list_remove(&cur->entry);
- found = cur;
- break;
- }
- }
-
- LeaveCriticalSection(&handler->cs);
-
- if (found)
- {
- IMFAsyncResult_Release(found->result);
- if (found->object)
- IUnknown_Release(found->object);
- heap_free(found);
- }
-
- return found ? S_OK : MF_E_UNEXPECTED;
+ return handler_cancel_object_creation(&this->handler, cancel_cookie);
}
static const IMFSchemeHandlerVtbl file_scheme_handler_vtbl =
@@ -849,38 +641,6 @@ static const IMFSchemeHandlerVtbl file_scheme_handler_vtbl =
file_scheme_handler_CancelObjectCreation,
};
-static HRESULT WINAPI file_scheme_handler_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 file_scheme_handler_callback_AddRef(IMFAsyncCallback *iface)
-{
- struct file_scheme_handler *handler = impl_from_IMFAsyncCallback(iface);
- return IMFSchemeHandler_AddRef(&handler->IMFSchemeHandler_iface);
-}
-
-static ULONG WINAPI file_scheme_handler_callback_Release(IMFAsyncCallback *iface)
-{
- struct file_scheme_handler *handler = impl_from_IMFAsyncCallback(iface);
- return IMFSchemeHandler_Release(&handler->IMFSchemeHandler_iface);
-}
-
-static HRESULT WINAPI file_scheme_handler_callback_GetParameters(IMFAsyncCallback *iface, DWORD *flags, DWORD *queue)
-{
- return E_NOTIMPL;
-}
-
static HRESULT file_scheme_handler_get_resolver(struct file_scheme_handler *handler, IMFSourceResolver **resolver)
{
HRESULT hr;
@@ -902,111 +662,63 @@ static HRESULT file_scheme_handler_get_resolver(struct file_scheme_handler *hand
return S_OK;
}
-static HRESULT WINAPI file_scheme_handler_callback_Invoke(IMFAsyncCallback *iface, IMFAsyncResult *result)
+static HRESULT file_scheme_handler_create_object(struct handler *handler, WCHAR *url, IMFByteStream *stream, DWORD flags,
+ IPropertyStore *props, IUnknown **out_object, MF_OBJECT_TYPE *out_obj_type)
{
static const WCHAR schemeW[] = {'f','i','l','e',':','/','/'};
- struct file_scheme_handler *handler = impl_from_IMFAsyncCallback(iface);
- struct file_scheme_handler_result *handler_result;
- MF_OBJECT_TYPE obj_type = MF_OBJECT_INVALID;
- IUnknown *object = NULL, *context_object;
- struct create_object_context *context;
+ HRESULT hr = S_OK;
+ WCHAR *path;
+ IMFByteStream *file_byte_stream;
+ struct file_scheme_handler *this = CONTAINING_RECORD(handler, struct file_scheme_handler, handler);
IMFSourceResolver *resolver;
- IMFAsyncResult *caller;
- IMFByteStream *stream;
- const WCHAR *url;
- HRESULT hr;
-
- caller = (IMFAsyncResult *)IMFAsyncResult_GetStateNoAddRef(result);
-
- if (FAILED(hr = IMFAsyncResult_GetObject(result, &context_object)))
- {
- WARN("Expected context set for callee result.\n");
- return hr;
- }
-
- context = impl_from_IUnknown(context_object);
/* Strip from scheme, MFCreateFile() won't be expecting it. */
- url = context->url;
- if (!wcsnicmp(context->url, schemeW, ARRAY_SIZE(schemeW)))
- url += ARRAY_SIZE(schemeW);
+ path = url;
+ if (!wcsnicmp(url, schemeW, ARRAY_SIZE(schemeW)))
+ path += ARRAY_SIZE(schemeW);
- hr = MFCreateFile(context->flags & MF_RESOLUTION_WRITE ? MF_ACCESSMODE_READWRITE : MF_ACCESSMODE_READ,
- MF_OPENMODE_FAIL_IF_NOT_EXIST, MF_FILEFLAGS_NONE, url, &stream);
+ hr = MFCreateFile(flags & MF_RESOLUTION_WRITE ? MF_ACCESSMODE_READWRITE : MF_ACCESSMODE_READ,
+ MF_OPENMODE_FAIL_IF_NOT_EXIST, MF_FILEFLAGS_NONE, path, &file_byte_stream);
if (SUCCEEDED(hr))
{
- if (context->flags & MF_RESOLUTION_MEDIASOURCE)
+ if (flags & MF_RESOLUTION_MEDIASOURCE)
{
- if (SUCCEEDED(hr = file_scheme_handler_get_resolver(handler, &resolver)))
+ if (SUCCEEDED(hr = file_scheme_handler_get_resolver(this, &resolver)))
{
- hr = IMFSourceResolver_CreateObjectFromByteStream(resolver, stream, context->url, context->flags,
- context->props, &obj_type, &object);
+ hr = IMFSourceResolver_CreateObjectFromByteStream(resolver, file_byte_stream, url, flags,
+ props, out_obj_type, out_object);
IMFSourceResolver_Release(resolver);
- IMFByteStream_Release(stream);
+ IMFByteStream_Release(file_byte_stream);
}
}
else
{
- object = (IUnknown *)stream;
- obj_type = MF_OBJECT_BYTESTREAM;
+ *out_object = (IUnknown *)file_byte_stream;
+ *out_obj_type = MF_OBJECT_BYTESTREAM;
}
}
- handler_result = heap_alloc(sizeof(*handler_result));
- if (handler_result)
- {
- handler_result->result = caller;
- IMFAsyncResult_AddRef(handler_result->result);
- handler_result->obj_type = obj_type;
- handler_result->object = object;
-
- EnterCriticalSection(&handler->cs);
- list_add_tail(&handler->results, &handler_result->entry);
- LeaveCriticalSection(&handler->cs);
- }
- else
- {
- if (object)
- IUnknown_Release(object);
- hr = E_OUTOFMEMORY;
- }
-
- IUnknown_Release(&context->IUnknown_iface);
-
- IMFAsyncResult_SetStatus(caller, hr);
- MFInvokeCallback(caller);
-
- return S_OK;
+ return hr;
}
-static const IMFAsyncCallbackVtbl file_scheme_handler_callback_vtbl =
-{
- file_scheme_handler_callback_QueryInterface,
- file_scheme_handler_callback_AddRef,
- file_scheme_handler_callback_Release,
- file_scheme_handler_callback_GetParameters,
- file_scheme_handler_callback_Invoke,
-};
-
static HRESULT file_scheme_handler_construct(REFIID riid, void **obj)
{
- struct file_scheme_handler *handler;
+ struct file_scheme_handler *this;
HRESULT hr;
TRACE("%s, %p.\n", debugstr_guid(riid), obj);
- handler = heap_alloc_zero(sizeof(*handler));
- if (!handler)
+ this = heap_alloc_zero(sizeof(*this));
+ if (!this)
return E_OUTOFMEMORY;
- handler->IMFSchemeHandler_iface.lpVtbl = &file_scheme_handler_vtbl;
- handler->IMFAsyncCallback_iface.lpVtbl = &file_scheme_handler_callback_vtbl;
- handler->refcount = 1;
- list_init(&handler->results);
- InitializeCriticalSection(&handler->cs);
+ handler_construct(&this->handler, file_scheme_handler_create_object);
+
+ this->IMFSchemeHandler_iface.lpVtbl = &file_scheme_handler_vtbl;
+ this->refcount = 1;
- hr = IMFSchemeHandler_QueryInterface(&handler->IMFSchemeHandler_iface, riid, obj);
- IMFSchemeHandler_Release(&handler->IMFSchemeHandler_iface);
+ hr = IMFSchemeHandler_QueryInterface(&this->IMFSchemeHandler_iface, riid, obj);
+ IMFSchemeHandler_Release(&this->IMFSchemeHandler_iface);
return hr;
}
diff --git a/dlls/winegstreamer/Makefile.in b/dlls/winegstreamer/Makefile.in
index 84916fe649..b00ce2586e 100644
--- a/dlls/winegstreamer/Makefile.in
+++ b/dlls/winegstreamer/Makefile.in
@@ -2,13 +2,14 @@ MODULE = winegstreamer.dll
IMPORTS = strmiids uuid winmm msacm32 msvfw32 ole32 oleaut32 user32 gdi32 advapi32 mfplat mfuuid
EXTRAINCL = $(GSTREAMER_CFLAGS)
EXTRALIBS = $(GSTREAMER_LIBS) $(PTHREAD_LIBS)
-PARENTSRC = ../strmbase
+PARENTSRC = ../strmbase ../mf
C_SRCS = \
dllfunc.c \
filter.c \
gst_cbs.c \
gstdemux.c \
+ handler.c \
main.c \
media_source.c \
mediatype.c \
diff --git a/dlls/winegstreamer/media_source.c b/dlls/winegstreamer/media_source.c
index 4e48c100b0..fce267ed3b 100644
--- a/dlls/winegstreamer/media_source.c
+++ b/dlls/winegstreamer/media_source.c
@@ -4,6 +4,7 @@
#include "gst_private.h"
#include "gst_cbs.h"
+#include "handler.h"
#include <stdarg.h>
@@ -1158,22 +1159,12 @@ static HRESULT media_source_constructor(IMFByteStream *bytestream, const char *d
/* IMFByteStreamHandler */
-struct container_stream_handler_result
-{
- struct list entry;
- IMFAsyncResult *result;
- MF_OBJECT_TYPE obj_type;
- IUnknown *object;
-};
-
struct container_stream_handler
{
IMFByteStreamHandler IMFByteStreamHandler_iface;
- IMFAsyncCallback IMFAsyncCallback_iface;
LONG refcount;
const char *demuxer_name;
- struct list results;
- CRITICAL_SECTION cs;
+ struct handler handler;
};
static struct container_stream_handler *impl_from_IMFByteStreamHandler(IMFByteStreamHandler *iface)
@@ -1181,11 +1172,6 @@ static struct container_stream_handler *impl_from_IMFByteStreamHandler(IMFByteSt
return CONTAINING_RECORD(iface, struct container_stream_handler, IMFByteStreamHandler_iface);
}
-static struct container_stream_handler *impl_from_IMFAsyncCallback(IMFAsyncCallback *iface)
-{
- return CONTAINING_RECORD(iface, struct container_stream_handler, IMFAsyncCallback_iface);
-}
-
static HRESULT WINAPI container_stream_handler_QueryInterface(IMFByteStreamHandler *iface, REFIID riid, void **obj)
{
TRACE("%p, %s, %p.\n", iface, debugstr_guid(riid), obj);
@@ -1215,245 +1201,44 @@ static ULONG WINAPI container_stream_handler_AddRef(IMFByteStreamHandler *iface)
static ULONG WINAPI container_stream_handler_Release(IMFByteStreamHandler *iface)
{
- struct container_stream_handler *handler = impl_from_IMFByteStreamHandler(iface);
- ULONG refcount = InterlockedDecrement(&handler->refcount);
- struct container_stream_handler_result *result, *next;
-
- TRACE("%p, refcount %u.\n", iface, refcount);
-
- if (!refcount)
- {
- LIST_FOR_EACH_ENTRY_SAFE(result, next, &handler->results, struct container_stream_handler_result, entry)
- {
- list_remove(&result->entry);
- IMFAsyncResult_Release(result->result);
- if (result->object)
- IUnknown_Release(result->object);
- heap_free(result);
- }
- DeleteCriticalSection(&handler->cs);
- heap_free(handler);
- }
-
- return refcount;
-}
-
-struct create_object_context
-{
- IUnknown IUnknown_iface;
- LONG refcount;
-
- IPropertyStore *props;
- IMFByteStream *stream;
- WCHAR *url;
- DWORD flags;
-};
-
-static struct create_object_context *impl_from_IUnknown(IUnknown *iface)
-{
- return CONTAINING_RECORD(iface, struct create_object_context, IUnknown_iface);
-}
-
-static HRESULT WINAPI create_object_context_QueryInterface(IUnknown *iface, REFIID riid, void **obj)
-{
- TRACE("%p, %s, %p.\n", iface, debugstr_guid(riid), obj);
-
- if (IsEqualIID(riid, &IID_IUnknown))
- {
- *obj = iface;
- IUnknown_AddRef(iface);
- return S_OK;
- }
-
- WARN("Unsupported %s.\n", debugstr_guid(riid));
- *obj = NULL;
- return E_NOINTERFACE;
-}
-
-static ULONG WINAPI create_object_context_AddRef(IUnknown *iface)
-{
- struct create_object_context *context = impl_from_IUnknown(iface);
- ULONG refcount = InterlockedIncrement(&context->refcount);
-
- TRACE("%p, refcount %u.\n", iface, refcount);
-
- return refcount;
-}
-
-static ULONG WINAPI create_object_context_Release(IUnknown *iface)
-{
- struct create_object_context *context = impl_from_IUnknown(iface);
- ULONG refcount = InterlockedDecrement(&context->refcount);
+ struct container_stream_handler *this = impl_from_IMFByteStreamHandler(iface);
+ ULONG refcount = InterlockedDecrement(&this->refcount);
TRACE("%p, refcount %u.\n", iface, refcount);
if (!refcount)
{
- if (context->props)
- IPropertyStore_Release(context->props);
- if (context->stream)
- IMFByteStream_Release(context->stream);
- if (context->url)
- heap_free(context->url);
- heap_free(context);
+ handler_destruct(&this->handler);
+ heap_free(this);
}
return refcount;
}
-static const IUnknownVtbl create_object_context_vtbl =
-{
- create_object_context_QueryInterface,
- create_object_context_AddRef,
- create_object_context_Release,
-};
-
-static WCHAR *heap_strdupW(const WCHAR *str)
-{
- WCHAR *ret = NULL;
-
- if (str)
- {
- unsigned int size;
-
- size = (lstrlenW(str) + 1) * sizeof(WCHAR);
- ret = heap_alloc(size);
- if (ret)
- memcpy(ret, str, size);
- }
-
- return ret;
-}
-
static HRESULT WINAPI container_stream_handler_BeginCreateObject(IMFByteStreamHandler *iface, IMFByteStream *stream, const WCHAR *url, DWORD flags,
IPropertyStore *props, IUnknown **cancel_cookie, IMFAsyncCallback *callback, IUnknown *state)
{
struct container_stream_handler *this = impl_from_IMFByteStreamHandler(iface);
- struct create_object_context *context;
- IMFAsyncResult *caller, *item;
- HRESULT hr;
TRACE("%p, %s, %#x, %p, %p, %p, %p.\n", iface, debugstr_w(url), flags, props, cancel_cookie, callback, state);
-
- if (cancel_cookie)
- *cancel_cookie = NULL;
-
- if (FAILED(hr = MFCreateAsyncResult(NULL, callback, state, &caller)))
- return hr;
-
- context = heap_alloc(sizeof(*context));
- if (!context)
- {
- IMFAsyncResult_Release(caller);
- return E_OUTOFMEMORY;
- }
-
- context->IUnknown_iface.lpVtbl = &create_object_context_vtbl;
- context->refcount = 1;
- context->props = props;
- if (context->props)
- IPropertyStore_AddRef(context->props);
- context->flags = flags;
- context->stream = stream;
- if (context->stream)
- IMFByteStream_AddRef(context->stream);
- if (url)
- context->url = heap_strdupW(url);
- if (!context->stream)
- {
- IMFAsyncResult_Release(caller);
- IUnknown_Release(&context->IUnknown_iface);
- return E_OUTOFMEMORY;
- }
-
- hr = MFCreateAsyncResult(&context->IUnknown_iface, &this->IMFAsyncCallback_iface, (IUnknown *)caller, &item);
- IUnknown_Release(&context->IUnknown_iface);
- IMFAsyncResult_Release(caller);
- if (SUCCEEDED(hr))
- {
- if (SUCCEEDED(hr = MFPutWorkItemEx(MFASYNC_CALLBACK_QUEUE_IO, item)))
- {
- if (cancel_cookie)
- IMFAsyncResult_GetState(item, cancel_cookie);
- }
-
- IMFAsyncResult_Release(item);
- }
-
- return hr;
+ return handler_begin_create_object(&this->handler, stream, url, flags, props, cancel_cookie, callback, state);
}
static HRESULT WINAPI container_stream_handler_EndCreateObject(IMFByteStreamHandler *iface, IMFAsyncResult *result,
MF_OBJECT_TYPE *obj_type, IUnknown **object)
{
struct container_stream_handler *this = impl_from_IMFByteStreamHandler(iface);
- struct container_stream_handler_result *found = NULL, *cur;
- HRESULT hr;
TRACE("%p, %p, %p, %p.\n", iface, result, obj_type, object);
-
- EnterCriticalSection(&this->cs);
-
- LIST_FOR_EACH_ENTRY(cur, &this->results, struct container_stream_handler_result, entry)
- {
- if (result == cur->result)
- {
- list_remove(&cur->entry);
- found = cur;
- break;
- }
- }
-
- LeaveCriticalSection(&this->cs);
-
- if (found)
- {
- *obj_type = found->obj_type;
- *object = found->object;
- hr = IMFAsyncResult_GetStatus(found->result);
- IMFAsyncResult_Release(found->result);
- heap_free(found);
- }
- else
- {
- *obj_type = MF_OBJECT_INVALID;
- *object = NULL;
- hr = MF_E_UNEXPECTED;
- }
-
- return hr;
+ return handler_end_create_object(&this->handler, result, obj_type, object);
}
static HRESULT WINAPI container_stream_handler_CancelObjectCreation(IMFByteStreamHandler *iface, IUnknown *cancel_cookie)
{
struct container_stream_handler *this = impl_from_IMFByteStreamHandler(iface);
- struct container_stream_handler_result *found = NULL, *cur;
TRACE("%p, %p.\n", iface, cancel_cookie);
-
- EnterCriticalSection(&this->cs);
-
- LIST_FOR_EACH_ENTRY(cur, &this->results, struct container_stream_handler_result, entry)
- {
- if (cancel_cookie == (IUnknown *)cur->result)
- {
- list_remove(&cur->entry);
- found = cur;
- break;
- }
- }
-
- LeaveCriticalSection(&this->cs);
-
- if (found)
- {
- IMFAsyncResult_Release(found->result);
- if (found->object)
- IUnknown_Release(found->object);
- heap_free(found);
- }
-
- return found ? S_OK : MF_E_UNEXPECTED;
+ return handler_cancel_object_creation(&this->handler, cancel_cookie);
}
static HRESULT WINAPI container_stream_handler_GetMaxNumberOfBytesRequiredForResolution(IMFByteStreamHandler *iface, QWORD *bytes)
@@ -1473,42 +1258,10 @@ static const IMFByteStreamHandlerVtbl container_stream_handler_vtbl =
container_stream_handler_GetMaxNumberOfBytesRequiredForResolution,
};
-static HRESULT WINAPI container_stream_handler_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 container_stream_handler_callback_AddRef(IMFAsyncCallback *iface)
-{
- struct container_stream_handler *handler = impl_from_IMFAsyncCallback(iface);
- return IMFByteStreamHandler_AddRef(&handler->IMFByteStreamHandler_iface);
-}
-
-static ULONG WINAPI container_stream_handler_callback_Release(IMFAsyncCallback *iface)
-{
- struct container_stream_handler *handler = impl_from_IMFAsyncCallback(iface);
- return IMFByteStreamHandler_Release(&handler->IMFByteStreamHandler_iface);
-}
-
-static HRESULT WINAPI container_stream_handler_callback_GetParameters(IMFAsyncCallback *iface, DWORD *flags, DWORD *queue)
-{
- return E_NOTIMPL;
-}
-
-static HRESULT container_stream_handler_create_object(struct container_stream_handler *This, WCHAR *url, IMFByteStream *stream, DWORD flags,
+static HRESULT container_stream_handler_create_object(struct handler *handler, WCHAR *url, IMFByteStream *stream, DWORD flags,
IPropertyStore *props, IUnknown **out_object, MF_OBJECT_TYPE *out_obj_type)
{
- TRACE("(%p %s %p %u %p %p %p)\n", This, debugstr_w(url), stream, flags, props, out_object, out_obj_type);
+ TRACE("(%p %s %p %u %p %p %p)\n", handler, debugstr_w(url), stream, flags, props, out_object, out_obj_type);
if (!(init_gstreamer()))
return E_FAIL;
@@ -1517,6 +1270,7 @@ static HRESULT container_stream_handler_create_object(struct container_stream_ha
{
HRESULT hr;
struct media_source *new_source;
+ struct container_stream_handler *This = CONTAINING_RECORD(handler, struct container_stream_handler, handler);
if (FAILED(hr = media_source_constructor(stream, This->demuxer_name, &new_source)))
return hr;
@@ -1535,64 +1289,6 @@ static HRESULT container_stream_handler_create_object(struct container_stream_ha
}
}
-static HRESULT WINAPI container_stream_handler_callback_Invoke(IMFAsyncCallback *iface, IMFAsyncResult *result)
-{
- struct container_stream_handler *handler = impl_from_IMFAsyncCallback(iface);
- struct container_stream_handler_result *handler_result;
- MF_OBJECT_TYPE obj_type = MF_OBJECT_INVALID;
- IUnknown *object = NULL, *context_object;
- struct create_object_context *context;
- IMFAsyncResult *caller;
- HRESULT hr;
-
- caller = (IMFAsyncResult *)IMFAsyncResult_GetStateNoAddRef(result);
-
- if (FAILED(hr = IMFAsyncResult_GetObject(result, &context_object)))
- {
- WARN("Expected context set for callee result.\n");
- return hr;
- }
-
- context = impl_from_IUnknown(context_object);
-
- hr = container_stream_handler_create_object(handler, context->url, context->stream, context->flags, context->props, &object, &obj_type);
-
- handler_result = heap_alloc(sizeof(*handler_result));
- if (handler_result)
- {
- handler_result->result = caller;
- IMFAsyncResult_AddRef(handler_result->result);
- handler_result->obj_type = obj_type;
- handler_result->object = object;
-
- EnterCriticalSection(&handler->cs);
- list_add_tail(&handler->results, &handler_result->entry);
- LeaveCriticalSection(&handler->cs);
- }
- else
- {
- if (object)
- IUnknown_Release(object);
- hr = E_OUTOFMEMORY;
- }
-
- IUnknown_Release(&context->IUnknown_iface);
-
- IMFAsyncResult_SetStatus(caller, hr);
- MFInvokeCallback(caller);
-
- return S_OK;
-}
-
-static const IMFAsyncCallbackVtbl container_stream_handler_callback_vtbl =
-{
- container_stream_handler_callback_QueryInterface,
- container_stream_handler_callback_AddRef,
- container_stream_handler_callback_Release,
- container_stream_handler_callback_GetParameters,
- container_stream_handler_callback_Invoke,
-};
-
HRESULT container_stream_handler_construct(REFIID riid, void **obj, const char *demuxer_name)
{
struct container_stream_handler *this;
@@ -1604,12 +1300,10 @@ HRESULT container_stream_handler_construct(REFIID riid, void **obj, const char *
if (!this)
return E_OUTOFMEMORY;
- list_init(&this->results);
- InitializeCriticalSection(&this->cs);
+ handler_construct(&this->handler, container_stream_handler_create_object);
this->demuxer_name = demuxer_name;
this->IMFByteStreamHandler_iface.lpVtbl = &container_stream_handler_vtbl;
- this->IMFAsyncCallback_iface.lpVtbl = &container_stream_handler_callback_vtbl;
this->refcount = 1;
hr = IMFByteStreamHandler_QueryInterface(&this->IMFByteStreamHandler_iface, riid, obj);
--
2.25.0
More information about the wine-devel
mailing list