[PATCH 2/5] evr: Add input type validation through dxva.
Nikolay Sivov
nsivov at codeweavers.com
Mon Jun 29 07:43:38 CDT 2020
Signed-off-by: Nikolay Sivov <nsivov at codeweavers.com>
---
dlls/evr/mixer.c | 201 +++++++++++++++++++++++++++++++++++++++----
dlls/evr/tests/evr.c | 87 ++++++++++++++++++-
2 files changed, 269 insertions(+), 19 deletions(-)
diff --git a/dlls/evr/mixer.c b/dlls/evr/mixer.c
index e8905f633ab..6fcad15ec64 100644
--- a/dlls/evr/mixer.c
+++ b/dlls/evr/mixer.c
@@ -18,7 +18,6 @@
#define COBJMACROS
-#include "wine/debug.h"
#include "evr.h"
#include "d3d9.h"
#include "dxva2api.h"
@@ -30,6 +29,9 @@
#include "initguid.h"
#include "evr9.h"
+#include "wine/debug.h"
+#include "wine/heap.h"
+
WINE_DEFAULT_DEBUG_CHANNEL(evr);
#define MAX_MIXER_INPUT_STREAMS 16
@@ -38,6 +40,14 @@ struct input_stream
{
unsigned int id;
IMFAttributes *attributes;
+ IMFVideoMediaType *media_type;
+};
+
+struct output_stream
+{
+ IMFVideoMediaType *media_type;
+ IMFVideoMediaType **media_types;
+ unsigned int type_count;
};
struct video_mixer
@@ -55,6 +65,7 @@ struct video_mixer
struct input_stream inputs[MAX_MIXER_INPUT_STREAMS];
unsigned int input_ids[MAX_MIXER_INPUT_STREAMS];
unsigned int input_count;
+ struct output_stream output;
IDirect3DDeviceManager9 *device_manager;
@@ -122,6 +133,26 @@ static void video_mixer_init_input(struct input_stream *stream)
IMFAttributes_SetUINT32(stream->attributes, &MF_SA_REQUIRED_SAMPLE_COUNT, 1);
}
+static void video_mixer_clear_types(struct video_mixer *mixer)
+{
+ unsigned int i;
+
+ for (i = 0; i < mixer->input_count; ++i)
+ {
+ if (mixer->inputs[i].media_type)
+ IMFVideoMediaType_Release(mixer->inputs[i].media_type);
+ mixer->inputs[i].media_type = NULL;
+ }
+ for (i = 0; i < mixer->output.type_count; ++i)
+ {
+ IMFVideoMediaType_Release(mixer->output.media_types[i]);
+ }
+ heap_free(mixer->output.media_types);
+ if (mixer->output.media_type)
+ IMFVideoMediaType_Release(mixer->output.media_type);
+ mixer->output.media_type = NULL;
+}
+
static HRESULT WINAPI video_mixer_transform_QueryInterface(IMFTransform *iface, REFIID riid, void **obj)
{
struct video_mixer *mixer = impl_from_IMFTransform(iface);
@@ -198,6 +229,7 @@ static ULONG WINAPI video_mixer_transform_Release(IMFTransform *iface)
if (mixer->inputs[i].attributes)
IMFAttributes_Release(mixer->inputs[i].attributes);
}
+ video_mixer_clear_types(mixer);
if (mixer->device_manager)
IDirect3DDeviceManager9_Release(mixer->device_manager);
DeleteCriticalSection(&mixer->cs);
@@ -430,9 +462,27 @@ static HRESULT WINAPI video_mixer_transform_GetInputAvailableType(IMFTransform *
static HRESULT WINAPI video_mixer_transform_GetOutputAvailableType(IMFTransform *iface, DWORD id, DWORD index,
IMFMediaType **type)
{
- FIXME("%p, %u, %u, %p.\n", iface, id, index, type);
+ struct video_mixer *mixer = impl_from_IMFTransform(iface);
+ HRESULT hr = S_OK;
- return E_NOTIMPL;
+ TRACE("%p, %u, %u, %p.\n", iface, id, index, type);
+
+ if (id)
+ return MF_E_INVALIDSTREAMNUMBER;
+
+ EnterCriticalSection(&mixer->cs);
+
+ if (index >= mixer->output.type_count)
+ hr = MF_E_NO_MORE_TYPES;
+ else
+ {
+ *type = (IMFMediaType *)mixer->output.media_types[index];
+ IMFMediaType_AddRef(*type);
+ }
+
+ LeaveCriticalSection(&mixer->cs);
+
+ return hr;
}
static HRESULT video_mixer_init_dxva_videodesc(IMFMediaType *media_type, DXVA2_VideoDesc *video_desc)
@@ -465,24 +515,93 @@ done:
return hr;
}
+static int rt_formats_sort_compare(const void *left, const void *right)
+{
+ D3DFORMAT format1 = *(D3DFORMAT *)left, format2 = *(D3DFORMAT *)right;
+
+ if (format1 < format2) return -1;
+ if (format1 > format2) return 1;
+ return 0;
+}
+
+static HRESULT video_mixer_collect_output_types(struct video_mixer *mixer, const DXVA2_VideoDesc *video_desc,
+ IDirectXVideoProcessorService *service, unsigned int device_count, const GUID *devices)
+{
+ unsigned int i, j, format_count, count;
+ D3DFORMAT *rt_formats = NULL, *formats, *ptr;
+ GUID subtype;
+ HRESULT hr;
+
+ count = 0;
+ for (i = 0; i < device_count; ++i)
+ {
+ if (SUCCEEDED(IDirectXVideoProcessorService_GetVideoProcessorRenderTargets(service, &devices[i], video_desc,
+ &format_count, &formats)))
+ {
+ if (!(ptr = heap_realloc(rt_formats, (count + format_count) * sizeof(*rt_formats))))
+ {
+ hr = E_OUTOFMEMORY;
+ CoTaskMemFree(formats);
+ break;
+ }
+ rt_formats = ptr;
+
+ memcpy(&rt_formats[count], formats, format_count * sizeof(*formats));
+ count += format_count;
+
+ CoTaskMemFree(formats);
+ }
+ }
+
+ if (count)
+ {
+ qsort(rt_formats, count, sizeof(*rt_formats), rt_formats_sort_compare);
+
+ j = 0;
+ for (i = j + 1; i < count; ++i)
+ {
+ if (rt_formats[i] != rt_formats[j])
+ {
+ rt_formats[++j] = rt_formats[i];
+ }
+ }
+ count = j + 1;
+
+ memcpy(&subtype, &MFVideoFormat_Base, sizeof(subtype));
+ if ((mixer->output.media_types = heap_calloc(count, sizeof(*mixer->output.media_types))))
+ {
+ for (i = 0; i < count; ++i)
+ {
+ subtype.Data1 = rt_formats[i];
+ MFCreateVideoMediaTypeFromSubtype(&subtype, &mixer->output.media_types[i]);
+ }
+ mixer->output.type_count = count;
+ }
+ else
+ hr = E_OUTOFMEMORY;
+ }
+
+ heap_free(rt_formats);
+
+ return hr;
+}
+
static HRESULT WINAPI video_mixer_transform_SetInputType(IMFTransform *iface, DWORD id, IMFMediaType *media_type, DWORD flags)
{
struct video_mixer *mixer = impl_from_IMFTransform(iface);
IDirectXVideoProcessorService *service;
DXVA2_VideoDesc video_desc;
HRESULT hr = E_NOTIMPL;
+ unsigned int count;
HANDLE handle;
+ GUID *guids;
TRACE("%p, %u, %p, %#x.\n", iface, id, media_type, flags);
- if (id)
- {
- FIXME("Unimplemented for substreams.\n");
- return E_NOTIMPL;
- }
-
EnterCriticalSection(&mixer->cs);
+ video_mixer_clear_types(mixer);
+
if (!mixer->device_manager)
hr = MF_E_NOT_INITIALIZED;
else
@@ -494,8 +613,21 @@ static HRESULT WINAPI video_mixer_transform_SetInputType(IMFTransform *iface, DW
{
if (SUCCEEDED(hr = video_mixer_init_dxva_videodesc(media_type, &video_desc)))
{
- FIXME("Probe for supported devices.\n");
- hr = E_NOTIMPL;
+ if (!id)
+ {
+ if (SUCCEEDED(hr = IDirectXVideoProcessorService_GetVideoProcessorDeviceGuids(service, &video_desc,
+ &count, &guids)))
+ {
+ if (SUCCEEDED(hr = video_mixer_collect_output_types(mixer, &video_desc, service, count, guids)))
+ FIXME("Set input type.\n");
+ CoTaskMemFree(guids);
+ }
+ }
+ else
+ {
+ FIXME("Unimplemented for substreams.\n");
+ hr = E_NOTIMPL;
+ }
}
}
IDirect3DDeviceManager9_CloseDeviceHandle(mixer->device_manager, handle);
@@ -516,16 +648,55 @@ static HRESULT WINAPI video_mixer_transform_SetOutputType(IMFTransform *iface, D
static HRESULT WINAPI video_mixer_transform_GetInputCurrentType(IMFTransform *iface, DWORD id, IMFMediaType **type)
{
- FIXME("%p, %u, %p.\n", iface, id, type);
+ struct video_mixer *mixer = impl_from_IMFTransform(iface);
+ struct input_stream *stream;
+ HRESULT hr = S_OK;
- return E_NOTIMPL;
+ TRACE("%p, %u, %p.\n", iface, id, type);
+
+ EnterCriticalSection(&mixer->cs);
+
+ if ((stream = video_mixer_get_input(mixer, id)))
+ {
+ if (!stream->media_type)
+ hr = MF_E_TRANSFORM_TYPE_NOT_SET;
+ else
+ {
+ *type = (IMFMediaType *)stream->media_type;
+ IMFMediaType_AddRef(*type);
+ }
+ }
+ else
+ hr = MF_E_INVALIDSTREAMNUMBER;
+
+ LeaveCriticalSection(&mixer->cs);
+
+ return hr;
}
static HRESULT WINAPI video_mixer_transform_GetOutputCurrentType(IMFTransform *iface, DWORD id, IMFMediaType **type)
{
- FIXME("%p, %u, %p.\n", iface, id, type);
+ struct video_mixer *mixer = impl_from_IMFTransform(iface);
+ HRESULT hr = S_OK;
- return E_NOTIMPL;
+ TRACE("%p, %u, %p.\n", iface, id, type);
+
+ if (id)
+ return MF_E_INVALIDSTREAMNUMBER;
+
+ EnterCriticalSection(&mixer->cs);
+
+ if (!mixer->output.media_type)
+ hr = MF_E_TRANSFORM_TYPE_NOT_SET;
+ else
+ {
+ *type = (IMFMediaType *)mixer->output.media_type;
+ IMFMediaType_AddRef(*type);
+ }
+
+ LeaveCriticalSection(&mixer->cs);
+
+ return hr;
}
static HRESULT WINAPI video_mixer_transform_GetInputStatus(IMFTransform *iface, DWORD id, DWORD *flags)
diff --git a/dlls/evr/tests/evr.c b/dlls/evr/tests/evr.c
index c37f921b09e..6259e636328 100644
--- a/dlls/evr/tests/evr.c
+++ b/dlls/evr/tests/evr.c
@@ -376,17 +376,23 @@ static void test_pin_info(void)
static void test_default_mixer(void)
{
DWORD input_min, input_max, output_min, output_max;
+ IMFAttributes *attributes, *attributes2;
MFT_OUTPUT_STREAM_INFO output_info;
MFT_INPUT_STREAM_INFO input_info;
DWORD input_count, output_count;
+ IMFVideoProcessor *processor;
IMFVideoDeviceID *deviceid;
DWORD input_id, output_id;
- IMFAttributes *attributes, *attributes2;
IMFTransform *transform;
+ DXVA2_ValueRange range;
+ DXVA2_Fixed32 value;
IMFGetService *gs;
+ COLORREF color;
unsigned int i;
DWORD ids[16];
IUnknown *unk;
+ DWORD count;
+ GUID *guids;
HRESULT hr;
IID iid;
@@ -404,9 +410,37 @@ static void test_default_mixer(void)
ok(hr == S_OK, "Unexpected hr %#x.\n", hr);
IUnknown_Release(unk);
- hr = IMFGetService_GetService(gs, &MR_VIDEO_MIXER_SERVICE, &IID_IMFVideoProcessor, (void **)&unk);
+ hr = IMFGetService_GetService(gs, &MR_VIDEO_MIXER_SERVICE, &IID_IMFVideoProcessor, (void **)&processor);
ok(hr == S_OK, "Unexpected hr %#x.\n", hr);
- IUnknown_Release(unk);
+
+ color = 1;
+ hr = IMFVideoProcessor_GetBackgroundColor(processor, &color);
+todo_wine {
+ ok(hr == S_OK, "Unexpected hr %#x.\n", hr);
+ ok(!color, "Unexpected color %#x.\n", color);
+}
+ hr = IMFVideoProcessor_SetBackgroundColor(processor, 0x00121212);
+todo_wine
+ ok(hr == S_OK, "Unexpected hr %#x.\n", hr);
+
+ hr = IMFVideoProcessor_GetBackgroundColor(processor, &color);
+todo_wine {
+ ok(hr == S_OK, "Unexpected hr %#x.\n", hr);
+ ok(color == 0x121212, "Unexpected color %#x.\n", color);
+}
+ hr = IMFVideoProcessor_GetFilteringRange(processor, DXVA2_DetailFilterChromaLevel, &range);
+todo_wine
+ ok(hr == MF_E_TRANSFORM_TYPE_NOT_SET, "Unexpected hr %#x.\n", hr);
+
+ hr = IMFVideoProcessor_GetFilteringValue(processor, DXVA2_DetailFilterChromaLevel, &value);
+todo_wine
+ ok(hr == MF_E_TRANSFORM_TYPE_NOT_SET, "Unexpected hr %#x.\n", hr);
+
+ hr = IMFVideoProcessor_GetAvailableVideoProcessorModes(processor, &count, &guids);
+todo_wine
+ ok(hr == MF_E_TRANSFORM_TYPE_NOT_SET, "Unexpected hr %#x.\n", hr);
+
+ IMFVideoProcessor_Release(processor);
hr = IMFGetService_GetService(gs, &MR_VIDEO_MIXER_SERVICE, &IID_IMFVideoPositionMapper, (void **)&unk);
ok(hr == S_OK, "Unexpected hr %#x.\n", hr);
@@ -663,12 +697,17 @@ done:
static void test_default_mixer_type_negotiation(void)
{
IDirect3DDeviceManager9 *manager;
+ DXVA2_VideoProcessorCaps caps;
IMFVideoMediaType *video_type;
+ IMFVideoProcessor *processor;
IMFMediaType *media_type;
IDirect3DDevice9 *device;
IMFTransform *transform;
+ GUID guid, *guids;
IDirect3D9 *d3d;
+ IUnknown *unk;
HWND window;
+ DWORD count;
HRESULT hr;
UINT token;
@@ -685,7 +724,6 @@ static void test_default_mixer_type_negotiation(void)
ok(hr == E_NOTIMPL, "Unexpected hr %#x.\n", hr);
hr = IMFTransform_GetInputCurrentType(transform, 0, &media_type);
-todo_wine
ok(hr == MF_E_TRANSFORM_TYPE_NOT_SET, "Unexpected hr %#x.\n", hr);
hr = MFCreateMediaType(&media_type);
@@ -746,15 +784,56 @@ todo_wine
todo_wine
ok(hr == S_OK, "Unexpected hr %#x.\n", hr);
+ hr = IMFTransform_QueryInterface(transform, &IID_IMFVideoProcessor, (void **)&processor);
+ ok(hr == S_OK, "Unexpected hr %#x.\n", hr);
+
+ hr = IMFVideoProcessor_GetVideoProcessorMode(processor, &guid);
+todo_wine
+ ok(hr == MF_E_TRANSFORM_TYPE_NOT_SET, "Unexpected hr %#x.\n", hr);
+
+ hr = IMFVideoProcessor_GetVideoProcessorCaps(processor, (GUID *)&DXVA2_VideoProcSoftwareDevice, &caps);
+todo_wine
+ ok(hr == MF_E_TRANSFORM_TYPE_NOT_SET, "Unexpected hr %#x.\n", hr);
+
hr = IMFTransform_GetInputCurrentType(transform, 0, &media_type);
todo_wine
ok(hr == S_OK, "Unexpected hr %#x.\n", hr);
if (SUCCEEDED(hr))
{
ok(media_type != (IMFMediaType *)video_type, "Unexpected pointer.\n");
+ hr = IMFMediaType_QueryInterface(media_type, &IID_IMFVideoMediaType, (void **)&unk);
+ ok(hr == S_OK, "Unexpected hr %#x.\n", hr);
+ IUnknown_Release(unk);
+ IMFMediaType_Release(media_type);
+ }
+
+ hr = IMFVideoProcessor_GetAvailableVideoProcessorModes(processor, &count, &guids);
+todo_wine
+ ok(hr == MF_E_TRANSFORM_TYPE_NOT_SET, "Unexpected hr %#x.\n", hr);
+
+ hr = IMFTransform_GetOutputAvailableType(transform, 0, 0, &media_type);
+todo_wine
+ ok(hr == S_OK, "Unexpected hr %#x.\n", hr);
+
+ if (SUCCEEDED(hr))
+ {
+ hr = IMFTransform_SetOutputType(transform, 0, media_type, 0);
+ ok(hr == S_OK, "Unexpected hr %#x.\n", hr);
IMFMediaType_Release(media_type);
}
+ hr = IMFVideoProcessor_GetVideoProcessorMode(processor, &guid);
+todo_wine
+ ok(hr == S_FALSE, "Unexpected hr %#x.\n", hr);
+
+ hr = IMFVideoProcessor_GetAvailableVideoProcessorModes(processor, &count, &guids);
+todo_wine
+ ok(hr == S_OK, "Unexpected hr %#x.\n", hr);
+ if (SUCCEEDED(hr))
+ CoTaskMemFree(guids);
+
+ IMFVideoProcessor_Release(processor);
+
IMFVideoMediaType_Release(video_type);
IDirect3DDeviceManager9_Release(manager);
--
2.27.0
More information about the wine-devel
mailing list