winegstreamer/video_processor: Implement D3D awareness.

This commit is contained in:
Rémi Bernon 2024-04-02 21:57:49 +02:00 committed by Alexandre Julliard
parent c4fb3900bc
commit cf3134a841
3 changed files with 127 additions and 23 deletions

View file

@ -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);

View file

@ -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);

View file

@ -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)))