Signed-off-by: Nikolay Sivov nsivov@codeweavers.com --- dlls/evr/presenter.c | 61 ++++++++++++++++++++++++++++++++++++++++++++ dlls/evr/tests/evr.c | 28 ++++++++++++++++++++ 2 files changed, 89 insertions(+)
diff --git a/dlls/evr/presenter.c b/dlls/evr/presenter.c index cbe8b0d2ff4..29167d364df 100644 --- a/dlls/evr/presenter.c +++ b/dlls/evr/presenter.c @@ -37,6 +37,7 @@ struct video_presenter IMFVideoDeviceID IMFVideoDeviceID_iface; IMFTopologyServiceLookupClient IMFTopologyServiceLookupClient_iface; IMFVideoDisplayControl IMFVideoDisplayControl_iface; + IMFRateSupport IMFRateSupport_iface; IUnknown IUnknown_inner; IUnknown *outer_unk; LONG refcount; @@ -67,6 +68,11 @@ static struct video_presenter *impl_from_IMFVideoDisplayControl(IMFVideoDisplayC return CONTAINING_RECORD(iface, struct video_presenter, IMFVideoDisplayControl_iface); }
+static struct video_presenter *impl_from_IMFRateSupport(IMFRateSupport *iface) +{ + return CONTAINING_RECORD(iface, struct video_presenter, IMFRateSupport_iface); +} + static HRESULT WINAPI video_presenter_inner_QueryInterface(IUnknown *iface, REFIID riid, void **obj) { struct video_presenter *presenter = impl_from_IUnknown(iface); @@ -94,6 +100,10 @@ static HRESULT WINAPI video_presenter_inner_QueryInterface(IUnknown *iface, REFI { *obj = &presenter->IMFVideoDisplayControl_iface; } + else if (IsEqualIID(riid, &IID_IMFRateSupport)) + { + *obj = &presenter->IMFRateSupport_iface; + } else { WARN("Unimplemented interface %s.\n", debugstr_guid(riid)); @@ -409,6 +419,56 @@ static const IMFVideoDisplayControlVtbl video_presenter_control_vtbl = video_presenter_control_GetCurrentImage, };
+static HRESULT WINAPI video_presenter_rate_support_QueryInterface(IMFRateSupport *iface, REFIID riid, void **obj) +{ + struct video_presenter *presenter = impl_from_IMFRateSupport(iface); + return IMFVideoPresenter_QueryInterface(&presenter->IMFVideoPresenter_iface, riid, obj); +} + +static ULONG WINAPI video_presenter_rate_support_AddRef(IMFRateSupport *iface) +{ + struct video_presenter *presenter = impl_from_IMFRateSupport(iface); + return IMFVideoPresenter_AddRef(&presenter->IMFVideoPresenter_iface); +} + +static ULONG WINAPI video_presenter_rate_support_Release(IMFRateSupport *iface) +{ + struct video_presenter *presenter = impl_from_IMFRateSupport(iface); + return IMFVideoPresenter_Release(&presenter->IMFVideoPresenter_iface); +} + +static HRESULT WINAPI video_presenter_rate_support_GetSlowestRate(IMFRateSupport *iface, MFRATE_DIRECTION direction, + BOOL thin, float *rate) +{ + TRACE("%p, %d, %d, %p.\n", iface, direction, thin, rate); + + *rate = 0.0f; + + return S_OK; +} + +static HRESULT WINAPI video_presenter_rate_support_GetFastestRate(IMFRateSupport *iface, MFRATE_DIRECTION direction, + BOOL thin, float *rate) +{ + return E_NOTIMPL; +} + +static HRESULT WINAPI video_presenter_rate_support_IsRateSupported(IMFRateSupport *iface, BOOL thin, float rate, + float *nearest_supported_rate) +{ + return E_NOTIMPL; +} + +static const IMFRateSupportVtbl video_presenter_rate_support_vtbl = +{ + video_presenter_rate_support_QueryInterface, + video_presenter_rate_support_AddRef, + video_presenter_rate_support_Release, + video_presenter_rate_support_GetSlowestRate, + video_presenter_rate_support_GetFastestRate, + video_presenter_rate_support_IsRateSupported, +}; + 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); @@ -432,6 +492,7 @@ HRESULT evr_presenter_create(IUnknown *outer, void **out) object->IMFVideoDeviceID_iface.lpVtbl = &video_presenter_device_id_vtbl; object->IMFTopologyServiceLookupClient_iface.lpVtbl = &video_presenter_service_client_vtbl; object->IMFVideoDisplayControl_iface.lpVtbl = &video_presenter_control_vtbl; + object->IMFRateSupport_iface.lpVtbl = &video_presenter_rate_support_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 037916fc4e1..dd3fbbe0289 100644 --- a/dlls/evr/tests/evr.c +++ b/dlls/evr/tests/evr.c @@ -869,8 +869,10 @@ done: static void test_default_presenter(void) { IMFVideoPresenter *presenter; + IMFRateSupport *rate_support; IMFVideoDeviceID *deviceid; IUnknown *unk; + float rate; HRESULT hr; GUID iid;
@@ -902,6 +904,32 @@ static void test_default_presenter(void) ok(hr == S_OK, "Unexpected hr %#x.\n", hr); IUnknown_Release(unk);
+ /* Rate support. */ + hr = IMFVideoPresenter_QueryInterface(presenter, &IID_IMFRateSupport, (void **)&rate_support); + ok(hr == S_OK, "Unexpected hr %#x.\n", hr); + + rate = 1.0f; + hr = IMFRateSupport_GetSlowestRate(rate_support, MFRATE_FORWARD, FALSE, &rate); + ok(hr == S_OK, "Unexpected hr %#x.\n", hr); + ok(rate == 0.0f, "Unexpected rate %f.\n", rate); + + rate = 1.0f; + hr = IMFRateSupport_GetSlowestRate(rate_support, MFRATE_FORWARD, TRUE, &rate); + ok(hr == S_OK, "Unexpected hr %#x.\n", hr); + ok(rate == 0.0f, "Unexpected rate %f.\n", rate); + + rate = 1.0f; + hr = IMFRateSupport_GetSlowestRate(rate_support, MFRATE_REVERSE, FALSE, &rate); + ok(hr == S_OK, "Unexpected hr %#x.\n", hr); + ok(rate == 0.0f, "Unexpected rate %f.\n", rate); + + rate = 1.0f; + hr = IMFRateSupport_GetSlowestRate(rate_support, MFRATE_REVERSE, TRUE, &rate); + ok(hr == S_OK, "Unexpected hr %#x.\n", hr); + ok(rate == 0.0f, "Unexpected rate %f.\n", rate); + + IMFRateSupport_Release(rate_support); + IMFVideoPresenter_Release(presenter); }
Signed-off-by: Nikolay Sivov nsivov@codeweavers.com --- dlls/evr/presenter.c | 63 +++++++++++++++++++++++++++++++++++++------- 1 file changed, 53 insertions(+), 10 deletions(-)
diff --git a/dlls/evr/presenter.c b/dlls/evr/presenter.c index 29167d364df..c70b83d0727 100644 --- a/dlls/evr/presenter.c +++ b/dlls/evr/presenter.c @@ -31,6 +31,14 @@
WINE_DEFAULT_DEBUG_CHANNEL(evr);
+enum presenter_state +{ + PRESENTER_STATE_SHUT_DOWN = 0, + PRESENTER_STATE_STARTED, + PRESENTER_STATE_STOPPED, + PRESENTER_STATE_PAUSED, +}; + struct video_presenter { IMFVideoPresenter IMFVideoPresenter_iface; @@ -41,6 +49,9 @@ struct video_presenter IUnknown IUnknown_inner; IUnknown *outer_unk; LONG refcount; + + unsigned int state; + CRITICAL_SECTION cs; };
static struct video_presenter *impl_from_IUnknown(IUnknown *iface) @@ -134,6 +145,7 @@ static ULONG WINAPI video_presenter_inner_Release(IUnknown *iface)
if (!refcount) { + DeleteCriticalSection(&presenter->cs); heap_free(presenter); }
@@ -167,30 +179,54 @@ static ULONG WINAPI video_presenter_Release(IMFVideoPresenter *iface)
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)); + struct video_presenter *presenter = impl_from_IMFVideoPresenter(iface);
- return E_NOTIMPL; + TRACE("%p, %s, %s.\n", iface, debugstr_time(systime), wine_dbgstr_longlong(offset)); + + EnterCriticalSection(&presenter->cs); + presenter->state = PRESENTER_STATE_STARTED; + LeaveCriticalSection(&presenter->cs); + + return S_OK; }
static HRESULT WINAPI video_presenter_OnClockStop(IMFVideoPresenter *iface, MFTIME systime) { - FIXME("%p, %s.\n", iface, debugstr_time(systime)); + struct video_presenter *presenter = impl_from_IMFVideoPresenter(iface);
- return E_NOTIMPL; + TRACE("%p, %s.\n", iface, debugstr_time(systime)); + + EnterCriticalSection(&presenter->cs); + presenter->state = PRESENTER_STATE_STOPPED; + LeaveCriticalSection(&presenter->cs); + + return S_OK; }
static HRESULT WINAPI video_presenter_OnClockPause(IMFVideoPresenter *iface, MFTIME systime) { - FIXME("%p, %s.\n", iface, debugstr_time(systime)); + struct video_presenter *presenter = impl_from_IMFVideoPresenter(iface);
- return E_NOTIMPL; + TRACE("%p, %s.\n", iface, debugstr_time(systime)); + + EnterCriticalSection(&presenter->cs); + presenter->state = PRESENTER_STATE_PAUSED; + LeaveCriticalSection(&presenter->cs); + + return S_OK; }
static HRESULT WINAPI video_presenter_OnClockRestart(IMFVideoPresenter *iface, MFTIME systime) { - FIXME("%p, %s.\n", iface, debugstr_time(systime)); + struct video_presenter *presenter = impl_from_IMFVideoPresenter(iface);
- return E_NOTIMPL; + TRACE("%p, %s.\n", iface, debugstr_time(systime)); + + EnterCriticalSection(&presenter->cs); + presenter->state = PRESENTER_STATE_STARTED; + LeaveCriticalSection(&presenter->cs); + + return S_OK; }
static HRESULT WINAPI video_presenter_OnClockSetRate(IMFVideoPresenter *iface, MFTIME systime, float rate) @@ -295,9 +331,15 @@ static HRESULT WINAPI video_presenter_service_client_InitServicePointers(IMFTopo
static HRESULT WINAPI video_presenter_service_client_ReleaseServicePointers(IMFTopologyServiceLookupClient *iface) { - FIXME("%p.\n", iface); + struct video_presenter *presenter = impl_from_IMFTopologyServiceLookupClient(iface);
- return E_NOTIMPL; + TRACE("%p.\n", iface); + + EnterCriticalSection(&presenter->cs); + presenter->state = PRESENTER_STATE_SHUT_DOWN; + LeaveCriticalSection(&presenter->cs); + + return S_OK; }
static const IMFTopologyServiceLookupClientVtbl video_presenter_service_client_vtbl = @@ -496,6 +538,7 @@ HRESULT evr_presenter_create(IUnknown *outer, void **out) object->IUnknown_inner.lpVtbl = &video_presenter_inner_vtbl; object->outer_unk = outer ? outer : &object->IUnknown_inner; object->refcount = 1; + InitializeCriticalSection(&object->cs);
*out = &object->IUnknown_inner;
Signed-off-by: Nikolay Sivov nsivov@codeweavers.com --- dlls/evr/presenter.c | 71 ++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 68 insertions(+), 3 deletions(-)
diff --git a/dlls/evr/presenter.c b/dlls/evr/presenter.c index c70b83d0727..a7da0704927 100644 --- a/dlls/evr/presenter.c +++ b/dlls/evr/presenter.c @@ -50,6 +50,10 @@ struct video_presenter IUnknown *outer_unk; LONG refcount;
+ IMFTransform *mixer; + IMFClock *clock; + IMediaEventSink *event_sink; + unsigned int state; CRITICAL_SECTION cs; }; @@ -136,6 +140,19 @@ static ULONG WINAPI video_presenter_inner_AddRef(IUnknown *iface) return refcount; }
+static void video_presenter_clear_container(struct video_presenter *presenter) +{ + if (presenter->clock) + IMFClock_Release(presenter->clock); + if (presenter->mixer) + IMFTransform_Release(presenter->mixer); + if (presenter->event_sink) + IMediaEventSink_Release(presenter->event_sink); + presenter->clock = NULL; + presenter->mixer = NULL; + presenter->event_sink = NULL; +} + static ULONG WINAPI video_presenter_inner_Release(IUnknown *iface) { struct video_presenter *presenter = impl_from_IUnknown(iface); @@ -145,6 +162,7 @@ static ULONG WINAPI video_presenter_inner_Release(IUnknown *iface)
if (!refcount) { + video_presenter_clear_container(presenter); DeleteCriticalSection(&presenter->cs); heap_free(presenter); } @@ -324,9 +342,53 @@ static ULONG WINAPI video_presenter_service_client_Release(IMFTopologyServiceLoo static HRESULT WINAPI video_presenter_service_client_InitServicePointers(IMFTopologyServiceLookupClient *iface, IMFTopologyServiceLookup *service_lookup) { - FIXME("%p, %p.\n", iface, service_lookup); + struct video_presenter *presenter = impl_from_IMFTopologyServiceLookupClient(iface); + unsigned int count; + HRESULT hr = S_OK;
- return E_NOTIMPL; + TRACE("%p, %p.\n", iface, service_lookup); + + if (!service_lookup) + return E_POINTER; + + EnterCriticalSection(&presenter->cs); + + if (presenter->state == PRESENTER_STATE_STARTED || + presenter->state == PRESENTER_STATE_PAUSED) + { + hr = MF_E_INVALIDREQUEST; + } + else + { + video_presenter_clear_container(presenter); + + count = 1; + IMFTopologyServiceLookup_LookupService(service_lookup, MF_SERVICE_LOOKUP_GLOBAL, 0, + &MR_VIDEO_RENDER_SERVICE, &IID_IMFClock, (void **)&presenter->clock, &count); + + count = 1; + if (SUCCEEDED(hr = IMFTopologyServiceLookup_LookupService(service_lookup, MF_SERVICE_LOOKUP_GLOBAL, 0, + &MR_VIDEO_MIXER_SERVICE, &IID_IMFTransform, (void **)&presenter->mixer, &count))) + { + /* FIXME: presumably should validate mixer's device id. */ + } + else + WARN("Failed to get mixer interface, hr %#x.\n", hr); + + count = 1; + if (FAILED(hr = IMFTopologyServiceLookup_LookupService(service_lookup, MF_SERVICE_LOOKUP_GLOBAL, 0, + &MR_VIDEO_RENDER_SERVICE, &IID_IMediaEventSink, (void **)&presenter->event_sink, &count))) + { + WARN("Failed to get renderer event sink, hr %#x.\n", hr); + } + + if (SUCCEEDED(hr)) + presenter->state = PRESENTER_STATE_STOPPED; + } + + LeaveCriticalSection(&presenter->cs); + + return hr; }
static HRESULT WINAPI video_presenter_service_client_ReleaseServicePointers(IMFTopologyServiceLookupClient *iface) @@ -336,7 +398,10 @@ static HRESULT WINAPI video_presenter_service_client_ReleaseServicePointers(IMFT TRACE("%p.\n", iface);
EnterCriticalSection(&presenter->cs); + presenter->state = PRESENTER_STATE_SHUT_DOWN; + video_presenter_clear_container(presenter); + LeaveCriticalSection(&presenter->cs);
return S_OK; @@ -527,7 +592,7 @@ HRESULT evr_presenter_create(IUnknown *outer, void **out) { struct video_presenter *object;
- if (!(object = heap_alloc(sizeof(*object)))) + if (!(object = heap_alloc_zero(sizeof(*object)))) return E_OUTOFMEMORY;
object->IMFVideoPresenter_iface.lpVtbl = &video_presenter_vtbl;
Signed-off-by: Nikolay Sivov nsivov@codeweavers.com --- dlls/evr/mixer.c | 58 +++++++++++++++++++++++++++++++++++--------- dlls/evr/tests/evr.c | 17 +++++++++++++ 2 files changed, 63 insertions(+), 12 deletions(-)
diff --git a/dlls/evr/mixer.c b/dlls/evr/mixer.c index 23994375d45..c8bd300b0d3 100644 --- a/dlls/evr/mixer.c +++ b/dlls/evr/mixer.c @@ -60,6 +60,8 @@ struct video_mixer IMFVideoMixerBitmap IMFVideoMixerBitmap_iface; IMFVideoPositionMapper IMFVideoPositionMapper_iface; IMFVideoProcessor IMFVideoProcessor_iface; + IUnknown IUnknown_inner; + IUnknown *outer_unk; LONG refcount;
struct input_stream inputs[MAX_MIXER_INPUT_STREAMS]; @@ -74,6 +76,11 @@ struct video_mixer CRITICAL_SECTION cs; };
+static struct video_mixer *impl_from_IUnknown(IUnknown *iface) +{ + return CONTAINING_RECORD(iface, struct video_mixer, IUnknown_inner); +} + static struct video_mixer *impl_from_IMFTransform(IMFTransform *iface) { return CONTAINING_RECORD(iface, struct video_mixer, IMFTransform_iface); @@ -155,17 +162,20 @@ static void video_mixer_clear_types(struct video_mixer *mixer) mixer->output.media_type = NULL; }
-static HRESULT WINAPI video_mixer_transform_QueryInterface(IMFTransform *iface, REFIID riid, void **obj) +static HRESULT WINAPI video_mixer_inner_QueryInterface(IUnknown *iface, REFIID riid, void **obj) { - struct video_mixer *mixer = impl_from_IMFTransform(iface); + struct video_mixer *mixer = impl_from_IUnknown(iface);
TRACE("%p, %s, %p.\n", iface, debugstr_guid(riid), obj);
- if (IsEqualIID(riid, &IID_IMFTransform) || - IsEqualIID(riid, &IID_IUnknown)) + if (IsEqualIID(riid, &IID_IUnknown)) { *obj = iface; } + else if (IsEqualIID(riid, &IID_IMFTransform)) + { + *obj = &mixer->IMFTransform_iface; + } else if (IsEqualIID(riid, &IID_IMFVideoDeviceID)) { *obj = &mixer->IMFVideoDeviceID_iface; @@ -206,9 +216,9 @@ static HRESULT WINAPI video_mixer_transform_QueryInterface(IMFTransform *iface, return S_OK; }
-static ULONG WINAPI video_mixer_transform_AddRef(IMFTransform *iface) +static ULONG WINAPI video_mixer_inner_AddRef(IUnknown *iface) { - struct video_mixer *mixer = impl_from_IMFTransform(iface); + struct video_mixer *mixer = impl_from_IUnknown(iface); ULONG refcount = InterlockedIncrement(&mixer->refcount);
TRACE("%p, refcount %u.\n", iface, refcount); @@ -216,9 +226,9 @@ static ULONG WINAPI video_mixer_transform_AddRef(IMFTransform *iface) return refcount; }
-static ULONG WINAPI video_mixer_transform_Release(IMFTransform *iface) +static ULONG WINAPI video_mixer_inner_Release(IUnknown *iface) { - struct video_mixer *mixer = impl_from_IMFTransform(iface); + struct video_mixer *mixer = impl_from_IUnknown(iface); ULONG refcount = InterlockedDecrement(&mixer->refcount); unsigned int i;
@@ -241,6 +251,31 @@ static ULONG WINAPI video_mixer_transform_Release(IMFTransform *iface) return refcount; }
+static const IUnknownVtbl video_mixer_inner_vtbl = +{ + video_mixer_inner_QueryInterface, + video_mixer_inner_AddRef, + video_mixer_inner_Release, +}; + +static HRESULT WINAPI video_mixer_transform_QueryInterface(IMFTransform *iface, REFIID riid, void **obj) +{ + struct video_mixer *mixer = impl_from_IMFTransform(iface); + return IUnknown_QueryInterface(mixer->outer_unk, riid, obj); +} + +static ULONG WINAPI video_mixer_transform_AddRef(IMFTransform *iface) +{ + struct video_mixer *mixer = impl_from_IMFTransform(iface); + return IUnknown_AddRef(mixer->outer_unk); +} + +static ULONG WINAPI video_mixer_transform_Release(IMFTransform *iface) +{ + struct video_mixer *mixer = impl_from_IMFTransform(iface); + return IUnknown_Release(mixer->outer_unk); +} + static HRESULT WINAPI video_mixer_transform_GetStreamLimits(IMFTransform *iface, DWORD *input_minimum, DWORD *input_maximum, DWORD *output_minimum, DWORD *output_maximum) { @@ -1251,9 +1286,6 @@ HRESULT evr_mixer_create(IUnknown *outer, void **out) { struct video_mixer *object;
- if (outer) - return E_NOINTERFACE; - if (!(object = calloc(1, sizeof(*object)))) return E_OUTOFMEMORY;
@@ -1265,12 +1297,14 @@ HRESULT evr_mixer_create(IUnknown *outer, void **out) 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->IUnknown_inner.lpVtbl = &video_mixer_inner_vtbl; + object->outer_unk = outer ? outer : &object->IUnknown_inner; object->refcount = 1; object->input_count = 1; video_mixer_init_input(&object->inputs[0]); InitializeCriticalSection(&object->cs);
- *out = &object->IMFTransform_iface; + *out = &object->IUnknown_inner;
return S_OK; } diff --git a/dlls/evr/tests/evr.c b/dlls/evr/tests/evr.c index dd3fbbe0289..1046e70312d 100644 --- a/dlls/evr/tests/evr.c +++ b/dlls/evr/tests/evr.c @@ -119,6 +119,7 @@ static void test_aggregation(void) IBaseFilter *filter, *filter2; IMFVideoPresenter *presenter; IUnknown *unk, *unk2; + IMFTransform *mixer; HRESULT hr; ULONG ref;
@@ -191,6 +192,22 @@ static void test_aggregation(void)
IUnknown_Release(unk); } + + /* Default mixer. */ + presenter = (void *)0xdeadbeef; + hr = CoCreateInstance(&CLSID_MFVideoMixer9, &test_outer, CLSCTX_INPROC_SERVER, &IID_IMFTransform, + (void **)&mixer); + ok(hr == E_NOINTERFACE, "Unexpected hr %#x.\n", hr); + ok(!mixer, "Got interface %p.\n", mixer); + + hr = CoCreateInstance(&CLSID_MFVideoMixer9, &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)
Signed-off-by: Nikolay Sivov nsivov@codeweavers.com --- dlls/evr/evr.spec | 2 +- dlls/evr/main.c | 28 ++++++++++++++++++++++++++++ dlls/evr/tests/evr.c | 13 +++++++++++++ include/evr.idl | 3 ++- 4 files changed, 44 insertions(+), 2 deletions(-)
diff --git a/dlls/evr/evr.spec b/dlls/evr/evr.spec index e46cb04f644..73cbf05b461 100644 --- a/dlls/evr/evr.spec +++ b/dlls/evr/evr.spec @@ -14,7 +14,7 @@ @ stub MFCreateVideoMediaTypeFromVideoInfoHeader2 @ stub MFCreateVideoMediaTypeFromVideoInfoHeader @ stdcall MFCreateVideoMixer(ptr ptr ptr ptr) -@ stub MFCreateVideoMixerAndPresenter +@ stdcall MFCreateVideoMixerAndPresenter(ptr ptr ptr ptr ptr ptr) @ stub MFCreateVideoOTA @ stub MFCreateVideoPresenter2 @ stdcall MFCreateVideoPresenter(ptr ptr ptr ptr) diff --git a/dlls/evr/main.c b/dlls/evr/main.c index 2c6db8430ba..301330a51e2 100644 --- a/dlls/evr/main.c +++ b/dlls/evr/main.c @@ -196,3 +196,31 @@ HRESULT WINAPI DllUnregisterServer(void) { return __wine_unregister_resources(instance_evr); } + +HRESULT WINAPI MFCreateVideoMixerAndPresenter(IUnknown *mixer_outer, IUnknown *presenter_outer, + REFIID riid_mixer, void **mixer, REFIID riid_presenter, void **presenter) +{ + HRESULT hr; + + TRACE("%p, %p, %s, %p, %s, %p.\n", mixer_outer, presenter_outer, debugstr_guid(riid_mixer), mixer, + debugstr_guid(riid_presenter), presenter); + + if (!mixer || !presenter) + return E_POINTER; + + *mixer = *presenter = NULL; + + if (SUCCEEDED(hr = CoCreateInstance(&CLSID_MFVideoMixer9, mixer_outer, CLSCTX_INPROC_SERVER, riid_mixer, mixer))) + hr = CoCreateInstance(&CLSID_MFVideoPresenter9, presenter_outer, CLSCTX_INPROC_SERVER, riid_presenter, presenter); + + if (FAILED(hr)) + { + if (*mixer) + IUnknown_Release((IUnknown *)*mixer); + if (*presenter) + IUnknown_Release((IUnknown *)*presenter); + *mixer = *presenter = NULL; + } + + return hr; +} diff --git a/dlls/evr/tests/evr.c b/dlls/evr/tests/evr.c index 1046e70312d..b9f86eb2529 100644 --- a/dlls/evr/tests/evr.c +++ b/dlls/evr/tests/evr.c @@ -950,6 +950,18 @@ static void test_default_presenter(void) IMFVideoPresenter_Release(presenter); }
+static void test_MFCreateVideoMixerAndPresenter(void) +{ + IUnknown *mixer, *presenter; + HRESULT hr; + + hr = MFCreateVideoMixerAndPresenter(NULL, NULL, &IID_IUnknown, (void **)&mixer, &IID_IUnknown, (void **)&presenter); + ok(hr == S_OK, "Unexpected hr %#x.\n", hr); + + IUnknown_Release(mixer); + IUnknown_Release(presenter); +} + START_TEST(evr) { CoInitialize(NULL); @@ -965,6 +977,7 @@ START_TEST(evr) test_default_mixer_type_negotiation(); test_surface_sample(); test_default_presenter(); + test_MFCreateVideoMixerAndPresenter();
CoUninitialize(); } diff --git a/include/evr.idl b/include/evr.idl index 384a051944c..8628e111a31 100644 --- a/include/evr.idl +++ b/include/evr.idl @@ -299,7 +299,8 @@ cpp_quote("DEFINE_GUID(MR_VIDEO_MIXER_SERVICE, 0x073cd2fc, 0x6cf4, 0x40b7, 0x88, cpp_quote("DEFINE_GUID(MR_VIDEO_ACCELERATION_SERVICE, 0xefef5175, 0x5c7d, 0x4ce2, 0xbb, 0xbd, 0x34, 0xff, 0x8b, 0xca, 0x65, 0x54);") cpp_quote("DEFINE_GUID(MR_BUFFER_SERVICE, 0xa562248c, 0x9ac6, 0x4ffc, 0x9f, 0xba, 0x3a, 0xf8, 0xf8, 0xad, 0x1a, 0x4d);") 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 MFCreateVideoMixerAndPresenter(IUnknown *mixer_outer, IUnknown *presenter_outer, ") +cpp_quote(" REFIID riid_mixer, void **mixer, REFIID riid_presenter, void **presenter);") cpp_quote("HRESULT WINAPI MFCreateVideoPresenter(IUnknown *owner, REFIID riid_device, REFIID riid, void **obj);") cpp_quote("HRESULT WINAPI MFCreateVideoSampleFromSurface(IUnknown *surface, IMFSample **sample);")