Signed-off-by: Nikolay Sivov nsivov@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);