[PATCH 0/1] MR9719: mfmediaengine/tests: Test we receive a frame before calling Play.
Media Engine on Windows appears to use scrubbing to receive a frame before `IMFMediaEngine::Play` is called. This adds a test to confirm we can receive said frame. -- https://gitlab.winehq.org/wine/wine/-/merge_requests/9719
From: Brendan McGrath <bmcgrath(a)codeweavers.com> --- dlls/mfmediaengine/tests/mfmediaengine.c | 68 +++++++++++++++++++----- 1 file changed, 56 insertions(+), 12 deletions(-) diff --git a/dlls/mfmediaengine/tests/mfmediaengine.c b/dlls/mfmediaengine/tests/mfmediaengine.c index 79b0edf8da3..3cd30594c5e 100644 --- a/dlls/mfmediaengine/tests/mfmediaengine.c +++ b/dlls/mfmediaengine/tests/mfmediaengine.c @@ -1162,6 +1162,7 @@ struct test_transfer_notify IMFMediaEngineEx *media_engine; HANDLE ready_event, frame_ready_event; HRESULT error; + BOOL autoplay; }; static struct test_transfer_notify *impl_from_test_transfer_notify(IMFMediaEngineNotify *iface) @@ -1215,8 +1216,11 @@ static HRESULT WINAPI test_transfer_notify_EventNotify(IMFMediaEngineNotify *ifa switch (event) { case MF_MEDIA_ENGINE_EVENT_CANPLAY: - hr = IMFMediaEngineEx_Play(media_engine); - ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); + if (notify->autoplay) + { + hr = IMFMediaEngineEx_Play(media_engine); + ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); + } break; case MF_MEDIA_ENGINE_EVENT_FORMATCHANGE: @@ -1264,6 +1268,8 @@ static struct test_transfer_notify *create_transfer_notify(void) object->frame_ready_event = CreateEventW(NULL, FALSE, FALSE, NULL); ok(!!object->frame_ready_event, "Failed to create an event, error %lu.\n", GetLastError()); + object->autoplay = TRUE; + return object; } @@ -1290,6 +1296,7 @@ static void test_TransferVideoFrame(void) stream = load_resource(L"i420-64x64.avi", L"video/avi"); notify = create_transfer_notify(); + notify->autoplay = FALSE; if (!(device = create_d3d11_device())) { @@ -1333,7 +1340,8 @@ static void test_TransferVideoFrame(void) SysFreeString(url); IMFByteStream_Release(stream); - res = WaitForSingleObject(notify->frame_ready_event, 5000); + res = WaitForSingleObject(notify->frame_ready_event, 500); + todo_wine ok(!res, "Unexpected res %#lx.\n", res); if (FAILED(notify->error)) @@ -1347,6 +1355,50 @@ static void test_TransferVideoFrame(void) ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); ok(res == 2, "Unexpected stream count %lu.\n", res); + res = WaitForSingleObject(notify->frame_ready_event, 500); + + /* Obtain d3d device context */ + ID3D11Device_GetImmediateContext(device, &context); + + /* create the readback texture */ + ID3D11Texture2D_GetDesc(texture, &desc); + desc.Usage = D3D11_USAGE_STAGING; + desc.BindFlags = 0; + desc.CPUAccessFlags = D3D11_CPU_ACCESS_READ; + desc.MiscFlags = 0; + hr = ID3D11Device_CreateTexture2D(device, &desc, NULL, &rb_texture); + ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); + + /* confirm we have a frame available before calling play */ + pts = 0; + hr = IMFMediaEngineEx_OnVideoStreamTick(media_engine, &pts); + todo_wine + ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); + todo_wine + ok(pts == 0, "Unexpected timestamp.\n"); + + /* confirm we can transfer a frame before calling play */ + 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); + + ID3D11DeviceContext_CopySubresourceRegion(context, (ID3D11Resource *)rb_texture, + 0, 0, 0, 0, (ID3D11Resource *)texture, 0, NULL); + + memset(&map_desc, 0, sizeof(map_desc)); + hr = ID3D11DeviceContext_Map(context, (ID3D11Resource *)rb_texture, 0, D3D11_MAP_READ, 0, &map_desc); + ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); + ok(!!map_desc.pData, "got pData %p\n", map_desc.pData); + ok(map_desc.DepthPitch == 16384, "got DepthPitch %u\n", map_desc.DepthPitch); + ok(map_desc.RowPitch == desc.Width * 4, "got RowPitch %u\n", map_desc.RowPitch); + res = check_rgb32_data(L"rgb32frame.bmp", map_desc.pData, map_desc.RowPitch * desc.Height, &dst_rect); + todo_wine + ok(res == 0, "Unexpected %lu%% diff\n", res); + ID3D11DeviceContext_Unmap(context, (ID3D11Resource *)rb_texture, 0); + + hr = IMFMediaEngineEx_Play(media_engine); + ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); + /* FIXME: Wine first video frame is often full of garbage, wait for another update */ res = WaitForSingleObject(notify->ready_event, 500); /* It's also missing the MF_MEDIA_ENGINE_EVENT_TIMEUPDATE notifications */ @@ -1358,15 +1410,6 @@ static void test_TransferVideoFrame(void) hr = IMFMediaEngineEx_TransferVideoFrame(notify->media_engine, (IUnknown *)texture, NULL, &dst_rect, NULL); ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); - ID3D11Texture2D_GetDesc(texture, &desc); - desc.Usage = D3D11_USAGE_STAGING; - desc.BindFlags = 0; - desc.CPUAccessFlags = D3D11_CPU_ACCESS_READ; - desc.MiscFlags = 0; - hr = ID3D11Device_CreateTexture2D(device, &desc, NULL, &rb_texture); - ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); - - ID3D11Device_GetImmediateContext(device, &context); ID3D11DeviceContext_CopySubresourceRegion(context, (ID3D11Resource *)rb_texture, 0, 0, 0, 0, (ID3D11Resource *)texture, 0, NULL); @@ -1380,6 +1423,7 @@ static void test_TransferVideoFrame(void) ok(res == 0, "Unexpected %lu%% diff\n", res); ID3D11DeviceContext_Unmap(context, (ID3D11Resource *)rb_texture, 0); + /* free device context and readback texture */ ID3D11DeviceContext_Release(context); ID3D11Texture2D_Release(rb_texture); -- GitLab https://gitlab.winehq.org/wine/wine/-/merge_requests/9719
fwiw this behavior can also be observed with a custom effect MFT -- https://gitlab.winehq.org/wine/wine/-/merge_requests/9719#note_125140
participants (3)
-
Bernhard Kölbl -
Brendan McGrath -
Brendan McGrath (@redmcg)