The test has a little inspiration from the SDK samples.
-- v10: mfmediaengine: Add support for inserting video effects. mfmediaengine/tests: Add tests for video effects.
From: Bernhard Kölbl besentv@gmail.com
Signed-off-by: Bernhard Kölbl besentv@gmail.com --- dlls/mfmediaengine/tests/mfmediaengine.c | 557 +++++++++++++++++++++++ 1 file changed, 557 insertions(+)
diff --git a/dlls/mfmediaengine/tests/mfmediaengine.c b/dlls/mfmediaengine/tests/mfmediaengine.c index 655b19af050..7ee0f28a006 100644 --- a/dlls/mfmediaengine/tests/mfmediaengine.c +++ b/dlls/mfmediaengine/tests/mfmediaengine.c @@ -1326,6 +1326,562 @@ done: CloseHandle(notify.ready_event); }
+struct passthrough_mft +{ + IMFTransform IMFTransform_iface; + LONG refcount; + + IMFMediaType *media_type_in, *media_type_out; + IMFSample *sample; + LONG processing_count; + BOOL is_receiver; + + CRITICAL_SECTION cs; +}; + +const GUID *media_subtypes[] = +{ + &MFVideoFormat_I420, + /* Add more formats if needed. */ +}; + +static struct passthrough_mft *impl_from_IMFTransform(IMFTransform *iface) +{ + return CONTAINING_RECORD(iface, struct passthrough_mft, IMFTransform_iface); +} + +static HRESULT WINAPI passthrough_mft_QueryInterface(IMFTransform *iface, REFIID iid, void **out) +{ + struct passthrough_mft *impl = impl_from_IMFTransform(iface); + + if (IsEqualGUID(iid, &IID_IUnknown) || + IsEqualGUID(iid, &IID_IMFTransform)) + { + *out = &impl->IMFTransform_iface; + IUnknown_AddRef((IUnknown *)*out); + return S_OK; + } + + *out = NULL; + return E_NOINTERFACE; +} + +static ULONG WINAPI passthrough_mft_AddRef(IMFTransform *iface) +{ + struct passthrough_mft *impl = impl_from_IMFTransform(iface); + ULONG refcount = InterlockedIncrement(&impl->refcount); + return refcount; +} + +static ULONG WINAPI passthrough_mft_Release(IMFTransform *iface) +{ + struct passthrough_mft *impl = impl_from_IMFTransform(iface); + ULONG refcount = InterlockedDecrement(&impl->refcount); + + if (!refcount) + { + if (impl->media_type_out) IMFMediaType_Release(impl->media_type_out); + if (impl->media_type_in) IMFMediaType_Release(impl->media_type_in); + DeleteCriticalSection(&impl->cs); + free(impl); + } + + return refcount; +} + +static HRESULT WINAPI passthrough_mft_GetStreamLimits(IMFTransform *iface, DWORD *input_minimum, + DWORD *input_maximum, DWORD *output_minimum, DWORD *output_maximum) +{ + *input_minimum = *input_maximum = *output_minimum = *output_maximum = 1; + return S_OK; +} + +static HRESULT WINAPI passthrough_mft_GetStreamCount(IMFTransform *iface, DWORD *inputs, DWORD *outputs) +{ + *inputs = *outputs = 1; + return S_OK; +} + +static HRESULT WINAPI passthrough_mft_GetStreamIDs(IMFTransform *iface, DWORD input_size, DWORD *inputs, + DWORD output_size, DWORD *outputs) +{ + return E_NOTIMPL; +} + +static HRESULT WINAPI passthrough_mft_GetInputStreamInfo(IMFTransform *iface, DWORD id, MFT_INPUT_STREAM_INFO *info) +{ + return E_NOTIMPL; +} + +static HRESULT WINAPI passthrough_mft_GetOutputStreamInfo(IMFTransform *iface, DWORD id, MFT_OUTPUT_STREAM_INFO *info) +{ + if (id) + return MF_E_INVALIDSTREAMNUMBER; + + info->dwFlags = + MFT_OUTPUT_STREAM_PROVIDES_SAMPLES | + MFT_OUTPUT_STREAM_WHOLE_SAMPLES | + MFT_OUTPUT_STREAM_FIXED_SAMPLE_SIZE | + MFT_OUTPUT_STREAM_SINGLE_SAMPLE_PER_BUFFER; + + info->cbAlignment = 0; + info->cbSize = 0; + return S_OK; +} + +static HRESULT WINAPI passthrough_mft_GetAttributes(IMFTransform *iface, IMFAttributes **attributes) +{ + return E_NOTIMPL; +} + +static HRESULT WINAPI passthrough_mft_GetInputStreamAttributes(IMFTransform *iface, DWORD id, IMFAttributes **attributes) +{ + return E_NOTIMPL; +} + +static HRESULT WINAPI passthrough_mft_GetOutputStreamAttributes(IMFTransform *iface, DWORD id, IMFAttributes **attributes) +{ + return E_NOTIMPL; +} + +static HRESULT WINAPI passthrough_mft_DeleteInputStream(IMFTransform *iface, DWORD id) +{ + return E_NOTIMPL; +} + +static HRESULT WINAPI passthrough_mft_AddInputStreams(IMFTransform *iface, DWORD streams, DWORD *ids) +{ + return E_NOTIMPL; +} + +static HRESULT WINAPI passthrough_mft_GetInputAvailableType(IMFTransform *iface, DWORD id, DWORD index, + IMFMediaType **type) +{ + struct passthrough_mft *impl = impl_from_IMFTransform(iface); + IMFMediaType *mt; + + if (id) + return MF_E_INVALIDSTREAMNUMBER; + + EnterCriticalSection(&impl->cs); + + if (impl->media_type_in) + { + if (index > 0) + goto no_more_types; + + *type = impl->media_type_in; + IMFMediaType_AddRef(*type); + } + else + { + if (index >= ARRAY_SIZE(media_subtypes)) + goto no_more_types; + + MFCreateMediaType(&mt); + IMFMediaType_SetGUID(mt, &MF_MT_MAJOR_TYPE, &MFMediaType_Video); + IMFMediaType_SetGUID(mt, &MF_MT_SUBTYPE, media_subtypes[index]); + *type = mt; + } + LeaveCriticalSection(&impl->cs); + + return S_OK; + +no_more_types: + LeaveCriticalSection(&impl->cs); + + return MF_E_NO_MORE_TYPES; +} + +static HRESULT WINAPI passthrough_mft_GetOutputAvailableType(IMFTransform *iface, DWORD id, DWORD index, + IMFMediaType **type) +{ + struct passthrough_mft *impl = impl_from_IMFTransform(iface); + HRESULT hr = S_OK; + + if (id) + return MF_E_INVALIDSTREAMNUMBER; + + EnterCriticalSection(&impl->cs); + + if (index) + { + hr = MF_E_NO_MORE_TYPES; + } + else if (impl->media_type_out) + { + *type = impl->media_type_out; + IMFMediaType_AddRef(*type); + } + else if (impl->media_type_in) + { + *type = impl->media_type_in; + IMFMediaType_AddRef(*type); + } + else + { + hr = MF_E_TRANSFORM_TYPE_NOT_SET; + } + + LeaveCriticalSection(&impl->cs); + + return hr; +} + +static HRESULT WINAPI passthrough_mft_SetInputType(IMFTransform *iface, DWORD id, IMFMediaType *type, DWORD flags) +{ + struct passthrough_mft *impl = impl_from_IMFTransform(iface); + HRESULT hr = S_OK; + + if (id) + return MF_E_INVALIDSTREAMNUMBER; + + EnterCriticalSection(&impl->cs); + + if (!(flags & MFT_SET_TYPE_TEST_ONLY)) + { + if (impl->media_type_in) + IMFMediaType_Release(impl->media_type_in); + + impl->media_type_in = type; + IMFMediaType_AddRef(impl->media_type_in); + + /* Idk why, but Windows apparently expects this function to also set an output type... */ + if (impl->media_type_out) + IMFMediaType_Release(impl->media_type_out); + + impl->media_type_out = type; + IMFMediaType_AddRef(impl->media_type_out); + } + + LeaveCriticalSection(&impl->cs); + + return hr; +} + +static HRESULT WINAPI passthrough_mft_SetOutputType(IMFTransform *iface, DWORD id, IMFMediaType *type, DWORD flags) +{ + struct passthrough_mft *impl = impl_from_IMFTransform(iface); + + if (id) + return MF_E_INVALIDSTREAMNUMBER; + + EnterCriticalSection(&impl->cs); + + if (impl->media_type_out) + IMFMediaType_Release(impl->media_type_out); + + impl->media_type_out = type; + IMFMediaType_AddRef(impl->media_type_out); + + LeaveCriticalSection(&impl->cs); + + return S_OK; +} + +static HRESULT WINAPI passthrough_mft_GetInputCurrentType(IMFTransform *iface, DWORD id, IMFMediaType **type) +{ + struct passthrough_mft *impl = impl_from_IMFTransform(iface); + HRESULT hr = S_OK; + + if (id) return MF_E_INVALIDSTREAMNUMBER; + + EnterCriticalSection(&impl->cs); + + if (impl->media_type_in) + { + *type = impl->media_type_in; + IMFMediaType_AddRef(*type); + } + else + { + hr = MF_E_TRANSFORM_TYPE_NOT_SET; + } + + LeaveCriticalSection(&impl->cs); + + return hr; +} + +static HRESULT WINAPI passthrough_mft_GetOutputCurrentType(IMFTransform *iface, DWORD id, IMFMediaType **type) +{ + struct passthrough_mft *impl = impl_from_IMFTransform(iface); + HRESULT hr = S_OK; + + if (id) + return MF_E_INVALIDSTREAMNUMBER; + + EnterCriticalSection(&impl->cs); + + if (impl->media_type_out) + { + *type = impl->media_type_out; + IMFMediaType_AddRef(*type); + hr = S_OK; + } + else + { + hr = MF_E_TRANSFORM_TYPE_NOT_SET; + } + + LeaveCriticalSection(&impl->cs); + + return hr; +} + +static HRESULT WINAPI passthrough_mft_GetInputStatus(IMFTransform *iface, DWORD id, DWORD *flags) +{ + return E_NOTIMPL; +} + +static HRESULT WINAPI passthrough_mft_GetOutputStatus(IMFTransform *iface, DWORD *flags) +{ + return E_NOTIMPL; +} + +static HRESULT WINAPI passthrough_mft_SetOutputBounds(IMFTransform *iface, LONGLONG lower, LONGLONG upper) +{ + return E_NOTIMPL; +} + +static HRESULT WINAPI passthrough_mft_ProcessEvent(IMFTransform *iface, DWORD id, IMFMediaEvent *event) +{ + return E_NOTIMPL; +} + +static HRESULT WINAPI passthrough_mft_ProcessMessage(IMFTransform *iface, MFT_MESSAGE_TYPE message, ULONG_PTR param) +{ + if (message == MFT_MESSAGE_COMMAND_FLUSH) + return E_NOTIMPL; + + return S_OK; +} + +static HRESULT WINAPI passthrough_mft_ProcessInput(IMFTransform *iface, DWORD id, IMFSample *sample, DWORD flags) +{ + struct passthrough_mft *impl = impl_from_IMFTransform(iface); + HRESULT hr = S_OK; + + if (id) + return MF_E_INVALIDSTREAMNUMBER; + + EnterCriticalSection(&impl->cs); + if (impl->sample) + { + hr = MF_E_NOTACCEPTING; + } + else + { + impl->sample = sample; + IMFSample_AddRef(impl->sample); + } + + LeaveCriticalSection(&impl->cs); + + return hr; +} + +static HRESULT WINAPI passthrough_mft_ProcessOutput(IMFTransform *iface, DWORD flags, DWORD count, + MFT_OUTPUT_DATA_BUFFER *samples, DWORD *status) +{ + struct passthrough_mft *impl = impl_from_IMFTransform(iface); + HRESULT hr = S_OK; + UINT32 val = 41; + + if (count != 1) + return E_INVALIDARG; + + EnterCriticalSection(&impl->cs); + if (impl->sample) + { + hr = IMFSample_GetUINT32(impl->sample, &IID_IMFSample, &val); + if (impl->is_receiver) + { + ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); + ok(val == 42, "Got unexpexted value %u.\n", val); + } + else + { + ok(hr == MF_E_ATTRIBUTENOTFOUND, "Unexpected hr %#lx.\n", hr); + ok(val == 41, "Got unexpexted value %u.\n", val); + + IMFSample_SetUINT32(impl->sample, &IID_IMFSample, 42); + } + + samples->pSample = impl->sample; + *status = samples[0].dwStatus = 0; + impl->processing_count++; + + impl->sample = NULL; + + hr = S_OK; + } + else + { + hr = MF_E_TRANSFORM_NEED_MORE_INPUT; + } + + LeaveCriticalSection(&impl->cs); + + return hr; +} + +static const IMFTransformVtbl passthrough_mft_vtbl = +{ + passthrough_mft_QueryInterface, + passthrough_mft_AddRef, + passthrough_mft_Release, + passthrough_mft_GetStreamLimits, + passthrough_mft_GetStreamCount, + passthrough_mft_GetStreamIDs, + passthrough_mft_GetInputStreamInfo, + passthrough_mft_GetOutputStreamInfo, + passthrough_mft_GetAttributes, + passthrough_mft_GetInputStreamAttributes, + passthrough_mft_GetOutputStreamAttributes, + passthrough_mft_DeleteInputStream, + passthrough_mft_AddInputStreams, + passthrough_mft_GetInputAvailableType, + passthrough_mft_GetOutputAvailableType, + passthrough_mft_SetInputType, + passthrough_mft_SetOutputType, + passthrough_mft_GetInputCurrentType, + passthrough_mft_GetOutputCurrentType, + passthrough_mft_GetInputStatus, + passthrough_mft_GetOutputStatus, + passthrough_mft_SetOutputBounds, + passthrough_mft_ProcessEvent, + passthrough_mft_ProcessMessage, + passthrough_mft_ProcessInput, + passthrough_mft_ProcessOutput, +}; + +HRESULT passthrough_mft_create(BOOL is_receiver, struct passthrough_mft **out) +{ + struct passthrough_mft *impl; + + if (!(impl = calloc(1, sizeof(*impl)))) + return E_OUTOFMEMORY; + + impl->IMFTransform_iface.lpVtbl = &passthrough_mft_vtbl; + impl->is_receiver = is_receiver; + impl->refcount = 1; + + InitializeCriticalSection(&impl->cs); + + *out = impl; + return S_OK; +} + +static void test_video_effect(void) +{ + struct test_transfer_notify notify = {{&test_transfer_notify_vtbl}}; + WCHAR url[] = { L"i420-64x64.avi" }; + struct passthrough_mft *video_effect, *video_effect2; + IMFMediaEngineEx *media_engine_ex; + IMFDXGIDeviceManager *manager; + D3D11_TEXTURE2D_DESC desc; + ID3D11Texture2D *texture; + IMFByteStream *stream; + ID3D11Device *device; + RECT dst_rect; + UINT token; + HRESULT hr; + DWORD res; + ULONG ref; + + stream = load_resource(L"i420-64x64.avi", L"video/avi"); + + notify.ready_event = CreateEventW(NULL, FALSE, FALSE, NULL); + ok(!!notify.ready_event, "CreateEventW failed, error %lu\n", GetLastError()); + + if (!(device = create_d3d11_device())) + { + skip("Failed to create a D3D11 device, skipping tests.\n"); + return; + } + + hr = pMFCreateDXGIDeviceManager(&token, &manager); + ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); + hr = IMFDXGIDeviceManager_ResetDevice(manager, (IUnknown *)device, token); + ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); + + media_engine_ex = create_media_engine_ex(¬ify.IMFMediaEngineNotify_iface, + manager, DXGI_FORMAT_B8G8R8X8_UNORM); + + IMFDXGIDeviceManager_Release(manager); + + if (!(notify.media_engine = media_engine_ex)) + return; + + memset(&desc, 0, sizeof(desc)); + desc.Width = 64; + desc.Height = 64; + desc.ArraySize = 1; + desc.Format = DXGI_FORMAT_B8G8R8X8_UNORM; + desc.BindFlags = D3D11_BIND_RENDER_TARGET; + desc.SampleDesc.Count = 1; + hr = ID3D11Device_CreateTexture2D(device, &desc, NULL, &texture); + ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); + + video_effect = NULL; + hr = passthrough_mft_create(FALSE, &video_effect); + ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); + + video_effect2 = NULL; + hr = passthrough_mft_create(TRUE, &video_effect2); + 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); + todo_wine 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); + todo_wine EXPECT_REF(&video_effect2->IMFTransform_iface, 2); + + if (FAILED(hr)) + { + goto done; + } + + hr = IMFMediaEngineEx_SetSourceFromByteStream(media_engine_ex, stream, url); + ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); + IMFByteStream_Release(stream); + + /* Wait for MediaEngine to be ready. */ + res = WaitForSingleObject(notify.ready_event, 5000); + ok(!res, "Unexpected res %#lx.\n", res); + + /* Wait for another update. This makes MediaEngine shutdown more consistent on Windows. */ + res = WaitForSingleObject(notify.ready_event, 500); + /* Timeupdates are missing in Wine. */ + todo_wine ok(!res, "Unexpected res %#lx.\n", res); + + SetRect(&dst_rect, 0, 0, desc.Width, desc.Height); + hr = IMFMediaEngineEx_TransferVideoFrame(notify.media_engine, (IUnknown *)texture, NULL, &dst_rect, NULL); + ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); + + ok(video_effect->processing_count == 2, "Unexpected delta %lu.\n", video_effect->processing_count); + ok(video_effect2->processing_count == 2, "Unexpected delta %lu.\n", video_effect2->processing_count); + +done: + IMFMediaEngineEx_Shutdown(media_engine_ex); + + ref = IMFMediaEngineEx_Release(media_engine_ex); + ok(!ref, "Unexpected ref %lu.\n", ref); + + ID3D11Texture2D_Release(texture); + ID3D11Device_Release(device); + + ref = IMFTransform_Release(&video_effect2->IMFTransform_iface); + ok(!ref, "Unexpected ref %lu.\n", ref); + ref = IMFTransform_Release(&video_effect->IMFTransform_iface); + ok(!ref, "Unexpected ref %lu.\n", ref); + + CloseHandle(notify.ready_event); +} + START_TEST(mfmediaengine) { HRESULT hr; @@ -1357,6 +1913,7 @@ START_TEST(mfmediaengine) test_SetSourceFromByteStream(); test_audio_configuration(); test_TransferVideoFrame(); + test_video_effect();
IMFMediaEngineClassFactory_Release(factory);
From: Bernhard Kölbl besentv@gmail.com
--- dlls/mfmediaengine/main.c | 110 ++++++++++++++++++++++- dlls/mfmediaengine/tests/mfmediaengine.c | 20 ++--- 2 files changed, 114 insertions(+), 16 deletions(-)
diff --git a/dlls/mfmediaengine/main.c b/dlls/mfmediaengine/main.c index b3ac236c78e..3aeee7cd744 100644 --- a/dlls/mfmediaengine/main.c +++ b/dlls/mfmediaengine/main.c @@ -113,6 +113,19 @@ struct rect float left, top, right, bottom; };
+struct effect +{ + IUnknown *object; + BOOL optional; +}; + +struct effects +{ + struct effect *effects; + size_t count; + size_t capacity; +}; + struct media_engine { IMFMediaEngineEx IMFMediaEngineEx_iface; @@ -145,6 +158,7 @@ struct media_engine IMFMediaSource *source; IMFPresentationDescriptor *pd; } presentation; + struct effects video_effects; struct { LONGLONG pts; @@ -1018,6 +1032,46 @@ static HRESULT media_engine_create_source_node(IMFMediaSource *source, IMFPresen return S_OK; }
+static HRESULT media_engine_create_effects(struct effect *effects, size_t count, + IMFTopologyNode *src, IMFTopologyNode *sink, IMFTopology *topology) +{ + IMFTopologyNode *last = src; + HRESULT hr = S_OK; + size_t i; + + 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); + break; + } + + 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); + + if (SUCCEEDED(hr)) + 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,20 @@ static void media_engine_clear_presentation(struct media_engine *engine) memset(&engine->presentation, 0, sizeof(engine->presentation)); }
+static void media_engine_clear_effects(struct effects *effects) +{ + size_t i; + + for (i = 0; i < effects->count; ++i) + { + if (effects->effects[i].object) + IUnknown_Release(effects->effects[i].object); + } + + free(effects->effects); + memset(effects, 0, sizeof(*effects)); +} + static HRESULT media_engine_create_topology(struct media_engine *engine, IMFMediaSource *source) { IMFStreamDescriptor *sd_audio = NULL, *sd_video = NULL; @@ -1227,7 +1295,10 @@ 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_effects(engine->video_effects.effects, engine->video_effects.count, + video_src, grabber_node, topology))) + WARN("Failed to create video effect nodes, hr %#lx.\n", hr); }
if (SUCCEEDED(hr)) @@ -1382,6 +1453,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->video_effects); media_engine_release_video_frame_resources(engine); media_engine_clear_presentation(engine); if (engine->device_manager) @@ -2587,11 +2659,43 @@ static HRESULT WINAPI media_engine_IsProtected(IMFMediaEngineEx *iface, BOOL *pr return E_NOTIMPL; }
+static HRESULT media_engine_insert_effect(struct media_engine *engine, struct effects *effects, IUnknown *object, BOOL is_optional) +{ + HRESULT hr = S_OK; + + if (engine->flags & FLAGS_ENGINE_SHUT_DOWN) + hr = MF_E_SHUTDOWN; + else if (!mf_array_reserve((void **)&effects->effects, &effects->capacity, effects->count + 1, sizeof(*effects->effects))) + { + hr = E_OUTOFMEMORY; + } + else + { + effects->effects[effects->count].object = object; + if (object) + { + IUnknown_AddRef(effects->effects[effects->count].object); + } + effects->effects[effects->count].optional = is_optional; + + effects->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, &engine->video_effects, 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 7ee0f28a006..3cf56370d98 100644 --- a/dlls/mfmediaengine/tests/mfmediaengine.c +++ b/dlls/mfmediaengine/tests/mfmediaengine.c @@ -1833,17 +1833,12 @@ 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); - todo_wine EXPECT_REF(&video_effect->IMFTransform_iface, 2); + 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); - todo_wine EXPECT_REF(&video_effect2->IMFTransform_iface, 2); - - if (FAILED(hr)) - { - goto done; - } + ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); + EXPECT_REF(&video_effect2->IMFTransform_iface, 2);
hr = IMFMediaEngineEx_SetSourceFromByteStream(media_engine_ex, stream, url); ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); @@ -1865,19 +1860,18 @@ static void test_video_effect(void) ok(video_effect->processing_count == 2, "Unexpected delta %lu.\n", video_effect->processing_count); ok(video_effect2->processing_count == 2, "Unexpected delta %lu.\n", video_effect2->processing_count);
-done: IMFMediaEngineEx_Shutdown(media_engine_ex);
ref = IMFMediaEngineEx_Release(media_engine_ex); - ok(!ref, "Unexpected ref %lu.\n", ref); + todo_wine ok(!ref, "Unexpected ref %lu.\n", ref);
ID3D11Texture2D_Release(texture); ID3D11Device_Release(device);
ref = IMFTransform_Release(&video_effect2->IMFTransform_iface); - ok(!ref, "Unexpected ref %lu.\n", ref); + todo_wine ok(!ref, "Unexpected ref %lu.\n", ref); ref = IMFTransform_Release(&video_effect->IMFTransform_iface); - ok(!ref, "Unexpected ref %lu.\n", ref); + todo_wine ok(!ref, "Unexpected ref %lu.\n", ref);
CloseHandle(notify.ready_event); }
Hi,
It looks like your patch introduced the new failures shown below. Please investigate and fix them before resubmitting your patch. If they are not new, fixing them anyway would help a lot. Otherwise please ask for the known failures list to be updated.
The tests also ran into some preexisting test failures. If you know how to fix them that would be helpful. See the TestBot job for the details:
The full results can be found at: https://testbot.winehq.org/JobDetails.pl?Key=134237
Your paranoid android.
=== w10pro64_ja (64 bit report) ===
mfmediaengine: mfmediaengine.c:1860: Test failed: Unexpected delta 0. mfmediaengine.c:1861: Test failed: Unexpected delta 0.
=== debian11 (32 bit report) ===
mfmediaengine: mfmediaengine.c:1860: Test failed: Unexpected delta 4. mfmediaengine.c:1861: Test failed: Unexpected delta 4.
=== debian11 (32 bit ar:MA report) ===
mfmediaengine: mfmediaengine.c:1860: Test failed: Unexpected delta 4. mfmediaengine.c:1861: Test failed: Unexpected delta 4.
=== debian11 (32 bit de report) ===
mfmediaengine: mfmediaengine.c:1860: Test failed: Unexpected delta 4. mfmediaengine.c:1861: Test failed: Unexpected delta 4.
=== debian11 (32 bit fr report) ===
mfmediaengine: mfmediaengine.c:1860: Test failed: Unexpected delta 4. mfmediaengine.c:1861: Test failed: Unexpected delta 4.
=== debian11 (32 bit he:IL report) ===
mfmediaengine: mfmediaengine.c:1860: Test failed: Unexpected delta 4. mfmediaengine.c:1861: Test failed: Unexpected delta 4.
=== debian11 (32 bit hi:IN report) ===
mfmediaengine: mfmediaengine.c:1860: Test failed: Unexpected delta 4. mfmediaengine.c:1861: Test failed: Unexpected delta 4.
=== debian11 (32 bit ja:JP report) ===
mfmediaengine: mfmediaengine.c:1860: Test failed: Unexpected delta 4. mfmediaengine.c:1861: Test failed: Unexpected delta 4.
=== debian11 (32 bit zh:CN report) ===
mfmediaengine: mfmediaengine.c:1860: Test failed: Unexpected delta 4. mfmediaengine.c:1861: Test failed: Unexpected delta 4.
=== debian11b (32 bit WoW report) ===
mfmediaengine: mfmediaengine.c:1860: Test failed: Unexpected delta 4. mfmediaengine.c:1861: Test failed: Unexpected delta 4.
=== debian11b (64 bit WoW report) ===
mfmediaengine: mfmediaengine.c:1860: Test failed: Unexpected delta 4. mfmediaengine.c:1861: Test failed: Unexpected delta 4.
v5: I applied most of your changes but kept the 41 -> 42 count thingy for now.
Bernhard Kölbl (@besentv) commented about dlls/mfmediaengine/tests/mfmediaengine.c:
- EnterCriticalSection(&impl->cs);
- if (!(flags & MFT_SET_TYPE_TEST_ONLY))
- {
if (impl->media_type_in)
IMFMediaType_Release(impl->media_type_in);
impl->media_type_in = type;
IMFMediaType_AddRef(impl->media_type_in);
/* Idk why, but Windows apparently expects this function to also set an output type... */
if (impl->media_type_out)
IMFMediaType_Release(impl->media_type_out);
impl->media_type_out = type;
IMFMediaType_AddRef(impl->media_type_out);
Oh and it still doesn't work without this.