-- v4: mfreadwrite/reader: Pass the device manager to the stream transforms. winegstreamer/video_processor: Implement D3D awareness. mf/tests: Test video processor D3D11 awareness. mfreadwrite/tests: Add some source reader D3D11 awareness tests. mfreadwrite/reader: Avoid leaking the stream transform service MFT. mfreadwrite/tests: Shutdown the test stream event queues on source shutdown. mfreadwrite/tests: Avoid using MFCreateMediaBufferFromMediaType. mfreadwrite/tests: Do not accept MFVideoFormat_RGB32 in the test transform.
From: Rémi Bernon rbernon@codeweavers.com
--- dlls/mfreadwrite/tests/mfplat.c | 29 ++++++++++++++++------------- 1 file changed, 16 insertions(+), 13 deletions(-)
diff --git a/dlls/mfreadwrite/tests/mfplat.c b/dlls/mfreadwrite/tests/mfplat.c index a2c46869250..00b79353090 100644 --- a/dlls/mfreadwrite/tests/mfplat.c +++ b/dlls/mfreadwrite/tests/mfplat.c @@ -2488,6 +2488,13 @@ static HRESULT WINAPI test_decoder_SetInputType(IMFTransform *iface, DWORD id, I static HRESULT WINAPI test_decoder_SetOutputType(IMFTransform *iface, DWORD id, IMFMediaType *type, DWORD flags) { struct test_decoder *decoder = test_decoder_from_IMFTransform(iface); + GUID subtype; + HRESULT hr; + + if (type && SUCCEEDED(hr = IMFMediaType_GetGUID(type, &MF_MT_SUBTYPE, &subtype)) + && IsEqualGUID(&subtype, &MFVideoFormat_RGB32)) + return MF_E_INVALIDMEDIATYPE; + if (flags & MFT_SET_TYPE_TEST_ONLY) return S_OK; if (decoder->output_type) @@ -2900,7 +2907,7 @@ static void test_source_reader_transforms_d3d(void) ATTR_GUID(MF_MT_MAJOR_TYPE, MFMediaType_Video), ATTR_GUID(MF_MT_SUBTYPE, MFVideoFormat_RGB32), ATTR_RATIO(MF_MT_FRAME_SIZE, 96, 96), - ATTR_UINT32(MF_MT_ALL_SAMPLES_INDEPENDENT, 1, .todo = TRUE), + ATTR_UINT32(MF_MT_ALL_SAMPLES_INDEPENDENT, 1), ATTR_UINT32(MF_MT_COMPRESSED, 0, .todo = TRUE), ATTR_UINT32(MF_MT_INTERLACE_MODE, 2, .todo = TRUE), {0}, @@ -3019,18 +3026,14 @@ static void test_source_reader_transforms_d3d(void)
/* video processor transform is not D3D aware */ hr = IMFSourceReaderEx_GetTransformForStream(reader_ex, 0, 1, NULL, &video_processor); - todo_wine ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); - /* FIXME: Wine skips the video processor as the test decoder accepts the output type directly */ - if (hr == S_OK) - { - ok(video_processor->lpVtbl != &test_decoder_vtbl, "got unexpected transform\n"); - hr = IMFTransform_GetAttributes(video_processor, &attributes); - ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); - hr = IMFAttributes_GetUINT32(attributes, &MF_SA_D3D_AWARE, &value); - ok(hr == MF_E_ATTRIBUTENOTFOUND, "Unexpected hr %#lx.\n", hr); - IMFAttributes_Release(attributes); - IMFTransform_Release(video_processor); - } + ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); + ok(video_processor->lpVtbl != &test_decoder_vtbl, "got unexpected transform\n"); + hr = IMFTransform_GetAttributes(video_processor, &attributes); + ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); + hr = IMFAttributes_GetUINT32(attributes, &MF_SA_D3D_AWARE, &value); + ok(hr == MF_E_ATTRIBUTENOTFOUND, "Unexpected hr %#lx.\n", hr); + IMFAttributes_Release(attributes); + IMFTransform_Release(video_processor);
hr = IMFSourceReaderEx_GetTransformForStream(reader_ex, 0, 0, NULL, &test_decoder); ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
From: Rémi Bernon rbernon@codeweavers.com
It's not available on Win7. --- dlls/mfreadwrite/tests/mfplat.c | 54 ++++++++++++++++++++++----------- 1 file changed, 37 insertions(+), 17 deletions(-)
diff --git a/dlls/mfreadwrite/tests/mfplat.c b/dlls/mfreadwrite/tests/mfplat.c index 00b79353090..69478bd58cb 100644 --- a/dlls/mfreadwrite/tests/mfplat.c +++ b/dlls/mfreadwrite/tests/mfplat.c @@ -2604,28 +2604,25 @@ static HRESULT WINAPI test_decoder_ProcessOutput(IMFTransform *iface, DWORD flag
hr = MFCreateSample(&data->pSample); ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); - hr = MFCreateMediaBufferFromMediaType(decoder->output_type, 0, 0, 0, &buffer); - todo_wine ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); - if (hr != S_OK) - { - hr = MFCreateMemoryBuffer(96 * 96 * 4, &buffer); - ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); - } + hr = MFCreateMemoryBuffer(96 * 96 * 4, &buffer); + ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); hr = IMFSample_AddBuffer(data->pSample, buffer); ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); IMFMediaBuffer_Release(buffer); } + else + { + ok(!!data->pSample, "Missing sample\n");
- ok(!!data->pSample, "Missing sample\n"); - - hr = IMFSample_GetBufferByIndex(data->pSample, 0, &buffer); - ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); - todo_wine check_interface(buffer, &IID_IMF2DBuffer2, TRUE); - todo_wine check_interface(buffer, &IID_IMFGetService, TRUE); - check_interface(buffer, &IID_IMFDXGIBuffer, FALSE); - hr = MFGetService((IUnknown *)buffer, &MR_BUFFER_SERVICE, &IID_IDirect3DSurface9, (void **)&unknown); - todo_wine ok(hr == E_NOTIMPL, "Unexpected hr %#lx.\n", hr); - IMFMediaBuffer_Release(buffer); + hr = IMFSample_GetBufferByIndex(data->pSample, 0, &buffer); + ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); + todo_wine check_interface(buffer, &IID_IMF2DBuffer2, TRUE); + todo_wine check_interface(buffer, &IID_IMFGetService, TRUE); + check_interface(buffer, &IID_IMFDXGIBuffer, FALSE); + hr = MFGetService((IUnknown *)buffer, &MR_BUFFER_SERVICE, &IID_IDirect3DSurface9, (void **)&unknown); + todo_wine ok(hr == E_NOTIMPL, "Unexpected hr %#lx.\n", hr); + IMFMediaBuffer_Release(buffer); + }
if (decoder->next_output == MF_E_TRANSFORM_STREAM_CHANGE) { @@ -2817,6 +2814,16 @@ static void test_source_reader_transform_stream_change(void) ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); IMFMediaSource_Release(source);
+ /* skip tests on Win7 which misses IMFSourceReaderEx */ + hr = IMFSourceReader_QueryInterface(reader, &IID_IMFSourceReaderEx, (void **)&reader_ex); + ok(hr == S_OK || broken(hr == E_NOINTERFACE) /* Win7 */, "Unexpected hr %#lx.\n", hr); + if (broken(hr == E_NOINTERFACE)) + { + win_skip("missing IMFSourceReaderEx interface, skipping tests on Win7\n"); + goto skip_tests; + } + IMFSourceReaderEx_Release(reader_ex); + hr = IMFSourceReader_SetStreamSelection(reader, 0, TRUE); ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
@@ -2881,6 +2888,7 @@ static void test_source_reader_transform_stream_change(void)
IMFTransform_Release(test_decoder);
+skip_tests: IMFSourceReader_Release(reader);
hr = MFTUnregisterLocal(&factory); @@ -2993,6 +3001,17 @@ static void test_source_reader_transforms_d3d(void) IMFAttributes_Release(attributes); IMFMediaSource_Release(source);
+ /* skip tests on Win7 which misses IMFSourceReaderEx */ + hr = IMFSourceReader_QueryInterface(reader, &IID_IMFSourceReaderEx, (void **)&reader_ex); + ok(hr == S_OK || broken(hr == E_NOINTERFACE) /* Win7 */, "Unexpected hr %#lx.\n", hr); + if (broken(hr == E_NOINTERFACE)) + { + win_skip("missing IMFSourceReaderEx interface, skipping tests on Win7\n"); + IMFSourceReader_Release(reader); + goto skip_tests; + } + IMFSourceReaderEx_Release(reader_ex); + hr = IMFSourceReader_SetStreamSelection(reader, 0, TRUE); ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
@@ -3152,6 +3171,7 @@ static void test_source_reader_transforms_d3d(void) test_decoder_allocate_samples = FALSE;
+skip_tests: hr = MFTUnregisterLocal(&factory); ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
From: Rémi Bernon rbernon@codeweavers.com
--- dlls/mfreadwrite/tests/mfplat.c | 6 ++++++ 1 file changed, 6 insertions(+)
diff --git a/dlls/mfreadwrite/tests/mfplat.c b/dlls/mfreadwrite/tests/mfplat.c index 69478bd58cb..b70d0587072 100644 --- a/dlls/mfreadwrite/tests/mfplat.c +++ b/dlls/mfreadwrite/tests/mfplat.c @@ -554,9 +554,15 @@ static HRESULT WINAPI test_source_Shutdown(IMFMediaSource *iface) { struct test_source *source = impl_from_IMFMediaSource(iface); HRESULT hr; + UINT i;
hr = IMFMediaEventQueue_Shutdown(source->event_queue); ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); + for (i = 0; i < source->stream_count; ++i) + { + hr = IMFMediaEventQueue_Shutdown(source->streams[i]->event_queue); + ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); + }
return S_OK; }
From: Rémi Bernon rbernon@codeweavers.com
--- dlls/mfreadwrite/reader.c | 2 ++ 1 file changed, 2 insertions(+)
diff --git a/dlls/mfreadwrite/reader.c b/dlls/mfreadwrite/reader.c index 11eac81d2ca..9fe64206703 100644 --- a/dlls/mfreadwrite/reader.c +++ b/dlls/mfreadwrite/reader.c @@ -223,6 +223,8 @@ static void media_stream_destroy(struct media_stream *stream) transform_entry_destroy(entry); }
+ if (stream->transform_service) + IMFTransform_Release(stream->transform_service); if (stream->stream) IMFMediaStream_Release(stream->stream); if (stream->current)
From: Rémi Bernon rbernon@codeweavers.com
--- dlls/mfreadwrite/tests/Makefile.in | 2 +- dlls/mfreadwrite/tests/mfplat.c | 342 +++++++++++++++++++++++++++-- 2 files changed, 324 insertions(+), 20 deletions(-)
diff --git a/dlls/mfreadwrite/tests/Makefile.in b/dlls/mfreadwrite/tests/Makefile.in index 3bdab217148..c6262c01009 100644 --- a/dlls/mfreadwrite/tests/Makefile.in +++ b/dlls/mfreadwrite/tests/Makefile.in @@ -1,5 +1,5 @@ TESTDLL = mfreadwrite.dll -IMPORTS = ole32 user32 d3d9 dxva2 mfplat mf mfreadwrite mfuuid propsys +IMPORTS = ole32 user32 d3d11 d3d9 dxva2 mfplat mf mfreadwrite mfuuid propsys
SOURCES = \ mfplat.c \ diff --git a/dlls/mfreadwrite/tests/mfplat.c b/dlls/mfreadwrite/tests/mfplat.c index b70d0587072..d0f9c689390 100644 --- a/dlls/mfreadwrite/tests/mfplat.c +++ b/dlls/mfreadwrite/tests/mfplat.c @@ -42,6 +42,7 @@ DEFINE_GUID(GUID_NULL, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0); #include "initguid.h" #include "d3d9.h" #include "dxva2api.h" +#include "d3d11_4.h" #include "evr.h"
#include "wine/test.h" @@ -199,6 +200,7 @@ static IDirect3DDevice9 *create_d3d9_device(IDirect3D9 *d3d9, HWND focus_window) }
static HRESULT (WINAPI *pMFCreateMFByteStreamOnStream)(IStream *stream, IMFByteStream **bytestream); +static HRESULT (WINAPI *pMFCreateDXGIDeviceManager)(UINT *token, IMFDXGIDeviceManager **manager);
static void init_functions(void) { @@ -206,6 +208,7 @@ static void init_functions(void)
#define X(f) if (!(p##f = (void*)GetProcAddress(mod, #f))) return; X(MFCreateMFByteStreamOnStream); + X(MFCreateDXGIDeviceManager); #undef X }
@@ -2296,9 +2299,11 @@ skip_tests: }
static BOOL test_decoder_d3d_aware; +static BOOL test_decoder_d3d11_aware; static BOOL test_decoder_got_d3d_manager; static BOOL test_decoder_allocate_samples; -static IDirect3DDeviceManager9 *expect_d3d_manager; +static IDirect3DDeviceManager9 *expect_d3d9_manager; +static IMFDXGIDeviceManager *expect_dxgi_manager;
struct test_decoder { @@ -2564,20 +2569,35 @@ static HRESULT WINAPI test_decoder_ProcessMessage(IMFTransform *iface, MFT_MESSA return S_OK;
case MFT_MESSAGE_SET_D3D_MANAGER: - ok(test_decoder_d3d_aware, "Unexpected call.\n"); - if (param) + ok(test_decoder_d3d_aware || test_decoder_d3d11_aware, "Unexpected call.\n"); + if (!param) + return S_OK; + + if (test_decoder_d3d_aware) { IDirect3DDeviceManager9 *manager; HRESULT hr;
hr = IUnknown_QueryInterface((IUnknown *)param, &IID_IDirect3DDeviceManager9, (void **)&manager); ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); - ok(manager == expect_d3d_manager, "got manager %p\n", manager); + ok(manager == expect_d3d9_manager, "got manager %p\n", manager); IDirect3DDeviceManager9_Release(manager);
test_decoder_got_d3d_manager = TRUE; } - return test_decoder_d3d_aware ? S_OK : E_NOTIMPL; + if (test_decoder_d3d11_aware) + { + IMFDXGIDeviceManager *manager; + HRESULT hr; + + hr = IUnknown_QueryInterface((IUnknown *)param, &IID_IMFDXGIDeviceManager, (void **)&manager); + ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); + ok(manager == expect_dxgi_manager, "got manager %p\n", manager); + IMFDXGIDeviceManager_Release(manager); + + test_decoder_got_d3d_manager = TRUE; + } + return S_OK;
default: ok(0, "Unexpected call.\n"); @@ -2712,13 +2732,21 @@ static HRESULT WINAPI test_mft_factory_CreateInstance(IClassFactory *iface, IUnk decoder->IMFTransform_iface.lpVtbl = &test_decoder_vtbl; decoder->refcount = 1;
- if (test_decoder_d3d_aware) + if (test_decoder_d3d_aware || test_decoder_d3d11_aware) { hr = MFCreateAttributes(&decoder->attributes, 1); ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); + } + if (test_decoder_d3d_aware) + { hr = IMFAttributes_SetUINT32(decoder->attributes, &MF_SA_D3D_AWARE, 1); ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); } + if (test_decoder_d3d11_aware) + { + hr = IMFAttributes_SetUINT32(decoder->attributes, &MF_SA_D3D11_AWARE, 1); + ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); + }
*obj = &decoder->IMFTransform_iface; return S_OK; @@ -2901,7 +2929,7 @@ skip_tests: ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); }
-static void test_source_reader_transforms_d3d(void) +static void test_source_reader_transforms_d3d9(void) { static const struct attribute_desc test_stream_type_desc[] = { @@ -2966,8 +2994,11 @@ static void test_source_reader_transforms_d3d(void) if (!(d3d9_device = create_d3d9_device(d3d9, window))) { skip("Failed to create a D3D9 device, skipping tests.\n"); - goto done; + IDirect3D9_Release(d3d9); + DestroyWindow(window); + return; } + IDirect3D9_Release(d3d9);
test_decoder_d3d_aware = TRUE;
@@ -2984,9 +3015,11 @@ static void test_source_reader_transforms_d3d(void) ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); hr = IDirect3DDeviceManager9_ResetDevice(d3d9_manager, d3d9_device, token); ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); + IDirect3DDevice9_Release(d3d9_device); + hr = IMFAttributes_SetUnknown(attributes, &MF_SOURCE_READER_D3D_MANAGER, (IUnknown *)d3d9_manager); ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); - expect_d3d_manager = d3d9_manager; + expect_d3d9_manager = d3d9_manager;
/* test d3d aware decoder that doesn't allocate buffers */ @@ -3016,7 +3049,6 @@ static void test_source_reader_transforms_d3d(void) IMFSourceReader_Release(reader); goto skip_tests; } - IMFSourceReaderEx_Release(reader_ex);
hr = IMFSourceReader_SetStreamSelection(reader, 0, TRUE); ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); @@ -3046,10 +3078,8 @@ static void test_source_reader_transforms_d3d(void) IMFMediaType_Release(media_type);
- hr = IMFSourceReader_QueryInterface(reader, &IID_IMFSourceReaderEx, (void **)&reader_ex); - ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); + /* video processor transform is not D3D9 aware on more recent Windows */
- /* video processor transform is not D3D aware */ hr = IMFSourceReaderEx_GetTransformForStream(reader_ex, 0, 1, NULL, &video_processor); ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); ok(video_processor->lpVtbl != &test_decoder_vtbl, "got unexpected transform\n"); @@ -3057,6 +3087,19 @@ static void test_source_reader_transforms_d3d(void) ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); hr = IMFAttributes_GetUINT32(attributes, &MF_SA_D3D_AWARE, &value); ok(hr == MF_E_ATTRIBUTENOTFOUND, "Unexpected hr %#lx.\n", hr); + value = 0xdeadbeef; + hr = IMFAttributes_GetUINT32(attributes, &MF_SA_D3D11_AWARE, &value); + todo_wine ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); + todo_wine ok(value == 1, "got %u.\n", value); + hr = IMFAttributes_GetUINT32(attributes, &MF_SA_MINIMUM_OUTPUT_SAMPLE_COUNT, &value); + ok(hr == MF_E_ATTRIBUTENOTFOUND, "Unexpected hr %#lx.\n", hr); + IMFAttributes_Release(attributes); + + hr = IMFTransform_GetOutputStreamAttributes(video_processor, 0, &attributes); + ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); + hr = IMFAttributes_GetCount(attributes, &value); + ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); + ok(value == 0, "got %u.\n", value); IMFAttributes_Release(attributes); IMFTransform_Release(video_processor);
@@ -3070,7 +3113,6 @@ static void test_source_reader_transforms_d3d(void) ok(value == 1, "got %u\n", value); IMFAttributes_Release(attributes);
- IMFSourceReaderEx_Release(reader_ex);
fail_request_sample = FALSE; test_decoder_set_next_output(test_decoder, S_OK); @@ -3096,7 +3138,33 @@ static void test_source_reader_transforms_d3d(void)
fail_request_sample = TRUE;
+ + /* video processor output stream attributes are left empty in D3D9 mode */ + + hr = IMFSourceReaderEx_GetTransformForStream(reader_ex, 0, 1, NULL, &video_processor); + ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); + ok(video_processor->lpVtbl != &test_decoder_vtbl, "got unexpected transform\n"); + + hr = IMFTransform_GetAttributes(video_processor, &attributes); + ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); + value = 0xdeadbeef; + hr = IMFAttributes_GetUINT32(attributes, &MF_SA_MINIMUM_OUTPUT_SAMPLE_COUNT, &value); + todo_wine ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); + todo_wine ok(value == 6, "got %u.\n", value); + IMFAttributes_Release(attributes); + + hr = IMFTransform_GetOutputStreamAttributes(video_processor, 0, &attributes); + ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); + hr = IMFAttributes_GetCount(attributes, &value); + ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); + ok(value == 0, "got %u.\n", value); + IMFAttributes_Release(attributes); + + IMFTransform_Release(video_processor); + + IMFTransform_Release(test_decoder); + IMFSourceReaderEx_Release(reader_ex); IMFSourceReader_Release(reader);
@@ -3182,13 +3250,248 @@ skip_tests: ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
IDirect3DDeviceManager9_Release(d3d9_manager); - IDirect3DDevice9_Release(d3d9_device); - -done: - IDirect3D9_Release(d3d9); DestroyWindow(window);
+ test_decoder_got_d3d_manager = FALSE; test_decoder_d3d_aware = FALSE; + expect_d3d9_manager = NULL; +} + +static void test_source_reader_transforms_d3d11(void) +{ + static const struct attribute_desc test_stream_type_desc[] = + { + ATTR_GUID(MF_MT_MAJOR_TYPE, MFMediaType_Video), + ATTR_GUID(MF_MT_SUBTYPE, MFVideoFormat_TEST), + ATTR_RATIO(MF_MT_FRAME_SIZE, 96, 96), + {0}, + }; + static const struct attribute_desc rgb32_stream_type_desc[] = + { + ATTR_GUID(MF_MT_MAJOR_TYPE, MFMediaType_Video), + ATTR_GUID(MF_MT_SUBTYPE, MFVideoFormat_RGB32), + {0}, + }; + static const struct attribute_desc rgb32_expect_desc[] = + { + ATTR_GUID(MF_MT_MAJOR_TYPE, MFMediaType_Video), + ATTR_GUID(MF_MT_SUBTYPE, MFVideoFormat_RGB32), + ATTR_RATIO(MF_MT_FRAME_SIZE, 96, 96), + ATTR_UINT32(MF_MT_ALL_SAMPLES_INDEPENDENT, 1), + ATTR_UINT32(MF_MT_COMPRESSED, 0, .todo = TRUE), + ATTR_UINT32(MF_MT_INTERLACE_MODE, 2, .todo = TRUE), + {0}, + }; + const MFT_REGISTER_TYPE_INFO output_info[] = + { + {MFMediaType_Video, MFVideoFormat_NV12}, + {MFMediaType_Video, MFVideoFormat_YUY2}, + }; + const MFT_REGISTER_TYPE_INFO input_info[] = + { + {MFMediaType_Video, MFVideoFormat_TEST}, + }; + IClassFactory factory = {.lpVtbl = &test_mft_factory_vtbl}; + IMFTransform *test_decoder, *video_processor; + IMFStreamDescriptor *video_stream; + ID3D11Multithread *multithread; + IMFDXGIDeviceManager *manager; + IMFSourceReaderEx *reader_ex; + IMFAttributes *attributes; + IMFMediaType *media_type; + IMFSourceReader *reader; + IMFMediaBuffer *buffer; + IMFMediaSource *source; + UINT32 value, token; + ID3D11Device *d3d11; + LONGLONG timestamp; + DWORD index, flags; + IMFSample *sample; + HRESULT hr; + + if (!pMFCreateDXGIDeviceManager) + { + win_skip("MFCreateDXGIDeviceManager() is not available, skipping tests.\n"); + return; + } + + hr = D3D11CreateDevice(NULL, D3D_DRIVER_TYPE_HARDWARE, NULL, D3D11_CREATE_DEVICE_VIDEO_SUPPORT, NULL, 0, + D3D11_SDK_VERSION, &d3d11, NULL, NULL); + if (FAILED(hr)) + { + skip("D3D11 device creation failed, skipping tests.\n"); + return; + } + + hr = ID3D11Device_QueryInterface(d3d11, &IID_ID3D11Multithread, (void **)&multithread); + ok(hr == S_OK, "got %#lx\n", hr); + ID3D11Multithread_SetMultithreadProtected(multithread, TRUE); + ID3D11Multithread_Release(multithread); + + hr = pMFCreateDXGIDeviceManager(&token, &manager); + ok(hr == S_OK, "got %#lx\n", hr); + hr = IMFDXGIDeviceManager_ResetDevice(manager, (IUnknown *)d3d11, token); + ok(hr == S_OK, "got %#lx\n", hr); + ID3D11Device_Release(d3d11); + + + test_decoder_d3d11_aware = TRUE; + + hr = MFTRegisterLocal(&factory, &MFT_CATEGORY_VIDEO_DECODER, L"Test Decoder", 0, + ARRAY_SIZE(input_info), input_info, ARRAY_SIZE(output_info), output_info); + ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); + + hr = MFCreateAttributes(&attributes, 1); + ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); + hr = IMFAttributes_SetUINT32(attributes, &MF_SOURCE_READER_ENABLE_ADVANCED_VIDEO_PROCESSING, 1); + ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); + hr = IMFAttributes_SetUnknown(attributes, &MF_SOURCE_READER_D3D_MANAGER, (IUnknown *)manager); + ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); + expect_dxgi_manager = manager; + + + hr = MFCreateMediaType(&media_type); + ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); + init_media_type(media_type, test_stream_type_desc, -1); + hr = MFCreateStreamDescriptor(0, 1, &media_type, &video_stream); + ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); + IMFMediaType_Release(media_type); + + source = create_test_source(&video_stream, 1); + ok(!!source, "Failed to create test source.\n"); + IMFStreamDescriptor_Release(video_stream); + + hr = MFCreateSourceReaderFromMediaSource(source, attributes, &reader); + ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); + IMFAttributes_Release(attributes); + IMFMediaSource_Release(source); + + /* skip tests on Win7 which misses IMFSourceReaderEx */ + hr = IMFSourceReader_QueryInterface(reader, &IID_IMFSourceReaderEx, (void **)&reader_ex); + ok(hr == S_OK || broken(hr == E_NOINTERFACE) /* Win7 */, "Unexpected hr %#lx.\n", hr); + if (broken(hr == E_NOINTERFACE)) + { + win_skip("missing IMFSourceReaderEx interface, skipping tests on Win7\n"); + IMFSourceReader_Release(reader); + goto skip_tests; + } + + hr = IMFSourceReader_SetStreamSelection(reader, 0, TRUE); + ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); + + hr = IMFSourceReader_GetNativeMediaType(reader, 0, 0, &media_type); + ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); + check_media_type(media_type, test_stream_type_desc, -1); + IMFMediaType_Release(media_type); + + hr = IMFSourceReader_GetCurrentMediaType(reader, 0, &media_type); + ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); + check_media_type(media_type, test_stream_type_desc, -1); + IMFMediaType_Release(media_type); + ok(!test_decoder_got_d3d_manager, "d3d manager received\n"); + + hr = MFCreateMediaType(&media_type); + ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); + init_media_type(media_type, rgb32_stream_type_desc, -1); + hr = IMFSourceReader_SetCurrentMediaType(reader, 0, NULL, media_type); + ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); + IMFMediaType_Release(media_type); + + hr = IMFSourceReader_GetCurrentMediaType(reader, 0, &media_type); + ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); + check_media_type(media_type, rgb32_expect_desc, -1); + IMFMediaType_Release(media_type); + + + /* video processor output stream attributes are still empty */ + + hr = IMFSourceReaderEx_GetTransformForStream(reader_ex, 0, 1, NULL, &video_processor); + ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); + ok(video_processor->lpVtbl != &test_decoder_vtbl, "got unexpected transform\n"); + + hr = IMFTransform_GetAttributes(video_processor, &attributes); + ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); + hr = IMFAttributes_GetUINT32(attributes, &MF_SA_MINIMUM_OUTPUT_SAMPLE_COUNT, &value); + ok(hr == MF_E_ATTRIBUTENOTFOUND, "Unexpected hr %#lx.\n", hr); + IMFAttributes_Release(attributes); + + hr = IMFTransform_GetOutputStreamAttributes(video_processor, 0, &attributes); + ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); + hr = IMFAttributes_GetCount(attributes, &value); + ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); + ok(value == 0, "got %u.\n", value); + IMFAttributes_Release(attributes); + + IMFTransform_Release(video_processor); + + + hr = IMFSourceReaderEx_GetTransformForStream(reader_ex, 0, 0, NULL, &test_decoder); + ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); + ok(test_decoder->lpVtbl == &test_decoder_vtbl, "got unexpected transform\n"); + + fail_request_sample = FALSE; + test_decoder_set_next_output(test_decoder, S_OK); + + sample = (void *)0xdeadbeef; + index = flags = timestamp = 0xdeadbeef; + hr = IMFSourceReader_ReadSample(reader, 0, 0, &index, &flags, ×tamp, &sample); + ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); + ok(index == 0, "got %lu.\n", index); + ok(flags == 0, "got %lu.\n", flags); + ok(timestamp == 0, "got %I64d.\n", timestamp); + ok(sample != (void *)0xdeadbeef, "got %p.\n", sample); + + hr = IMFSample_GetBufferByIndex(sample, 0, &buffer); + ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); + check_interface(buffer, &IID_IMF2DBuffer2, TRUE); + check_interface(buffer, &IID_IMFGetService, FALSE); + check_interface(buffer, &IID_IMFDXGIBuffer, TRUE); + IMFMediaBuffer_Release(buffer); + + IMFSample_Release(sample); + + fail_request_sample = TRUE; + + + /* video processor output stream attributes are now set with some defaults */ + + hr = IMFSourceReaderEx_GetTransformForStream(reader_ex, 0, 1, NULL, &video_processor); + ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); + ok(video_processor->lpVtbl != &test_decoder_vtbl, "got unexpected transform\n"); + + hr = IMFTransform_GetAttributes(video_processor, &attributes); + ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); + value = 0xdeadbeef; + hr = IMFAttributes_GetUINT32(attributes, &MF_SA_MINIMUM_OUTPUT_SAMPLE_COUNT, &value); + todo_wine ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); + todo_wine ok(value == 6, "got %u.\n", value); + IMFAttributes_Release(attributes); + + hr = IMFTransform_GetOutputStreamAttributes(video_processor, 0, &attributes); + ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); + value = 0xdeadbeef; + hr = IMFAttributes_GetUINT32(attributes, &MF_SA_D3D11_BINDFLAGS, &value); + todo_wine ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); + todo_wine ok(value == 1024, "got %u.\n", value); + IMFAttributes_Release(attributes); + + IMFTransform_Release(video_processor); + + + IMFSourceReaderEx_Release(reader_ex); + IMFSourceReader_Release(reader); + IMFTransform_Release(test_decoder); + + +skip_tests: + hr = MFTUnregisterLocal(&factory); + ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); + + IMFDXGIDeviceManager_Release(manager); + + test_decoder_got_d3d_manager = FALSE; + test_decoder_d3d11_aware = FALSE; + expect_dxgi_manager = NULL; }
START_TEST(mfplat) @@ -3209,7 +3512,8 @@ START_TEST(mfplat) test_source_reader_transforms(TRUE, FALSE); test_source_reader_transforms(FALSE, TRUE); test_source_reader_transform_stream_change(); - test_source_reader_transforms_d3d(); + test_source_reader_transforms_d3d9(); + test_source_reader_transforms_d3d11(); test_reader_d3d9(); test_sink_writer_create(); test_sink_writer_mp4();
From: Rémi Bernon rbernon@codeweavers.com
--- dlls/mf/tests/mf.c | 2 + dlls/mf/tests/mf_test.h | 1 + dlls/mf/tests/transform.c | 308 ++++++++++++++++++++++++++++++++++++++ 3 files changed, 311 insertions(+)
diff --git a/dlls/mf/tests/mf.c b/dlls/mf/tests/mf.c index 3f75ca943c8..314d41fd1e3 100644 --- a/dlls/mf/tests/mf.c +++ b/dlls/mf/tests/mf.c @@ -80,6 +80,7 @@ extern GUID DMOVideoFormat_RGB32; HRESULT (WINAPI *pMFCreateSampleCopierMFT)(IMFTransform **copier); HRESULT (WINAPI *pMFGetTopoNodeCurrentType)(IMFTopologyNode *node, DWORD stream, BOOL output, IMFMediaType **type); HRESULT (WINAPI *pMFCreateDXGIDeviceManager)(UINT *token, IMFDXGIDeviceManager **manager); +HRESULT (WINAPI *pMFCreateVideoSampleAllocatorEx)(REFIID riid, void **obj); BOOL has_video_processor;
static BOOL is_vista(void) @@ -5723,6 +5724,7 @@ void init_functions(void)
mod = GetModuleHandleA("mfplat.dll"); X(MFCreateDXGIDeviceManager); + X(MFCreateVideoSampleAllocatorEx); #undef X
hr = CoInitialize(NULL); diff --git a/dlls/mf/tests/mf_test.h b/dlls/mf/tests/mf_test.h index 5a247e4a0ef..7e08caa571b 100644 --- a/dlls/mf/tests/mf_test.h +++ b/dlls/mf/tests/mf_test.h @@ -33,6 +33,7 @@ extern HRESULT (WINAPI *pMFCreateSampleCopierMFT)(IMFTransform **copier); extern HRESULT (WINAPI *pMFGetTopoNodeCurrentType)(IMFTopologyNode *node, DWORD stream, BOOL output, IMFMediaType **type); extern HRESULT (WINAPI *pMFCreateDXGIDeviceManager)(UINT *token, IMFDXGIDeviceManager **manager); +extern HRESULT (WINAPI *pMFCreateVideoSampleAllocatorEx)(REFIID riid, void **obj);
extern BOOL has_video_processor; void init_functions(void); diff --git a/dlls/mf/tests/transform.c b/dlls/mf/tests/transform.c index e43b1627789..66e65629cba 100644 --- a/dlls/mf/tests/transform.c +++ b/dlls/mf/tests/transform.c @@ -7294,6 +7294,7 @@ static void test_video_processor(void) static const struct attribute_desc expect_transform_attributes[] = { ATTR_UINT32(MFT_SUPPORT_3DVIDEO, 1, .todo = TRUE), + ATTR_UINT32(MF_SA_D3D11_AWARE, 1, .todo = TRUE), /* ATTR_UINT32(MF_SA_D3D_AWARE, 1), only on W7 */ {0}, }; @@ -8606,6 +8607,8 @@ failed: IMFDXGIDeviceManager_Release(manager); if (transform) IMFTransform_Release(transform); + + MFShutdown(); CoUninitialize(); }
@@ -8801,6 +8804,309 @@ static void test_iv50_decoder(void) IMFCollection_Release(collection); }
+static void test_video_processor_with_dxgi_manager(void) +{ + static const unsigned int set_width = 82, set_height = 84, aligned_width = 96, aligned_height = 96; + const struct attribute_desc output_sample_attributes[] = + { + {0}, + }; + const struct buffer_desc output_buffer_desc_rgb32 = + { + .length = aligned_width * aligned_height * 4, + .compare = compare_rgb32, .dump = dump_rgb32, .rect = {.right = set_width, .bottom = set_height}, + }; + const struct sample_desc output_sample_desc_rgb32 = + { + .attributes = output_sample_attributes, + .sample_time = 0, .sample_duration = 0, + .buffer_count = 1, .buffers = &output_buffer_desc_rgb32, + }; + + IMFVideoSampleAllocator *allocator = NULL; + IMFDXGIDeviceManager *manager = NULL; + IMFTrackedSample *tracked_sample; + IMFTransform *transform = NULL; + ID3D11Multithread *multithread; + MFT_OUTPUT_DATA_BUFFER output; + IMFCollection *output_samples; + MFT_OUTPUT_STREAM_INFO info; + IMFDXGIBuffer *dxgi_buffer; + const BYTE *nv12frame_data; + D3D11_TEXTURE2D_DESC desc; + ULONG nv12frame_data_len; + IMFSample *input_sample; + IMFMediaBuffer *buffer; + IMFAttributes *attribs; + ID3D11Texture2D *tex2d; + IMF2DBuffer2 *buffer2d; + ID3D11Device *d3d11; + IMFMediaType *type; + DWORD status, val; + ULONG i, length; + UINT32 value; + BYTE *data; + HRESULT hr; + UINT token; + DWORD ret; + + if (!pMFCreateDXGIDeviceManager || !pMFCreateVideoSampleAllocatorEx) + { + win_skip("MFCreateDXGIDeviceManager / MFCreateVideoSampleAllocatorEx are not available, skipping tests.\n"); + return; + } + + hr = D3D11CreateDevice(NULL, D3D_DRIVER_TYPE_HARDWARE, NULL, D3D11_CREATE_DEVICE_VIDEO_SUPPORT, NULL, 0, + D3D11_SDK_VERSION, &d3d11, NULL, NULL); + if (FAILED(hr)) + { + skip("D3D11 device creation failed, skipping tests.\n"); + return; + } + + hr = MFStartup(MF_VERSION, 0); + ok(hr == S_OK, "got %#lx\n", hr); + + hr = CoInitialize(NULL); + ok(hr == S_OK, "got %#lx\n", hr); + + hr = ID3D11Device_QueryInterface(d3d11, &IID_ID3D11Multithread, (void **)&multithread); + ok(hr == S_OK, "got %#lx\n", hr); + ID3D11Multithread_SetMultithreadProtected(multithread, TRUE); + ID3D11Multithread_Release(multithread); + + hr = pMFCreateDXGIDeviceManager(&token, &manager); + ok(hr == S_OK, "got %#lx\n", hr); + hr = IMFDXGIDeviceManager_ResetDevice(manager, (IUnknown *)d3d11, token); + ok(hr == S_OK, "got %#lx\n", hr); + ID3D11Device_Release(d3d11); + + hr = pMFCreateVideoSampleAllocatorEx(&IID_IMFVideoSampleAllocator, (void **)&allocator); + ok(hr == S_OK, "got %#lx\n", hr); + hr = IMFVideoSampleAllocator_SetDirectXManager(allocator, (IUnknown *)manager); + ok(hr == S_OK, "got %#lx\n", hr); + + if (FAILED(hr = CoCreateInstance(&CLSID_VideoProcessorMFT, NULL, CLSCTX_INPROC_SERVER, + &IID_IMFTransform, (void **)&transform))) + goto failed; + + hr = IMFTransform_ProcessMessage(transform, MFT_MESSAGE_SET_D3D_MANAGER, (ULONG_PTR)transform); + todo_wine ok(hr == E_NOINTERFACE, "got %#lx\n", hr); + + hr = IMFTransform_ProcessMessage(transform, MFT_MESSAGE_SET_D3D_MANAGER, (ULONG_PTR)manager); + ok(hr == S_OK || broken(hr == E_NOINTERFACE), "got %#lx\n", hr); + if (hr == E_NOINTERFACE) + { + win_skip("No hardware video decoding support.\n"); + goto failed; + } + + hr = IMFTransform_GetOutputStreamInfo(transform, 0, &info); + ok(hr == S_OK, "got %#lx\n", hr); + if (broken(!(info.dwFlags & MFT_OUTPUT_STREAM_PROVIDES_SAMPLES)) /* w8 / w1064v1507 */) + { + win_skip("missing video processor sample allocator support.\n"); + goto failed; + } + todo_wine ok(info.dwFlags == MFT_OUTPUT_STREAM_PROVIDES_SAMPLES, "got %#lx.\n", info.dwFlags); + + hr = MFCreateMediaType(&type); + ok(hr == S_OK, "got %#lx\n", hr); + hr = IMFMediaType_SetGUID(type, &MF_MT_MAJOR_TYPE, &MFMediaType_Video); + ok(hr == S_OK, "got %#lx\n", hr); + hr = IMFMediaType_SetGUID(type, &MF_MT_SUBTYPE, &MFVideoFormat_NV12); + ok(hr == S_OK, "got %#lx\n", hr); + hr = IMFMediaType_SetUINT64(type, &MF_MT_FRAME_SIZE, (UINT64)96 << 32 | 96); + ok(hr == S_OK, "got %#lx\n", hr); + hr = IMFTransform_SetInputType(transform, 0, type, 0); + ok(hr == S_OK, "got %#lx\n", hr); + hr = IMFVideoSampleAllocator_InitializeSampleAllocator(allocator, 4, type); + ok(hr == S_OK, "got %#lx\n", hr); + IMFMediaType_Release(type); + + hr = IMFTransform_GetOutputAvailableType(transform, 0, 0, &type); + ok(hr == S_OK, "got %#lx\n", hr); + hr = IMFMediaType_SetGUID(type, &MF_MT_MAJOR_TYPE, &MFMediaType_Video); + ok(hr == S_OK, "got %#lx\n", hr); + hr = IMFMediaType_SetGUID(type, &MF_MT_SUBTYPE, &MFVideoFormat_RGB32); + ok(hr == S_OK, "got %#lx\n", hr); + hr = IMFMediaType_SetUINT64(type, &MF_MT_FRAME_SIZE, (UINT64)96 << 32 | 96); + ok(hr == S_OK, "got %#lx\n", hr); + hr = IMFTransform_SetOutputType(transform, 0, type, 0); + ok(hr == S_OK, "got %#lx\n", hr); + IMFMediaType_Release(type); + + status = 0; + memset(&output, 0, sizeof(output)); + hr = IMFTransform_ProcessOutput(transform, 0, 1, &output, &status); + todo_wine ok(hr == MF_E_TRANSFORM_NEED_MORE_INPUT, "got %#lx\n", hr); + + load_resource(L"nv12frame.bmp", &nv12frame_data, &nv12frame_data_len); + /* skip BMP header and RGB data from the dump */ + length = *(DWORD *)(nv12frame_data + 2); + nv12frame_data_len = nv12frame_data_len - length; + nv12frame_data = nv12frame_data + length; + ok(nv12frame_data_len == 13824, "got length %lu\n", nv12frame_data_len); + + + /* native wants a dxgi buffer on input */ + + hr = IMFVideoSampleAllocator_AllocateSample(allocator, &input_sample); + ok(hr == S_OK, "got %#lx\n", hr); + hr = IMFSample_SetSampleTime(input_sample, 0); + ok(hr == S_OK, "got %#lx\n", hr); + hr = IMFSample_SetSampleDuration(input_sample, 0); + ok(hr == S_OK, "got %#lx\n", hr); + hr = IMFSample_GetBufferByIndex(input_sample, 0, &buffer); + ok(hr == S_OK, "got %#lx\n", hr); + hr = IMFMediaBuffer_Lock(buffer, &data, NULL, NULL); + ok(hr == S_OK, "got %#lx\n", hr); + memcpy(data, nv12frame_data, nv12frame_data_len); + hr = IMFMediaBuffer_Unlock(buffer); + ok(hr == S_OK, "got %#lx\n", hr); + IMFMediaBuffer_Release(buffer); + + hr = IMFTransform_ProcessInput(transform, 0, input_sample, 0); + ok(hr == S_OK, "got %#lx\n", hr); + + hr = IMFTransform_GetOutputStreamInfo(transform, 0, &info); + ok(hr == S_OK, "got %#lx\n", hr); + todo_wine ok(info.dwFlags == MFT_OUTPUT_STREAM_PROVIDES_SAMPLES, "got %#lx.\n", info.dwFlags); + + + status = 0; + memset(&output, 0, sizeof(output)); + hr = IMFTransform_ProcessOutput(transform, 0, 1, &output, &status); + todo_wine ok(hr == S_OK, "got %#lx\n", hr); + ok(!output.pEvents, "got events\n"); + todo_wine ok(!!output.pSample, "got no sample\n"); + ok(output.dwStatus == 0, "got %#lx\n", output.dwStatus); + ok(status == 0, "got %#lx\n", status); + if (!output.pSample) goto skip_tests; + + hr = IMFTransform_GetAttributes(transform, &attribs); + ok(hr == S_OK, "got %#lx\n", hr); + hr = IMFAttributes_GetUINT32(attribs, &MF_SA_MINIMUM_OUTPUT_SAMPLE_COUNT, &value); + ok(hr == MF_E_ATTRIBUTENOTFOUND, "Unexpected hr %#lx.\n", hr); + IMFAttributes_Release(attribs); + + hr = IMFTransform_GetOutputStreamAttributes(transform, 0, &attribs); + ok(hr == S_OK, "got %#lx\n", hr); + hr = IMFAttributes_GetCount(attribs, &value); + ok(hr == S_OK, "got %#lx\n", hr); + ok(value == 0, "got %u.\n", value); + IMFAttributes_Release(attribs); + + + hr = IMFSample_QueryInterface(output.pSample, &IID_IMFTrackedSample, (void **)&tracked_sample); + ok(hr == S_OK, "got %#lx\n", hr); + IMFTrackedSample_Release(tracked_sample); + + hr = IMFSample_GetBufferCount(output.pSample, &val); + ok(hr == S_OK, "got %#lx\n", hr); + ok(val == 1, "got %lu.\n", val); + hr = IMFSample_GetBufferByIndex(output.pSample, 0, &buffer); + ok(hr == S_OK, "got %#lx\n", hr); + hr = IMFMediaBuffer_QueryInterface(buffer, &IID_IMFDXGIBuffer, (void **)&dxgi_buffer); + ok(hr == S_OK, "got %#lx\n", hr); + hr = IMFMediaBuffer_QueryInterface(buffer, &IID_IMF2DBuffer2, (void **)&buffer2d); + ok(hr == S_OK, "got %#lx\n", hr); + + hr = IMFDXGIBuffer_GetResource(dxgi_buffer, &IID_ID3D11Texture2D, (void **)&tex2d); + ok(hr == S_OK, "got %#lx\n", hr); + memset(&desc, 0xcc, sizeof(desc)); + ID3D11Texture2D_GetDesc(tex2d, &desc); + ok(desc.Format == DXGI_FORMAT_B8G8R8X8_UNORM, "got %#x.\n", desc.Format); + ok(!desc.Usage, "got %u.\n", desc.Usage); + ok(desc.BindFlags == (D3D11_BIND_RENDER_TARGET | D3D11_BIND_SHADER_RESOURCE), "got %#x.\n", desc.BindFlags); + ok(!desc.CPUAccessFlags, "got %#x.\n", desc.CPUAccessFlags); + ok(!desc.MiscFlags, "got %#x.\n", desc.MiscFlags); + ok(desc.MipLevels == 1, "git %u.\n", desc.MipLevels); + ok(desc.Width == aligned_width, "got %u.\n", desc.Width); + ok(desc.Height == aligned_height, "got %u.\n", desc.Height); + + ID3D11Texture2D_Release(tex2d); + IMFDXGIBuffer_Release(dxgi_buffer); + IMF2DBuffer2_Release(buffer2d); + IMFMediaBuffer_Release(buffer); + + + hr = MFCreateCollection(&output_samples); + ok(hr == S_OK, "MFCreateCollection returned %#lx\n", hr); + + hr = IMFCollection_AddElement(output_samples, (IUnknown *)output.pSample); + ok(hr == S_OK, "AddElement returned %#lx\n", hr); + IMFSample_Release(output.pSample); + + ret = check_mf_sample_collection(output_samples, &output_sample_desc_rgb32, L"rgb32frame.bmp"); + ok(ret <= 5, "got %lu%% diff\n", ret); + + for (i = 0; i < 9; i++) + { + hr = IMFTransform_ProcessInput(transform, 0, input_sample, 0); + ok(hr == S_OK, "got %#lx\n", hr); + + status = 0; + memset(&output, 0, sizeof(output)); + hr = IMFTransform_ProcessOutput(transform, 0, 1, &output, &status); + ok(hr == S_OK, "got %#lx\n", hr); + ok(!output.pEvents, "got events\n"); + ok(!!output.pSample, "got no sample\n"); + ok(output.dwStatus == 0, "got %#lx\n", output.dwStatus); + ok(status == 0, "got %#lx\n", status); + + hr = IMFCollection_AddElement(output_samples, (IUnknown *)output.pSample); + ok(hr == S_OK, "AddElement returned %#lx\n", hr); + IMFSample_Release(output.pSample); + } + + hr = IMFTransform_ProcessInput(transform, 0, input_sample, 0); + ok(hr == S_OK, "got %#lx\n", hr); + + status = 0; + memset(&output, 0, sizeof(output)); + hr = IMFTransform_ProcessOutput(transform, 0, 1, &output, &status); + ok(hr == MF_E_SAMPLEALLOCATOR_EMPTY, "got %#lx\n", hr); + + IMFCollection_Release(output_samples); + + status = 0; + memset(&output, 0, sizeof(output)); + hr = IMFTransform_ProcessOutput(transform, 0, 1, &output, &status); + ok(hr == S_OK, "got %#lx\n", hr); + ok(!output.pEvents, "got events\n"); + ok(!!output.pSample, "got no sample\n"); + ok(output.dwStatus == 0, "got %#lx\n", output.dwStatus); + ok(status == 0, "got %#lx\n", status); + IMFSample_Release(output.pSample); + +skip_tests: + hr = IMFTransform_ProcessMessage(transform, MFT_MESSAGE_SET_D3D_MANAGER, 0); + ok(hr == S_OK, "got %#lx\n", hr); + + memset(&info, 0xcc, sizeof(info)); + hr = IMFTransform_GetOutputStreamInfo(transform, 0, &info); + ok(hr == S_OK, "got %#lx\n", hr); + todo_wine ok(info.dwFlags == MFT_OUTPUT_STREAM_PROVIDES_SAMPLES, "got %#lx.\n", info.dwFlags); + + + hr = IMFVideoSampleAllocator_UninitializeSampleAllocator(allocator); + ok(hr == S_OK, "AddElement returned %#lx\n", hr); + + IMFSample_Release(input_sample); + +failed: + if (allocator) + IMFVideoSampleAllocator_Release(allocator); + if (manager) + IMFDXGIDeviceManager_Release(manager); + if (transform) + IMFTransform_Release(transform); + + MFShutdown(); + CoUninitialize(); +} + START_TEST(transform) { init_functions(); @@ -8830,4 +9136,6 @@ START_TEST(transform)
test_h264_with_dxgi_manager(); test_h264_decoder_concat_streams(); + + test_video_processor_with_dxgi_manager(); }
From: Rémi Bernon rbernon@codeweavers.com
--- dlls/mf/tests/transform.c | 21 ++-- dlls/mfreadwrite/tests/mfplat.c | 6 +- dlls/winegstreamer/video_processor.c | 171 +++++++++++++++++++++++++-- 3 files changed, 177 insertions(+), 21 deletions(-)
diff --git a/dlls/mf/tests/transform.c b/dlls/mf/tests/transform.c index 66e65629cba..9f17902f4ac 100644 --- a/dlls/mf/tests/transform.c +++ b/dlls/mf/tests/transform.c @@ -7294,7 +7294,7 @@ static void test_video_processor(void) static const struct attribute_desc expect_transform_attributes[] = { ATTR_UINT32(MFT_SUPPORT_3DVIDEO, 1, .todo = TRUE), - ATTR_UINT32(MF_SA_D3D11_AWARE, 1, .todo = TRUE), + ATTR_UINT32(MF_SA_D3D11_AWARE, 1), /* ATTR_UINT32(MF_SA_D3D_AWARE, 1), only on W7 */ {0}, }; @@ -8908,7 +8908,7 @@ static void test_video_processor_with_dxgi_manager(void) win_skip("missing video processor sample allocator support.\n"); goto failed; } - todo_wine ok(info.dwFlags == MFT_OUTPUT_STREAM_PROVIDES_SAMPLES, "got %#lx.\n", info.dwFlags); + ok(info.dwFlags == MFT_OUTPUT_STREAM_PROVIDES_SAMPLES, "got %#lx.\n", info.dwFlags);
hr = MFCreateMediaType(&type); ok(hr == S_OK, "got %#lx\n", hr); @@ -8939,7 +8939,7 @@ static void test_video_processor_with_dxgi_manager(void) status = 0; memset(&output, 0, sizeof(output)); hr = IMFTransform_ProcessOutput(transform, 0, 1, &output, &status); - todo_wine ok(hr == MF_E_TRANSFORM_NEED_MORE_INPUT, "got %#lx\n", hr); + ok(hr == MF_E_TRANSFORM_NEED_MORE_INPUT, "got %#lx\n", hr);
load_resource(L"nv12frame.bmp", &nv12frame_data, &nv12frame_data_len); /* skip BMP header and RGB data from the dump */ @@ -8971,18 +8971,17 @@ static void test_video_processor_with_dxgi_manager(void)
hr = IMFTransform_GetOutputStreamInfo(transform, 0, &info); ok(hr == S_OK, "got %#lx\n", hr); - todo_wine ok(info.dwFlags == MFT_OUTPUT_STREAM_PROVIDES_SAMPLES, "got %#lx.\n", info.dwFlags); + ok(info.dwFlags == MFT_OUTPUT_STREAM_PROVIDES_SAMPLES, "got %#lx.\n", info.dwFlags);
status = 0; memset(&output, 0, sizeof(output)); hr = IMFTransform_ProcessOutput(transform, 0, 1, &output, &status); - todo_wine ok(hr == S_OK, "got %#lx\n", hr); + ok(hr == S_OK, "got %#lx\n", hr); ok(!output.pEvents, "got events\n"); - todo_wine ok(!!output.pSample, "got no sample\n"); + ok(!!output.pSample, "got no sample\n"); ok(output.dwStatus == 0, "got %#lx\n", output.dwStatus); ok(status == 0, "got %#lx\n", status); - if (!output.pSample) goto skip_tests;
hr = IMFTransform_GetAttributes(transform, &attribs); ok(hr == S_OK, "got %#lx\n", hr); @@ -9039,6 +9038,7 @@ static void test_video_processor_with_dxgi_manager(void) IMFSample_Release(output.pSample);
ret = check_mf_sample_collection(output_samples, &output_sample_desc_rgb32, L"rgb32frame.bmp"); + todo_wine /* FIXME: video process vertically flips the frame... */ ok(ret <= 5, "got %lu%% diff\n", ret);
for (i = 0; i < 9; i++) @@ -9073,14 +9073,17 @@ static void test_video_processor_with_dxgi_manager(void) status = 0; memset(&output, 0, sizeof(output)); hr = IMFTransform_ProcessOutput(transform, 0, 1, &output, &status); + /* FIXME: Wine sample release happens entirely asynchronously */ + flaky_wine_if(hr == MF_E_SAMPLEALLOCATOR_EMPTY) ok(hr == S_OK, "got %#lx\n", hr); ok(!output.pEvents, "got events\n"); + flaky_wine_if(hr == MF_E_SAMPLEALLOCATOR_EMPTY) ok(!!output.pSample, "got no sample\n"); ok(output.dwStatus == 0, "got %#lx\n", output.dwStatus); ok(status == 0, "got %#lx\n", status); - IMFSample_Release(output.pSample); + if (output.pSample) + IMFSample_Release(output.pSample);
-skip_tests: hr = IMFTransform_ProcessMessage(transform, MFT_MESSAGE_SET_D3D_MANAGER, 0); ok(hr == S_OK, "got %#lx\n", hr);
diff --git a/dlls/mfreadwrite/tests/mfplat.c b/dlls/mfreadwrite/tests/mfplat.c index d0f9c689390..624ee2d90a8 100644 --- a/dlls/mfreadwrite/tests/mfplat.c +++ b/dlls/mfreadwrite/tests/mfplat.c @@ -3086,11 +3086,11 @@ static void test_source_reader_transforms_d3d9(void) hr = IMFTransform_GetAttributes(video_processor, &attributes); ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); hr = IMFAttributes_GetUINT32(attributes, &MF_SA_D3D_AWARE, &value); + todo_wine /* Wine exposes MF_SA_D3D_AWARE on the video processor, as Win7 */ ok(hr == MF_E_ATTRIBUTENOTFOUND, "Unexpected hr %#lx.\n", hr); - value = 0xdeadbeef; hr = IMFAttributes_GetUINT32(attributes, &MF_SA_D3D11_AWARE, &value); - todo_wine ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); - todo_wine ok(value == 1, "got %u.\n", value); + ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); + ok(value == 1, "got %u.\n", value); hr = IMFAttributes_GetUINT32(attributes, &MF_SA_MINIMUM_OUTPUT_SAMPLE_COUNT, &value); ok(hr == MF_E_ATTRIBUTENOTFOUND, "Unexpected hr %#lx.\n", hr); IMFAttributes_Release(attributes); diff --git a/dlls/winegstreamer/video_processor.c b/dlls/winegstreamer/video_processor.c index 3075bf997d2..b60b367faab 100644 --- a/dlls/winegstreamer/video_processor.c +++ b/dlls/winegstreamer/video_processor.c @@ -83,6 +83,12 @@ struct video_processor
wg_transform_t wg_transform; struct wg_sample_queue *wg_sample_queue; + + IUnknown *device_manager; + IMFVideoSampleAllocatorEx *allocator; + + IMFTransform *copier; + IMFMediaBuffer *copier_buffer; };
static HRESULT try_create_wg_transform(struct video_processor *impl) @@ -108,6 +114,82 @@ static HRESULT try_create_wg_transform(struct video_processor *impl) return S_OK; }
+static HRESULT video_processor_init_allocator(struct video_processor *processor) +{ + IMFVideoSampleAllocatorEx *allocator; + UINT32 count; + HRESULT hr; + + if (processor->allocator) + return S_OK; + + if (FAILED(hr = MFCreateVideoSampleAllocatorEx(&IID_IMFVideoSampleAllocatorEx, (void **)&allocator))) + return hr; + if (FAILED(IMFAttributes_GetUINT32(processor->attributes, &MF_SA_MINIMUM_OUTPUT_SAMPLE_COUNT, &count))) + count = 2; + if (FAILED(hr = IMFVideoSampleAllocatorEx_SetDirectXManager(allocator, processor->device_manager)) + || FAILED(hr = IMFVideoSampleAllocatorEx_InitializeSampleAllocatorEx(allocator, count, max(count + 2, 11), + processor->output_attributes, processor->output_type))) + { + IMFVideoSampleAllocatorEx_Release(allocator); + return hr; + } + + processor->allocator = allocator; + return S_OK; +} + +static HRESULT video_processor_uninit_allocator(struct video_processor *processor) +{ + HRESULT hr; + + if (!processor->allocator) + return S_OK; + + if (SUCCEEDED(hr = IMFVideoSampleAllocatorEx_UninitializeSampleAllocator(processor->allocator))) + hr = IMFVideoSampleAllocatorEx_SetDirectXManager(processor->allocator, NULL); + IMFVideoSampleAllocatorEx_Release(processor->allocator); + processor->allocator = NULL; + + return hr; +} + +static HRESULT video_processor_init_copier(struct video_processor *processor, const MFT_OUTPUT_STREAM_INFO *info) +{ + IMFTransform *copier; + HRESULT hr; + + if (processor->copier) + return S_OK; + + if (FAILED(hr = MFCreateSampleCopierMFT(&copier))) + return hr; + + if (SUCCEEDED(hr = IMFTransform_SetInputType(copier, 0, processor->output_type, 0)) + && SUCCEEDED(hr = IMFTransform_SetOutputType(copier, 0, processor->output_type, 0)) + && SUCCEEDED(hr = MFCreateMemoryBuffer(info->cbSize, &processor->copier_buffer))) + processor->copier = copier; + else + IMFTransform_Release(copier); + + return hr; +} + +static void video_processor_uninit_copier(struct video_processor *processor) +{ + if (processor->copier) + { + IMFTransform_Release(processor->copier); + processor->copier = NULL; + } + + if (processor->copier_buffer) + { + IMFMediaBuffer_Release(processor->copier_buffer); + processor->copier_buffer = NULL; + } +} + static struct video_processor *impl_from_IMFTransform(IMFTransform *iface) { return CONTAINING_RECORD(iface, struct video_processor, IMFTransform_iface); @@ -151,6 +233,10 @@ static ULONG WINAPI video_processor_Release(IMFTransform *iface)
if (!refcount) { + video_processor_uninit_allocator(impl); + video_processor_uninit_copier(impl); + if (impl->device_manager) + IUnknown_Release(impl->device_manager); if (impl->wg_transform) wg_transform_destroy(impl->wg_transform); if (impl->input_type) @@ -223,7 +309,7 @@ static HRESULT WINAPI video_processor_GetAttributes(IMFTransform *iface, IMFAttr { struct video_processor *impl = impl_from_IMFTransform(iface);
- FIXME("iface %p, attributes %p semi-stub!\n", iface, attributes); + TRACE("iface %p, attributes %p\n", iface, attributes);
if (!attributes) return E_POINTER; @@ -242,7 +328,7 @@ static HRESULT WINAPI video_processor_GetOutputStreamAttributes(IMFTransform *if { struct video_processor *impl = impl_from_IMFTransform(iface);
- FIXME("iface %p, id %#lx, attributes %p semi-stub!\n", iface, id, attributes); + TRACE("iface %p, id %#lx, attributes %p\n", iface, id, attributes);
if (!attributes) return E_POINTER; @@ -406,6 +492,10 @@ static HRESULT WINAPI video_processor_SetOutputType(IMFTransform *iface, DWORD i if (flags & MFT_SET_TYPE_TEST_ONLY) return S_OK;
+ if (FAILED(hr = video_processor_uninit_allocator(impl))) + return hr; + video_processor_uninit_copier(impl); + if (impl->output_type) IMFMediaType_Release(impl->output_type); IMFMediaType_AddRef((impl->output_type = type)); @@ -506,8 +596,34 @@ static HRESULT WINAPI video_processor_ProcessEvent(IMFTransform *iface, DWORD id
static HRESULT WINAPI video_processor_ProcessMessage(IMFTransform *iface, MFT_MESSAGE_TYPE message, ULONG_PTR param) { - FIXME("iface %p, message %#x, param %#Ix stub!\n", iface, message, param); - return S_OK; + struct video_processor *processor = impl_from_IMFTransform(iface); + HRESULT hr; + + TRACE("iface %p, message %#x, param %Ix.\n", iface, message, param); + + switch (message) + { + case MFT_MESSAGE_SET_D3D_MANAGER: + if (FAILED(hr = video_processor_uninit_allocator(processor))) + return hr; + video_processor_uninit_copier(processor); + + if (processor->device_manager) + { + processor->output_info.dwFlags &= ~MFT_OUTPUT_STREAM_PROVIDES_SAMPLES; + IUnknown_Release(processor->device_manager); + } + if ((processor->device_manager = (IUnknown *)param)) + { + IUnknown_AddRef(processor->device_manager); + processor->output_info.dwFlags |= MFT_OUTPUT_STREAM_PROVIDES_SAMPLES; + } + return S_OK; + + default: + FIXME("Ignoring message %#x.\n", message); + return S_OK; + } }
static HRESULT WINAPI video_processor_ProcessInput(IMFTransform *iface, DWORD id, IMFSample *sample, DWORD flags) @@ -527,6 +643,7 @@ static HRESULT WINAPI video_processor_ProcessOutput(IMFTransform *iface, DWORD f { struct video_processor *impl = impl_from_IMFTransform(iface); MFT_OUTPUT_STREAM_INFO info; + IMFSample *output_sample; HRESULT hr;
TRACE("iface %p, flags %#lx, count %lu, samples %p, status %p.\n", iface, flags, count, samples, status); @@ -538,16 +655,47 @@ static HRESULT WINAPI video_processor_ProcessOutput(IMFTransform *iface, DWORD f return MF_E_TRANSFORM_TYPE_NOT_SET;
samples->dwStatus = 0; - if (!samples->pSample) - return E_INVALIDARG; - if (FAILED(hr = IMFTransform_GetOutputStreamInfo(iface, 0, &info))) return hr;
- if (SUCCEEDED(hr = wg_transform_read_mf(impl->wg_transform, samples->pSample, + if (impl->output_info.dwFlags & MFT_OUTPUT_STREAM_PROVIDES_SAMPLES) + { + if (FAILED(hr = MFCreateSample(&output_sample))) + return hr; + if (FAILED(hr = video_processor_init_allocator(impl))) + goto done; + if (FAILED(hr = IMFVideoSampleAllocatorEx_AllocateSample(impl->allocator, &samples->pSample))) + goto done; + + if (FAILED(hr = video_processor_init_copier(impl, &info))) + goto done; + if (FAILED(hr = IMFSample_AddBuffer(output_sample, impl->copier_buffer))) + goto done; + } + else + { + if (!(output_sample = samples->pSample)) + return E_INVALIDARG; + IMFSample_AddRef(output_sample); + } + + if (FAILED(hr = wg_transform_read_mf(impl->wg_transform, output_sample, info.cbSize, NULL, &samples->dwStatus))) - wg_sample_queue_flush(impl->wg_sample_queue, false); + goto done; + wg_sample_queue_flush(impl->wg_sample_queue, false);
+ if (impl->output_info.dwFlags & MFT_OUTPUT_STREAM_PROVIDES_SAMPLES) + { + MFT_OUTPUT_DATA_BUFFER output = {.pSample = samples->pSample}; + DWORD status; + HRESULT hr; + + if (SUCCEEDED(hr = IMFTransform_ProcessInput(impl->copier, 0, output_sample, 0))) + hr = IMFTransform_ProcessOutput(impl->copier, 0, 1, &output, &status); + } + +done: + IMFSample_Release(output_sample); return hr; }
@@ -622,6 +770,11 @@ HRESULT video_processor_create(REFIID riid, void **ret)
if (FAILED(hr = MFCreateAttributes(&impl->attributes, 0))) goto failed; + if (FAILED(hr = IMFAttributes_SetUINT32(impl->attributes, &MF_SA_D3D11_AWARE, TRUE))) + goto failed; + /* native only has MF_SA_D3D_AWARE on Win7, but it is useful to have in mfreadwrite */ + if (FAILED(hr = IMFAttributes_SetUINT32(impl->attributes, &MF_SA_D3D_AWARE, TRUE))) + goto failed; if (FAILED(hr = MFCreateAttributes(&impl->output_attributes, 0))) goto failed; if (FAILED(hr = wg_sample_queue_create(&impl->wg_sample_queue)))
From: Rémi Bernon rbernon@codeweavers.com
--- dlls/mfreadwrite/reader.c | 59 +++++++++++++++++++++++++++++++++ dlls/mfreadwrite/tests/mfplat.c | 17 +++++----- 2 files changed, 67 insertions(+), 9 deletions(-)
diff --git a/dlls/mfreadwrite/reader.c b/dlls/mfreadwrite/reader.c index 9fe64206703..16eb14472ab 100644 --- a/dlls/mfreadwrite/reader.c +++ b/dlls/mfreadwrite/reader.c @@ -79,6 +79,7 @@ struct transform_entry UINT32 pending_flags; GUID category; BOOL hidden; + BOOL attributes_initialized; };
struct media_stream @@ -816,6 +817,35 @@ static HRESULT transform_entry_update_input_type(struct transform_entry *entry, return hr; }
+static void transform_entry_initialize_attributes(struct source_reader *reader, struct transform_entry *entry) +{ + IMFAttributes *attributes; + + if (SUCCEEDED(IMFTransform_GetAttributes(entry->transform, &attributes))) + { + if (FAILED(IMFAttributes_GetItem(attributes, &MF_SA_MINIMUM_OUTPUT_SAMPLE_COUNT, NULL))) + IMFAttributes_SetUINT32(attributes, &MF_SA_MINIMUM_OUTPUT_SAMPLE_COUNT, 6); + + IMFAttributes_Release(attributes); + } + + if (SUCCEEDED(IMFTransform_GetOutputStreamAttributes(entry->transform, 0, &attributes))) + { + UINT32 shared, shared_without_mutex, bind_flags; + + if (SUCCEEDED(IMFAttributes_GetUINT32(reader->attributes, &MF_SA_D3D11_SHARED, &shared))) + IMFAttributes_SetUINT32(attributes, &MF_SA_D3D11_SHARED, shared); + if (SUCCEEDED(IMFAttributes_GetUINT32(reader->attributes, &MF_SA_D3D11_SHARED_WITHOUT_MUTEX, &shared_without_mutex))) + IMFAttributes_SetUINT32(attributes, &MF_SA_D3D11_SHARED_WITHOUT_MUTEX, shared_without_mutex); + if (SUCCEEDED(IMFAttributes_GetUINT32(reader->attributes, &MF_SOURCE_READER_D3D11_BIND_FLAGS, &bind_flags))) + IMFAttributes_SetUINT32(attributes, &MF_SA_D3D11_BINDFLAGS, bind_flags); + else if ((reader->flags & SOURCE_READER_DXGI_DEVICE_MANAGER) && FAILED(IMFAttributes_GetItem(attributes, &MF_SA_D3D11_BINDFLAGS, NULL))) + IMFAttributes_SetUINT32(attributes, &MF_SA_D3D11_BINDFLAGS, 1024); + + IMFAttributes_Release(attributes); + } +} + static HRESULT source_reader_pull_transform_samples(struct source_reader *reader, struct media_stream *stream, struct transform_entry *entry) { @@ -828,6 +858,12 @@ static HRESULT source_reader_pull_transform_samples(struct source_reader *reader if ((ptr = list_next(&stream->transforms, &entry->entry))) next = LIST_ENTRY(ptr, struct transform_entry, entry);
+ if (!entry->attributes_initialized) + { + transform_entry_initialize_attributes(reader, entry); + entry->attributes_initialized = TRUE; + } + if (FAILED(hr = IMFTransform_GetOutputStreamInfo(entry->transform, 0, &stream_info))) return hr; stream_info.cbSize = max(stream_info.cbSize, entry->min_buffer_size); @@ -2011,10 +2047,33 @@ static HRESULT source_reader_create_transform(struct source_reader *reader, BOOL
for (i = 0; i < count; i++) { + IMFAttributes *attributes; IMFMediaType *media_type;
if (FAILED(IMFActivate_ActivateObject(activates[i], &IID_IMFTransform, (void **)&transform))) continue; + + if (!reader->device_manager || FAILED(IMFTransform_GetAttributes(transform, &attributes))) + entry->attributes_initialized = TRUE; + else + { + UINT32 d3d_aware = FALSE; + + if (reader->flags & SOURCE_READER_DXGI_DEVICE_MANAGER) + { + if (SUCCEEDED(IMFAttributes_GetUINT32(attributes, &MF_SA_D3D11_AWARE, &d3d_aware)) && d3d_aware) + IMFTransform_ProcessMessage(transform, MFT_MESSAGE_SET_D3D_MANAGER, (ULONG_PTR)reader->device_manager); + } + else if (reader->flags & SOURCE_READER_D3D9_DEVICE_MANAGER) + { + if (SUCCEEDED(IMFAttributes_GetUINT32(attributes, &MF_SA_D3D_AWARE, &d3d_aware) && d3d_aware)) + IMFTransform_ProcessMessage(transform, MFT_MESSAGE_SET_D3D_MANAGER, (ULONG_PTR)reader->device_manager); + } + + entry->attributes_initialized = !d3d_aware; + IMFAttributes_Release(attributes); + } + if (SUCCEEDED(hr = IMFTransform_SetInputType(transform, 0, input_type, 0)) && SUCCEEDED(hr = IMFTransform_GetInputCurrentType(transform, 0, &media_type))) { diff --git a/dlls/mfreadwrite/tests/mfplat.c b/dlls/mfreadwrite/tests/mfplat.c index 624ee2d90a8..65cd94748ac 100644 --- a/dlls/mfreadwrite/tests/mfplat.c +++ b/dlls/mfreadwrite/tests/mfplat.c @@ -3070,7 +3070,7 @@ static void test_source_reader_transforms_d3d9(void) hr = IMFSourceReader_SetCurrentMediaType(reader, 0, NULL, media_type); ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); IMFMediaType_Release(media_type); - todo_wine ok(!!test_decoder_got_d3d_manager, "d3d manager not received\n"); + ok(!!test_decoder_got_d3d_manager, "d3d manager not received\n");
hr = IMFSourceReader_GetCurrentMediaType(reader, 0, &media_type); ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); @@ -3147,10 +3147,9 @@ static void test_source_reader_transforms_d3d9(void)
hr = IMFTransform_GetAttributes(video_processor, &attributes); ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); - value = 0xdeadbeef; hr = IMFAttributes_GetUINT32(attributes, &MF_SA_MINIMUM_OUTPUT_SAMPLE_COUNT, &value); - todo_wine ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); - todo_wine ok(value == 6, "got %u.\n", value); + ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); + ok(value == 6, "got %u.\n", value); IMFAttributes_Release(attributes);
hr = IMFTransform_GetOutputStreamAttributes(video_processor, 0, &attributes); @@ -3204,7 +3203,7 @@ static void test_source_reader_transforms_d3d9(void) hr = IMFSourceReader_SetCurrentMediaType(reader, 0, NULL, media_type); ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); IMFMediaType_Release(media_type); - todo_wine ok(!!test_decoder_got_d3d_manager, "d3d manager not received\n"); + ok(!!test_decoder_got_d3d_manager, "d3d manager not received\n");
hr = IMFSourceReader_QueryInterface(reader, &IID_IMFSourceReaderEx, (void **)&reader_ex); @@ -3463,16 +3462,16 @@ static void test_source_reader_transforms_d3d11(void) ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); value = 0xdeadbeef; hr = IMFAttributes_GetUINT32(attributes, &MF_SA_MINIMUM_OUTPUT_SAMPLE_COUNT, &value); - todo_wine ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); - todo_wine ok(value == 6, "got %u.\n", value); + ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); + ok(value == 6, "got %u.\n", value); IMFAttributes_Release(attributes);
hr = IMFTransform_GetOutputStreamAttributes(video_processor, 0, &attributes); ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); value = 0xdeadbeef; hr = IMFAttributes_GetUINT32(attributes, &MF_SA_D3D11_BINDFLAGS, &value); - todo_wine ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); - todo_wine ok(value == 1024, "got %u.\n", value); + ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); + ok(value == 1024, "got %u.\n", value); IMFAttributes_Release(attributes);
IMFTransform_Release(video_processor);
Rebased on top of latest changes, fix the reference leaks before adding tests. The windows test failures should be fixed now.
That should be reviewed by someone who keeps track of what's going on in winegstreamer transform, and I think that's @rbernon himself. I have a quick question regarding changes here, what's the idea behind have a copier internally? Is it for the case when downstream node does not provide d3d samples? I'm not entirely sure how this is resolved on windows, I know that this happens:
source -> unware-mft -> evr ==> source -> unaware-mft -> copier -> evr
Then, if you have:
source-> aware-mft -> evr ==> does that use just one allocator from evr, or mft provides another one?
and in any case, does it get resolved to:
source -> copier -> aware-mft -> evr?
Source in general can support allocators I think, but there is a special API for those, and regular media formats sources don't have that.
I have a quick question regarding changes here, what's the idea behind have a copier internally? Is it for the case when downstream node does not provide d3d samples?
This is mostly to do the same as in the video decoder, and the idea was to benefit from any sample copy optimization (Copy2DTo, etc) that could be implemented in the copier, without having to reimplement it in every transform.
Ultimately, it could perhaps be replaced by mapping the D3D buffers to memory and letting GStreamer write to it directly, but that requires more work to provide buffer stride information to GStreamer. In the meantime, we could also perhaps map the D3D buffers as contiguous memory, which may be equivalent to using the sample copier but possibly less efficient.
I'm not entirely sure how this is resolved on windows, I know that this happens:
source -> unware-mft -> evr ==> source -> unaware-mft -> copier -> evr
Then, if you have:
source-> aware-mft -> evr ==> does that use just one allocator from evr, or mft provides another one?
and in any case, does it get resolved to:
source -> copier -> aware-mft -> evr?
The tests from https://gitlab.winehq.org/wine/wine/-/merge_requests/5464 show that native may insert copiers right before sinks, *and only right before sinks*, in the following conditions:
1) sink exposes a device manager (d3d aware attribute has no effect), and
2.a) sink is immediately preceded by a d3d-unaware transform that allocates its own samples, or
2.b) sink is immediately preceded by a d3d-aware transform, but that transform advertises that it will allocate samples *without any prior device manager initialization* (which means that the d3d-aware transform might allocate non-d3d samples), and dxva topology initialization is not enforced (DXVA_MODE != FULL).
I understand that the copier is there to make sure that only D3D samples are passed to the sink, in the case where the preceding transform would have allocated non-D3D samples.
As far as I could see, no copier is inserted elsewhere, so I assume that even when they received a D3D device manager, transforms are supposed to support being fed with non-D3D buffers as input.
Source in general can support allocators I think, but there is a special API for those, and regular media formats sources don't have that.
I'm interested, which API is that?
Do you think I should drop the copier and simply rely on media buffer Lock instead?