mfplat: Implement MFCreateAsyncResult().

Signed-off-by: Nikolay Sivov <nsivov@codeweavers.com>
Signed-off-by: Alexandre Julliard <julliard@winehq.org>
stable
Nikolay Sivov 2019-02-18 16:24:09 +03:00 committed by Alexandre Julliard
parent cfc323db26
commit 9a6fcdf42f
5 changed files with 347 additions and 2 deletions

View File

@ -3,4 +3,5 @@ IMPORTLIB = mfplat
IMPORTS = advapi32 ole32
C_SRCS = \
main.c
main.c \
queue.c

View File

@ -38,7 +38,7 @@
@ stdcall MFCopyImage(ptr long ptr long long long)
@ stub MFCreateAMMediaTypeFromMFMediaType
@ stub MFCreateAlignedMemoryBuffer
@ stub MFCreateAsyncResult
@ stdcall MFCreateAsyncResult(ptr ptr ptr ptr)
@ stdcall MFCreateAttributes(ptr long)
@ stub MFCreateAudioMediaType
@ stub MFCreateCollection

190
dlls/mfplat/queue.c 100644
View File

@ -0,0 +1,190 @@
/*
* Copyright 2019 Nikolay Sivov for CodeWeavers
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
*/
#include <stdarg.h>
#define COBJMACROS
#include "mfapi.h"
#include "wine/debug.h"
#include "wine/heap.h"
WINE_DEFAULT_DEBUG_CHANNEL(mfplat);
struct async_result
{
MFASYNCRESULT result;
LONG refcount;
IUnknown *object;
IUnknown *state;
};
static struct async_result *impl_from_IMFAsyncResult(IMFAsyncResult *iface)
{
return CONTAINING_RECORD(iface, struct async_result, result.AsyncResult);
}
static HRESULT WINAPI async_result_QueryInterface(IMFAsyncResult *iface, REFIID riid, void **obj)
{
TRACE("%p, %s, %p.\n", iface, debugstr_guid(riid), obj);
if (IsEqualIID(riid, &IID_IMFAsyncResult) ||
IsEqualIID(riid, &IID_IUnknown))
{
*obj = iface;
IMFAsyncResult_AddRef(iface);
return S_OK;
}
*obj = NULL;
WARN("Unsupported interface %s.\n", debugstr_guid(riid));
return E_NOINTERFACE;
}
static ULONG WINAPI async_result_AddRef(IMFAsyncResult *iface)
{
struct async_result *result = impl_from_IMFAsyncResult(iface);
ULONG refcount = InterlockedIncrement(&result->refcount);
TRACE("%p, %u.\n", iface, refcount);
return refcount;
}
static ULONG WINAPI async_result_Release(IMFAsyncResult *iface)
{
struct async_result *result = impl_from_IMFAsyncResult(iface);
ULONG refcount = InterlockedDecrement(&result->refcount);
TRACE("%p, %u.\n", iface, refcount);
if (!refcount)
{
if (result->result.pCallback)
IMFAsyncCallback_Release(result->result.pCallback);
if (result->object)
IUnknown_Release(result->object);
if (result->state)
IUnknown_Release(result->state);
heap_free(result);
}
return refcount;
}
static HRESULT WINAPI async_result_GetState(IMFAsyncResult *iface, IUnknown **state)
{
struct async_result *result = impl_from_IMFAsyncResult(iface);
TRACE("%p, %p.\n", iface, state);
if (!result->state)
return E_POINTER;
*state = result->state;
IUnknown_AddRef(*state);
return S_OK;
}
static HRESULT WINAPI async_result_GetStatus(IMFAsyncResult *iface)
{
struct async_result *result = impl_from_IMFAsyncResult(iface);
TRACE("%p.\n", iface);
return result->result.hrStatusResult;
}
static HRESULT WINAPI async_result_SetStatus(IMFAsyncResult *iface, HRESULT status)
{
struct async_result *result = impl_from_IMFAsyncResult(iface);
TRACE("%p, %#x.\n", iface, status);
result->result.hrStatusResult = status;
return S_OK;
}
static HRESULT WINAPI async_result_GetObject(IMFAsyncResult *iface, IUnknown **object)
{
struct async_result *result = impl_from_IMFAsyncResult(iface);
TRACE("%p, %p.\n", iface, object);
if (!result->object)
return E_POINTER;
*object = result->object;
IUnknown_AddRef(*object);
return S_OK;
}
static IUnknown * WINAPI async_result_GetStateNoAddRef(IMFAsyncResult *iface)
{
struct async_result *result = impl_from_IMFAsyncResult(iface);
TRACE("%p.\n", iface);
return result->state;
}
static const IMFAsyncResultVtbl async_result_vtbl =
{
async_result_QueryInterface,
async_result_AddRef,
async_result_Release,
async_result_GetState,
async_result_GetStatus,
async_result_SetStatus,
async_result_GetObject,
async_result_GetStateNoAddRef,
};
HRESULT WINAPI MFCreateAsyncResult(IUnknown *object, IMFAsyncCallback *callback, IUnknown *state, IMFAsyncResult **out)
{
struct async_result *result;
TRACE("%p, %p, %p, %p.\n", object, callback, state, out);
if (!out)
return E_INVALIDARG;
result = heap_alloc_zero(sizeof(*result));
if (!result)
return E_OUTOFMEMORY;
result->result.AsyncResult.lpVtbl = &async_result_vtbl;
result->refcount = 1;
result->object = object;
if (result->object)
IUnknown_AddRef(result->object);
result->result.pCallback = callback;
if (result->result.pCallback)
IMFAsyncCallback_AddRef(result->result.pCallback);
result->state = state;
if (result->state)
IUnknown_AddRef(result->state);
*out = &result->result.AsyncResult;
return S_OK;
}

View File

@ -693,6 +693,145 @@ static void test_MFSample(void)
IMFSample_Release(sample);
}
static HRESULT WINAPI testcallback_QueryInterface(IMFAsyncCallback *iface, REFIID riid, void **obj)
{
if (IsEqualIID(riid, &IID_IMFAsyncCallback) ||
IsEqualIID(riid, &IID_IUnknown))
{
*obj = iface;
IMFAsyncCallback_AddRef(iface);
return S_OK;
}
*obj = NULL;
return E_NOINTERFACE;
}
static ULONG WINAPI testcallback_AddRef(IMFAsyncCallback *iface)
{
return 2;
}
static ULONG WINAPI testcallback_Release(IMFAsyncCallback *iface)
{
return 1;
}
static HRESULT WINAPI testcallback_GetParameters(IMFAsyncCallback *iface, DWORD *flags, DWORD *queue)
{
ok(0, "Unexpected call.\n");
return E_NOTIMPL;
}
static HRESULT WINAPI testcallback_Invoke(IMFAsyncCallback *iface, IMFAsyncResult *result)
{
ok(0, "Unexpected call.\n");
return E_NOTIMPL;
}
static const IMFAsyncCallbackVtbl testcallbackvtbl =
{
testcallback_QueryInterface,
testcallback_AddRef,
testcallback_Release,
testcallback_GetParameters,
testcallback_Invoke,
};
static void test_MFCreateAsyncResult(void)
{
IMFAsyncCallback callback = { &testcallbackvtbl };
IMFAsyncResult *result, *result2;
IUnknown *state, *object;
MFASYNCRESULT *data;
ULONG refcount;
HRESULT hr;
hr = MFCreateAsyncResult(NULL, NULL, NULL, NULL);
ok(FAILED(hr), "Unexpected hr %#x.\n", hr);
hr = MFCreateAsyncResult(NULL, NULL, NULL, &result);
ok(hr == S_OK, "Failed to create object, hr %#x.\n", hr);
data = (MFASYNCRESULT *)result;
ok(data->pCallback == NULL, "Unexpected callback value.\n");
ok(data->hrStatusResult == S_OK, "Unexpected status %#x.\n", data->hrStatusResult);
ok(data->dwBytesTransferred == 0, "Unexpected byte length %u.\n", data->dwBytesTransferred);
ok(data->hEvent == NULL, "Unexpected event.\n");
hr = IMFAsyncResult_GetState(result, NULL);
ok(hr == E_POINTER, "Unexpected hr %#x.\n", hr);
state = (void *)0xdeadbeef;
hr = IMFAsyncResult_GetState(result, &state);
ok(hr == E_POINTER, "Unexpected hr %#x.\n", hr);
ok(state == (void *)0xdeadbeef, "Unexpected state.\n");
hr = IMFAsyncResult_GetStatus(result);
ok(hr == S_OK, "Unexpected status %#x.\n", hr);
data->hrStatusResult = 123;
hr = IMFAsyncResult_GetStatus(result);
ok(hr == 123, "Unexpected status %#x.\n", hr);
hr = IMFAsyncResult_SetStatus(result, E_FAIL);
ok(hr == S_OK, "Failed to set status, hr %#x.\n", hr);
ok(data->hrStatusResult == E_FAIL, "Unexpected status %#x.\n", hr);
hr = IMFAsyncResult_GetObject(result, NULL);
ok(hr == E_POINTER, "Unexpected hr %#x.\n", hr);
object = (void *)0xdeadbeef;
hr = IMFAsyncResult_GetObject(result, &object);
ok(hr == E_POINTER, "Failed to get object, hr %#x.\n", hr);
ok(object == (void *)0xdeadbeef, "Unexpected object.\n");
state = IMFAsyncResult_GetStateNoAddRef(result);
ok(state == NULL, "Unexpected state.\n");
/* Object. */
hr = MFCreateAsyncResult((IUnknown *)result, &callback, NULL, &result2);
ok(hr == S_OK, "Failed to create object, hr %#x.\n", hr);
data = (MFASYNCRESULT *)result2;
ok(data->pCallback == &callback, "Unexpected callback value.\n");
ok(data->hrStatusResult == S_OK, "Unexpected status %#x.\n", data->hrStatusResult);
ok(data->dwBytesTransferred == 0, "Unexpected byte length %u.\n", data->dwBytesTransferred);
ok(data->hEvent == NULL, "Unexpected event.\n");
object = NULL;
hr = IMFAsyncResult_GetObject(result2, &object);
ok(hr == S_OK, "Failed to get object, hr %#x.\n", hr);
ok(object == (IUnknown *)result, "Unexpected object.\n");
IUnknown_Release(object);
IMFAsyncResult_Release(result2);
/* State object. */
hr = MFCreateAsyncResult(NULL, &callback, (IUnknown *)result, &result2);
ok(hr == S_OK, "Failed to create object, hr %#x.\n", hr);
data = (MFASYNCRESULT *)result2;
ok(data->pCallback == &callback, "Unexpected callback value.\n");
ok(data->hrStatusResult == S_OK, "Unexpected status %#x.\n", data->hrStatusResult);
ok(data->dwBytesTransferred == 0, "Unexpected byte length %u.\n", data->dwBytesTransferred);
ok(data->hEvent == NULL, "Unexpected event.\n");
state = NULL;
hr = IMFAsyncResult_GetState(result2, &state);
ok(hr == S_OK, "Failed to get state object, hr %#x.\n", hr);
ok(state == (IUnknown *)result, "Unexpected state.\n");
IUnknown_Release(state);
state = IMFAsyncResult_GetStateNoAddRef(result2);
ok(state == (IUnknown *)result, "Unexpected state.\n");
refcount = IMFAsyncResult_Release(result2);
ok(!refcount, "Unexpected refcount %u\n.", refcount);
refcount = IMFAsyncResult_Release(result);
ok(!refcount, "Unexpected refcount %u\n.", refcount);
}
START_TEST(mfplat)
{
CoInitialize(NULL);
@ -708,6 +847,7 @@ START_TEST(mfplat)
test_MFCreateMFByteStreamOnStream();
test_MFCreateMemoryBuffer();
test_source_resolver();
test_MFCreateAsyncResult();
CoUninitialize();
}

View File

@ -54,6 +54,19 @@ extern "C" {
DEFINE_MEDIATYPE_GUID(MFVideoFormat_WMV3, MAKEFOURCC('W','M','V','3'));
DEFINE_MEDIATYPE_GUID(MFVideoFormat_RGB32, D3DFMT_X8R8G8B8);
#if defined(__cplusplus) && !defined(CINTERFACE)
typedef struct tagMFASYNCRESULT : public IMFAsyncResult {
#else
typedef struct tagMFASYNCRESULT
{
IMFAsyncResult AsyncResult;
#endif
OVERLAPPED overlapped;
IMFAsyncCallback *pCallback;
HRESULT hrStatusResult;
DWORD dwBytesTransferred;
HANDLE hEvent;
} MFASYNCRESULT;
DEFINE_GUID(MF_MT_AVG_BITRATE, 0x20332624, 0xfb0d, 0x4d9e, 0xbd, 0x0d, 0xcb, 0xf6, 0x78, 0x6c, 0x10, 0x2e);
DEFINE_GUID(MF_MT_FRAME_RATE, 0xc459a2e8, 0x3d2c, 0x4e44, 0xb1, 0x32, 0xfe, 0xe5, 0x15, 0x6c, 0x7b, 0xb0);
@ -70,6 +83,7 @@ typedef unsigned __int64 MFWORKITEM_KEY;
HRESULT WINAPI MFCancelWorkItem(MFWORKITEM_KEY key);
HRESULT WINAPI MFCopyImage(BYTE *dest, LONG deststride, const BYTE *src, LONG srcstride, DWORD width, DWORD lines);
HRESULT WINAPI MFCreateAttributes(IMFAttributes **attributes, UINT32 size);
HRESULT WINAPI MFCreateAsyncResult(IUnknown *object, IMFAsyncCallback *callback, IUnknown *state, IMFAsyncResult **result);
HRESULT WINAPI MFCreateEventQueue(IMFMediaEventQueue **queue);
HRESULT WINAPI MFCreateFile(MF_FILE_ACCESSMODE accessmode, MF_FILE_OPENMODE openmode, MF_FILE_FLAGS flags,
LPCWSTR url, IMFByteStream **bytestream);