Signed-off-by: Nikolay Sivov nsivov@codeweavers.com --- dlls/evr/mixer.c | 134 +++++++++++++++++++++++++++++++++++++++++++ dlls/evr/tests/evr.c | 8 +-- include/evr9.idl | 2 +- 3 files changed, 137 insertions(+), 7 deletions(-)
diff --git a/dlls/evr/mixer.c b/dlls/evr/mixer.c index 006427b77af..e8905f633ab 100644 --- a/dlls/evr/mixer.c +++ b/dlls/evr/mixer.c @@ -49,6 +49,7 @@ struct video_mixer IMFGetService IMFGetService_iface; IMFVideoMixerBitmap IMFVideoMixerBitmap_iface; IMFVideoPositionMapper IMFVideoPositionMapper_iface; + IMFVideoProcessor IMFVideoProcessor_iface; LONG refcount;
struct input_stream inputs[MAX_MIXER_INPUT_STREAMS]; @@ -95,6 +96,11 @@ static struct video_mixer *impl_from_IMFVideoPositionMapper(IMFVideoPositionMapp return CONTAINING_RECORD(iface, struct video_mixer, IMFVideoPositionMapper_iface); }
+static struct video_mixer *impl_from_IMFVideoProcessor(IMFVideoProcessor *iface) +{ + return CONTAINING_RECORD(iface, struct video_mixer, IMFVideoProcessor_iface); +} + static int video_mixer_compare_input_id(const void *a, const void *b) { const unsigned int *key = a; @@ -152,6 +158,10 @@ static HRESULT WINAPI video_mixer_transform_QueryInterface(IMFTransform *iface, { *obj = &mixer->IMFVideoPositionMapper_iface; } + else if (IsEqualIID(riid, &IID_IMFVideoProcessor)) + { + *obj = &mixer->IMFVideoProcessor_iface; + } else { WARN("Unsupported interface %s.\n", debugstr_guid(riid)); @@ -914,6 +924,129 @@ static const IMFVideoPositionMapperVtbl video_mixer_position_mapper_vtbl = video_mixer_position_mapper_MapOutputCoordinateToInputStream, };
+static HRESULT WINAPI video_mixer_processor_QueryInterface(IMFVideoProcessor *iface, REFIID riid, void **obj) +{ + struct video_mixer *mixer = impl_from_IMFVideoProcessor(iface); + return IMFTransform_QueryInterface(&mixer->IMFTransform_iface, riid, obj); +} + +static ULONG WINAPI video_mixer_processor_AddRef(IMFVideoProcessor *iface) +{ + struct video_mixer *mixer = impl_from_IMFVideoProcessor(iface); + return IMFTransform_AddRef(&mixer->IMFTransform_iface); +} + +static ULONG WINAPI video_mixer_processor_Release(IMFVideoProcessor *iface) +{ + struct video_mixer *mixer = impl_from_IMFVideoProcessor(iface); + return IMFTransform_Release(&mixer->IMFTransform_iface); +} + +static HRESULT WINAPI video_mixer_processor_GetAvailableVideoProcessorModes(IMFVideoProcessor *iface, UINT *count, + GUID **modes) +{ + FIXME("%p, %p, %p.\n", iface, count, modes); + + return E_NOTIMPL; +} + +static HRESULT WINAPI video_mixer_processor_GetVideoProcessorCaps(IMFVideoProcessor *iface, GUID *mode, + DXVA2_VideoProcessorCaps *caps) +{ + FIXME("%p, %s, %p.\n", iface, debugstr_guid(mode), caps); + + return E_NOTIMPL; +} + +static HRESULT WINAPI video_mixer_processor_GetVideoProcessorMode(IMFVideoProcessor *iface, GUID *mode) +{ + FIXME("%p, %p.\n", iface, mode); + + return E_NOTIMPL; +} + +static HRESULT WINAPI video_mixer_processor_SetVideoProcessorMode(IMFVideoProcessor *iface, GUID *mode) +{ + FIXME("%p, %s.\n", iface, debugstr_guid(mode)); + + return E_NOTIMPL; +} + +static HRESULT WINAPI video_mixer_processor_GetProcAmpRange(IMFVideoProcessor *iface, DWORD prop, DXVA2_ValueRange *range) +{ + FIXME("%p, %#x, %p.\n", iface, prop, range); + + return E_NOTIMPL; +} + +static HRESULT WINAPI video_mixer_processor_GetProcAmpValues(IMFVideoProcessor *iface, DWORD flags, DXVA2_ProcAmpValues *values) +{ + FIXME("%p, %#x, %p.\n", iface, flags, values); + + return E_NOTIMPL; +} + +static HRESULT WINAPI video_mixer_processor_SetProcAmpValues(IMFVideoProcessor *iface, DWORD flags, DXVA2_ProcAmpValues *values) +{ + FIXME("%p, %#x, %p.\n", iface, flags, values); + + return E_NOTIMPL; +} + +static HRESULT WINAPI video_mixer_processor_GetFilteringRange(IMFVideoProcessor *iface, DWORD prop, DXVA2_ValueRange *range) +{ + FIXME("%p, %#x, %p.\n", iface, prop, range); + + return E_NOTIMPL; +} + +static HRESULT WINAPI video_mixer_processor_GetFilteringValue(IMFVideoProcessor *iface, DWORD prop, DXVA2_Fixed32 *value) +{ + FIXME("%p, %#x, %p.\n", iface, prop, value); + + return E_NOTIMPL; +} + +static HRESULT WINAPI video_mixer_processor_SetFilteringValue(IMFVideoProcessor *iface, DWORD prop, DXVA2_Fixed32 *value) +{ + FIXME("%p, %#x, %p.\n", iface, prop, value); + + return E_NOTIMPL; +} + +static HRESULT WINAPI video_mixer_processor_GetBackgroundColor(IMFVideoProcessor *iface, COLORREF *color) +{ + FIXME("%p, %p.\n", iface, color); + + return E_NOTIMPL; +} + +static HRESULT WINAPI video_mixer_processor_SetBackgroundColor(IMFVideoProcessor *iface, COLORREF color) +{ + FIXME("%p, %#x.\n", iface, color); + + return E_NOTIMPL; +} + +static const IMFVideoProcessorVtbl video_mixer_processor_vtbl = +{ + video_mixer_processor_QueryInterface, + video_mixer_processor_AddRef, + video_mixer_processor_Release, + video_mixer_processor_GetAvailableVideoProcessorModes, + video_mixer_processor_GetVideoProcessorCaps, + video_mixer_processor_GetVideoProcessorMode, + video_mixer_processor_SetVideoProcessorMode, + video_mixer_processor_GetProcAmpRange, + video_mixer_processor_GetProcAmpValues, + video_mixer_processor_SetProcAmpValues, + video_mixer_processor_GetFilteringRange, + video_mixer_processor_GetFilteringValue, + video_mixer_processor_SetFilteringValue, + video_mixer_processor_GetBackgroundColor, + video_mixer_processor_SetBackgroundColor, +}; + HRESULT WINAPI MFCreateVideoMixer(IUnknown *owner, REFIID riid_device, REFIID riid, void **obj) { TRACE("%p, %s, %s, %p.\n", owner, debugstr_guid(riid_device), debugstr_guid(riid), obj); @@ -943,6 +1076,7 @@ HRESULT evr_mixer_create(IUnknown *outer, void **out) object->IMFGetService_iface.lpVtbl = &video_mixer_getservice_vtbl; object->IMFVideoMixerBitmap_iface.lpVtbl = &video_mixer_bitmap_vtbl; object->IMFVideoPositionMapper_iface.lpVtbl = &video_mixer_position_mapper_vtbl; + object->IMFVideoProcessor_iface.lpVtbl = &video_mixer_processor_vtbl; object->refcount = 1; object->input_count = 1; video_mixer_init_input(&object->inputs[0]); diff --git a/dlls/evr/tests/evr.c b/dlls/evr/tests/evr.c index 5bfa87014d8..c37f921b09e 100644 --- a/dlls/evr/tests/evr.c +++ b/dlls/evr/tests/evr.c @@ -405,10 +405,8 @@ static void test_default_mixer(void) IUnknown_Release(unk);
hr = IMFGetService_GetService(gs, &MR_VIDEO_MIXER_SERVICE, &IID_IMFVideoProcessor, (void **)&unk); -todo_wine ok(hr == S_OK, "Unexpected hr %#x.\n", hr); - if (SUCCEEDED(hr)) - IUnknown_Release(unk); + IUnknown_Release(unk);
hr = IMFGetService_GetService(gs, &MR_VIDEO_MIXER_SERVICE, &IID_IMFVideoPositionMapper, (void **)&unk); ok(hr == S_OK, "Unexpected hr %#x.\n", hr); @@ -425,10 +423,8 @@ todo_wine IUnknown_Release(unk);
hr = IMFTransform_QueryInterface(transform, &IID_IMFVideoProcessor, (void **)&unk); -todo_wine ok(hr == S_OK, "Unexpected hr %#x.\n", hr); - if (SUCCEEDED(hr)) - IUnknown_Release(unk); + IUnknown_Release(unk);
hr = IMFTransform_QueryInterface(transform, &IID_IMFVideoMixerControl, (void **)&unk); ok(hr == S_OK, "Unexpected hr %#x.\n", hr); diff --git a/include/evr9.idl b/include/evr9.idl index 1572d878387..b3d363cdee9 100644 --- a/include/evr9.idl +++ b/include/evr9.idl @@ -62,7 +62,7 @@ interface IMFVideoMixerBitmap : IUnknown
[ object, - uuid(6AB0000C-FECE-4d1f-A2AC-A9573530656E), + uuid(6ab0000c-fece-4d1f-a2ac-a9573530656e), pointer_default(unique) ] interface IMFVideoProcessor : IUnknown
Signed-off-by: Nikolay Sivov nsivov@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);
Signed-off-by: Nikolay Sivov nsivov@codeweavers.com --- dlls/evr/mixer.c | 25 +++++++++++++++++++++---- dlls/evr/tests/evr.c | 10 +++++----- 2 files changed, 26 insertions(+), 9 deletions(-)
diff --git a/dlls/evr/mixer.c b/dlls/evr/mixer.c index 6fcad15ec64..23994375d45 100644 --- a/dlls/evr/mixer.c +++ b/dlls/evr/mixer.c @@ -67,6 +67,8 @@ struct video_mixer unsigned int input_count; struct output_stream output;
+ COLORREF bkgnd_color; + IDirect3DDeviceManager9 *device_manager;
CRITICAL_SECTION cs; @@ -1187,16 +1189,31 @@ static HRESULT WINAPI video_mixer_processor_SetFilteringValue(IMFVideoProcessor
static HRESULT WINAPI video_mixer_processor_GetBackgroundColor(IMFVideoProcessor *iface, COLORREF *color) { - FIXME("%p, %p.\n", iface, color); + struct video_mixer *mixer = impl_from_IMFVideoProcessor(iface);
- return E_NOTIMPL; + TRACE("%p, %p.\n", iface, color); + + if (!color) + return E_POINTER; + + EnterCriticalSection(&mixer->cs); + *color = mixer->bkgnd_color; + LeaveCriticalSection(&mixer->cs); + + return S_OK; }
static HRESULT WINAPI video_mixer_processor_SetBackgroundColor(IMFVideoProcessor *iface, COLORREF color) { - FIXME("%p, %#x.\n", iface, color); + struct video_mixer *mixer = impl_from_IMFVideoProcessor(iface);
- return E_NOTIMPL; + TRACE("%p, %#x.\n", iface, color); + + EnterCriticalSection(&mixer->cs); + mixer->bkgnd_color = color; + LeaveCriticalSection(&mixer->cs); + + return S_OK; }
static const IMFVideoProcessorVtbl video_mixer_processor_vtbl = diff --git a/dlls/evr/tests/evr.c b/dlls/evr/tests/evr.c index 6259e636328..70fc6b18e2f 100644 --- a/dlls/evr/tests/evr.c +++ b/dlls/evr/tests/evr.c @@ -413,21 +413,21 @@ static void test_default_mixer(void) hr = IMFGetService_GetService(gs, &MR_VIDEO_MIXER_SERVICE, &IID_IMFVideoProcessor, (void **)&processor); ok(hr == S_OK, "Unexpected hr %#x.\n", hr);
+ hr = IMFVideoProcessor_GetBackgroundColor(processor, NULL); + ok(hr == E_POINTER, "Unexpected hr %#x.\n", hr); + 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);
Signed-off-by: Nikolay Sivov nsivov@codeweavers.com --- dlls/evr/Makefile.in | 3 +- dlls/evr/evr.spec | 2 +- dlls/evr/evr_classes.idl | 7 ++ dlls/evr/evr_private.h | 23 +++++ dlls/evr/main.c | 1 + dlls/evr/presenter.c | 218 +++++++++++++++++++++++++++++++++++++++ dlls/evr/tests/evr.c | 33 ++++++ include/evr.idl | 1 + 8 files changed, 286 insertions(+), 2 deletions(-) create mode 100644 dlls/evr/presenter.c
diff --git a/dlls/evr/Makefile.in b/dlls/evr/Makefile.in index 5671511f6ae..daaf9cc872a 100644 --- a/dlls/evr/Makefile.in +++ b/dlls/evr/Makefile.in @@ -8,6 +8,7 @@ EXTRADLLFLAGS = -mno-cygwin C_SRCS = \ evr.c \ main.c \ - mixer.c + mixer.c \ + presenter.c
IDL_SRCS = evr_classes.idl diff --git a/dlls/evr/evr.spec b/dlls/evr/evr.spec index 214f2b81d85..e46cb04f644 100644 --- a/dlls/evr/evr.spec +++ b/dlls/evr/evr.spec @@ -17,7 +17,7 @@ @ stub MFCreateVideoMixerAndPresenter @ stub MFCreateVideoOTA @ stub MFCreateVideoPresenter2 -@ stub MFCreateVideoPresenter +@ stdcall MFCreateVideoPresenter(ptr ptr ptr ptr) @ stub MFCreateVideoSampleAllocator @ stdcall MFCreateVideoSampleFromSurface(ptr ptr) @ stub MFGetPlaneSize diff --git a/dlls/evr/evr_classes.idl b/dlls/evr/evr_classes.idl index 31f0d34fe75..1885a34d77f 100644 --- a/dlls/evr/evr_classes.idl +++ b/dlls/evr/evr_classes.idl @@ -31,3 +31,10 @@ coclass EnhancedVideoRenderer { interface IBaseFilter; } uuid(e474e05a-ab65-4f6a-827c-218b1baaf31f) ] coclass MFVideoMixer9 { interface IMFTransform; } + +[ + helpstring("MF Video Presenter"), + threading(both), + uuid(98455561-5136-4d28-ab08-4cee40ea2781) +] +coclass MFVideoPresenter9 { interface IMFVideoPresenter; } diff --git a/dlls/evr/evr_private.h b/dlls/evr/evr_private.h index 5698eb0c21e..7ae83140579 100644 --- a/dlls/evr/evr_private.h +++ b/dlls/evr/evr_private.h @@ -22,8 +22,31 @@ #include "dshow.h" #include "evr.h" #include "wine/strmbase.h" +#include "wine/debug.h" + +static inline const char *debugstr_time(LONGLONG time) +{ + ULONGLONG abstime = time >= 0 ? time : -time; + unsigned int i = 0, j = 0; + char buffer[23], rev[23]; + + while (abstime || i <= 8) + { + buffer[i++] = '0' + (abstime % 10); + abstime /= 10; + if (i == 7) buffer[i++] = '.'; + } + if (time < 0) buffer[i++] = '-'; + + while (i--) rev[j++] = buffer[i]; + while (rev[j-1] == '0' && rev[j-2] != '.') --j; + rev[j] = 0; + + return wine_dbg_sprintf("%s", rev); +}
HRESULT evr_filter_create(IUnknown *outer_unk, void **ppv) DECLSPEC_HIDDEN; HRESULT evr_mixer_create(IUnknown *outer_unk, void **ppv) DECLSPEC_HIDDEN; +HRESULT evr_presenter_create(IUnknown *outer_unk, void **ppv) DECLSPEC_HIDDEN;
#endif /* __EVR_PRIVATE_INCLUDED__ */ diff --git a/dlls/evr/main.c b/dlls/evr/main.c index 85c81f13604..2c6db8430ba 100644 --- a/dlls/evr/main.c +++ b/dlls/evr/main.c @@ -72,6 +72,7 @@ static const struct object_creation_info object_creation[] = { { &CLSID_EnhancedVideoRenderer, evr_filter_create }, { &CLSID_MFVideoMixer9, evr_mixer_create }, + { &CLSID_MFVideoPresenter9, evr_presenter_create }, };
static HRESULT WINAPI classfactory_QueryInterface(IClassFactory *iface, REFIID riid, void **ppobj) diff --git a/dlls/evr/presenter.c b/dlls/evr/presenter.c new file mode 100644 index 00000000000..234c1f076ca --- /dev/null +++ b/dlls/evr/presenter.c @@ -0,0 +1,218 @@ +/* + * Copyright 2020 Nikolay Sivov + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA + */ + +#define COBJMACROS + +#include "evr.h" +#include "d3d9.h" +#include "mfapi.h" +#include "mferror.h" + +#include "evr_classes.h" +#include "evr_private.h" + +#include "wine/debug.h" +#include "wine/heap.h" + +WINE_DEFAULT_DEBUG_CHANNEL(evr); + +struct video_presenter +{ + IMFVideoPresenter IMFVideoPresenter_iface; + IUnknown IUnknown_inner; + IUnknown *outer_unk; + LONG refcount; +}; + +static struct video_presenter *impl_from_IUnknown(IUnknown *iface) +{ + return CONTAINING_RECORD(iface, struct video_presenter, IUnknown_inner); +} + +static struct video_presenter *impl_from_IMFVideoPresenter(IMFVideoPresenter *iface) +{ + return CONTAINING_RECORD(iface, struct video_presenter, IMFVideoPresenter_iface); +} + +static HRESULT WINAPI video_presenter_inner_QueryInterface(IUnknown *iface, REFIID riid, void **obj) +{ + struct video_presenter *presenter = impl_from_IUnknown(iface); + + TRACE("%p, %s, %p.\n", iface, debugstr_guid(riid), obj); + + if (IsEqualIID(riid, &IID_IUnknown)) + { + *obj = iface; + } + else if (IsEqualIID(riid, &IID_IMFClockStateSink) + || IsEqualIID(riid, &IID_IMFVideoPresenter)) + { + *obj = &presenter->IMFVideoPresenter_iface; + } + else + { + WARN("Unimplemented interface %s.\n", debugstr_guid(riid)); + *obj = NULL; + return E_NOINTERFACE; + } + + IUnknown_AddRef((IUnknown *)*obj); + return S_OK; +} + +static ULONG WINAPI video_presenter_inner_AddRef(IUnknown *iface) +{ + struct video_presenter *presenter = impl_from_IUnknown(iface); + ULONG refcount = InterlockedIncrement(&presenter->refcount); + + TRACE("%p, refcount %u.\n", iface, refcount); + + return refcount; +} + +static ULONG WINAPI video_presenter_inner_Release(IUnknown *iface) +{ + struct video_presenter *presenter = impl_from_IUnknown(iface); + ULONG refcount = InterlockedDecrement(&presenter->refcount); + + TRACE("%p, refcount %u.\n", iface, refcount); + + if (!refcount) + { + heap_free(presenter); + } + + return refcount; +} + +static const IUnknownVtbl video_presenter_inner_vtbl = +{ + video_presenter_inner_QueryInterface, + video_presenter_inner_AddRef, + video_presenter_inner_Release, +}; + +static HRESULT WINAPI video_presenter_QueryInterface(IMFVideoPresenter *iface, REFIID riid, void **obj) +{ + struct video_presenter *presenter = impl_from_IMFVideoPresenter(iface); + return IUnknown_QueryInterface(presenter->outer_unk, riid, obj); +} + +static ULONG WINAPI video_presenter_AddRef(IMFVideoPresenter *iface) +{ + struct video_presenter *presenter = impl_from_IMFVideoPresenter(iface); + return IUnknown_AddRef(presenter->outer_unk); +} + +static ULONG WINAPI video_presenter_Release(IMFVideoPresenter *iface) +{ + struct video_presenter *presenter = impl_from_IMFVideoPresenter(iface); + return IUnknown_Release(presenter->outer_unk); +} + +static HRESULT WINAPI video_presenter_OnClockStart(IMFVideoPresenter *iface, MFTIME systime, LONGLONG offset) +{ + FIXME("%p, %s, %s.\n", iface, debugstr_time(systime), wine_dbgstr_longlong(offset)); + + return E_NOTIMPL; +} + +static HRESULT WINAPI video_presenter_OnClockStop(IMFVideoPresenter *iface, MFTIME systime) +{ + FIXME("%p, %s.\n", iface, debugstr_time(systime)); + + return E_NOTIMPL; +} + +static HRESULT WINAPI video_presenter_OnClockPause(IMFVideoPresenter *iface, MFTIME systime) +{ + FIXME("%p, %s.\n", iface, debugstr_time(systime)); + + return E_NOTIMPL; +} + +static HRESULT WINAPI video_presenter_OnClockRestart(IMFVideoPresenter *iface, MFTIME systime) +{ + FIXME("%p, %s.\n", iface, debugstr_time(systime)); + + return E_NOTIMPL; +} + +static HRESULT WINAPI video_presenter_OnClockSetRate(IMFVideoPresenter *iface, MFTIME systime, float rate) +{ + FIXME("%p, %s, %f.\n", iface, debugstr_time(systime), rate); + + return E_NOTIMPL; +} + +static HRESULT WINAPI video_presenter_ProcessMessage(IMFVideoPresenter *iface, MFVP_MESSAGE_TYPE message, ULONG_PTR param) +{ + FIXME("%p, %d, %lu.\n", iface, message, param); + + return E_NOTIMPL; +} + +static HRESULT WINAPI video_presenter_GetCurrentMediaType(IMFVideoPresenter *iface, IMFVideoMediaType **media_type) +{ + FIXME("%p, %p.\n", iface, media_type); + + return E_NOTIMPL; +} + +static const IMFVideoPresenterVtbl video_presenter_vtbl = +{ + video_presenter_QueryInterface, + video_presenter_AddRef, + video_presenter_Release, + video_presenter_OnClockStart, + video_presenter_OnClockStop, + video_presenter_OnClockPause, + video_presenter_OnClockRestart, + video_presenter_OnClockSetRate, + video_presenter_ProcessMessage, + video_presenter_GetCurrentMediaType, +}; + +HRESULT WINAPI MFCreateVideoPresenter(IUnknown *owner, REFIID riid_device, REFIID riid, void **obj) +{ + TRACE("%p, %s, %s, %p.\n", owner, debugstr_guid(riid_device), debugstr_guid(riid), obj); + + *obj = NULL; + + if (!IsEqualIID(riid_device, &IID_IDirect3DDevice9)) + return E_INVALIDARG; + + return CoCreateInstance(&CLSID_MFVideoPresenter9, owner, CLSCTX_INPROC_SERVER, riid, obj); +} + +HRESULT evr_presenter_create(IUnknown *outer, void **out) +{ + struct video_presenter *object; + + if (!(object = heap_alloc(sizeof(*object)))) + return E_OUTOFMEMORY; + + object->IMFVideoPresenter_iface.lpVtbl = &video_presenter_vtbl; + object->IUnknown_inner.lpVtbl = &video_presenter_inner_vtbl; + object->outer_unk = outer ? outer : &object->IUnknown_inner; + object->refcount = 1; + + *out = &object->IUnknown_inner; + + return S_OK; +} diff --git a/dlls/evr/tests/evr.c b/dlls/evr/tests/evr.c index 70fc6b18e2f..44979a09501 100644 --- a/dlls/evr/tests/evr.c +++ b/dlls/evr/tests/evr.c @@ -117,6 +117,7 @@ static IUnknown test_outer = {&outer_vtbl}; static void test_aggregation(void) { IBaseFilter *filter, *filter2; + IMFVideoPresenter *presenter; IUnknown *unk, *unk2; HRESULT hr; ULONG ref; @@ -171,6 +172,22 @@ static void test_aggregation(void) ref = IUnknown_Release(unk); ok(!ref, "Got unexpected refcount %d.\n", ref); ok(outer_ref == 1, "Got unexpected refcount %d.\n", outer_ref); + + /* Default presenter. */ + presenter = (void *)0xdeadbeef; + hr = CoCreateInstance(&CLSID_MFVideoPresenter9, &test_outer, CLSCTX_INPROC_SERVER, &IID_IMFVideoPresenter, + (void **)&presenter); + ok(hr == E_NOINTERFACE, "Unexpected hr %#x.\n", hr); + ok(!presenter, "Got interface %p.\n", presenter); + + hr = CoCreateInstance(&CLSID_MFVideoPresenter9, &test_outer, CLSCTX_INPROC_SERVER, &IID_IUnknown, (void **)&unk); + ok(hr == S_OK, "Unexpected hr %#x.\n", hr); + ok(outer_ref == 1, "Got unexpected refcount %d.\n", outer_ref); + ok(unk != &test_outer, "Returned IUnknown should not be outer IUnknown.\n"); + ref = get_refcount(unk); + ok(ref == 1, "Got unexpected refcount %d.\n", ref); + + IUnknown_Release(unk); }
#define check_interface(a, b, c) check_interface_(__LINE__, a, b, c) @@ -846,6 +863,21 @@ done: DestroyWindow(window); }
+static void test_default_presenter(void) +{ + IMFVideoPresenter *presenter; + HRESULT hr; + GUID iid; + + hr = MFCreateVideoPresenter(NULL, &IID_IMFVideoPresenter, &IID_IMFVideoPresenter, (void **)&presenter); + ok(hr == E_INVALIDARG, "Unexpected hr %#x.\n", hr); + + hr = MFCreateVideoPresenter(NULL, &IID_IDirect3DDevice9, &IID_IMFVideoPresenter, (void **)&presenter); + ok(hr == S_OK, "Failed to create default presenter, hr %#x.\n", hr); + + IMFVideoPresenter_Release(presenter); +} + START_TEST(evr) { CoInitialize(NULL); @@ -860,6 +892,7 @@ START_TEST(evr) test_default_mixer(); test_default_mixer_type_negotiation(); test_surface_sample(); + test_default_presenter();
CoUninitialize(); } diff --git a/include/evr.idl b/include/evr.idl index 4599e298790..5a623c2c29c 100644 --- a/include/evr.idl +++ b/include/evr.idl @@ -225,4 +225,5 @@ cpp_quote("DEFINE_GUID(MR_BUFFER_SERVICE, 0xa562248c, 0x9ac6, 0x4ffc, 0x9f, 0xba cpp_quote("DEFINE_GUID(VIDEO_ZOOM_RECT, 0x7aaa1638, 0x1b7f, 0x4c93, 0xbd, 0x89, 0x5b, 0x9c, 0x9f, 0xb6, 0xfc, 0xf0);")
cpp_quote("HRESULT WINAPI MFCreateVideoMixer(IUnknown *owner, REFIID riid_device, REFIID riid, void **obj);") +cpp_quote("HRESULT WINAPI MFCreateVideoPresenter(IUnknown *owner, REFIID riid_device, REFIID riid, void **obj);") cpp_quote("HRESULT WINAPI MFCreateVideoSampleFromSurface(IUnknown *surface, IMFSample **sample);")
Hi,
While running your changed tests, I think I found new failures. Being a bot and all I'm not very good at pattern recognition, so I might be wrong, but could you please double-check?
Full results can be found at: https://testbot.winehq.org/JobDetails.pl?Key=74382
Your paranoid android.
=== wxppro (32 bit report) ===
evr: evr.c:184: Test failed: Unexpected hr 0x80004005. 0a20:evr: unhandled exception c0000005 at 004017F9
=== debiant (32 bit report) ===
evr: evr.c:180: Test failed: Unexpected hr 0x80040154. evr.c:184: Test failed: Unexpected hr 0x80040154. Unhandled exception: page fault on read access to 0x00000000 in 32-bit code (0x00402287).
Report validation errors: evr:evr crashed (c0000005)
=== debiant (32 bit French report) ===
evr: evr.c:180: Test failed: Unexpected hr 0x80040154. evr.c:184: Test failed: Unexpected hr 0x80040154. Unhandled exception: page fault on read access to 0x00000000 in 32-bit code (0x00402287).
Report validation errors: evr:evr crashed (c0000005)
=== debiant (32 bit Japanese:Japan report) ===
evr: evr.c:180: Test failed: Unexpected hr 0x80040154. evr.c:184: Test failed: Unexpected hr 0x80040154. Unhandled exception: page fault on read access to 0x00000000 in 32-bit code (0x00402287).
Report validation errors: evr:evr crashed (c0000005)
=== debiant (32 bit Chinese:China report) ===
evr: evr.c:180: Test failed: Unexpected hr 0x80040154. evr.c:184: Test failed: Unexpected hr 0x80040154. Unhandled exception: page fault on read access to 0x00000000 in 32-bit code (0x00402287).
Report validation errors: evr:evr crashed (c0000005)
=== debiant (32 bit WoW report) ===
evr: evr.c:180: Test failed: Unexpected hr 0x80040154. evr.c:184: Test failed: Unexpected hr 0x80040154. Unhandled exception: page fault on read access to 0x00000000 in 32-bit code (0x00402287).
Report validation errors: evr:evr crashed (c0000005)
=== debiant (64 bit WoW report) ===
evr: evr.c:180: Test failed: Unexpected hr 0x80040154. evr.c:184: Test failed: Unexpected hr 0x80040154. Unhandled exception: page fault on read access to 0x00000000 in 32-bit code (0x00402287).
Report validation errors: evr:evr crashed (c0000005)
Please ignore 4/5 and 5/5, I'll add some skips for winxp later.
Signed-off-by: Nikolay Sivov nsivov@codeweavers.com --- dlls/evr/presenter.c | 49 ++++++++++++++++++++++++++++++++++++++++++++ dlls/evr/tests/evr.c | 13 ++++++++++++ 2 files changed, 62 insertions(+)
diff --git a/dlls/evr/presenter.c b/dlls/evr/presenter.c index 234c1f076ca..34c9a06fcf3 100644 --- a/dlls/evr/presenter.c +++ b/dlls/evr/presenter.c @@ -34,6 +34,7 @@ WINE_DEFAULT_DEBUG_CHANNEL(evr); struct video_presenter { IMFVideoPresenter IMFVideoPresenter_iface; + IMFVideoDeviceID IMFVideoDeviceID_iface; IUnknown IUnknown_inner; IUnknown *outer_unk; LONG refcount; @@ -49,6 +50,11 @@ static struct video_presenter *impl_from_IMFVideoPresenter(IMFVideoPresenter *if return CONTAINING_RECORD(iface, struct video_presenter, IMFVideoPresenter_iface); }
+static struct video_presenter *impl_from_IMFVideoDeviceID(IMFVideoDeviceID *iface) +{ + return CONTAINING_RECORD(iface, struct video_presenter, IMFVideoDeviceID_iface); +} + static HRESULT WINAPI video_presenter_inner_QueryInterface(IUnknown *iface, REFIID riid, void **obj) { struct video_presenter *presenter = impl_from_IUnknown(iface); @@ -64,6 +70,10 @@ static HRESULT WINAPI video_presenter_inner_QueryInterface(IUnknown *iface, REFI { *obj = &presenter->IMFVideoPresenter_iface; } + else if (IsEqualIID(riid, &IID_IMFVideoDeviceID)) + { + *obj = &presenter->IMFVideoDeviceID_iface; + } else { WARN("Unimplemented interface %s.\n", debugstr_guid(riid)); @@ -188,6 +198,44 @@ static const IMFVideoPresenterVtbl video_presenter_vtbl = video_presenter_GetCurrentMediaType, };
+static HRESULT WINAPI video_presenter_device_id_QueryInterface(IMFVideoDeviceID *iface, REFIID riid, void **obj) +{ + struct video_presenter *presenter = impl_from_IMFVideoDeviceID(iface); + return IMFVideoPresenter_QueryInterface(&presenter->IMFVideoPresenter_iface, riid, obj); +} + +static ULONG WINAPI video_presenter_device_id_AddRef(IMFVideoDeviceID *iface) +{ + struct video_presenter *presenter = impl_from_IMFVideoDeviceID(iface); + return IMFVideoPresenter_AddRef(&presenter->IMFVideoPresenter_iface); +} + +static ULONG WINAPI video_presenter_device_id_Release(IMFVideoDeviceID *iface) +{ + struct video_presenter *presenter = impl_from_IMFVideoDeviceID(iface); + return IMFVideoPresenter_Release(&presenter->IMFVideoPresenter_iface); +} + +static HRESULT WINAPI video_presenter_device_id_GetDeviceID(IMFVideoDeviceID *iface, IID *device_id) +{ + TRACE("%p, %p.\n", iface, device_id); + + if (!device_id) + return E_POINTER; + + memcpy(device_id, &IID_IDirect3DDevice9, sizeof(*device_id)); + + return S_OK; +} + +static const IMFVideoDeviceIDVtbl video_presenter_device_id_vtbl = +{ + video_presenter_device_id_QueryInterface, + video_presenter_device_id_AddRef, + video_presenter_device_id_Release, + video_presenter_device_id_GetDeviceID, +}; + HRESULT WINAPI MFCreateVideoPresenter(IUnknown *owner, REFIID riid_device, REFIID riid, void **obj) { TRACE("%p, %s, %s, %p.\n", owner, debugstr_guid(riid_device), debugstr_guid(riid), obj); @@ -208,6 +256,7 @@ HRESULT evr_presenter_create(IUnknown *outer, void **out) return E_OUTOFMEMORY;
object->IMFVideoPresenter_iface.lpVtbl = &video_presenter_vtbl; + object->IMFVideoDeviceID_iface.lpVtbl = &video_presenter_device_id_vtbl; object->IUnknown_inner.lpVtbl = &video_presenter_inner_vtbl; object->outer_unk = outer ? outer : &object->IUnknown_inner; object->refcount = 1; diff --git a/dlls/evr/tests/evr.c b/dlls/evr/tests/evr.c index 44979a09501..dc48e10683c 100644 --- a/dlls/evr/tests/evr.c +++ b/dlls/evr/tests/evr.c @@ -866,6 +866,7 @@ done: static void test_default_presenter(void) { IMFVideoPresenter *presenter; + IMFVideoDeviceID *deviceid; HRESULT hr; GUID iid;
@@ -875,6 +876,18 @@ static void test_default_presenter(void) hr = MFCreateVideoPresenter(NULL, &IID_IDirect3DDevice9, &IID_IMFVideoPresenter, (void **)&presenter); ok(hr == S_OK, "Failed to create default presenter, hr %#x.\n", hr);
+ hr = IMFVideoPresenter_QueryInterface(presenter, &IID_IMFVideoDeviceID, (void **)&deviceid); + ok(hr == S_OK, "Unexpected hr %#x.\n", hr); + + hr = IMFVideoDeviceID_GetDeviceID(deviceid, NULL); + ok(hr == E_POINTER, "Unexpected hr %#x.\n", hr); + + hr = IMFVideoDeviceID_GetDeviceID(deviceid, &iid); + ok(hr == S_OK, "Unexpected hr %#x.\n", hr); + ok(IsEqualIID(&iid, &IID_IDirect3DDevice9), "Unexpected id %s.\n", wine_dbgstr_guid(&iid)); + + IMFVideoDeviceID_Release(deviceid); + IMFVideoPresenter_Release(presenter); }
Hi,
While running your changed tests, I think I found new failures. Being a bot and all I'm not very good at pattern recognition, so I might be wrong, but could you please double-check?
Full results can be found at: https://testbot.winehq.org/JobDetails.pl?Key=74383
Your paranoid android.
=== wxppro (32 bit report) ===
evr: evr.c:184: Test failed: Unexpected hr 0x80004005. 0a00:evr: unhandled exception c0000005 at 004017F9
=== debiant (32 bit report) ===
evr: evr.c:180: Test failed: Unexpected hr 0x80040154. evr.c:184: Test failed: Unexpected hr 0x80040154. Unhandled exception: page fault on read access to 0x00000000 in 32-bit code (0x00402287).
Report validation errors: evr:evr crashed (c0000005)
=== debiant (32 bit French report) ===
evr: evr.c:180: Test failed: Unexpected hr 0x80040154. evr.c:184: Test failed: Unexpected hr 0x80040154. Unhandled exception: page fault on read access to 0x00000000 in 32-bit code (0x00402287).
Report validation errors: evr:evr crashed (c0000005)
=== debiant (32 bit Japanese:Japan report) ===
evr: evr.c:180: Test failed: Unexpected hr 0x80040154. evr.c:184: Test failed: Unexpected hr 0x80040154. Unhandled exception: page fault on read access to 0x00000000 in 32-bit code (0x00402287).
Report validation errors: evr:evr crashed (c0000005)
=== debiant (32 bit Chinese:China report) ===
evr: evr.c:180: Test failed: Unexpected hr 0x80040154. evr.c:184: Test failed: Unexpected hr 0x80040154. Unhandled exception: page fault on read access to 0x00000000 in 32-bit code (0x00402287).
Report validation errors: evr:evr crashed (c0000005)
=== debiant (32 bit WoW report) ===
evr: evr.c:180: Test failed: Unexpected hr 0x80040154. evr.c:184: Test failed: Unexpected hr 0x80040154. Unhandled exception: page fault on read access to 0x00000000 in 32-bit code (0x00402287).
Report validation errors: evr:evr crashed (c0000005)
=== debiant (64 bit WoW report) ===
evr: evr.c:180: Test failed: Unexpected hr 0x80040154. evr.c:184: Test failed: Unexpected hr 0x80040154. Unhandled exception: page fault on read access to 0x00000000 in 32-bit code (0x00402287).
Report validation errors: evr:evr crashed (c0000005)