-- v5: mfmediaengine: Implement RemoveAllEffects(). mfmediaengine/tests: Add tests for RemoveAllEffects(). mfmediaengine/tests: Make ref checks more consistent. winegstreamer: Leave media source critical section before unlocking workqueue.
From: Bernhard Kölbl bkoelbl@codeweavers.com
Today, if media_source_Shutdown is called around the same time as a work item is put on the async_commands_queue, we end up in a deadlock if Shutdown enters media source's cs first, as it waits for the queue's callback to finish, which, in turn, waits for the object's cs to be released.
To avoid this leave the cs, before unlocking the workqueue, to let any callback on the queue finish running.
Signed-off-by: Bernhard Kölbl bkoelbl@codeweavers.com --- dlls/winegstreamer/media_source.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/dlls/winegstreamer/media_source.c b/dlls/winegstreamer/media_source.c index 7b0857158ae..8b9d42ea3f0 100644 --- a/dlls/winegstreamer/media_source.c +++ b/dlls/winegstreamer/media_source.c @@ -1570,10 +1570,10 @@ static HRESULT WINAPI media_source_Shutdown(IMFMediaSource *iface) free(source->descriptors); free(source->streams);
- MFUnlockWorkQueue(source->async_commands_queue); - LeaveCriticalSection(&source->cs);
+ MFUnlockWorkQueue(source->async_commands_queue); + return S_OK; }
From: Bernhard Kölbl bkoelbl@codeweavers.com
Do this by waiting for the first available frame with a separate ready event.
Signed-off-by: Bernhard Kölbl bkoelbl@codeweavers.com --- dlls/mfmediaengine/tests/mfmediaengine.c | 17 +++++++++-------- 1 file changed, 9 insertions(+), 8 deletions(-)
diff --git a/dlls/mfmediaengine/tests/mfmediaengine.c b/dlls/mfmediaengine/tests/mfmediaengine.c index aa9de414fcb..38063d1d21a 100644 --- a/dlls/mfmediaengine/tests/mfmediaengine.c +++ b/dlls/mfmediaengine/tests/mfmediaengine.c @@ -1139,7 +1139,7 @@ struct test_transfer_notify LONG refcount;
IMFMediaEngineEx *media_engine; - HANDLE ready_event; + HANDLE ready_event, frame_ready_event; HRESULT error; };
@@ -1175,6 +1175,7 @@ static ULONG WINAPI test_transfer_notify_Release(IMFMediaEngineNotify *iface)
if (!refcount) { + CloseHandle(notify->frame_ready_event); CloseHandle(notify->ready_event); free(notify); } @@ -1211,6 +1212,8 @@ static HRESULT WINAPI test_transfer_notify_EventNotify(IMFMediaEngineNotify *ifa notify->error = param2; /* fallthrough */ case MF_MEDIA_ENGINE_EVENT_FIRSTFRAMEREADY: + SetEvent(notify->frame_ready_event); + break; case MF_MEDIA_ENGINE_EVENT_TIMEUPDATE: SetEvent(notify->ready_event); break; @@ -1237,6 +1240,9 @@ static struct test_transfer_notify *create_transfer_notify(void) object->ready_event = CreateEventW(NULL, FALSE, FALSE, NULL); ok(!!object->ready_event, "Failed to create an event, error %lu.\n", GetLastError());
+ object->frame_ready_event = CreateEventW(NULL, FALSE, FALSE, NULL); + ok(!!object->frame_ready_event, "Failed to create an event, error %lu.\n", GetLastError()); + return object; }
@@ -1295,7 +1301,7 @@ static void test_TransferVideoFrame(void) SysFreeString(url); IMFByteStream_Release(stream);
- res = WaitForSingleObject(notify->ready_event, 5000); + res = WaitForSingleObject(notify->frame_ready_event, 5000); ok(!res, "Unexpected res %#lx.\n", res);
if (FAILED(notify->error)) @@ -1858,14 +1864,9 @@ static void test_effect(void) IMFByteStream_Release(stream);
/* Wait for MediaEngine to be ready. */ - res = WaitForSingleObject(notify->ready_event, 5000); + res = WaitForSingleObject(notify->frame_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);
From: Bernhard Kölbl bkoelbl@codeweavers.com
Signed-off-by: Bernhard Kölbl bkoelbl@codeweavers.com --- dlls/mfmediaengine/tests/mfmediaengine.c | 28 +++++++++++++++++++++--- 1 file changed, 25 insertions(+), 3 deletions(-)
diff --git a/dlls/mfmediaengine/tests/mfmediaengine.c b/dlls/mfmediaengine/tests/mfmediaengine.c index 38063d1d21a..829f056d2a2 100644 --- a/dlls/mfmediaengine/tests/mfmediaengine.c +++ b/dlls/mfmediaengine/tests/mfmediaengine.c @@ -1829,6 +1829,9 @@ static void test_effect(void) hr = ID3D11Device_CreateTexture2D(device, &desc, NULL, &texture); ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
+ hr = IMFMediaEngineEx_RemoveAllEffects(media_engine_ex); + todo_wine ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); + hr = passthrough_mft_create(0, &video_effect); ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
@@ -1843,6 +1846,22 @@ static void test_effect(void) ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); EXPECT_REF(&video_effect2->IMFTransform_iface, 2);
+ hr = IMFMediaEngineEx_RemoveAllEffects(media_engine_ex); + todo_wine ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); + todo_wine EXPECT_REF(&video_effect->IMFTransform_iface, 1); + todo_wine EXPECT_REF(&video_effect2->IMFTransform_iface, 1); + + if (FAILED(hr)) /* Temporary skip */ + goto done; + + hr = IMFMediaEngineEx_InsertVideoEffect(media_engine_ex, (IUnknown *)&video_effect->IMFTransform_iface, FALSE); + 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); + ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); + todo_wine EXPECT_REF(&video_effect2->IMFTransform_iface, 2); + hr = passthrough_mft_create(0, &audio_effect); ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
@@ -1892,8 +1911,11 @@ done: { IMFMediaEngineEx_Shutdown(media_engine_ex);
+ hr = IMFMediaEngineEx_RemoveAllEffects(media_engine_ex); + todo_wine ok(hr == MF_E_SHUTDOWN, "Unexpected hr %#lx.\n", hr); + ref = IMFMediaEngineEx_Release(media_engine_ex); - todo_wine ok(!ref, "Unexpected ref %lu.\n", ref); + ok(!ref, "Unexpected ref %lu.\n", ref); }
if (texture) @@ -1915,12 +1937,12 @@ done: if (video_effect2) { ref = IMFTransform_Release(&video_effect2->IMFTransform_iface); - todo_wine ok(!ref, "Unexpected ref %lu.\n", ref); + ok(!ref, "Unexpected ref %lu.\n", ref); } if (video_effect) { ref = IMFTransform_Release(&video_effect->IMFTransform_iface); - todo_wine ok(!ref, "Unexpected ref %lu.\n", ref); + ok(!ref, "Unexpected ref %lu.\n", ref); }
IMFMediaEngineNotify_Release(¬ify->IMFMediaEngineNotify_iface);
From: Bernhard Kölbl bkoelbl@codeweavers.com
Signed-off-by: Bernhard Kölbl bkoelbl@codeweavers.com --- dlls/mfmediaengine/main.c | 17 +++++++++++++++-- dlls/mfmediaengine/tests/mfmediaengine.c | 23 ++++++++++------------- 2 files changed, 25 insertions(+), 15 deletions(-)
diff --git a/dlls/mfmediaengine/main.c b/dlls/mfmediaengine/main.c index e664db81d1d..2f8addaf873 100644 --- a/dlls/mfmediaengine/main.c +++ b/dlls/mfmediaengine/main.c @@ -2719,9 +2719,22 @@ static HRESULT WINAPI media_engine_InsertAudioEffect(IMFMediaEngineEx *iface, IU
static HRESULT WINAPI media_engine_RemoveAllEffects(IMFMediaEngineEx *iface) { - FIXME("%p stub.\n", iface); + struct media_engine *engine = impl_from_IMFMediaEngineEx(iface); + HRESULT hr = S_OK;
- return E_NOTIMPL; + TRACE("%p.\n", iface); + + EnterCriticalSection(&engine->cs); + if (engine->flags & FLAGS_ENGINE_SHUT_DOWN) + hr = MF_E_SHUTDOWN; + else + { + media_engine_clear_effects(&engine->audio_effects); + media_engine_clear_effects(&engine->video_effects); + } + LeaveCriticalSection(&engine->cs); + + return hr; }
static HRESULT WINAPI media_engine_SetTimelineMarkerTimer(IMFMediaEngineEx *iface, double timeout) diff --git a/dlls/mfmediaengine/tests/mfmediaengine.c b/dlls/mfmediaengine/tests/mfmediaengine.c index 829f056d2a2..f4914496ca9 100644 --- a/dlls/mfmediaengine/tests/mfmediaengine.c +++ b/dlls/mfmediaengine/tests/mfmediaengine.c @@ -1830,7 +1830,7 @@ static void test_effect(void) ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
hr = IMFMediaEngineEx_RemoveAllEffects(media_engine_ex); - todo_wine ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); + ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
hr = passthrough_mft_create(0, &video_effect); ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); @@ -1847,20 +1847,17 @@ static void test_effect(void) EXPECT_REF(&video_effect2->IMFTransform_iface, 2);
hr = IMFMediaEngineEx_RemoveAllEffects(media_engine_ex); - todo_wine ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); - todo_wine EXPECT_REF(&video_effect->IMFTransform_iface, 1); - todo_wine EXPECT_REF(&video_effect2->IMFTransform_iface, 1); - - if (FAILED(hr)) /* Temporary skip */ - goto done; + ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); + EXPECT_REF(&video_effect->IMFTransform_iface, 1); + EXPECT_REF(&video_effect2->IMFTransform_iface, 1);
hr = IMFMediaEngineEx_InsertVideoEffect(media_engine_ex, (IUnknown *)&video_effect->IMFTransform_iface, FALSE); ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); - todo_wine EXPECT_REF(&video_effect->IMFTransform_iface, 2); + EXPECT_REF(&video_effect->IMFTransform_iface, 2);
hr = IMFMediaEngineEx_InsertVideoEffect(media_engine_ex, (IUnknown *)&video_effect2->IMFTransform_iface, FALSE); ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); - todo_wine EXPECT_REF(&video_effect2->IMFTransform_iface, 2); + EXPECT_REF(&video_effect2->IMFTransform_iface, 2);
hr = passthrough_mft_create(0, &audio_effect); ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); @@ -1912,10 +1909,10 @@ done: IMFMediaEngineEx_Shutdown(media_engine_ex);
hr = IMFMediaEngineEx_RemoveAllEffects(media_engine_ex); - todo_wine ok(hr == MF_E_SHUTDOWN, "Unexpected hr %#lx.\n", hr); + ok(hr == MF_E_SHUTDOWN, "Unexpected hr %#lx.\n", hr);
ref = IMFMediaEngineEx_Release(media_engine_ex); - ok(!ref, "Unexpected ref %lu.\n", ref); + todo_wine ok(!ref, "Unexpected ref %lu.\n", ref); }
if (texture) @@ -1937,12 +1934,12 @@ done: if (video_effect2) { ref = IMFTransform_Release(&video_effect2->IMFTransform_iface); - ok(!ref, "Unexpected ref %lu.\n", ref); + todo_wine ok(!ref, "Unexpected ref %lu.\n", ref); } if (video_effect) { 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=135598
Your paranoid android.
=== w1064v1809 (32 bit report) ===
mfmediaengine: mfmediaengine.c:1926: Test failed: Unexpected ref 1. mfmediaengine.c:1931: Test failed: Unexpected ref 4. mfmediaengine.c:1937: Test failed: Unexpected ref 1. mfmediaengine.c:1942: Test failed: Unexpected ref 1.
=== w10pro64 (32 bit report) ===
mfmediaengine: mfmediaengine.c:1926: Test failed: Unexpected ref 3. mfmediaengine.c:1931: Test failed: Unexpected ref 3.
=== w1064_adm (64 bit report) ===
mfmediaengine: mfmediaengine.c:1926: Test failed: Unexpected ref 4.
v5: - Rebase and push commit from !3491 for easier testing.
On Mon Jul 31 20:49:42 2023 +0000, Nikolay Sivov wrote:
So, why was it locking up?
check !3491
I'm not entirely sure why these problems still occur on the testbot, because:
1. When I run these tests on my local machine, they don't fail at all even after multiple tries. (I even asked a bunch of people to run this on their machines and they didn't have any issues either) 2. http://test.winehq.org/data/tests/mfmediaengine:mfmediaengine.html doesn't show any problems either and the tests have been upstream for a while now.