mfplat: Implement MFCreateAsyncResult().
Signed-off-by: Nikolay Sivov <nsivov@codeweavers.com> Signed-off-by: Alexandre Julliard <julliard@winehq.org>
This commit is contained in:
parent
cfc323db26
commit
9a6fcdf42f
|
@ -3,4 +3,5 @@ IMPORTLIB = mfplat
|
|||
IMPORTS = advapi32 ole32
|
||||
|
||||
C_SRCS = \
|
||||
main.c
|
||||
main.c \
|
||||
queue.c
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
}
|
|
@ -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();
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
|
|
Loading…
Reference in New Issue