Signed-off-by: Nikolay Sivov nsivov@codeweavers.com --- dlls/evr/mixer.c | 178 +++++++++++++++++++++++++++++++++++++++---- dlls/evr/tests/evr.c | 114 +++++++++++++++++++++++++++ 2 files changed, 276 insertions(+), 16 deletions(-)
diff --git a/dlls/evr/mixer.c b/dlls/evr/mixer.c index 3101d17ffdb..54ea156b35f 100644 --- a/dlls/evr/mixer.c +++ b/dlls/evr/mixer.c @@ -21,17 +21,30 @@ #include "wine/debug.h" #include "evr.h" #include "d3d9.h" +#include "mferror.h"
#include "evr_classes.h"
WINE_DEFAULT_DEBUG_CHANNEL(evr);
+#define MAX_MIXER_INPUT_STREAMS 16 + +struct input_stream +{ + unsigned int id; +}; + struct video_mixer { IMFTransform IMFTransform_iface; IMFVideoDeviceID IMFVideoDeviceID_iface; IMFTopologyServiceLookupClient IMFTopologyServiceLookupClient_iface; LONG refcount; + + struct input_stream inputs[MAX_MIXER_INPUT_STREAMS]; + unsigned int input_ids[MAX_MIXER_INPUT_STREAMS]; + unsigned int input_count; + CRITICAL_SECTION cs; };
static struct video_mixer *impl_from_IMFTransform(IMFTransform *iface) @@ -49,6 +62,21 @@ static struct video_mixer *impl_from_IMFTopologyServiceLookupClient(IMFTopologyS return CONTAINING_RECORD(iface, struct video_mixer, IMFTopologyServiceLookupClient_iface); }
+static int video_mixer_compare_input_id(const void *a, const void *b) +{ + const unsigned int *key = a; + const struct input_stream *input = b; + + if (*key > input->id) return 1; + if (*key < input->id) return -1; + return 0; +} + +static struct input_stream * video_mixer_get_input(const struct video_mixer *mixer, unsigned int id) +{ + return bsearch(&id, mixer->inputs, mixer->input_count, sizeof(*mixer->inputs), video_mixer_compare_input_id); +} + static HRESULT WINAPI video_mixer_transform_QueryInterface(IMFTransform *iface, REFIID riid, void **obj) { struct video_mixer *mixer = impl_from_IMFTransform(iface); @@ -97,7 +125,10 @@ static ULONG WINAPI video_mixer_transform_Release(IMFTransform *iface) TRACE("%p, refcount %u.\n", iface, refcount);
if (!refcount) + { + DeleteCriticalSection(&mixer->cs); free(mixer); + }
return refcount; } @@ -105,38 +136,81 @@ static ULONG WINAPI video_mixer_transform_Release(IMFTransform *iface) static HRESULT WINAPI video_mixer_transform_GetStreamLimits(IMFTransform *iface, DWORD *input_minimum, DWORD *input_maximum, DWORD *output_minimum, DWORD *output_maximum) { - FIXME("%p, %p, %p, %p, %p.\n", iface, input_minimum, input_maximum, output_minimum, output_maximum); + TRACE("%p, %p, %p, %p, %p.\n", iface, input_minimum, input_maximum, output_minimum, output_maximum);
- return E_NOTIMPL; + *input_minimum = 1; + *input_maximum = 16; + *output_minimum = 1; + *output_maximum = 1; + + return S_OK; }
static HRESULT WINAPI video_mixer_transform_GetStreamCount(IMFTransform *iface, DWORD *inputs, DWORD *outputs) { - FIXME("%p, %p, %p.\n", iface, inputs, outputs); + struct video_mixer *mixer = impl_from_IMFTransform(iface);
- return E_NOTIMPL; + TRACE("%p, %p, %p.\n", iface, inputs, outputs); + + EnterCriticalSection(&mixer->cs); + if (inputs) *inputs = mixer->input_count; + if (outputs) *outputs = 1; + LeaveCriticalSection(&mixer->cs); + + return S_OK; }
static HRESULT WINAPI video_mixer_transform_GetStreamIDs(IMFTransform *iface, DWORD input_size, DWORD *inputs, DWORD output_size, DWORD *outputs) { - FIXME("%p, %u, %p, %u, %p.\n", iface, input_size, inputs, output_size, outputs); + struct video_mixer *mixer = impl_from_IMFTransform(iface); + HRESULT hr = S_OK;
- return E_NOTIMPL; + TRACE("%p, %u, %p, %u, %p.\n", iface, input_size, inputs, output_size, outputs); + + EnterCriticalSection(&mixer->cs); + if (mixer->input_count > input_size || !output_size) + hr = MF_E_BUFFERTOOSMALL; + else if (inputs) + memcpy(inputs, mixer->input_ids, mixer->input_count * sizeof(*inputs)); + if (outputs) *outputs = 0; + LeaveCriticalSection(&mixer->cs); + + return hr; }
static HRESULT WINAPI video_mixer_transform_GetInputStreamInfo(IMFTransform *iface, DWORD id, MFT_INPUT_STREAM_INFO *info) { - FIXME("%p, %u, %p.\n", iface, id, info); + struct video_mixer *mixer = impl_from_IMFTransform(iface); + struct input_stream *input; + HRESULT hr = S_OK;
- return E_NOTIMPL; + TRACE("%p, %u, %p.\n", iface, id, info); + + EnterCriticalSection(&mixer->cs); + if (!(input = video_mixer_get_input(mixer, id))) + hr = MF_E_INVALIDSTREAMNUMBER; + else + { + memset(info, 0, sizeof(*info)); + if (id) + info->dwFlags |= MFT_INPUT_STREAM_REMOVABLE | MFT_INPUT_STREAM_OPTIONAL; + } + LeaveCriticalSection(&mixer->cs); + + return hr; }
static HRESULT WINAPI video_mixer_transform_GetOutputStreamInfo(IMFTransform *iface, DWORD id, MFT_OUTPUT_STREAM_INFO *info) { - FIXME("%p, %u, %p.\n", iface, id, info); + TRACE("%p, %u, %p.\n", iface, id, info);
- return E_NOTIMPL; + if (id) + return MF_E_INVALIDSTREAMNUMBER; + + memset(info, 0, sizeof(*info)); + + return S_OK; }
static HRESULT WINAPI video_mixer_transform_GetAttributes(IMFTransform *iface, IMFAttributes **attributes) @@ -157,23 +231,93 @@ static HRESULT WINAPI video_mixer_transform_GetInputStreamAttributes(IMFTransfor static HRESULT WINAPI video_mixer_transform_GetOutputStreamAttributes(IMFTransform *iface, DWORD id, IMFAttributes **attributes) { - FIXME("%p, %u, %p.\n", iface, id, attributes); + TRACE("%p, %u, %p.\n", iface, id, attributes);
return E_NOTIMPL; }
static HRESULT WINAPI video_mixer_transform_DeleteInputStream(IMFTransform *iface, DWORD id) { - FIXME("%p, %u.\n", iface, id); + struct video_mixer *mixer = impl_from_IMFTransform(iface); + struct input_stream *input; + HRESULT hr = S_OK; + unsigned int idx;
- return E_NOTIMPL; + TRACE("%p, %u.\n", iface, id); + + EnterCriticalSection(&mixer->cs); + + /* Can't delete reference stream. */ + if (!id || !(input = video_mixer_get_input(mixer, id))) + hr = MF_E_INVALIDSTREAMNUMBER; + else + { + mixer->input_count--; + idx = input - mixer->inputs; + if (idx < mixer->input_count) + { + memmove(&mixer->inputs[idx], &mixer->inputs[idx + 1], (mixer->input_count - idx) * sizeof(*mixer->inputs)); + memmove(&mixer->input_ids[idx], &mixer->input_ids[idx + 1], (mixer->input_count - idx) * + sizeof(*mixer->input_ids)); + } + } + + LeaveCriticalSection(&mixer->cs); + + return hr; }
-static HRESULT WINAPI video_mixer_transform_AddInputStreams(IMFTransform *iface, DWORD streams, DWORD *ids) +static int video_mixer_add_input_sort_compare(const void *a, const void *b) { - FIXME("%p, %u, %p.\n", iface, streams, ids); + const struct input_stream *left = a, *right = b; + return left->id != right->id ? (left->id < right->id ? -1 : 1) : 0; +};
- return E_NOTIMPL; +static HRESULT WINAPI video_mixer_transform_AddInputStreams(IMFTransform *iface, DWORD count, DWORD *ids) +{ + struct video_mixer *mixer = impl_from_IMFTransform(iface); + struct input_stream inputs[MAX_MIXER_INPUT_STREAMS] = { 0 }; + unsigned int i, len; + HRESULT hr = S_OK; + + TRACE("%p, %u, %p.\n", iface, count, ids); + + if (!ids) + return E_POINTER; + + EnterCriticalSection(&mixer->cs); + if (count > ARRAY_SIZE(mixer->inputs) - mixer->input_count) + hr = E_INVALIDARG; + else + { + /* Test for collisions. */ + memcpy(inputs, mixer->inputs, mixer->input_count * sizeof(*inputs)); + for (i = 0; i < count; ++i) + inputs[i + mixer->input_count].id = ids[i]; + + len = mixer->input_count + count; + + qsort(inputs, len, sizeof(*inputs), video_mixer_add_input_sort_compare); + + for (i = 1; i < len; ++i) + { + if (inputs[i - 1].id == inputs[i].id) + { + hr = E_INVALIDARG; + break; + } + } + + if (SUCCEEDED(hr)) + { + memcpy(&mixer->input_ids[mixer->input_count], ids, count * sizeof(*ids)); + memcpy(mixer->inputs, inputs, len * sizeof(*inputs)); + mixer->input_count += count; + } + } + LeaveCriticalSection(&mixer->cs); + + return hr; }
static HRESULT WINAPI video_mixer_transform_GetInputAvailableType(IMFTransform *iface, DWORD id, DWORD index, @@ -407,6 +551,8 @@ HRESULT evr_mixer_create(IUnknown *outer, void **out) object->IMFVideoDeviceID_iface.lpVtbl = &video_mixer_device_id_vtbl; object->IMFTopologyServiceLookupClient_iface.lpVtbl = &video_mixer_service_client_vtbl; object->refcount = 1; + object->input_count = 1; + InitializeCriticalSection(&object->cs);
*out = &object->IMFTransform_iface;
diff --git a/dlls/evr/tests/evr.c b/dlls/evr/tests/evr.c index 56fb1680b07..db20fa76643 100644 --- a/dlls/evr/tests/evr.c +++ b/dlls/evr/tests/evr.c @@ -25,6 +25,7 @@ #include "evr.h" #include "initguid.h" #include "dxva2api.h" +#include "mferror.h"
static const WCHAR sink_id[] = {'E','V','R',' ','I','n','p','u','t','0',0};
@@ -340,8 +341,16 @@ static void test_pin_info(void)
static void test_default_mixer(void) { + DWORD input_min, input_max, output_min, output_max; + MFT_OUTPUT_STREAM_INFO output_info; + MFT_INPUT_STREAM_INFO input_info; + DWORD input_count, output_count; IMFVideoDeviceID *deviceid; + DWORD input_id, output_id; + IMFAttributes *attributes, *attributes2; IMFTransform *transform; + unsigned int i; + DWORD ids[16]; IUnknown *unk; HRESULT hr; IID iid; @@ -365,6 +374,111 @@ static void test_default_mixer(void)
IMFVideoDeviceID_Release(deviceid);
+ /* Stream configuration. */ + input_count = output_count = 0; + hr = IMFTransform_GetStreamCount(transform, &input_count, &output_count); + ok(hr == S_OK, "Failed to get stream count, hr %#x.\n", hr); + ok(input_count == 1 && output_count == 1, "Unexpected stream count %u/%u.\n", input_count, output_count); + + hr = IMFTransform_GetStreamLimits(transform, &input_min, &input_max, &output_min, &output_max); + ok(hr == S_OK, "Failed to get stream limits, hr %#x.\n", hr); + ok(input_min == 1 && input_max == 16 && output_min == 1 && output_max == 1, "Unexpected stream limits %u/%u, %u/%u.\n", + input_min, input_max, output_min, output_max); + + hr = IMFTransform_GetInputStreamInfo(transform, 1, &input_info); + ok(hr == MF_E_INVALIDSTREAMNUMBER, "Unexpected hr %#x.\n", hr); + + hr = IMFTransform_GetOutputStreamInfo(transform, 1, &output_info); + ok(hr == MF_E_INVALIDSTREAMNUMBER, "Unexpected hr %#x.\n", hr); + + memset(&input_info, 0xcc, sizeof(input_info)); + hr = IMFTransform_GetInputStreamInfo(transform, 0, &input_info); + ok(hr == S_OK, "Failed to get input info, hr %#x.\n", hr); + + memset(&output_info, 0xcc, sizeof(output_info)); + hr = IMFTransform_GetOutputStreamInfo(transform, 0, &output_info); + ok(hr == S_OK, "Failed to get input info, hr %#x.\n", hr); + ok(!(output_info.dwFlags & (MFT_OUTPUT_STREAM_PROVIDES_SAMPLES | MFT_OUTPUT_STREAM_CAN_PROVIDE_SAMPLES)), + "Unexpected output flags %#x.\n", output_info.dwFlags); + + hr = IMFTransform_GetStreamIDs(transform, 1, &input_id, 1, &output_id); + ok(hr == S_OK, "Failed to get input info, hr %#x.\n", hr); + ok(input_id == 0 && output_id == 0, "Unexpected stream ids.\n"); + + hr = IMFTransform_GetInputStreamAttributes(transform, 1, &attributes); +todo_wine + ok(hr == MF_E_INVALIDSTREAMNUMBER, "Unexpected hr %#x.\n", hr); + + hr = IMFTransform_GetOutputStreamAttributes(transform, 1, &attributes); + ok(hr == E_NOTIMPL, "Unexpected hr %#x.\n", hr); + + hr = IMFTransform_GetOutputStreamAttributes(transform, 0, &attributes); + ok(hr == E_NOTIMPL, "Unexpected hr %#x.\n", hr); + + hr = IMFTransform_AddInputStreams(transform, 16, NULL); + ok(hr == E_POINTER, "Unexpected hr %#x.\n", hr); + + hr = IMFTransform_AddInputStreams(transform, 16, ids); + ok(hr == E_INVALIDARG, "Unexpected hr %#x.\n", hr); + + memset(ids, 0, sizeof(ids)); + hr = IMFTransform_AddInputStreams(transform, 15, ids); + ok(hr == E_INVALIDARG, "Unexpected hr %#x.\n", hr); + + for (i = 0; i < ARRAY_SIZE(ids); ++i) + ids[i] = i + 1; + + hr = IMFTransform_AddInputStreams(transform, 15, ids); + ok(hr == S_OK, "Unexpected hr %#x.\n", hr); + + input_count = output_count = 0; + hr = IMFTransform_GetStreamCount(transform, &input_count, &output_count); + ok(hr == S_OK, "Failed to get stream count, hr %#x.\n", hr); + ok(input_count == 16 && output_count == 1, "Unexpected stream count %u/%u.\n", input_count, output_count); + + memset(&input_info, 0, sizeof(input_info)); + hr = IMFTransform_GetInputStreamInfo(transform, 1, &input_info); + ok(hr == S_OK, "Failed to get input info, hr %#x.\n", hr); + ok((input_info.dwFlags & (MFT_INPUT_STREAM_REMOVABLE | MFT_INPUT_STREAM_OPTIONAL)) == + (MFT_INPUT_STREAM_REMOVABLE | MFT_INPUT_STREAM_OPTIONAL), "Unexpected flags %#x.\n", input_info.dwFlags); + + attributes = NULL; + hr = IMFTransform_GetInputStreamAttributes(transform, 0, &attributes); +todo_wine { + ok(hr == S_OK, "Unexpected hr %#x.\n", hr); + ok(!!attributes, "Unexpected attributes.\n"); +} + attributes2 = NULL; + hr = IMFTransform_GetInputStreamAttributes(transform, 0, &attributes2); +todo_wine + ok(hr == S_OK, "Unexpected hr %#x.\n", hr); + ok(attributes == attributes2, "Unexpected instance.\n"); + + if (attributes2) + IMFAttributes_Release(attributes2); + if (attributes) + IMFAttributes_Release(attributes); + + attributes = NULL; + hr = IMFTransform_GetInputStreamAttributes(transform, 1, &attributes); +todo_wine { + ok(hr == S_OK, "Unexpected hr %#x.\n", hr); + ok(!!attributes, "Unexpected attributes.\n"); +} + if (attributes) + IMFAttributes_Release(attributes); + + hr = IMFTransform_DeleteInputStream(transform, 0); + ok(hr == MF_E_INVALIDSTREAMNUMBER, "Unexpected hr %#x.\n", hr); + + hr = IMFTransform_DeleteInputStream(transform, 1); + ok(hr == S_OK, "Unexpected hr %#x.\n", hr); + + input_count = output_count = 0; + hr = IMFTransform_GetStreamCount(transform, &input_count, &output_count); + ok(hr == S_OK, "Failed to get stream count, hr %#x.\n", hr); + ok(input_count == 15 && output_count == 1, "Unexpected stream count %u/%u.\n", input_count, output_count); + IMFTransform_Release(transform);
hr = MFCreateVideoMixer(NULL, &IID_IMFTransform, &IID_IMFTransform, (void **)&transform);
Signed-off-by: Nikolay Sivov nsivov@codeweavers.com --- dlls/evr/Makefile.in | 1 + dlls/evr/mixer.c | 44 ++++++++++++++++++++++++++++++++++++++++++-- dlls/evr/tests/evr.c | 16 ++++------------ 3 files changed, 47 insertions(+), 14 deletions(-)
diff --git a/dlls/evr/Makefile.in b/dlls/evr/Makefile.in index bf3048f62ee..5671511f6ae 100644 --- a/dlls/evr/Makefile.in +++ b/dlls/evr/Makefile.in @@ -1,6 +1,7 @@ MODULE = evr.dll IMPORTLIB = evr IMPORTS = mfuuid strmiids strmbase uuid dxguid ole32 oleaut32 +DELAYIMPORTS = mfplat
EXTRADLLFLAGS = -mno-cygwin
diff --git a/dlls/evr/mixer.c b/dlls/evr/mixer.c index 54ea156b35f..ad5d46482e4 100644 --- a/dlls/evr/mixer.c +++ b/dlls/evr/mixer.c @@ -21,6 +21,7 @@ #include "wine/debug.h" #include "evr.h" #include "d3d9.h" +#include "mfapi.h" #include "mferror.h"
#include "evr_classes.h" @@ -32,6 +33,7 @@ WINE_DEFAULT_DEBUG_CHANNEL(evr); struct input_stream { unsigned int id; + IMFAttributes *attributes; };
struct video_mixer @@ -77,6 +79,12 @@ static struct input_stream * video_mixer_get_input(const struct video_mixer *mix return bsearch(&id, mixer->inputs, mixer->input_count, sizeof(*mixer->inputs), video_mixer_compare_input_id); }
+static void video_mixer_init_input(struct input_stream *stream) +{ + if (SUCCEEDED(MFCreateAttributes(&stream->attributes, 1))) + IMFAttributes_SetUINT32(stream->attributes, &MF_SA_REQUIRED_SAMPLE_COUNT, 1); +} + static HRESULT WINAPI video_mixer_transform_QueryInterface(IMFTransform *iface, REFIID riid, void **obj) { struct video_mixer *mixer = impl_from_IMFTransform(iface); @@ -121,11 +129,17 @@ static ULONG WINAPI video_mixer_transform_Release(IMFTransform *iface) { struct video_mixer *mixer = impl_from_IMFTransform(iface); ULONG refcount = InterlockedDecrement(&mixer->refcount); + unsigned int i;
TRACE("%p, refcount %u.\n", iface, refcount);
if (!refcount) { + for (i = 0; i < mixer->input_count; ++i) + { + if (mixer->inputs[i].attributes) + IMFAttributes_Release(mixer->inputs[i].attributes); + } DeleteCriticalSection(&mixer->cs); free(mixer); } @@ -223,9 +237,26 @@ static HRESULT WINAPI video_mixer_transform_GetAttributes(IMFTransform *iface, I static HRESULT WINAPI video_mixer_transform_GetInputStreamAttributes(IMFTransform *iface, DWORD id, IMFAttributes **attributes) { - FIXME("%p, %u, %p.\n", iface, id, attributes); + struct video_mixer *mixer = impl_from_IMFTransform(iface); + struct input_stream *input; + HRESULT hr = S_OK;
- return E_NOTIMPL; + TRACE("%p, %u, %p.\n", iface, id, attributes); + + EnterCriticalSection(&mixer->cs); + + if (!(input = video_mixer_get_input(mixer, id))) + hr = MF_E_INVALIDSTREAMNUMBER; + else + { + *attributes = input->attributes; + if (*attributes) + IMFAttributes_AddRef(*attributes); + } + + LeaveCriticalSection(&mixer->cs); + + return hr; }
static HRESULT WINAPI video_mixer_transform_GetOutputStreamAttributes(IMFTransform *iface, DWORD id, @@ -256,6 +287,8 @@ static HRESULT WINAPI video_mixer_transform_DeleteInputStream(IMFTransform *ifac idx = input - mixer->inputs; if (idx < mixer->input_count) { + if (mixer->inputs[idx].attributes) + IMFAttributes_Release(mixer->inputs[idx].attributes); memmove(&mixer->inputs[idx], &mixer->inputs[idx + 1], (mixer->input_count - idx) * sizeof(*mixer->inputs)); memmove(&mixer->input_ids[idx], &mixer->input_ids[idx + 1], (mixer->input_count - idx) * sizeof(*mixer->input_ids)); @@ -277,6 +310,7 @@ static HRESULT WINAPI video_mixer_transform_AddInputStreams(IMFTransform *iface, { struct video_mixer *mixer = impl_from_IMFTransform(iface); struct input_stream inputs[MAX_MIXER_INPUT_STREAMS] = { 0 }; + struct input_stream *input; unsigned int i, len; HRESULT hr = S_OK;
@@ -310,6 +344,11 @@ static HRESULT WINAPI video_mixer_transform_AddInputStreams(IMFTransform *iface,
if (SUCCEEDED(hr)) { + for (i = 0; i < count; ++i) + { + if ((input = bsearch(&ids[i], inputs, len, sizeof(*inputs), video_mixer_compare_input_id))) + video_mixer_init_input(input); + } memcpy(&mixer->input_ids[mixer->input_count], ids, count * sizeof(*ids)); memcpy(mixer->inputs, inputs, len * sizeof(*inputs)); mixer->input_count += count; @@ -552,6 +591,7 @@ HRESULT evr_mixer_create(IUnknown *outer, void **out) object->IMFTopologyServiceLookupClient_iface.lpVtbl = &video_mixer_service_client_vtbl; object->refcount = 1; object->input_count = 1; + video_mixer_init_input(&object->inputs[0]); InitializeCriticalSection(&object->cs);
*out = &object->IMFTransform_iface; diff --git a/dlls/evr/tests/evr.c b/dlls/evr/tests/evr.c index db20fa76643..be004d9eae4 100644 --- a/dlls/evr/tests/evr.c +++ b/dlls/evr/tests/evr.c @@ -406,7 +406,6 @@ static void test_default_mixer(void) ok(input_id == 0 && output_id == 0, "Unexpected stream ids.\n");
hr = IMFTransform_GetInputStreamAttributes(transform, 1, &attributes); -todo_wine ok(hr == MF_E_INVALIDSTREAMNUMBER, "Unexpected hr %#x.\n", hr);
hr = IMFTransform_GetOutputStreamAttributes(transform, 1, &attributes); @@ -444,29 +443,22 @@ todo_wine
attributes = NULL; hr = IMFTransform_GetInputStreamAttributes(transform, 0, &attributes); -todo_wine { ok(hr == S_OK, "Unexpected hr %#x.\n", hr); ok(!!attributes, "Unexpected attributes.\n"); -} + attributes2 = NULL; hr = IMFTransform_GetInputStreamAttributes(transform, 0, &attributes2); -todo_wine ok(hr == S_OK, "Unexpected hr %#x.\n", hr); ok(attributes == attributes2, "Unexpected instance.\n");
- if (attributes2) - IMFAttributes_Release(attributes2); - if (attributes) - IMFAttributes_Release(attributes); + IMFAttributes_Release(attributes2); + IMFAttributes_Release(attributes);
attributes = NULL; hr = IMFTransform_GetInputStreamAttributes(transform, 1, &attributes); -todo_wine { ok(hr == S_OK, "Unexpected hr %#x.\n", hr); ok(!!attributes, "Unexpected attributes.\n"); -} - if (attributes) - IMFAttributes_Release(attributes); + IMFAttributes_Release(attributes);
hr = IMFTransform_DeleteInputStream(transform, 0); ok(hr == MF_E_INVALIDSTREAMNUMBER, "Unexpected hr %#x.\n", hr);
Signed-off-by: Nikolay Sivov nsivov@codeweavers.com --- dlls/evr/mixer.c | 87 ++++++++++++++++++++++++++++++++++++++++++++ dlls/evr/tests/evr.c | 4 ++ include/evr.idl | 38 +++++++++++++++++++ 3 files changed, 129 insertions(+)
diff --git a/dlls/evr/mixer.c b/dlls/evr/mixer.c index ad5d46482e4..81b3adb1763 100644 --- a/dlls/evr/mixer.c +++ b/dlls/evr/mixer.c @@ -41,6 +41,7 @@ struct video_mixer IMFTransform IMFTransform_iface; IMFVideoDeviceID IMFVideoDeviceID_iface; IMFTopologyServiceLookupClient IMFTopologyServiceLookupClient_iface; + IMFVideoMixerControl2 IMFVideoMixerControl2_iface; LONG refcount;
struct input_stream inputs[MAX_MIXER_INPUT_STREAMS]; @@ -64,6 +65,11 @@ static struct video_mixer *impl_from_IMFTopologyServiceLookupClient(IMFTopologyS return CONTAINING_RECORD(iface, struct video_mixer, IMFTopologyServiceLookupClient_iface); }
+static struct video_mixer *impl_from_IMFVideoMixerControl2(IMFVideoMixerControl2 *iface) +{ + return CONTAINING_RECORD(iface, struct video_mixer, IMFVideoMixerControl2_iface); +} + static int video_mixer_compare_input_id(const void *a, const void *b) { const unsigned int *key = a; @@ -104,6 +110,11 @@ static HRESULT WINAPI video_mixer_transform_QueryInterface(IMFTransform *iface, { *obj = &mixer->IMFTopologyServiceLookupClient_iface; } + else if (IsEqualIID(riid, &IID_IMFVideoMixerControl2) || + IsEqualIID(riid, &IID_IMFVideoMixerControl)) + { + *obj = &mixer->IMFVideoMixerControl2_iface; + } else { WARN("Unsupported interface %s.\n", debugstr_guid(riid)); @@ -564,6 +575,81 @@ static const IMFTopologyServiceLookupClientVtbl video_mixer_service_client_vtbl video_mixer_service_client_ReleaseServicePointers, };
+static HRESULT WINAPI video_mixer_control_QueryInterface(IMFVideoMixerControl2 *iface, REFIID riid, void **obj) +{ + struct video_mixer *mixer = impl_from_IMFVideoMixerControl2(iface); + return IMFTransform_QueryInterface(&mixer->IMFTransform_iface, riid, obj); +} + +static ULONG WINAPI video_mixer_control_AddRef(IMFVideoMixerControl2 *iface) +{ + struct video_mixer *mixer = impl_from_IMFVideoMixerControl2(iface); + return IMFTransform_AddRef(&mixer->IMFTransform_iface); +} + +static ULONG WINAPI video_mixer_control_Release(IMFVideoMixerControl2 *iface) +{ + struct video_mixer *mixer = impl_from_IMFVideoMixerControl2(iface); + return IMFTransform_Release(&mixer->IMFTransform_iface); +} + +static HRESULT WINAPI video_mixer_control_SetStreamZOrder(IMFVideoMixerControl2 *iface, DWORD stream_id, DWORD zorder) +{ + FIXME("%p, %u, %u.\n", iface, stream_id, zorder); + + return E_NOTIMPL; +} + +static HRESULT WINAPI video_mixer_control_GetStreamZOrder(IMFVideoMixerControl2 *iface, DWORD stream_id, DWORD *zorder) +{ + FIXME("%p, %u, %p.\n", iface, stream_id, zorder); + + return E_NOTIMPL; +} + +static HRESULT WINAPI video_mixer_control_SetStreamOutputRect(IMFVideoMixerControl2 *iface, DWORD stream_id, + const MFVideoNormalizedRect *rect) +{ + FIXME("%p, %u, %p.\n", iface, stream_id, rect); + + return E_NOTIMPL; +} + +static HRESULT WINAPI video_mixer_control_GetStreamOutputRect(IMFVideoMixerControl2 *iface, DWORD stream_id, + MFVideoNormalizedRect *rect) +{ + FIXME("%p, %u, %p.\n", iface, stream_id, rect); + + return E_NOTIMPL; +} + +static HRESULT WINAPI video_mixer_control_SetMixingPrefs(IMFVideoMixerControl2 *iface, DWORD flags) +{ + FIXME("%p, %#x.\n", iface, flags); + + return E_NOTIMPL; +} + +static HRESULT WINAPI video_mixer_control_GetMixingPrefs(IMFVideoMixerControl2 *iface, DWORD *flags) +{ + FIXME("%p, %p.\n", iface, flags); + + return E_NOTIMPL; +} + +static const IMFVideoMixerControl2Vtbl video_mixer_control_vtbl = +{ + video_mixer_control_QueryInterface, + video_mixer_control_AddRef, + video_mixer_control_Release, + video_mixer_control_SetStreamZOrder, + video_mixer_control_GetStreamZOrder, + video_mixer_control_SetStreamOutputRect, + video_mixer_control_GetStreamOutputRect, + video_mixer_control_SetMixingPrefs, + video_mixer_control_GetMixingPrefs, +}; + 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); @@ -589,6 +675,7 @@ HRESULT evr_mixer_create(IUnknown *outer, void **out) object->IMFTransform_iface.lpVtbl = &video_mixer_transform_vtbl; object->IMFVideoDeviceID_iface.lpVtbl = &video_mixer_device_id_vtbl; object->IMFTopologyServiceLookupClient_iface.lpVtbl = &video_mixer_service_client_vtbl; + object->IMFVideoMixerControl2_iface.lpVtbl = &video_mixer_control_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 be004d9eae4..9cf5d419198 100644 --- a/dlls/evr/tests/evr.c +++ b/dlls/evr/tests/evr.c @@ -362,6 +362,10 @@ static void test_default_mixer(void) ok(hr == S_OK, "Unexpected hr %#x.\n", hr); IUnknown_Release(unk);
+ hr = IMFTransform_QueryInterface(transform, &IID_IMFVideoMixerControl, (void **)&unk); + ok(hr == S_OK, "Unexpected hr %#x.\n", hr); + IUnknown_Release(unk); + hr = IMFTransform_QueryInterface(transform, &IID_IMFVideoDeviceID, (void **)&deviceid); ok(hr == S_OK, "Unexpected hr %#x.\n", hr);
diff --git a/include/evr.idl b/include/evr.idl index 39b4853b2e3..83603b92ccd 100644 --- a/include/evr.idl +++ b/include/evr.idl @@ -160,4 +160,42 @@ interface IMFVideoDeviceID : IUnknown ); }
+[ + object, + uuid(a5c6c53f-c202-4aa5-9695-175ba8c508a5) +] +interface IMFVideoMixerControl : IUnknown +{ + HRESULT SetStreamZOrder( + [in] DWORD stream_id, + [in] DWORD zorder + ); + HRESULT GetStreamZOrder( + [in] DWORD stream_id, + [out] DWORD *zorder + ); + HRESULT SetStreamOutputRect( + [in] DWORD stream_id, + [in] const MFVideoNormalizedRect *rect + ); + HRESULT GetStreamOutputRect( + [in] DWORD stream_id, + [out] MFVideoNormalizedRect *rect + ); +} + +[ + object, + uuid(8459616d-966e-4930-b658-54fa7e5a16d3) +] +interface IMFVideoMixerControl2 : IMFVideoMixerControl +{ + HRESULT SetMixingPrefs( + [in] DWORD flags + ); + HRESULT GetMixingPrefs( + [out] DWORD *flags + ); +} + cpp_quote("HRESULT WINAPI MFCreateVideoMixer(IUnknown *owner, REFIID riid_device, REFIID riid, void **obj);")