From: Bernhard Kölbl besentv@gmail.com
--- dlls/mfmediaengine/main.c | 114 ++++++++++++++++++++++- dlls/mfmediaengine/tests/mfmediaengine.c | 9 +- 2 files changed, 116 insertions(+), 7 deletions(-)
diff --git a/dlls/mfmediaengine/main.c b/dlls/mfmediaengine/main.c index b3ac236c78e..a1bc50609b9 100644 --- a/dlls/mfmediaengine/main.c +++ b/dlls/mfmediaengine/main.c @@ -113,6 +113,12 @@ struct rect float left, top, right, bottom; };
+struct effect +{ + IUnknown *object; + BOOL optional; +}; + struct media_engine { IMFMediaEngineEx IMFMediaEngineEx_iface; @@ -146,6 +152,12 @@ struct media_engine IMFPresentationDescriptor *pd; } presentation; struct + { + struct effect *effects; + size_t count; + size_t capacity; + } video_effects; + struct { LONGLONG pts; SIZE size; @@ -1018,6 +1030,48 @@ static HRESULT media_engine_create_source_node(IMFMediaSource *source, IMFPresen return S_OK; }
+static HRESULT media_engine_create_video_effects(struct media_engine *engine, + IMFTopologyNode *src, IMFTopologyNode *sink, IMFTopology *topology) +{ + struct effect *effects = NULL; + IMFTopologyNode *last = src; + size_t i, count = 0; + HRESULT hr; + + effects = engine->video_effects.effects; + count = engine->video_effects.count; + + IMFTopologyNode_AddRef(last); + + for (i = 0; i < count; ++i) + { + IMFTopologyNode *node = NULL; + + if (FAILED(hr = MFCreateTopologyNode(MF_TOPOLOGY_TRANSFORM_NODE, &node))) + { + WARN("Failed to create transform node, hr %#lx", hr); + continue; + } + + IMFTopologyNode_SetObject(node, (IUnknown *)effects[i].object); + IMFTopologyNode_SetUINT32(node, &MF_TOPONODE_NOSHUTDOWN_ON_REMOVE, FALSE); + + if (effects[i].optional) + IMFTopologyNode_SetUINT32(node, &MF_TOPONODE_CONNECT_METHOD, MF_CONNECT_AS_OPTIONAL); + + IMFTopology_AddNode(topology, node); + IMFTopologyNode_ConnectOutput(last, 0, node, 0); + + IMFTopologyNode_Release(last); + last = node; + } + + IMFTopologyNode_Release(last); + + hr = IMFTopologyNode_ConnectOutput(last, 0, sink, 0); + return hr; +} + static HRESULT media_engine_create_audio_renderer(struct media_engine *engine, IMFTopologyNode **node) { unsigned int category, role; @@ -1105,6 +1159,19 @@ static void media_engine_clear_presentation(struct media_engine *engine) memset(&engine->presentation, 0, sizeof(engine->presentation)); }
+static void media_engine_clear_effects(struct media_engine *engine) +{ + size_t i; + + for (i = 0; i < engine->video_effects.count; ++i) + IUnknown_Release(engine->video_effects.effects[i].object); + + free(engine->video_effects.effects); + engine->video_effects.effects = NULL; + engine->video_effects.capacity = 0; + engine->video_effects.count = 0; +} + static HRESULT media_engine_create_topology(struct media_engine *engine, IMFMediaSource *source) { IMFStreamDescriptor *sd_audio = NULL, *sd_video = NULL; @@ -1227,7 +1294,9 @@ static HRESULT media_engine_create_topology(struct media_engine *engine, IMFMedi { IMFTopology_AddNode(topology, video_src); IMFTopology_AddNode(topology, grabber_node); - IMFTopologyNode_ConnectOutput(video_src, 0, grabber_node, 0); + + if (FAILED(hr = media_engine_create_video_effects(engine, video_src, grabber_node, topology))) + WARN("Failed to create video effect nodes, hr %#lx.\n", hr); }
if (SUCCEEDED(hr)) @@ -1382,6 +1451,7 @@ static void free_media_engine(struct media_engine *engine) IMFAttributes_Release(engine->attributes); if (engine->resolver) IMFSourceResolver_Release(engine->resolver); + media_engine_clear_effects(engine); media_engine_release_video_frame_resources(engine); media_engine_clear_presentation(engine); if (engine->device_manager) @@ -2587,11 +2657,49 @@ static HRESULT WINAPI media_engine_IsProtected(IMFMediaEngineEx *iface, BOOL *pr return E_NOTIMPL; }
+static HRESULT media_engine_insert_effect(struct media_engine *engine, IUnknown *effect, BOOL is_optional) +{ + size_t *count, *capacity; + struct effect **effects; + HRESULT hr = S_OK; + + capacity = &engine->video_effects.capacity; + effects = &engine->video_effects.effects; + count = &engine->video_effects.count; + + if (engine->flags & FLAGS_ENGINE_SHUT_DOWN) + hr = MF_E_SHUTDOWN; + else if (!mf_array_reserve((void **)effects, capacity, *count + 1, sizeof(**effects))) + { + hr = E_OUTOFMEMORY; + } + else + { + if (effect) + { + (*effects)[*count].object = effect; + IUnknown_AddRef((*effects)[*count].object); + } + (*effects)[*count].optional = is_optional; + + (*count)++; + } + + return hr; +} + static HRESULT WINAPI media_engine_InsertVideoEffect(IMFMediaEngineEx *iface, IUnknown *effect, BOOL is_optional) { - FIXME("%p, %p, %d stub.\n", iface, effect, is_optional); + struct media_engine *engine = impl_from_IMFMediaEngineEx(iface); + HRESULT hr = S_OK;
- return E_NOTIMPL; + TRACE("%p, %p, %d.\n", iface, effect, is_optional); + + EnterCriticalSection(&engine->cs); + hr = media_engine_insert_effect(engine, effect, is_optional); + LeaveCriticalSection(&engine->cs); + + return hr; }
static HRESULT WINAPI media_engine_InsertAudioEffect(IMFMediaEngineEx *iface, IUnknown *effect, BOOL is_optional) diff --git a/dlls/mfmediaengine/tests/mfmediaengine.c b/dlls/mfmediaengine/tests/mfmediaengine.c index c61267133b6..826d1028362 100644 --- a/dlls/mfmediaengine/tests/mfmediaengine.c +++ b/dlls/mfmediaengine/tests/mfmediaengine.c @@ -2013,18 +2013,19 @@ static void test_video_effect(void) ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
hr = IMFMediaEngineEx_InsertVideoEffect(media_engine_ex, (IUnknown *)&video_effect->IMFTransform_iface, FALSE); - todo_wine ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); + ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); EXPECT_REF(&video_effect->IMFTransform_iface, 2);
hr = IMFMediaEngineEx_InsertVideoEffect(media_engine_ex, (IUnknown *)&video_effect2->IMFTransform_iface, FALSE); - todo_wine ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); + ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); EXPECT_REF(&video_effect2->IMFTransform_iface, 2);
hr = IMFMediaEngineEx_InsertVideoEffect(media_engine_ex, (IUnknown *)&video_effect3->IMFTransform_iface, FALSE); - todo_wine ok(hr == S_OK || broken(hr == MF_E_INVALIDREQUEST), "Unexpected hr %#lx.\n", hr); + ok(hr == S_OK || broken(hr == MF_E_INVALIDREQUEST), "Unexpected hr %#lx.\n", hr);
- if (FAILED(hr)) /* Win8 to Win10v1507 and Wine */ + if (FAILED(hr)) { + win_skip("Inserting more than two effects fails on Win8 to Win10v1507 %#lx, skipping tests.\n", hr); goto done; } EXPECT_REF(&video_effect3->IMFTransform_iface, 2);