mfplat/tests: Add some tests for D3D11-aware sample allocator.

Signed-off-by: Nikolay Sivov <nsivov@codeweavers.com>
Signed-off-by: Alexandre Julliard <julliard@winehq.org>
This commit is contained in:
Nikolay Sivov 2021-02-02 19:56:13 +03:00 committed by Alexandre Julliard
parent 33e0d15d17
commit be5b34b1ee
3 changed files with 427 additions and 1 deletions

View File

@ -70,6 +70,13 @@ static void _expect_ref(IUnknown *obj, ULONG ref, int line)
ok_(__FILE__,line)(rc == ref, "Unexpected refcount %d, expected %d.\n", rc, ref);
}
static ULONG get_refcount(void *iface)
{
IUnknown *unknown = iface;
IUnknown_AddRef(unknown);
return IUnknown_Release(unknown);
}
#define check_interface(a, b, c) check_interface_(__LINE__, a, b, c)
static void check_interface_(unsigned int line, void *iface_ptr, REFIID iid, BOOL supported)
{
@ -124,6 +131,9 @@ static HRESULT (WINAPI *pMFCreateMediaBufferFromMediaType)(IMFMediaType *media_t
static HRESULT (WINAPI *pMFCreateDXSurfaceBuffer)(REFIID riid, IUnknown *surface, BOOL bottom_up, IMFMediaBuffer **buffer);
static HRESULT (WINAPI *pMFCreateTrackedSample)(IMFTrackedSample **sample);
static DWORD (WINAPI *pMFMapDXGIFormatToDX9Format)(DXGI_FORMAT dxgi_format);
static HRESULT (WINAPI *pMFCreateVideoSampleAllocatorEx)(REFIID riid, void **allocator);
static HRESULT (WINAPI *pMFCreateDXGISurfaceBuffer)(REFIID riid, IUnknown *surface, UINT subresource, BOOL bottomup,
IMFMediaBuffer **buffer);
static HWND create_window(void)
{
@ -450,7 +460,7 @@ static const IMFAsyncCallbackVtbl events_callback_vtbl =
static BOOL get_event(IMFMediaEventGenerator *generator, MediaEventType expected_event_type, PROPVARIANT *value)
{
struct test_callback callback = { 0 };
struct test_callback callback = {{ 0 }};
MediaEventType event_type;
BOOL ret = FALSE;
HRESULT hr;
@ -780,12 +790,14 @@ static void init_functions(void)
X(MFCopyImage);
X(MFCreate2DMediaBuffer);
X(MFCreateDXGIDeviceManager);
X(MFCreateDXGISurfaceBuffer);
X(MFCreateDXSurfaceBuffer);
X(MFCreateSourceResolver);
X(MFCreateMediaBufferFromMediaType);
X(MFCreateMFByteStreamOnStream);
X(MFCreateTrackedSample);
X(MFCreateTransformActivate);
X(MFCreateVideoSampleAllocatorEx);
X(MFGetPlaneSize);
X(MFGetStrideForBitmapInfoHeader);
X(MFMapDXGIFormatToDX9Format);
@ -5246,6 +5258,7 @@ static void test_MFCreate2DMediaBuffer(void)
ok(hr == S_OK, "Failed to create a buffer, hr %#x.\n", hr);
check_interface(buffer, &IID_IMFGetService, TRUE);
check_interface(buffer, &IID_IMF2DBuffer, TRUE);
/* Full backing buffer size, with 64 bytes per row alignment. */
hr = IMFMediaBuffer_GetMaxLength(buffer, &max_length);
@ -6025,6 +6038,386 @@ static void test_MFMapDXGIFormatToDX9Format(void)
}
}
static HRESULT WINAPI test_notify_callback_QueryInterface(IMFVideoSampleAllocatorNotify *iface,
REFIID riid, void **obj)
{
if (IsEqualIID(riid, &IID_IMFVideoSampleAllocatorNotify) ||
IsEqualIID(riid, &IID_IUnknown))
{
*obj = iface;
IMFVideoSampleAllocatorNotify_AddRef(iface);
return S_OK;
}
*obj = NULL;
return E_NOINTERFACE;
}
static ULONG WINAPI test_notify_callback_AddRef(IMFVideoSampleAllocatorNotify *iface)
{
return 2;
}
static ULONG WINAPI test_notify_callback_Release(IMFVideoSampleAllocatorNotify *iface)
{
return 1;
}
static HRESULT WINAPI test_notify_callback_NotifyRelease(IMFVideoSampleAllocatorNotify *iface)
{
return E_NOTIMPL;
}
static const IMFVideoSampleAllocatorNotifyVtbl test_notify_callback_vtbl =
{
test_notify_callback_QueryInterface,
test_notify_callback_AddRef,
test_notify_callback_Release,
test_notify_callback_NotifyRelease,
};
static IMFMediaType * create_video_type(const GUID *subtype)
{
IMFMediaType *video_type;
HRESULT hr;
hr = MFCreateMediaType(&video_type);
ok(hr == S_OK, "Unexpected hr %#x.\n", hr);
hr = IMFMediaType_SetGUID(video_type, &MF_MT_MAJOR_TYPE, &MFMediaType_Video);
ok(hr == S_OK, "Unexpected hr %#x.\n", hr);
hr = IMFMediaType_SetGUID(video_type, &MF_MT_SUBTYPE, subtype);
ok(hr == S_OK, "Unexpected hr %#x.\n", hr);
return video_type;
}
static ID3D11Device *create_d3d11_device(void)
{
static const D3D_FEATURE_LEVEL default_feature_level[] =
{
D3D_FEATURE_LEVEL_11_0,
D3D_FEATURE_LEVEL_10_1,
D3D_FEATURE_LEVEL_10_0,
};
const D3D_FEATURE_LEVEL *feature_level;
unsigned int feature_level_count;
ID3D11Device *device;
feature_level = default_feature_level;
feature_level_count = ARRAY_SIZE(default_feature_level);
if (SUCCEEDED(pD3D11CreateDevice(NULL, D3D_DRIVER_TYPE_HARDWARE, NULL, 0,
feature_level, feature_level_count, D3D11_SDK_VERSION, &device, NULL, NULL)))
return device;
if (SUCCEEDED(pD3D11CreateDevice(NULL, D3D_DRIVER_TYPE_WARP, NULL, 0,
feature_level, feature_level_count, D3D11_SDK_VERSION, &device, NULL, NULL)))
return device;
if (SUCCEEDED(pD3D11CreateDevice(NULL, D3D_DRIVER_TYPE_REFERENCE, NULL, 0,
feature_level, feature_level_count, D3D11_SDK_VERSION, &device, NULL, NULL)))
return device;
return NULL;
}
static void test_dxgi_surface_buffer(void)
{
IMFDXGIBuffer *dxgi_buffer;
D3D11_TEXTURE2D_DESC desc;
ID3D11Texture2D *texture;
IMFMediaBuffer *buffer;
ID3D11Device *device;
UINT index, size;
IUnknown *obj;
HRESULT hr;
BYTE *data;
if (!pMFCreateDXGISurfaceBuffer)
{
skip("MFCreateDXGISurfaceBuffer() is not available.\n");
return;
}
device = create_d3d11_device();
memset(&desc, 0, sizeof(desc));
desc.Width = 64;
desc.Height = 64;
desc.ArraySize = 1;
desc.Format = DXGI_FORMAT_R8G8B8A8_UNORM;
desc.SampleDesc.Count = 1;
desc.SampleDesc.Quality = 0;
hr = ID3D11Device_CreateTexture2D(device, &desc, NULL, &texture);
ok(hr == S_OK, "Failed to create a texture, hr %#x.\n", hr);
hr = pMFCreateDXGISurfaceBuffer(&IID_ID3D11Texture2D, (IUnknown *)texture, 0, FALSE, &buffer);
ok(hr == S_OK || broken(hr == MF_E_INVALIDMEDIATYPE) /* Win8 */, "Failed to create a buffer, hr %#x.\n", hr);
if (FAILED(hr))
{
ID3D11Texture2D_Release(texture);
ID3D11Device_Release(device);
return;
}
check_interface(buffer, &IID_IMF2DBuffer, TRUE);
check_interface(buffer, &IID_IMF2DBuffer2, TRUE);
check_interface(buffer, &IID_IMFDXGIBuffer, TRUE);
check_interface(buffer, &IID_IMFGetService, FALSE);
hr = IMFMediaBuffer_QueryInterface(buffer, &IID_IMFDXGIBuffer, (void **)&dxgi_buffer);
ok(hr == S_OK, "Failed to get interface, hr %#x.\n", hr);
EXPECT_REF(texture, 2);
hr = IMFDXGIBuffer_GetResource(dxgi_buffer, &IID_ID3D11Texture2D, (void **)&obj);
ok(hr == S_OK, "Failed to get resource, hr %#x.\n", hr);
EXPECT_REF(texture, 3);
ok(obj == (IUnknown *)texture, "Unexpected resource pointer.\n");
IUnknown_Release(obj);
hr = IMFDXGIBuffer_GetSubresourceIndex(dxgi_buffer, NULL);
ok(hr == E_POINTER, "Unexpected hr %#x.\n", hr);
hr = IMFDXGIBuffer_GetSubresourceIndex(dxgi_buffer, &index);
ok(hr == S_OK, "Unexpected hr %#x.\n", hr);
ok(index == 0, "Unexpected subresource index.\n");
hr = IMFDXGIBuffer_SetUnknown(dxgi_buffer, &IID_IMFDXGIBuffer, (void *)device);
ok(hr == S_OK, "Unexpected hr %#x.\n", hr);
hr = ID3D11Texture2D_GetPrivateData(texture, &IID_IMFDXGIBuffer, &size, &data);
ok(hr == DXGI_ERROR_NOT_FOUND, "Unexpected hr %#x.\n", hr);
hr = IMFDXGIBuffer_GetUnknown(dxgi_buffer, &IID_IMFDXGIBuffer, &IID_ID3D11Device, (void **)&obj);
ok(hr == S_OK, "Unexpected hr %#x.\n", hr);
ok(obj == (IUnknown *)device, "Unexpected pointer.\n");
IUnknown_Release(obj);
hr = IMFDXGIBuffer_SetUnknown(dxgi_buffer, &IID_IMFDXGIBuffer, NULL);
ok(hr == S_OK, "Unexpected hr %#x.\n", hr);
hr = IMFDXGIBuffer_GetUnknown(dxgi_buffer, &IID_IMFDXGIBuffer, &IID_IUnknown, (void **)&obj);
ok(hr == MF_E_NOT_FOUND, "Unexpected hr %#x.\n", hr);
IMFDXGIBuffer_Release(dxgi_buffer);
IMFMediaBuffer_Release(buffer);
ID3D11Texture2D_Release(texture);
ID3D11Device_Release(device);
}
static void test_sample_allocator(void)
{
IMFVideoSampleAllocatorNotify test_notify = { &test_notify_callback_vtbl };
IMFVideoSampleAllocatorCallback *allocator_cb;
IMFVideoSampleAllocatorEx *allocatorex;
IMFMediaType *media_type, *video_type;
IMFVideoSampleAllocator *allocator;
IMFDXGIDeviceManager *manager;
IMFSample *sample, *sample2;
IMFMediaBuffer *buffer;
ID3D11Device *device;
LONG refcount, count;
unsigned int token;
IUnknown *unk;
HRESULT hr;
BYTE *data;
if (!pMFCreateVideoSampleAllocatorEx)
{
skip("MFCreateVideoSampleAllocatorEx() is not available.\n");
return;
}
hr = pMFCreateVideoSampleAllocatorEx(&IID_IUnknown, (void **)&unk);
ok(hr == S_OK, "Unexpected hr %#x.\n", hr);
check_interface(unk, &IID_IMFVideoSampleAllocator, TRUE);
check_interface(unk, &IID_IMFVideoSampleAllocatorEx, TRUE);
check_interface(unk, &IID_IMFVideoSampleAllocatorCallback, TRUE);
IUnknown_Release(unk);
hr = pMFCreateVideoSampleAllocatorEx(&IID_IMFVideoSampleAllocator, (void **)&allocator);
ok(hr == S_OK, "Unexpected hr %#x.\n", hr);
hr = IMFVideoSampleAllocator_QueryInterface(allocator, &IID_IMFVideoSampleAllocatorCallback, (void **)&allocator_cb);
ok(hr == S_OK, "Unexpected hr %#x.\n", hr);
hr = IMFVideoSampleAllocatorCallback_SetCallback(allocator_cb, NULL);
ok(hr == S_OK, "Unexpected hr %#x.\n", hr);
hr = IMFVideoSampleAllocatorCallback_SetCallback(allocator_cb, &test_notify);
ok(hr == S_OK, "Unexpected hr %#x.\n", hr);
hr = IMFVideoSampleAllocatorCallback_SetCallback(allocator_cb, NULL);
ok(hr == S_OK, "Unexpected hr %#x.\n", hr);
hr = IMFVideoSampleAllocatorCallback_GetFreeSampleCount(allocator_cb, NULL);
ok(hr == E_POINTER, "Unexpected hr %#x.\n", hr);
count = 10;
hr = IMFVideoSampleAllocatorCallback_GetFreeSampleCount(allocator_cb, &count);
ok(hr == S_OK, "Unexpected hr %#x.\n", hr);
ok(!count, "Unexpected count %d.\n", count);
hr = IMFVideoSampleAllocator_UninitializeSampleAllocator(allocator);
ok(hr == S_OK, "Unexpected hr %#x.\n", hr);
hr = IMFVideoSampleAllocator_AllocateSample(allocator, &sample);
ok(hr == MF_E_NOT_INITIALIZED, "Unexpected hr %#x.\n", hr);
hr = IMFVideoSampleAllocator_SetDirectXManager(allocator, NULL);
ok(hr == S_OK, "Unexpected hr %#x.\n", hr);
hr = MFCreateMediaType(&media_type);
ok(hr == S_OK, "Unexpected hr %#x.\n", hr);
hr = IMFVideoSampleAllocator_InitializeSampleAllocator(allocator, 2, media_type);
ok(hr == MF_E_ATTRIBUTENOTFOUND, "Unexpected hr %#x.\n", hr);
video_type = create_video_type(&MFVideoFormat_RGB32);
hr = IMFVideoSampleAllocator_InitializeSampleAllocator(allocator, 2, video_type);
ok(hr == MF_E_ATTRIBUTENOTFOUND, "Unexpected hr %#x.\n", hr);
/* Frame size is required. */
hr = IMFMediaType_SetUINT64(video_type, &MF_MT_FRAME_SIZE, (UINT64) 320 << 32 | 240);
ok(hr == S_OK, "Unexpected hr %#x.\n", hr);
hr = IMFVideoSampleAllocator_InitializeSampleAllocator(allocator, 0, video_type);
ok(hr == E_INVALIDARG, "Unexpected hr %#x.\n", hr);
hr = IMFVideoSampleAllocator_InitializeSampleAllocator(allocator, 1, video_type);
ok(hr == S_OK, "Unexpected hr %#x.\n", hr);
count = 0;
hr = IMFVideoSampleAllocatorCallback_GetFreeSampleCount(allocator_cb, &count);
ok(hr == S_OK, "Unexpected hr %#x.\n", hr);
ok(count == 1, "Unexpected count %d.\n", count);
sample = NULL;
hr = IMFVideoSampleAllocator_AllocateSample(allocator, &sample);
ok(hr == S_OK, "Unexpected hr %#x.\n", hr);
refcount = get_refcount(sample);
hr = IMFVideoSampleAllocatorCallback_GetFreeSampleCount(allocator_cb, &count);
ok(hr == S_OK, "Unexpected hr %#x.\n", hr);
ok(!count, "Unexpected count %d.\n", count);
hr = IMFVideoSampleAllocator_AllocateSample(allocator, &sample2);
ok(hr == MF_E_SAMPLEALLOCATOR_EMPTY, "Unexpected hr %#x.\n", hr);
/* Reinitialize with active sample. */
hr = IMFVideoSampleAllocator_InitializeSampleAllocator(allocator, 2, video_type);
ok(hr == S_OK, "Unexpected hr %#x.\n", hr);
ok(refcount == get_refcount(sample), "Unexpected refcount %u.\n", get_refcount(sample));
hr = IMFVideoSampleAllocatorCallback_GetFreeSampleCount(allocator_cb, &count);
ok(hr == S_OK, "Unexpected hr %#x.\n", hr);
ok(!count, "Unexpected count %d.\n", count);
check_interface(sample, &IID_IMFTrackedSample, TRUE);
check_interface(sample, &IID_IMFDesiredSample, FALSE);
hr = IMFSample_GetBufferByIndex(sample, 0, &buffer);
ok(hr == S_OK, "Unexpected hr %#x.\n", hr);
check_interface(buffer, &IID_IMF2DBuffer, TRUE);
check_interface(buffer, &IID_IMF2DBuffer2, TRUE);
check_interface(buffer, &IID_IMFGetService, TRUE);
check_interface(buffer, &IID_IMFDXGIBuffer, FALSE);
IMFMediaBuffer_Release(buffer);
IMFSample_Release(sample);
IMFVideoSampleAllocatorCallback_Release(allocator_cb);
IMFVideoSampleAllocator_Release(allocator);
/* IMFVideoSampleAllocatorEx */
hr = pMFCreateVideoSampleAllocatorEx(&IID_IMFVideoSampleAllocatorEx, (void **)&allocatorex);
ok(hr == S_OK, "Unexpected hr %#x.\n", hr);
hr = IMFVideoSampleAllocatorEx_QueryInterface(allocatorex, &IID_IMFVideoSampleAllocatorCallback, (void **)&allocator_cb);
ok(hr == S_OK, "Unexpected hr %#x.\n", hr);
hr = IMFVideoSampleAllocatorEx_InitializeSampleAllocatorEx(allocatorex, 1, 0, NULL, video_type);
ok(hr == E_INVALIDARG, "Unexpected hr %#x.\n", hr);
hr = IMFVideoSampleAllocatorEx_InitializeSampleAllocatorEx(allocatorex, 0, 0, NULL, video_type);
ok(hr == S_OK, "Unexpected hr %#x.\n", hr);
count = 0;
hr = IMFVideoSampleAllocatorCallback_GetFreeSampleCount(allocator_cb, &count);
ok(hr == S_OK, "Unexpected hr %#x.\n", hr);
ok(count == 1, "Unexpected count %d.\n", count);
hr = IMFVideoSampleAllocatorEx_AllocateSample(allocatorex, &sample);
ok(hr == S_OK, "Unexpected hr %#x.\n", hr);
hr = IMFVideoSampleAllocatorEx_AllocateSample(allocatorex, &sample2);
ok(hr == MF_E_SAMPLEALLOCATOR_EMPTY, "Unexpected hr %#x.\n", hr);
IMFSample_Release(sample);
IMFVideoSampleAllocatorCallback_Release(allocator_cb);
IMFVideoSampleAllocatorEx_Release(allocatorex);
/* Using device manager */
if (!(device = create_d3d11_device()))
{
skip("Failed to create a D3D11 device, skipping tests.\n");
return;
}
hr = pMFCreateDXGIDeviceManager(&token, &manager);
ok(hr == S_OK, "Failed to create device manager, hr %#x.\n", hr);
hr = IMFDXGIDeviceManager_ResetDevice(manager, (IUnknown *)device, token);
ok(hr == S_OK, "Failed to set a device, hr %#x.\n", hr);
hr = pMFCreateVideoSampleAllocatorEx(&IID_IMFVideoSampleAllocator, (void **)&allocator);
ok(hr == S_OK, "Unexpected hr %#x.\n", hr);
hr = IMFVideoSampleAllocator_SetDirectXManager(allocator, (IUnknown *)manager);
ok(hr == S_OK, "Unexpected hr %#x.\n", hr);
hr = IMFVideoSampleAllocator_InitializeSampleAllocator(allocator, 0, video_type);
ok(hr == E_INVALIDARG, "Unexpected hr %#x.\n", hr);
hr = IMFVideoSampleAllocator_InitializeSampleAllocator(allocator, 1, video_type);
ok(hr == S_OK, "Unexpected hr %#x.\n", hr);
hr = IMFVideoSampleAllocator_AllocateSample(allocator, &sample);
ok(hr == S_OK, "Unexpected hr %#x.\n", hr);
hr = IMFSample_GetBufferByIndex(sample, 0, &buffer);
ok(hr == S_OK, "Unexpected hr %#x.\n", hr);
check_interface(buffer, &IID_IMF2DBuffer, TRUE);
check_interface(buffer, &IID_IMF2DBuffer2, TRUE);
check_interface(buffer, &IID_IMFDXGIBuffer, TRUE);
check_interface(buffer, &IID_IMFGetService, FALSE);
hr = IMFMediaBuffer_Lock(buffer, &data, NULL, NULL);
ok(hr == S_OK, "Unexpected hr %#x.\n", hr);
hr = IMFMediaBuffer_Unlock(buffer);
ok(hr == S_OK, "Unexpected hr %#x.\n", hr);
IMFSample_Release(sample);
IMFVideoSampleAllocator_Release(allocator);
IMFMediaType_Release(media_type);
IMFDXGIDeviceManager_Release(manager);
ID3D11Device_Release(device);
}
START_TEST(mfplat)
{
char **argv;
@ -6085,6 +6478,8 @@ START_TEST(mfplat)
test_MFCreateTrackedSample();
test_MFFrameRateToAverageTimePerFrame();
test_MFMapDXGIFormatToDX9Format();
test_dxgi_surface_buffer();
test_sample_allocator();
CoUninitialize();
}

View File

@ -510,6 +510,8 @@ HRESULT WINAPI MFCreateAttributes(IMFAttributes **attributes, UINT32 size);
HRESULT WINAPI MFCreateAsyncResult(IUnknown *object, IMFAsyncCallback *callback, IUnknown *state, IMFAsyncResult **result);
HRESULT WINAPI MFCreateCollection(IMFCollection **collection);
HRESULT WINAPI MFCreateDXGIDeviceManager(UINT *token, IMFDXGIDeviceManager **manager);
HRESULT WINAPI MFCreateDXGISurfaceBuffer(REFIID riid, IUnknown *surface, UINT subresource, BOOL bottomup,
IMFMediaBuffer **buffer);
HRESULT WINAPI MFCreateDXSurfaceBuffer(REFIID riid, IUnknown *surface, BOOL bottom_up, IMFMediaBuffer **buffer);
HRESULT WINAPI MFCreateEventQueue(IMFMediaEventQueue **queue);
HRESULT WINAPI MFCreateFile(MF_FILE_ACCESSMODE accessmode, MF_FILE_OPENMODE openmode, MF_FILE_FLAGS flags,
@ -522,6 +524,7 @@ HRESULT WINAPI MFCreateMediaType(IMFMediaType **type);
HRESULT WINAPI MFCreateMFVideoFormatFromMFMediaType(IMFMediaType *media_type, MFVIDEOFORMAT **video_format, UINT32 *size);
HRESULT WINAPI MFCreateSample(IMFSample **sample);
HRESULT WINAPI MFCreateVideoMediaTypeFromSubtype(const GUID *subtype, IMFVideoMediaType **media_type);
HRESULT WINAPI MFCreateVideoSampleAllocatorEx(REFIID riid, void **allocator);
HRESULT WINAPI MFCreateMemoryBuffer(DWORD max_length, IMFMediaBuffer **buffer);
HRESULT WINAPI MFCreateWaveFormatExFromMFMediaType(IMFMediaType *type, WAVEFORMATEX **format, UINT32 *size, UINT32 flags);
HRESULT WINAPI MFEndCreateFile(IMFAsyncResult *result, IMFByteStream **stream);

View File

@ -167,6 +167,34 @@ interface IMF2DBuffer2 : IMF2DBuffer
HRESULT Copy2DTo([in] IMF2DBuffer2 *dest_buffer);
}
[
object,
uuid(e7174cfa-1c9e-48b1-8866-626226bfc258),
local
]
interface IMFDXGIBuffer : IUnknown
{
HRESULT GetResource(
[in] REFIID riid,
[out] void **object
);
HRESULT GetSubresourceIndex(
[out] UINT *index
);
HRESULT GetUnknown(
[in] REFIID guid,
[in] REFIID riid,
[out] void **object
);
HRESULT SetUnknown(
[in] REFIID guid,
[in] IUnknown *data
);
}
[
object,
uuid(44ae0fa8-ea31-4109-8d2e-4cae4997c555),