From: Rémi Bernon rbernon@codeweavers.com
--- dlls/mf/tests/transform.c | 24 +++--- dlls/mfreadwrite/tests/mfplat.c | 6 +- dlls/winegstreamer/video_processor.c | 120 ++++++++++++++++++++++++--- 3 files changed, 127 insertions(+), 23 deletions(-)
diff --git a/dlls/mf/tests/transform.c b/dlls/mf/tests/transform.c index 8bb51cc790c..ff74674f0ca 100644 --- a/dlls/mf/tests/transform.c +++ b/dlls/mf/tests/transform.c @@ -7343,7 +7343,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}, }; @@ -8062,9 +8062,10 @@ static void test_video_processor(void) } ret = IMFSample_Release(output_sample); ok(ret == 0, "Release returned %lu\n", ret); - winetest_pop_context();
skip_test: + winetest_pop_context(); + hr = IMFTransform_SetInputType(transform, 0, NULL, 0); ok(hr == S_OK, "got %#lx\n", hr); hr = IMFTransform_SetOutputType(transform, 0, NULL, 0); @@ -9089,7 +9090,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); @@ -9120,7 +9121,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 */ @@ -9152,18 +9153,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); @@ -9220,6 +9220,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++) @@ -9254,14 +9255,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 cce077ae63b..a5f72dd8a86 100644 --- a/dlls/winegstreamer/video_processor.c +++ b/dlls/winegstreamer/video_processor.c @@ -83,6 +83,9 @@ struct video_processor
wg_transform_t wg_transform; struct wg_sample_queue *wg_sample_queue; + + IUnknown *device_manager; + IMFVideoSampleAllocatorEx *allocator; };
static HRESULT try_create_wg_transform(struct video_processor *impl) @@ -108,6 +111,46 @@ 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, 10), + 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 struct video_processor *impl_from_IMFTransform(IMFTransform *iface) { return CONTAINING_RECORD(iface, struct video_processor, IMFTransform_iface); @@ -151,6 +194,9 @@ static ULONG WINAPI video_processor_Release(IMFTransform *iface)
if (!refcount) { + video_processor_uninit_allocator(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 +269,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 +288,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; @@ -438,6 +484,9 @@ 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; + if (impl->output_type) IMFMediaType_Release(impl->output_type); IMFMediaType_AddRef((impl->output_type = type)); @@ -538,8 +587,33 @@ 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; + + 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) @@ -559,6 +633,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); @@ -570,16 +645,36 @@ 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, - info.cbSize, NULL, &samples->dwStatus))) - wg_sample_queue_flush(impl->wg_sample_queue, false); + if (impl->output_info.dwFlags & MFT_OUTPUT_STREAM_PROVIDES_SAMPLES) + { + if (FAILED(hr = video_processor_init_allocator(impl))) + return hr; + if (FAILED(hr = IMFVideoSampleAllocatorEx_AllocateSample(impl->allocator, &output_sample))) + return hr; + } + 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))) + goto done; + wg_sample_queue_flush(impl->wg_sample_queue, false);
+ if (impl->output_info.dwFlags & MFT_OUTPUT_STREAM_PROVIDES_SAMPLES) + { + samples->pSample = output_sample; + IMFSample_AddRef(output_sample); + } + +done: + IMFSample_Release(output_sample); return hr; }
@@ -654,6 +749,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)))