[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