From: Bernhard Kölbl besentv@gmail.com
Testing playback of a short mp4 file with h264 video and aac audio.
This test would hang before the changes made to media format handling for output nodes in the media session. Adding it now to reduce the risk of regressions. --- dlls/mfmediaengine/tests/mfmediaengine.c | 192 +++++++++++++++++++++++ dlls/mfmediaengine/tests/resource.rc | 7 + dlls/mfmediaengine/tests/test.mp4 | Bin 0 -> 4355 bytes 3 files changed, 199 insertions(+) create mode 100644 dlls/mfmediaengine/tests/test.mp4
diff --git a/dlls/mfmediaengine/tests/mfmediaengine.c b/dlls/mfmediaengine/tests/mfmediaengine.c index 3a5b2bf8253..df662e356af 100644 --- a/dlls/mfmediaengine/tests/mfmediaengine.c +++ b/dlls/mfmediaengine/tests/mfmediaengine.c @@ -1313,6 +1313,197 @@ done: CloseHandle(notify.ready_event); }
+static WCHAR *unpack_resource(const WCHAR *name) +{ + static WCHAR path[MAX_PATH]; + void *res_data; + DWORD written; + HANDLE file; + HRSRC res; + + GetTempPathW(ARRAY_SIZE(path), path); + lstrcatW(path, name); + + file = CreateFileW(path, GENERIC_READ|GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, 0, 0); + ok(file != INVALID_HANDLE_VALUE, "file creation failed, at %s, error %ld\n", wine_dbgstr_w(path), GetLastError()); + + res = FindResourceW(NULL, name, (LPCWSTR)RT_RCDATA); + ok(res != 0, "couldn't find resource\n"); + + res_data = LockResource(LoadResource(GetModuleHandleA(NULL), res)); + WriteFile(file, res_data, SizeofResource(GetModuleHandleA(NULL), res), &written, NULL); + ok(written == SizeofResource(GetModuleHandleA(NULL), res), "couldn't write resource\n" ); + + CloseHandle(file); + + return path; +} + +struct playback_notify +{ + IMFMediaEngineNotify IMFMediaEngineNotify_iface; + + IMFMediaEngineEx *media_engine; + HANDLE ended_event; + HANDLE ready_event; + HRESULT error; +}; + +static HRESULT WINAPI playback_notify_QueryInterface(IMFMediaEngineNotify *iface, REFIID riid, void **obj) +{ + if (IsEqualIID(riid, &IID_IUnknown) || + IsEqualIID(riid, &IID_IMFMediaEngineNotify)) + { + *obj = iface; + IMFMediaEngineNotify_AddRef(iface); + return S_OK; + } + + *obj = NULL; + return E_NOINTERFACE; +} + +static ULONG WINAPI playback_notify_AddRef(IMFMediaEngineNotify *iface) +{ + return 2; +} + +static ULONG WINAPI playback_notify_Release(IMFMediaEngineNotify *iface) +{ + return 1; +} + +static HRESULT WINAPI playback_notify_EventNotify(IMFMediaEngineNotify *iface, DWORD event, DWORD_PTR param1, DWORD param2) +{ + struct playback_notify *notify = CONTAINING_RECORD(iface, struct playback_notify, IMFMediaEngineNotify_iface); + IMFMediaEngineEx *media_engine = notify->media_engine; + DWORD width, height; + HRESULT hr; + BOOL ret; + + switch (event) + { + case MF_MEDIA_ENGINE_EVENT_CANPLAY: + hr = IMFMediaEngineEx_Play(media_engine); + ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); + break; + + case MF_MEDIA_ENGINE_EVENT_FORMATCHANGE: + ret = IMFMediaEngineEx_HasVideo(media_engine); + ok(ret, "Unexpected HasVideo %u.\n", ret); + hr = IMFMediaEngineEx_GetNativeVideoSize(media_engine, &width, &height); + ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); + ok(width == 32, "Unexpected width %lu.\n", width); + ok(height == 24, "Unexpected height %lu.\n", height); + break; + + case MF_MEDIA_ENGINE_EVENT_ERROR: + ok(broken(param2 == MF_E_UNSUPPORTED_BYTESTREAM_TYPE), "Unexpected error %#lx\n", param2); + notify->error = param2; + /* fallthrough */ + case MF_MEDIA_ENGINE_EVENT_FIRSTFRAMEREADY: + hr = IMFMediaEngineEx_Play(media_engine); + ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); + case MF_MEDIA_ENGINE_EVENT_TIMEUPDATE: + SetEvent(notify->ready_event); + break; + case MF_MEDIA_ENGINE_EVENT_ENDED: + SetEvent(notify->ended_event); + break; + } + + return S_OK; +} + +static IMFMediaEngineNotifyVtbl playback_notify_vtbl = +{ + playback_notify_QueryInterface, + playback_notify_AddRef, + playback_notify_Release, + playback_notify_EventNotify, +}; + +static void test_video_playback(void) +{ + struct playback_notify notify = {{&playback_notify_vtbl}}; + IMFMediaEngineEx *media_engine; + IMFDXGIDeviceManager *manager; + double current_time, duration; + LONGLONG presentation_time; + WCHAR *filename = NULL; + ID3D11Device *device; + UINT token; + HRESULT hr; + DWORD res; + + notify.ready_event = CreateEventW(NULL, FALSE, FALSE, NULL); + ok(!!notify.ready_event, "CreateEventW failed, error %lu\n", GetLastError()); + + notify.ended_event = CreateEventW(NULL, FALSE, FALSE, NULL); + ok(!!notify.ended_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 = create_media_engine_ex(¬ify.IMFMediaEngineNotify_iface, + manager, DXGI_FORMAT_B8G8R8X8_UNORM); + + IMFDXGIDeviceManager_Release(manager); + + media_engine = create_media_engine_ex(¬ify.IMFMediaEngineNotify_iface, NULL, DXGI_FORMAT_B8G8R8X8_UNORM); + + if (!(notify.media_engine = media_engine)) + return; + + filename = unpack_resource(L"test.mp4"); + ok(!!filename, "Failed to unpack resource.\n"); + + hr = IMFMediaEngineEx_SetSource(media_engine, filename); + ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); + + res = WaitForSingleObject(notify.ready_event, 5000); + ok(!res, "Unexpected res %#lx.\n", res); + + if (FAILED(notify.error)) + { + win_skip("Media engine reported error %#lx, skipping tests.\n", notify.error); + goto done; + } + + duration = IMFMediaEngineEx_GetDuration(media_engine); + todo_wine ok(duration == 0.167, "IMFMediaEngineEx_GetDuration returned %lf.\n", duration); + + while (WaitForSingleObject(notify.ended_event, 25) > WAIT_OBJECT_0) + { + current_time = IMFMediaEngineEx_GetCurrentTime(media_engine); + ok(current_time <= 0.260, "IMFMediaEngineEx_GetCurrentTime returned %lf.\n", current_time); + + hr = IMFMediaEngineEx_OnVideoStreamTick(media_engine, &presentation_time); + ok(hr == S_OK || hr == S_FALSE, "Unexpected hr %#lx.\n", hr); + ok(presentation_time <= 1670000, "presentation_time was %llu.\n", presentation_time); + } + + current_time = IMFMediaEngineEx_GetCurrentTime(media_engine); + ok(current_time <= 0.260, "IMFMediaEngineEx_GetCurrentTime returned %lf.\n", current_time); + +done: + IMFMediaEngineEx_Shutdown(media_engine); + IMFMediaEngineEx_Release(media_engine); + + ID3D11Device_Release(device); + + CloseHandle(notify.ended_event); + CloseHandle(notify.ready_event); +} + START_TEST(mfmediaengine) { HRESULT hr; @@ -1344,6 +1535,7 @@ START_TEST(mfmediaengine) test_SetSourceFromByteStream(); test_audio_configuration(); test_TransferVideoFrames(); + test_video_playback();
IMFMediaEngineClassFactory_Release(factory);
diff --git a/dlls/mfmediaengine/tests/resource.rc b/dlls/mfmediaengine/tests/resource.rc index 50152586758..60ef1da78e6 100644 --- a/dlls/mfmediaengine/tests/resource.rc +++ b/dlls/mfmediaengine/tests/resource.rc @@ -30,3 +30,10 @@ i420-64x64.avi RCDATA i420-64x64.avi /* Generated from running the tests on Windows */ /* @makedep: rgb32frame.bmp */ rgb32frame.bmp RCDATA rgb32frame.bmp + +/* ffmpeg -filter_complex "testsrc=duration=0.16:size=32x24:rate=30,colorspace=iall=bt709:all=bt709:format=yuv420p[0]; \ + * sine=frequency=1000:duration=0.16[1]" -c:v h264 -profile:v main \ + * -map "[0]:v" -map "[1]:a" -to 0.16s -f mp4 -y test.mp4 + */ +/* @makedep: test.mp4 */ +test.mp4 RCDATA test.mp4 diff --git a/dlls/mfmediaengine/tests/test.mp4 b/dlls/mfmediaengine/tests/test.mp4 new file mode 100644 index 0000000000000000000000000000000000000000..bb367c996be78ac1dec5c6c9e40d4c1d2e26d1a4 GIT binary patch literal 4355 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
literal 0 HcmV?d00001