The test has a little inspiration from the SDK samples.
-- v14: mfmediaengine: Add support for inserting video effects.
From: Bernhard Kölbl besentv@gmail.com
Signed-off-by: Bernhard Kölbl besentv@gmail.com --- dlls/mfmediaengine/tests/mfmediaengine.c | 527 +++++++++++++++++++++++ 1 file changed, 527 insertions(+)
diff --git a/dlls/mfmediaengine/tests/mfmediaengine.c b/dlls/mfmediaengine/tests/mfmediaengine.c index c6baaed5942..863b3974b87 100644 --- a/dlls/mfmediaengine/tests/mfmediaengine.c +++ b/dlls/mfmediaengine/tests/mfmediaengine.c @@ -1358,6 +1358,532 @@ done: IMFMediaEngineNotify_Release(¬ify->IMFMediaEngineNotify_iface); }
+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) +{ + static const GUID *types[] = { &MFMediaType_Video }; + HRESULT hr; + + if (id) + return MF_E_INVALIDSTREAMNUMBER; + + if (index > ARRAY_SIZE(types) - 1) + return MF_E_NO_MORE_TYPES; + + if (SUCCEEDED(hr = MFCreateMediaType(type))) + hr = IMFMediaType_SetGUID(*type, &MF_MT_MAJOR_TYPE, types[index]); + + return hr; +} + +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); + } + + 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); + } + 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) +{ + WCHAR url[] = { L"i420-64x64.avi" }; + struct passthrough_mft *video_effect, *video_effect2; + struct test_transfer_notify *notify; + 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 = create_transfer_notify(); + + 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, "Unexpected delta %lu.\n", video_effect->processing_count); + ok(video_effect2->processing_count, "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); + + IMFMediaEngineNotify_Release(¬ify->IMFMediaEngineNotify_iface); +} + START_TEST(mfmediaengine) { HRESULT hr; @@ -1389,6 +1915,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..e3da2fa0752 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 863b3974b87..f5523ed4853 100644 --- a/dlls/mfmediaengine/tests/mfmediaengine.c +++ b/dlls/mfmediaengine/tests/mfmediaengine.c @@ -1835,17 +1835,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); @@ -1867,19 +1862,18 @@ static void test_video_effect(void) ok(video_effect->processing_count, "Unexpected delta %lu.\n", video_effect->processing_count); ok(video_effect2->processing_count, "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);
IMFMediaEngineNotify_Release(¬ify->IMFMediaEngineNotify_iface); }
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=134426
Your paranoid android.
=== w864 (64 bit report) ===
mfmediaengine: mfmediaengine.c:1874: Test failed: Unexpected ref 3. mfmediaengine.c:1876: Test failed: Unexpected ref 3.
Fixed another whitespace error.
Nikolay Sivov (@nsivov) commented about dlls/mfmediaengine/tests/mfmediaengine.c:
- 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. */
+};
This should be removed now.
Nikolay Sivov (@nsivov) commented about dlls/mfmediaengine/tests/mfmediaengine.c:
IMFMediaType **type)
+{
- static const GUID *types[] = { &MFMediaType_Video };
- HRESULT hr;
- if (id)
return MF_E_INVALIDSTREAMNUMBER;
- if (index > ARRAY_SIZE(types) - 1)
return MF_E_NO_MORE_TYPES;
- if (SUCCEEDED(hr = MFCreateMediaType(type)))
hr = IMFMediaType_SetGUID(*type, &MF_MT_MAJOR_TYPE, types[index]);
- return hr;
+}
That's fine. You could as well use MFMediaType_Video without types array, but then it's possible we'll reuse same test transform for audio effect test later.
Nikolay Sivov (@nsivov) commented about dlls/mfmediaengine/tests/mfmediaengine.c:
- 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);
}
Please remove second 'val' test, and fix a typo in its test message. Instead of 'is_receiver' I'd called it something like 'index', to make it clear which one comes first.
Nikolay Sivov (@nsivov) commented about dlls/mfmediaengine/tests/mfmediaengine.c:
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;
There is no cleanup on error paths.
Nikolay Sivov (@nsivov) commented about dlls/mfmediaengine/tests/mfmediaengine.c:
- 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);
Let's initialize out pointers in the helper.
Nikolay Sivov (@nsivov) commented about dlls/mfmediaengine/tests/mfmediaengine.c:
- /* 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, "Unexpected delta %lu.\n", video_effect->processing_count);
- ok(video_effect2->processing_count, "Unexpected delta %lu.\n", video_effect2->processing_count);
Should text message be reworded? Not clear why that would be a delta. Also we'll probably want '> 0' check for these signed counters.
On Tue Jul 4 13:50:18 2023 +0000, Nikolay Sivov wrote:
That's fine. You could as well use MFMediaType_Video without types array, but then it's possible we'll reuse same test transform for audio effect test later.
Yes this is my intention.