Signed-off-by: Nikolay Sivov <nsivov(a)codeweavers.com>
---
dlls/mf/evr.c | 333 +++++++++++++++++++++++++++------------------
dlls/mf/tests/mf.c | 8 +-
2 files changed, 208 insertions(+), 133 deletions(-)
diff --git a/dlls/mf/evr.c b/dlls/mf/evr.c
index c5b2ceecd67..e90cf686f26 100644
--- a/dlls/mf/evr.c
+++ b/dlls/mf/evr.c
@@ -854,12 +854,195 @@ static ULONG WINAPI video_renderer_Release(IMFVideoRenderer *iface)
return IMFMediaSink_Release(&renderer->IMFMediaSink_iface);
}
+static HRESULT video_renderer_create_mixer(IMFAttributes *attributes, IMFTransform **out)
+{
+ unsigned int flags = 0;
+ IMFActivate *activate;
+ CLSID clsid;
+ HRESULT hr;
+
+ if (attributes && SUCCEEDED(hr = IMFAttributes_GetUnknown(attributes, &MF_ACTIVATE_CUSTOM_VIDEO_MIXER_ACTIVATE,
+ &IID_IMFActivate, (void **)&activate)))
+ {
+ IMFAttributes_GetUINT32(attributes, &MF_ACTIVATE_CUSTOM_VIDEO_MIXER_FLAGS, &flags);
+ hr = IMFActivate_ActivateObject(activate, &IID_IMFTransform, (void **)out);
+ IMFActivate_Release(activate);
+ if (SUCCEEDED(hr) || !(flags & MF_ACTIVATE_CUSTOM_MIXER_ALLOWFAIL))
+ return hr;
+ }
+
+ if (!attributes || FAILED(IMFAttributes_GetGUID(attributes, &MF_ACTIVATE_CUSTOM_VIDEO_MIXER_CLSID, &clsid)))
+ memcpy(&clsid, &CLSID_MFVideoMixer9, sizeof(clsid));
+
+ return CoCreateInstance(&clsid, NULL, CLSCTX_INPROC_SERVER, &IID_IMFTransform, (void **)out);
+}
+
+static HRESULT video_renderer_create_presenter(IMFAttributes *attributes, IMFVideoPresenter **out)
+{
+ unsigned int flags = 0;
+ IMFActivate *activate;
+ CLSID clsid;
+ HRESULT hr;
+
+ if (attributes && SUCCEEDED(IMFAttributes_GetUnknown(attributes, &MF_ACTIVATE_CUSTOM_VIDEO_PRESENTER_ACTIVATE,
+ &IID_IMFActivate, (void **)&activate)))
+ {
+ IMFAttributes_GetUINT32(attributes, &MF_ACTIVATE_CUSTOM_VIDEO_PRESENTER_FLAGS, &flags);
+ hr = IMFActivate_ActivateObject(activate, &IID_IMFVideoPresenter, (void **)out);
+ IMFActivate_Release(activate);
+ if (SUCCEEDED(hr) || !(flags & MF_ACTIVATE_CUSTOM_PRESENTER_ALLOWFAIL))
+ return hr;
+ }
+
+ if (!attributes || FAILED(IMFAttributes_GetGUID(attributes, &MF_ACTIVATE_CUSTOM_VIDEO_PRESENTER_CLSID, &clsid)))
+ memcpy(&clsid, &CLSID_MFVideoPresenter9, sizeof(clsid));
+
+ return CoCreateInstance(&clsid, NULL, CLSCTX_INPROC_SERVER, &IID_IMFVideoPresenter, (void **)out);
+}
+
+static HRESULT video_renderer_configure_mixer(struct video_renderer *renderer)
+{
+ IMFTopologyServiceLookupClient *lookup_client;
+ HRESULT hr;
+
+ if (SUCCEEDED(hr = IMFTransform_QueryInterface(renderer->mixer, &IID_IMFTopologyServiceLookupClient,
+ (void **)&lookup_client)))
+ {
+ renderer->flags |= EVR_INIT_SERVICES;
+ if (SUCCEEDED(hr = IMFTopologyServiceLookupClient_InitServicePointers(lookup_client,
+ &renderer->IMFTopologyServiceLookup_iface)))
+ {
+ renderer->flags |= EVR_MIXER_INITED_SERVICES;
+ }
+ renderer->flags &= ~EVR_INIT_SERVICES;
+ IMFTopologyServiceLookupClient_Release(lookup_client);
+ }
+
+ if (SUCCEEDED(hr))
+ {
+ unsigned int input_count, output_count;
+ unsigned int *ids, *oids;
+ size_t i;
+
+ /* Create stream sinks for inputs that mixer already has by default. */
+ if (SUCCEEDED(IMFTransform_GetStreamCount(renderer->mixer, &input_count, &output_count)))
+ {
+ ids = heap_calloc(input_count, sizeof(*ids));
+ oids = heap_calloc(output_count, sizeof(*oids));
+
+ if (ids && oids)
+ {
+ if (SUCCEEDED(IMFTransform_GetStreamIDs(renderer->mixer, input_count, ids, output_count, oids)))
+ {
+ for (i = 0; i < input_count; ++i)
+ {
+ video_renderer_add_stream(renderer, ids[i], NULL);
+ }
+ }
+
+ }
+
+ heap_free(ids);
+ heap_free(oids);
+ }
+ }
+
+ return hr;
+}
+
+static HRESULT video_renderer_configure_presenter(struct video_renderer *renderer)
+{
+ IMFTopologyServiceLookupClient *lookup_client;
+ HRESULT hr;
+
+ if (SUCCEEDED(hr = IMFVideoPresenter_QueryInterface(renderer->presenter, &IID_IMFTopologyServiceLookupClient,
+ (void **)&lookup_client)))
+ {
+ renderer->flags |= EVR_INIT_SERVICES;
+ if (SUCCEEDED(hr = IMFTopologyServiceLookupClient_InitServicePointers(lookup_client,
+ &renderer->IMFTopologyServiceLookup_iface)))
+ {
+ renderer->flags |= EVR_PRESENTER_INITED_SERVICES;
+ }
+ renderer->flags &= ~EVR_INIT_SERVICES;
+ IMFTopologyServiceLookupClient_Release(lookup_client);
+ }
+
+ return hr;
+}
+
+static HRESULT video_renderer_initialize(struct video_renderer *renderer, IMFTransform *mixer,
+ IMFVideoPresenter *presenter)
+{
+ HRESULT hr;
+
+ if (renderer->mixer)
+ {
+ IMFTransform_Release(renderer->mixer);
+ renderer->mixer = NULL;
+ }
+
+ if (renderer->presenter)
+ {
+ IMFVideoPresenter_Release(renderer->presenter);
+ renderer->presenter = NULL;
+ }
+
+ renderer->mixer = mixer;
+ IMFTransform_AddRef(renderer->mixer);
+
+ renderer->presenter = presenter;
+ IMFVideoPresenter_AddRef(renderer->presenter);
+
+ if (SUCCEEDED(hr = video_renderer_configure_mixer(renderer)))
+ hr = video_renderer_configure_presenter(renderer);
+
+ return hr;
+}
+
static HRESULT WINAPI video_renderer_InitializeRenderer(IMFVideoRenderer *iface, IMFTransform *mixer,
IMFVideoPresenter *presenter)
{
- FIXME("%p, %p, %p.\n", iface, mixer, presenter);
+ struct video_renderer *renderer = impl_from_IMFVideoRenderer(iface);
+ HRESULT hr;
- return E_NOTIMPL;
+ TRACE("%p, %p, %p.\n", iface, mixer, presenter);
+
+ if (mixer)
+ IMFTransform_AddRef(mixer);
+ else if (FAILED(hr = video_renderer_create_mixer(NULL, &mixer)))
+ {
+ WARN("Failed to create default mixer object, hr %#x.\n", hr);
+ return hr;
+ }
+
+ if (presenter)
+ IMFVideoPresenter_AddRef(presenter);
+ else if (FAILED(hr = video_renderer_create_presenter(NULL, &presenter)))
+ {
+ WARN("Failed to create default presenter, hr %#x.\n", hr);
+ IMFTransform_Release(mixer);
+ return hr;
+ }
+
+ EnterCriticalSection(&renderer->cs);
+
+ if (renderer->flags & EVR_SHUT_DOWN)
+ hr = MF_E_SHUTDOWN;
+ else
+ {
+ /* FIXME: check clock state */
+ /* FIXME: check that streams are not initialized */
+
+ hr = video_renderer_initialize(renderer, mixer, presenter);
+ }
+
+ LeaveCriticalSection(&renderer->cs);
+
+ IMFTransform_Release(mixer);
+ IMFVideoPresenter_Release(presenter);
+
+ return hr;
}
static const IMFVideoRendererVtbl video_renderer_vtbl =
@@ -1191,128 +1374,11 @@ static const IMediaEventSinkVtbl media_event_sink_vtbl =
video_renderer_event_sink_Notify,
};
-static HRESULT video_renderer_create_mixer(struct video_renderer *renderer, IMFAttributes *attributes,
- IMFTransform **out)
-{
- IMFTopologyServiceLookupClient *lookup_client;
- unsigned int flags = 0;
- IMFActivate *activate;
- CLSID clsid;
- HRESULT hr;
-
- if (SUCCEEDED(hr = IMFAttributes_GetUnknown(attributes, &MF_ACTIVATE_CUSTOM_VIDEO_MIXER_ACTIVATE,
- &IID_IMFActivate, (void **)&activate)))
- {
- IMFAttributes_GetUINT32(attributes, &MF_ACTIVATE_CUSTOM_VIDEO_MIXER_FLAGS, &flags);
- hr = IMFActivate_ActivateObject(activate, &IID_IMFTransform, (void **)out);
- IMFActivate_Release(activate);
- if (FAILED(hr) && !(flags & MF_ACTIVATE_CUSTOM_MIXER_ALLOWFAIL))
- return hr;
- }
-
- /* Activation object failed, use class activation. */
- if (FAILED(hr))
- {
- if (FAILED(IMFAttributes_GetGUID(attributes, &MF_ACTIVATE_CUSTOM_VIDEO_MIXER_CLSID, &clsid)))
- memcpy(&clsid, &CLSID_MFVideoMixer9, sizeof(clsid));
- hr = CoCreateInstance(&clsid, NULL, CLSCTX_INPROC_SERVER, &IID_IMFTransform, (void **)out);
- }
-
- if (FAILED(hr))
- {
- WARN("Failed to create a mixer object, hr %#x.\n", hr);
- return hr;
- }
-
- if (SUCCEEDED(hr = IMFTransform_QueryInterface(*out, &IID_IMFTopologyServiceLookupClient,
- (void **)&lookup_client)))
- {
- renderer->flags |= EVR_INIT_SERVICES;
- if (SUCCEEDED(hr = IMFTopologyServiceLookupClient_InitServicePointers(lookup_client,
- &renderer->IMFTopologyServiceLookup_iface)))
- {
- renderer->flags |= EVR_MIXER_INITED_SERVICES;
- }
- renderer->flags &= ~EVR_INIT_SERVICES;
- IMFTopologyServiceLookupClient_Release(lookup_client);
- }
-
- if (SUCCEEDED(hr))
- {
- unsigned int input_count, output_count;
- unsigned int *ids, *oids;
- size_t i;
-
- /* Create stream sinks for inputs that mixer already has by default. */
- if (SUCCEEDED(IMFTransform_GetStreamCount(*out, &input_count, &output_count)))
- {
- ids = heap_calloc(input_count, sizeof(*ids));
- oids = heap_calloc(output_count, sizeof(*oids));
-
- if (ids && oids)
- {
- if (SUCCEEDED(IMFTransform_GetStreamIDs(*out, input_count, ids, output_count, oids)))
- {
- for (i = 0; i < input_count; ++i)
- {
- video_renderer_add_stream(renderer, ids[i], NULL);
- }
- }
-
- }
-
- heap_free(ids);
- heap_free(oids);
- }
- }
-
- return hr;
-}
-
-static HRESULT video_renderer_create_presenter(struct video_renderer *renderer, IMFAttributes *attributes,
- IMFVideoPresenter **out)
-{
- IMFTopologyServiceLookupClient *lookup_client;
- unsigned int flags = 0;
- IMFActivate *activate;
- CLSID clsid;
- HRESULT hr;
-
- if (SUCCEEDED(IMFAttributes_GetUnknown(attributes, &MF_ACTIVATE_CUSTOM_VIDEO_PRESENTER_ACTIVATE,
- &IID_IMFActivate, (void **)&activate)))
- {
- IMFAttributes_GetUINT32(attributes, &MF_ACTIVATE_CUSTOM_VIDEO_PRESENTER_FLAGS, &flags);
- hr = IMFActivate_ActivateObject(activate, &IID_IMFVideoPresenter, (void **)out);
- IMFActivate_Release(activate);
- if (FAILED(hr) && !(flags & MF_ACTIVATE_CUSTOM_PRESENTER_ALLOWFAIL))
- return hr;
- }
-
- if (FAILED(IMFAttributes_GetGUID(attributes, &MF_ACTIVATE_CUSTOM_VIDEO_PRESENTER_CLSID, &clsid)))
- memcpy(&clsid, &CLSID_MFVideoPresenter9, sizeof(clsid));
-
- if (SUCCEEDED(hr = CoCreateInstance(&clsid, NULL, CLSCTX_INPROC_SERVER, &IID_IMFVideoPresenter, (void **)out)))
- {
- if (SUCCEEDED(hr = IMFVideoPresenter_QueryInterface(*out, &IID_IMFTopologyServiceLookupClient,
- (void **)&lookup_client)))
- {
- renderer->flags |= EVR_INIT_SERVICES;
- if (SUCCEEDED(hr = IMFTopologyServiceLookupClient_InitServicePointers(lookup_client,
- &renderer->IMFTopologyServiceLookup_iface)))
- {
- renderer->flags |= EVR_PRESENTER_INITED_SERVICES;
- }
- renderer->flags &= ~EVR_INIT_SERVICES;
- IMFTopologyServiceLookupClient_Release(lookup_client);
- }
- }
-
- return hr;
-}
-
static HRESULT evr_create_object(IMFAttributes *attributes, void *user_context, IUnknown **obj)
{
struct video_renderer *object;
+ IMFVideoPresenter *presenter;
+ IMFTransform *mixer;
HRESULT hr;
TRACE("%p, %p, %p.\n", attributes, user_context, obj);
@@ -1335,18 +1401,30 @@ static HRESULT evr_create_object(IMFAttributes *attributes, void *user_context,
goto failed;
/* Create mixer and presenter. */
- if (FAILED(hr = video_renderer_create_mixer(object, attributes, &object->mixer)))
+ if (FAILED(hr = video_renderer_create_mixer(attributes, &mixer)))
+ goto failed;
+
+ if (FAILED(hr = video_renderer_create_presenter(attributes, &presenter)))
goto failed;
- if (FAILED(hr = video_renderer_create_presenter(object, attributes, &object->presenter)))
+ if (FAILED(hr = video_renderer_initialize(object, mixer, presenter)))
goto failed;
+ IMFTransform_Release(mixer);
+ IMFVideoPresenter_Release(presenter);
+
*obj = (IUnknown *)&object->IMFMediaSink_iface;
return S_OK;
failed:
+ if (mixer)
+ IMFTransform_Release(mixer);
+
+ if (presenter)
+ IMFVideoPresenter_Release(presenter);
+
video_renderer_release_services(object);
IMFMediaSink_Release(&object->IMFMediaSink_iface);
@@ -1394,7 +1472,6 @@ HRESULT WINAPI MFCreateVideoRendererActivate(HWND hwnd, IMFActivate **activate)
*/
HRESULT WINAPI MFCreateVideoRenderer(REFIID riid, void **renderer)
{
- IMFAttributes *attributes;
IUnknown *obj;
HRESULT hr;
@@ -1402,13 +1479,7 @@ HRESULT WINAPI MFCreateVideoRenderer(REFIID riid, void **renderer)
*renderer = NULL;
- if (FAILED(hr = MFCreateAttributes(&attributes, 0)))
- return hr;
-
- hr = evr_create_object(attributes, NULL, &obj);
- IMFAttributes_Release(attributes);
-
- if (SUCCEEDED(hr))
+ if (SUCCEEDED(hr = evr_create_object(NULL, NULL, &obj)))
{
hr = IUnknown_QueryInterface(obj, riid, renderer);
IUnknown_Release(obj);
diff --git a/dlls/mf/tests/mf.c b/dlls/mf/tests/mf.c
index 0bc297cc69c..88cfa8d7625 100644
--- a/dlls/mf/tests/mf.c
+++ b/dlls/mf/tests/mf.c
@@ -3253,9 +3253,13 @@ static void test_evr(void)
hr = CoInitialize(NULL);
ok(hr == S_OK, "Failed to initialize, hr %#x.\n", hr);
- hr = MFCreateVideoRenderer(&IID_IUnknown, (void **)&unk);
+ hr = MFCreateVideoRenderer(&IID_IMFVideoRenderer, (void **)&video_renderer);
ok(hr == S_OK, "Unexpected hr %#x.\n", hr);
- IUnknown_Release(unk);
+
+ hr = IMFVideoRenderer_InitializeRenderer(video_renderer, NULL, NULL);
+ ok(hr == S_OK, "Unexpected hr %#x.\n", hr);
+
+ IMFVideoRenderer_Release(video_renderer);
hr = MFCreateVideoRendererActivate(NULL, NULL);
ok(hr == E_POINTER, "Unexpected hr %#x.\n", hr);
--
2.28.0