From: Nikolay Sivov nsivov@codeweavers.com
Signed-off-by: Nikolay Sivov nsivov@codeweavers.com --- dlls/evr/evr.c | 42 ++++++++++++++++++++++++++++++++++++++++++ dlls/evr/tests/evr.c | 1 + 2 files changed, 43 insertions(+)
diff --git a/dlls/evr/evr.c b/dlls/evr/evr.c index e64151b650c..c8d0794132f 100644 --- a/dlls/evr/evr.c +++ b/dlls/evr/evr.c @@ -35,6 +35,7 @@ struct evr struct strmbase_renderer renderer; IEVRFilterConfig IEVRFilterConfig_iface; IAMFilterMiscFlags IAMFilterMiscFlags_iface; + IMFGetService IMFGetService_iface; };
static struct evr *impl_from_strmbase_renderer(struct strmbase_renderer *iface) @@ -50,6 +51,8 @@ static HRESULT evr_query_interface(struct strmbase_renderer *iface, REFIID iid, *out = &filter->IEVRFilterConfig_iface; else if (IsEqualGUID(iid, &IID_IAMFilterMiscFlags)) *out = &filter->IAMFilterMiscFlags_iface; + else if (IsEqualGUID(iid, &IID_IMFGetService)) + *out = &filter->IMFGetService_iface; else return E_NOINTERFACE;
@@ -173,6 +176,44 @@ static const IAMFilterMiscFlagsVtbl filter_misc_flags_vtbl = filter_misc_flags_GetMiscFlags, };
+static struct evr *impl_from_IMFGetService(IMFGetService *iface) +{ + return CONTAINING_RECORD(iface, struct evr, IMFGetService_iface); +} + +static HRESULT WINAPI filter_get_service_QueryInterface(IMFGetService *iface, REFIID riid, void **obj) +{ + struct evr *filter = impl_from_IMFGetService(iface); + return IUnknown_QueryInterface(filter->renderer.filter.outer_unk, riid, obj); +} + +static ULONG WINAPI filter_get_service_AddRef(IMFGetService *iface) +{ + struct evr *filter = impl_from_IMFGetService(iface); + return IUnknown_AddRef(filter->renderer.filter.outer_unk); +} + +static ULONG WINAPI filter_get_service_Release(IMFGetService *iface) +{ + struct evr *filter = impl_from_IMFGetService(iface); + return IUnknown_Release(filter->renderer.filter.outer_unk); +} + +static HRESULT WINAPI filter_get_service_GetService(IMFGetService *iface, REFGUID service, REFIID riid, void **obj) +{ + FIXME("%p, %s, %s, %p.\n", iface, debugstr_guid(service), debugstr_guid(riid), obj); + + return E_NOTIMPL; +} + +static const IMFGetServiceVtbl filter_get_service_vtbl = +{ + filter_get_service_QueryInterface, + filter_get_service_AddRef, + filter_get_service_Release, + filter_get_service_GetService, +}; + HRESULT evr_filter_create(IUnknown *outer, void **out) { struct evr *object; @@ -184,6 +225,7 @@ HRESULT evr_filter_create(IUnknown *outer, void **out) &CLSID_EnhancedVideoRenderer, L"EVR Input0", &renderer_ops); object->IEVRFilterConfig_iface.lpVtbl = &filter_config_vtbl; object->IAMFilterMiscFlags_iface.lpVtbl = &filter_misc_flags_vtbl; + object->IMFGetService_iface.lpVtbl = &filter_get_service_vtbl;
TRACE("Created EVR %p.\n", object); *out = &object->renderer.filter.IUnknown_inner; diff --git a/dlls/evr/tests/evr.c b/dlls/evr/tests/evr.c index 37bb55739d3..7875a05ce83 100644 --- a/dlls/evr/tests/evr.c +++ b/dlls/evr/tests/evr.c @@ -279,6 +279,7 @@ static void test_interfaces(void) check_interface(filter, &IID_IAMFilterMiscFlags, TRUE); check_interface(filter, &IID_IBaseFilter, TRUE); check_interface(filter, &IID_IEVRFilterConfig, TRUE); + check_interface(filter, &IID_IMFGetService, TRUE); check_interface(filter, &IID_IMediaFilter, TRUE); check_interface(filter, &IID_IMediaPosition, TRUE); check_interface(filter, &IID_IMediaSeeking, TRUE);
On 8/19/22 07:55, Nikolay Sivov wrote:
+static HRESULT WINAPI filter_get_service_GetService(IMFGetService *iface, REFGUID service, REFIID riid, void **obj) +{
- FIXME("%p, %s, %s, %p.\n", iface, debugstr_guid(service), debugstr_guid(riid), obj);
- return E_NOTIMPL;
+}
Can you please trace argument names, as elsewhere in DirectShow?
From: Nikolay Sivov nsivov@codeweavers.com
Signed-off-by: Nikolay Sivov nsivov@codeweavers.com --- dlls/evr/evr.c | 43 +++++++++++++++++++++++++++++++++++++++++++ dlls/evr/tests/evr.c | 1 + 2 files changed, 44 insertions(+)
diff --git a/dlls/evr/evr.c b/dlls/evr/evr.c index c8d0794132f..50ad32bd791 100644 --- a/dlls/evr/evr.c +++ b/dlls/evr/evr.c @@ -36,6 +36,7 @@ struct evr IEVRFilterConfig IEVRFilterConfig_iface; IAMFilterMiscFlags IAMFilterMiscFlags_iface; IMFGetService IMFGetService_iface; + IMFVideoRenderer IMFVideoRenderer_iface; };
static struct evr *impl_from_strmbase_renderer(struct strmbase_renderer *iface) @@ -53,6 +54,8 @@ static HRESULT evr_query_interface(struct strmbase_renderer *iface, REFIID iid, *out = &filter->IAMFilterMiscFlags_iface; else if (IsEqualGUID(iid, &IID_IMFGetService)) *out = &filter->IMFGetService_iface; + else if (IsEqualGUID(iid, &IID_IMFVideoRenderer)) + *out = &filter->IMFVideoRenderer_iface; else return E_NOINTERFACE;
@@ -214,6 +217,45 @@ static const IMFGetServiceVtbl filter_get_service_vtbl = filter_get_service_GetService, };
+static struct evr *impl_from_IMFVideoRenderer(IMFVideoRenderer *iface) +{ + return CONTAINING_RECORD(iface, struct evr, IMFVideoRenderer_iface); +} + +static HRESULT WINAPI filter_video_renderer_QueryInterface(IMFVideoRenderer *iface, REFIID riid, void **obj) +{ + struct evr *filter = impl_from_IMFVideoRenderer(iface); + return IUnknown_QueryInterface(filter->renderer.filter.outer_unk, riid, obj); +} + +static ULONG WINAPI filter_video_renderer_AddRef(IMFVideoRenderer *iface) +{ + struct evr *filter = impl_from_IMFVideoRenderer(iface); + return IUnknown_AddRef(filter->renderer.filter.outer_unk); +} + +static ULONG WINAPI filter_video_renderer_Release(IMFVideoRenderer *iface) +{ + struct evr *filter = impl_from_IMFVideoRenderer(iface); + return IUnknown_Release(filter->renderer.filter.outer_unk); +} + +static HRESULT WINAPI filter_video_renderer_InitializeRenderer(IMFVideoRenderer *iface, IMFTransform *mixer, + IMFVideoPresenter *presenter) +{ + FIXME("%p, %p, %p.\n", iface, mixer, presenter); + + return E_NOTIMPL; +} + +static const IMFVideoRendererVtbl filter_video_renderer_vtbl = +{ + filter_video_renderer_QueryInterface, + filter_video_renderer_AddRef, + filter_video_renderer_Release, + filter_video_renderer_InitializeRenderer, +}; + HRESULT evr_filter_create(IUnknown *outer, void **out) { struct evr *object; @@ -226,6 +268,7 @@ HRESULT evr_filter_create(IUnknown *outer, void **out) object->IEVRFilterConfig_iface.lpVtbl = &filter_config_vtbl; object->IAMFilterMiscFlags_iface.lpVtbl = &filter_misc_flags_vtbl; object->IMFGetService_iface.lpVtbl = &filter_get_service_vtbl; + object->IMFVideoRenderer_iface.lpVtbl = &filter_video_renderer_vtbl;
TRACE("Created EVR %p.\n", object); *out = &object->renderer.filter.IUnknown_inner; diff --git a/dlls/evr/tests/evr.c b/dlls/evr/tests/evr.c index 7875a05ce83..c4604c954b3 100644 --- a/dlls/evr/tests/evr.c +++ b/dlls/evr/tests/evr.c @@ -280,6 +280,7 @@ static void test_interfaces(void) check_interface(filter, &IID_IBaseFilter, TRUE); check_interface(filter, &IID_IEVRFilterConfig, TRUE); check_interface(filter, &IID_IMFGetService, TRUE); + check_interface(filter, &IID_IMFVideoRenderer, TRUE); check_interface(filter, &IID_IMediaFilter, TRUE); check_interface(filter, &IID_IMediaPosition, TRUE); check_interface(filter, &IID_IMediaSeeking, TRUE);
From: Nikolay Sivov nsivov@codeweavers.com
Signed-off-by: Nikolay Sivov nsivov@codeweavers.com --- dlls/evr/evr.c | 111 +++++++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 107 insertions(+), 4 deletions(-)
diff --git a/dlls/evr/evr.c b/dlls/evr/evr.c index 50ad32bd791..b5df9ba36de 100644 --- a/dlls/evr/evr.c +++ b/dlls/evr/evr.c @@ -30,6 +30,11 @@
WINE_DEFAULT_DEBUG_CHANNEL(evr);
+enum evr_flags +{ + EVR_INITIALIZED = 0x1, +}; + struct evr { struct strmbase_renderer renderer; @@ -37,8 +42,69 @@ struct evr IAMFilterMiscFlags IAMFilterMiscFlags_iface; IMFGetService IMFGetService_iface; IMFVideoRenderer IMFVideoRenderer_iface; + + IMFTransform *mixer; + IMFVideoPresenter *presenter; + + unsigned int flags; };
+static void evr_uninitialize(struct evr *filter) +{ + if (filter->mixer) + { + IMFTransform_Release(filter->mixer); + filter->mixer = NULL; + } + + if (filter->presenter) + { + IMFVideoPresenter_Release(filter->presenter); + filter->presenter = NULL; + } + + filter->flags &= ~EVR_INITIALIZED; +} + +static HRESULT evr_initialize(struct evr *filter, IMFTransform *mixer, IMFVideoPresenter *presenter) +{ + HRESULT hr = S_OK; + + if (mixer) + { + IMFTransform_AddRef(mixer); + } + else if (FAILED(hr = CoCreateInstance(&CLSID_MFVideoMixer9, NULL, CLSCTX_INPROC_SERVER, + &IID_IMFTransform, (void **)&mixer))) + { + WARN("Failed to create default mixer instance, hr %#lx.\n", hr); + return hr; + } + + if (presenter) + { + IMFVideoPresenter_AddRef(presenter); + } + else if (FAILED(hr = CoCreateInstance(&CLSID_MFVideoPresenter9, NULL, CLSCTX_INPROC_SERVER, + &IID_IMFVideoPresenter, (void **)&presenter))) + { + WARN("Failed to create default presenter instance, hr %#lx.\n", hr); + IMFTransform_Release(mixer); + return hr; + } + + evr_uninitialize(filter); + + filter->mixer = mixer; + filter->presenter = presenter; + + /* FIXME: configure mixer and presenter */ + + filter->flags |= EVR_INITIALIZED; + + return hr; +} + static struct evr *impl_from_strmbase_renderer(struct strmbase_renderer *iface) { return CONTAINING_RECORD(iface, struct evr, renderer); @@ -67,6 +133,7 @@ static void evr_destroy(struct strmbase_renderer *iface) { struct evr *filter = impl_from_strmbase_renderer(iface);
+ evr_uninitialize(filter); strmbase_renderer_cleanup(&filter->renderer); free(filter); } @@ -204,9 +271,36 @@ static ULONG WINAPI filter_get_service_Release(IMFGetService *iface)
static HRESULT WINAPI filter_get_service_GetService(IMFGetService *iface, REFGUID service, REFIID riid, void **obj) { - FIXME("%p, %s, %s, %p.\n", iface, debugstr_guid(service), debugstr_guid(riid), obj); + struct evr *filter = impl_from_IMFGetService(iface); + HRESULT hr = E_NOINTERFACE; + IMFGetService *gs;
- return E_NOTIMPL; + TRACE("%p, %s, %s, %p.\n", iface, debugstr_guid(service), debugstr_guid(riid), obj); + + EnterCriticalSection(&filter->renderer.filter.filter_cs); + + if (IsEqualGUID(service, &MR_VIDEO_RENDER_SERVICE)) + { + if (!filter->presenter) + hr = evr_initialize(filter, NULL, NULL); + + if (filter->presenter) + hr = IMFVideoPresenter_QueryInterface(filter->presenter, &IID_IMFGetService, (void **)&gs); + } + else + { + FIXME("Unsupported service %s.\n", debugstr_guid(service)); + } + + LeaveCriticalSection(&filter->renderer.filter.filter_cs); + + if (gs) + { + hr = IMFGetService_GetService(gs, service, riid, obj); + IMFGetService_Release(gs); + } + + return hr; }
static const IMFGetServiceVtbl filter_get_service_vtbl = @@ -243,9 +337,18 @@ static ULONG WINAPI filter_video_renderer_Release(IMFVideoRenderer *iface) static HRESULT WINAPI filter_video_renderer_InitializeRenderer(IMFVideoRenderer *iface, IMFTransform *mixer, IMFVideoPresenter *presenter) { - FIXME("%p, %p, %p.\n", iface, mixer, presenter); + struct evr *filter = impl_from_IMFVideoRenderer(iface); + HRESULT hr;
- return E_NOTIMPL; + TRACE("%p, %p, %p.\n", iface, mixer, presenter); + + EnterCriticalSection(&filter->renderer.filter.filter_cs); + + hr = evr_initialize(filter, mixer, presenter); + + LeaveCriticalSection(&filter->renderer.filter.filter_cs); + + return hr; }
static const IMFVideoRendererVtbl filter_video_renderer_vtbl =
On 8/19/22 07:56, Nikolay Sivov wrote:
diff --git a/dlls/evr/evr.c b/dlls/evr/evr.c index 50ad32bd791..b5df9ba36de 100644 --- a/dlls/evr/evr.c +++ b/dlls/evr/evr.c @@ -30,6 +30,11 @@
WINE_DEFAULT_DEBUG_CHANNEL(evr);
+enum evr_flags +{
- EVR_INITIALIZED = 0x1,
+};
- struct evr { struct strmbase_renderer renderer;
@@ -37,8 +42,69 @@ struct evr IAMFilterMiscFlags IAMFilterMiscFlags_iface; IMFGetService IMFGetService_iface; IMFVideoRenderer IMFVideoRenderer_iface;
- IMFTransform *mixer;
- IMFVideoPresenter *presenter;
- unsigned int flags;
We don't use this field at all in this patch.
From: Nikolay Sivov nsivov@codeweavers.com
Signed-off-by: Nikolay Sivov nsivov@codeweavers.com --- dlls/evr/tests/evr.c | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+)
diff --git a/dlls/evr/tests/evr.c b/dlls/evr/tests/evr.c index c4604c954b3..28a472a8a7f 100644 --- a/dlls/evr/tests/evr.c +++ b/dlls/evr/tests/evr.c @@ -571,6 +571,26 @@ static void test_misc_flags(void) ok(!ref, "Got outstanding refcount %ld.\n", ref); }
+static void test_display_control(void) +{ + IBaseFilter *filter = create_evr(); + IMFVideoDisplayControl *display_control; + HRESULT hr; + ULONG ref; + + hr = MFGetService((IUnknown *)filter, &MR_VIDEO_RENDER_SERVICE, + &IID_IMFVideoDisplayControl, (void **)&display_control); + ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); + + hr = IMFVideoDisplayControl_SetVideoWindow(display_control, 0); + ok(hr == E_INVALIDARG, "Unexpected hr %#lx.\n", hr); + + IMFVideoDisplayControl_Release(display_control); + + ref = IBaseFilter_Release(filter); + ok(!ref, "Got outstanding refcount %ld.\n", ref); +} + static IMFMediaType * create_video_type(const GUID *subtype) { IMFMediaType *video_type; @@ -3243,6 +3263,7 @@ START_TEST(evr) test_pin_info(); test_unconnected_eos(); test_misc_flags(); + test_display_control();
test_default_mixer(); test_default_mixer_type_negotiation();