Nikolay Sivov : mfplat: Implement async method of creating objects from bytestreams.

Alexandre Julliard julliard at winehq.org
Mon Mar 11 16:29:53 CDT 2019


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

Author: Nikolay Sivov <nsivov at codeweavers.com>
Date:   Mon Mar 11 13:28:10 2019 +0300

mfplat: Implement async method of creating objects from bytestreams.

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

---

 dlls/mfplat/main.c | 193 +++++++++++++++++++++++++++++++++++++++++++++--------
 1 file changed, 166 insertions(+), 27 deletions(-)

diff --git a/dlls/mfplat/main.c b/dlls/mfplat/main.c
index 0e62052..06be27d 100644
--- a/dlls/mfplat/main.c
+++ b/dlls/mfplat/main.c
@@ -1919,6 +1919,19 @@ struct resolver_queued_result
     enum resolved_object_origin origin;
 };
 
+struct resolver_cancel_object
+{
+    IUnknown IUnknown_iface;
+    LONG refcount;
+    union
+    {
+        IUnknown *handler;
+        IMFByteStreamHandler *stream_handler;
+    } u;
+    IUnknown *cancel_cookie;
+    enum resolved_object_origin origin;
+};
+
 typedef struct source_resolver
 {
     IMFSourceResolver IMFSourceResolver_iface;
@@ -1976,6 +1989,17 @@ static HRESULT resolver_handler_end_create(struct source_resolver *resolver, enu
 
         if (data->hEvent)
             SetEvent(data->hEvent);
+        else
+        {
+            IUnknown *caller_state = IMFAsyncResult_GetStateNoAddRef(inner_result);
+            IMFAsyncResult *caller_result;
+
+            if (SUCCEEDED(MFCreateAsyncResult(queued_result->object, data->pCallback, caller_state, &caller_result)))
+            {
+                MFInvokeCallback(caller_result);
+                IMFAsyncResult_Release(caller_result);
+            }
+        }
     }
     else
         heap_free(queued_result);
@@ -1983,6 +2007,84 @@ static HRESULT resolver_handler_end_create(struct source_resolver *resolver, enu
     return S_OK;
 }
 
+static struct resolver_cancel_object *impl_cancel_obj_from_IUnknown(IUnknown *iface)
+{
+    return CONTAINING_RECORD(iface, struct resolver_cancel_object, IUnknown_iface);
+}
+
+static HRESULT WINAPI resolver_cancel_object_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 resolver_cancel_object_AddRef(IUnknown *iface)
+{
+    struct resolver_cancel_object *object = impl_cancel_obj_from_IUnknown(iface);
+    return InterlockedIncrement(&object->refcount);
+}
+
+static ULONG WINAPI resolver_cancel_object_Release(IUnknown *iface)
+{
+    struct resolver_cancel_object *object = impl_cancel_obj_from_IUnknown(iface);
+    ULONG refcount = InterlockedDecrement(&object->refcount);
+
+    if (!refcount)
+    {
+        if (object->cancel_cookie)
+            IUnknown_Release(object->cancel_cookie);
+        IUnknown_Release(object->u.handler);
+        heap_free(object);
+    }
+
+    return refcount;
+}
+
+static const IUnknownVtbl resolver_cancel_object_vtbl =
+{
+    resolver_cancel_object_QueryInterface,
+    resolver_cancel_object_AddRef,
+    resolver_cancel_object_Release,
+};
+
+static struct resolver_cancel_object *unsafe_impl_cancel_obj_from_IUnknown(IUnknown *iface)
+{
+    if (!iface)
+        return NULL;
+
+    return (iface->lpVtbl == &resolver_cancel_object_vtbl) ?
+            CONTAINING_RECORD(iface, struct resolver_cancel_object, IUnknown_iface) : NULL;
+}
+
+static HRESULT resolver_create_cancel_object(IUnknown *handler, enum resolved_object_origin origin,
+        IUnknown *cancel_cookie, IUnknown **cancel_object)
+{
+    struct resolver_cancel_object *object;
+
+    object = heap_alloc_zero(sizeof(*object));
+    if (!object)
+        return E_OUTOFMEMORY;
+
+    object->IUnknown_iface.lpVtbl = &resolver_cancel_object_vtbl;
+    object->refcount = 1;
+    object->u.handler = handler;
+    IUnknown_AddRef(object->u.handler);
+    object->cancel_cookie = cancel_cookie;
+    IUnknown_AddRef(object->cancel_cookie);
+    object->origin = origin;
+
+    *cancel_object = &object->IUnknown_iface;
+
+    return S_OK;
+}
+
 static HRESULT WINAPI source_resolver_callback_QueryInterface(IMFAsyncCallback *iface, REFIID riid, void **obj)
 {
     if (IsEqualIID(riid, &IID_IMFAsyncCallback) ||
@@ -2160,7 +2262,7 @@ static HRESULT resolver_end_create_object(struct source_resolver *resolver, enum
     return hr;
 }
 
-static HRESULT WINAPI mfsourceresolver_QueryInterface(IMFSourceResolver *iface, REFIID riid, void **obj)
+static HRESULT WINAPI source_resolver_QueryInterface(IMFSourceResolver *iface, REFIID riid, void **obj)
 {
     mfsourceresolver *This = impl_from_IMFSourceResolver(iface);
 
@@ -2309,49 +2411,86 @@ static HRESULT WINAPI mfsourceresolver_EndCreateObjectFromURL(IMFSourceResolver
     return E_NOTIMPL;
 }
 
-static HRESULT WINAPI mfsourceresolver_BeginCreateObjectFromByteStream(IMFSourceResolver *iface, IMFByteStream *stream,
-    const WCHAR *url, DWORD flags, IPropertyStore *props, IUnknown **cancel_cookie, IMFAsyncCallback *callback,
-    IUnknown *unk_state)
+static HRESULT WINAPI source_resolver_BeginCreateObjectFromByteStream(IMFSourceResolver *iface, IMFByteStream *stream,
+        const WCHAR *url, DWORD flags, IPropertyStore *props, IUnknown **cancel_cookie, IMFAsyncCallback *callback,
+        IUnknown *state)
 {
-    mfsourceresolver *This = impl_from_IMFSourceResolver(iface);
+    struct source_resolver *resolver = impl_from_IMFSourceResolver(iface);
+    IMFByteStreamHandler *handler;
+    IUnknown *inner_cookie = NULL;
+    IMFAsyncResult *result;
+    HRESULT hr;
 
-    FIXME("(%p)->(%p, %s, %#x, %p, %p, %p, %p): stub\n", This, stream, debugstr_w(url), flags, props, cancel_cookie,
-        callback, unk_state);
+    TRACE("%p, %p, %s, %#x, %p, %p, %p, %p.\n", iface, stream, debugstr_w(url), flags, props, cancel_cookie,
+            callback, state);
 
-    return E_NOTIMPL;
+    if (FAILED(hr = resolver_get_bytestream_handler(stream, url, flags, &handler)))
+        return hr;
+
+    if (cancel_cookie)
+        *cancel_cookie = NULL;
+
+    hr = MFCreateAsyncResult((IUnknown *)handler, callback, state, &result);
+    IMFByteStreamHandler_Release(handler);
+    if (FAILED(hr))
+        return hr;
+
+    hr = IMFByteStreamHandler_BeginCreateObject(handler, stream, url, flags, props,
+            cancel_cookie ? &inner_cookie : NULL, &resolver->stream_callback, (IUnknown *)result);
+
+    /* Cancel object wraps underlying handler cancel cookie with context necessary to call CancelObjectCreate(). */
+    if (SUCCEEDED(hr) && inner_cookie)
+        resolver_create_cancel_object((IUnknown *)handler, OBJECT_FROM_BYTESTREAM, inner_cookie, cancel_cookie);
+
+    IMFAsyncResult_Release(result);
+
+    return hr;
 }
 
-static HRESULT WINAPI mfsourceresolver_EndCreateObjectFromByteStream(IMFSourceResolver *iface, IMFAsyncResult *result,
-    MF_OBJECT_TYPE *obj_type, IUnknown **object)
+static HRESULT WINAPI source_resolver_EndCreateObjectFromByteStream(IMFSourceResolver *iface, IMFAsyncResult *result,
+        MF_OBJECT_TYPE *obj_type, IUnknown **object)
 {
-    mfsourceresolver *This = impl_from_IMFSourceResolver(iface);
+    struct source_resolver *resolver = impl_from_IMFSourceResolver(iface);
 
-    FIXME("(%p)->(%p, %p, %p): stub\n", This, result, obj_type, object);
+    TRACE("%p, %p, %p, %p.\n", iface, result, obj_type, object);
 
-    return E_NOTIMPL;
+    return resolver_end_create_object(resolver, OBJECT_FROM_BYTESTREAM, result, obj_type, object);
 }
 
-static HRESULT WINAPI mfsourceresolver_CancelObjectCreation(IMFSourceResolver *iface, IUnknown *cancel_cookie)
+static HRESULT WINAPI source_resolver_CancelObjectCreation(IMFSourceResolver *iface, IUnknown *cancel_cookie)
 {
-    mfsourceresolver *This = impl_from_IMFSourceResolver(iface);
+    struct resolver_cancel_object *object;
+    HRESULT hr;
 
-    FIXME("(%p)->(%p): stub\n", This, cancel_cookie);
+    TRACE("%p, %p.\n", iface, cancel_cookie);
 
-    return E_NOTIMPL;
+    if (!(object = unsafe_impl_cancel_obj_from_IUnknown(cancel_cookie)))
+        return E_UNEXPECTED;
+
+    switch (object->origin)
+    {
+        case OBJECT_FROM_BYTESTREAM:
+            hr = IMFByteStreamHandler_CancelObjectCreation(object->u.stream_handler, object->cancel_cookie);
+            break;
+        default:
+            hr = E_UNEXPECTED;
+    }
+
+    return hr;
 }
 
 static const IMFSourceResolverVtbl mfsourceresolvervtbl =
 {
-   mfsourceresolver_QueryInterface,
-   source_resolver_AddRef,
-   source_resolver_Release,
-   mfsourceresolver_CreateObjectFromURL,
-   source_resolver_CreateObjectFromByteStream,
-   mfsourceresolver_BeginCreateObjectFromURL,
-   mfsourceresolver_EndCreateObjectFromURL,
-   mfsourceresolver_BeginCreateObjectFromByteStream,
-   mfsourceresolver_EndCreateObjectFromByteStream,
-   mfsourceresolver_CancelObjectCreation,
+    source_resolver_QueryInterface,
+    source_resolver_AddRef,
+    source_resolver_Release,
+    mfsourceresolver_CreateObjectFromURL,
+    source_resolver_CreateObjectFromByteStream,
+    mfsourceresolver_BeginCreateObjectFromURL,
+    mfsourceresolver_EndCreateObjectFromURL,
+    source_resolver_BeginCreateObjectFromByteStream,
+    source_resolver_EndCreateObjectFromByteStream,
+    source_resolver_CancelObjectCreation,
 };
 
 /***********************************************************************




More information about the wine-cvs mailing list