-- v3: mf/tests: Test IMFClockStateSink in shutdown state. mf/tests: Test sample processing for MPEG4 media sink. mf/tests: Use IMFMediaEventGenerator interface in event wait helper.
From: Ziqing Hui zhui@codeweavers.com
--- dlls/mf/tests/mf.c | 24 +++++++++++++++++++----- 1 file changed, 19 insertions(+), 5 deletions(-)
diff --git a/dlls/mf/tests/mf.c b/dlls/mf/tests/mf.c index 743946f7fba..379bfd5c4b0 100644 --- a/dlls/mf/tests/mf.c +++ b/dlls/mf/tests/mf.c @@ -1971,18 +1971,23 @@ static IMFAsyncCallback *create_test_callback(BOOL check_media_event) }
#define wait_media_event(a, b, c, d, e) wait_media_event_(__LINE__, a, b, c, d, e) -static HRESULT wait_media_event_(int line, IMFMediaSession *session, IMFAsyncCallback *callback, +static HRESULT wait_media_event_(int line, void *object, IMFAsyncCallback *callback, MediaEventType expect_type, DWORD timeout, PROPVARIANT *value) { struct test_callback *impl = impl_from_IMFAsyncCallback(callback); + IMFMediaEventGenerator *event_generator; MediaEventType type; HRESULT hr, status; DWORD ret; GUID guid;
+ hr = IUnknown_QueryInterface((IUnknown *)object, &IID_IMFMediaEventGenerator, (void **)&event_generator); + ok_(__FILE__, line)(hr == S_OK, "Unexpected hr %#lx.\n", hr); + do { - hr = IMFMediaSession_BeginGetEvent(session, &impl->IMFAsyncCallback_iface, (IUnknown *)session); + hr = IMFMediaEventGenerator_BeginGetEvent(event_generator, + &impl->IMFAsyncCallback_iface, (IUnknown *)event_generator); ok_(__FILE__, line)(hr == S_OK, "Unexpected hr %#lx.\n", hr); ret = WaitForSingleObject(impl->event, timeout); ok_(__FILE__, line)(ret == WAIT_OBJECT_0, "WaitForSingleObject returned %lu\n", ret); @@ -1990,6 +1995,8 @@ static HRESULT wait_media_event_(int line, IMFMediaSession *session, IMFAsyncCal ok_(__FILE__, line)(hr == S_OK, "Unexpected hr %#lx.\n", hr); } while (type != expect_type);
+ IMFMediaEventGenerator_Release(event_generator); + ok_(__FILE__, line)(type == expect_type, "got type %lu\n", type);
hr = IMFMediaEvent_GetExtendedType(impl->media_event, &guid); @@ -2006,18 +2013,23 @@ static HRESULT wait_media_event_(int line, IMFMediaSession *session, IMFAsyncCal }
#define wait_media_event_until_blocking(a, b, c, d, e) wait_media_event_until_blocking_(__LINE__, a, b, c, d, e) -static HRESULT wait_media_event_until_blocking_(int line, IMFMediaSession *session, IMFAsyncCallback *callback, - MediaEventType expect_type, DWORD timeout, PROPVARIANT *value) +static HRESULT wait_media_event_until_blocking_(int line, void *object, IMFAsyncCallback *callback, + MediaEventType expect_type, DWORD timeout, PROPVARIANT *value) { struct test_callback *impl = impl_from_IMFAsyncCallback(callback); + IMFMediaEventGenerator *event_generator; MediaEventType type; HRESULT hr, status; DWORD ret; GUID guid;
+ hr = IUnknown_QueryInterface((IUnknown *)object, &IID_IMFMediaEventGenerator, (void **)&event_generator); + ok_(__FILE__, line)(hr == S_OK, "Unexpected hr %#lx.\n", hr); + do { - hr = IMFMediaSession_BeginGetEvent(session, &impl->IMFAsyncCallback_iface, (IUnknown *)session); + hr = IMFMediaEventGenerator_BeginGetEvent(event_generator, + &impl->IMFAsyncCallback_iface, (IUnknown *)event_generator); ok_(__FILE__, line)(hr == S_OK, "Unexpected hr %#lx.\n", hr); ret = WaitForSingleObject(impl->event, timeout); if (ret == WAIT_TIMEOUT) return WAIT_TIMEOUT; @@ -2025,6 +2037,8 @@ static HRESULT wait_media_event_until_blocking_(int line, IMFMediaSession *sessi ok_(__FILE__, line)(hr == S_OK, "Unexpected hr %#lx.\n", hr); } while (type != expect_type);
+ IMFMediaEventGenerator_Release(event_generator); + ok_(__FILE__, line)(type == expect_type, "got type %lu\n", type);
hr = IMFMediaEvent_GetExtendedType(impl->media_event, &guid);
From: Ziqing Hui zhui@codeweavers.com
--- dlls/mf/tests/mf.c | 171 +++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 164 insertions(+), 7 deletions(-)
diff --git a/dlls/mf/tests/mf.c b/dlls/mf/tests/mf.c index 379bfd5c4b0..2ad3df533a6 100644 --- a/dlls/mf/tests/mf.c +++ b/dlls/mf/tests/mf.c @@ -81,6 +81,44 @@ HRESULT (WINAPI *pMFGetTopoNodeCurrentType)(IMFTopologyNode *node, DWORD stream, HRESULT (WINAPI *pMFCreateDXGIDeviceManager)(UINT *token, IMFDXGIDeviceManager **manager); BOOL has_video_processor;
+const static BYTE test_h264_header[] = +{ + 0x00, 0x00, 0x01, 0x67, 0x64, 0x00, 0x14, 0xac, 0xd9, 0x46, 0x36, 0xc0, + 0x5a, 0x83, 0x03, 0x03, 0x52, 0x80, 0x00, 0x00, 0x03, 0x00, 0x80, 0x00, + 0x00, 0x03, 0x01, 0x47, 0x8a, 0x14, 0xcb, 0x00, 0x00, 0x01, 0x68, 0xeb, + 0xec, 0xb2, 0x2c, +}; + +const static BYTE test_h264_frame[] = +{ + 0x00, 0x00, 0x01, 0x65, 0x88, 0x84, 0x00, 0x17, 0xff, 0xe8, 0xff, 0xf2, + 0x3f, 0x9b, 0x0f, 0x5c, 0xdd, 0x08, 0x3f, 0xf5, 0xe8, 0xfc, 0xbb, 0xed, + 0x67, 0xbd, 0x22, 0xa1, 0xd7, 0xba, 0x21, 0xe6, 0x75, 0x8d, 0x3c, 0x11, + 0x12, 0x18, 0xd9, 0x81, 0x11, 0x75, 0x6a, 0x9b, 0x14, 0xcc, 0x50, 0x96, + 0x3f, 0x70, 0xd4, 0xf8, 0x3d, 0x17, 0xc9, 0x4e, 0x23, 0x96, 0x4e, 0x37, + 0xb9, 0xbe, 0x74, 0xf1, 0x53, 0x9f, 0xb4, 0x59, 0x57, 0x32, 0xee, 0x7f, + 0xfd, 0xea, 0x48, 0x2d, 0x80, 0x9e, 0x19, 0x61, 0x59, 0xcb, 0x14, 0xbd, + 0xcd, 0xb3, 0x3e, 0x81, 0x05, 0x56, 0x8e, 0x9c, 0xd9, 0x3f, 0x01, 0x6b, + 0x3e, 0x3c, 0x95, 0xcb, 0xc4, 0x1c, 0xfd, 0xb1, 0x72, 0x23, 0xbb, 0x7b, + 0xf8, 0xb8, 0x50, 0xda, 0x3c, 0x70, 0xc5, 0x7a, 0xc1, 0xe3, 0x13, 0x29, + 0x79, 0x7a, 0xbe, 0xff, 0x5a, 0x26, 0xc3, 0xb6, 0x56, 0xbb, 0x6a, 0x97, + 0x4d, 0xdc, 0x1e, 0x07, 0x4a, 0xaf, 0xff, 0x9e, 0x60, 0x20, 0x69, 0xf9, + 0xfc, 0xe8, 0xe0, 0xa6, 0x10, 0xa3, 0xab, 0x0f, 0xbe, 0x9c, 0x59, 0xa6, + 0xb4, 0x69, 0x4d, 0xc6, 0x09, 0xaa, 0xa8, 0xab, 0xbc, 0x64, 0xfd, 0x7e, + 0xde, 0x5f, 0x55, 0x06, 0xb9, 0xae, 0xce, 0x76, 0x5f, 0x63, 0x3a, 0x12, + 0x2e, 0x9e, 0xbd, 0x28, 0x71, 0x69, 0x34, 0xc9, 0xab, 0x20, 0x28, 0xb8, + 0x4b, 0x20, 0x1c, 0xe1, 0xc8, 0xc4, 0xa6, 0x7d, 0x73, 0x53, 0x73, 0xbf, + 0x21, 0x19, 0x9a, 0xd5, 0xa7, 0xcf, 0x47, 0x5a, 0xda, 0x34, 0x50, 0x7b, + 0x69, 0x8e, 0x52, 0xb2, 0x61, 0xda, 0x8e, 0x20, 0x95, 0x73, 0xc5, 0xb9, + 0x2b, 0x14, 0x48, 0xc1, 0x68, 0x3a, 0x7c, 0x78, 0x14, 0xe9, 0x92, 0xc7, + 0x89, 0xfc, 0x4f, 0x90, 0xaf, 0x54, 0x1e, 0xd0, 0xf0, 0x00, 0x25, 0x3e, + 0xcf, 0xbc, 0x18, 0xad, 0xc9, 0x6b, 0x9d, 0x77, 0x21, 0x6d, 0x5d, 0x2e, + 0xce, 0x09, 0xd9, 0xee, 0x79, 0xb6, 0xe7, 0xe4, 0xf4, 0x7f, 0x6e, 0x11, + 0x7b, 0x32, 0xfb, 0xf6, 0x8c, 0xbf, 0x05, 0xe1, 0x9a, 0x9c, 0x6c, 0x48, + 0x79, 0xac, 0x8f, 0x16, 0xb6, 0xf6, 0x3e, 0x76, 0xab, 0x40, 0x28, 0x61, + +}; + static BOOL is_vista(void) { return !pMFGetTopoNodeCurrentType; @@ -1866,7 +1904,7 @@ struct test_callback
HANDLE event; IMFMediaEvent *media_event; - BOOL check_media_event; + BOOL check_media_event, finalize_media_sink; };
static struct test_callback *impl_from_IMFAsyncCallback(IMFAsyncCallback *iface) @@ -1940,6 +1978,18 @@ static HRESULT WINAPI testcallback_Invoke(IMFAsyncCallback *iface, IMFAsyncResul IUnknown_Release(object); }
+ if (callback->finalize_media_sink) + { + hr = IMFAsyncResult_GetObject(result, &object); + ok(hr == E_POINTER, "Unexpected hr %#lx.\n", hr); + + hr = IMFAsyncResult_GetState(result, &object); + ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); + hr = IMFFinalizableMediaSink_EndFinalize((IMFFinalizableMediaSink *)object, result); + ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); + IUnknown_Release(object); + } + SetEvent(callback->event);
return S_OK; @@ -1954,7 +2004,7 @@ static const IMFAsyncCallbackVtbl testcallbackvtbl = testcallback_Invoke, };
-static IMFAsyncCallback *create_test_callback(BOOL check_media_event) +static IMFAsyncCallback *create_test_callback(BOOL check_media_event, BOOL finalize_media_sink) { struct test_callback *callback;
@@ -1963,6 +2013,7 @@ static IMFAsyncCallback *create_test_callback(BOOL check_media_event)
callback->refcount = 1; callback->check_media_event = check_media_event; + callback->finalize_media_sink = finalize_media_sink; callback->IMFAsyncCallback_iface.lpVtbl = &testcallbackvtbl; callback->event = CreateEventW(NULL, FALSE, FALSE, NULL); ok(!!callback->event, "CreateEventW failed, error %lu\n", GetLastError()); @@ -1970,6 +2021,26 @@ static IMFAsyncCallback *create_test_callback(BOOL check_media_event) return &callback->IMFAsyncCallback_iface; }
+static void test_callback_set(IMFAsyncCallback *iface, BOOL check_media_event, BOOL finalize_media_sink) +{ + struct test_callback *callback = CONTAINING_RECORD(iface, struct test_callback, IMFAsyncCallback_iface); + + callback->check_media_event = check_media_event; + callback->finalize_media_sink = finalize_media_sink; + + if (!callback->check_media_event && callback->media_event) + { + IMFMediaEvent_Release(callback->media_event); + callback->media_event = NULL; + } +} + +static DWORD test_callback_wait_event(IMFAsyncCallback *iface, DWORD time) +{ + struct test_callback *callback = CONTAINING_RECORD(iface, struct test_callback, IMFAsyncCallback_iface); + return WaitForSingleObject(callback->event, time); +} + #define wait_media_event(a, b, c, d, e) wait_media_event_(__LINE__, a, b, c, d, e) static HRESULT wait_media_event_(int line, void *object, IMFAsyncCallback *callback, MediaEventType expect_type, DWORD timeout, PROPVARIANT *value) @@ -2146,8 +2217,8 @@ static void test_media_session_events(void) hr = MFStartup(MF_VERSION, MFSTARTUP_FULL); ok(hr == S_OK, "Startup failure, hr %#lx.\n", hr);
- callback = create_test_callback(TRUE); - callback2 = create_test_callback(TRUE); + callback = create_test_callback(TRUE, FALSE); + callback2 = create_test_callback(TRUE, FALSE);
hr = MFCreateMediaSession(NULL, &session); ok(hr == S_OK, "Failed to create media session, hr %#lx.\n", hr); @@ -2202,7 +2273,7 @@ static void test_media_session_events(void) IMFAsyncCallback_Release(callback2);
- callback = create_test_callback(TRUE); + callback = create_test_callback(TRUE, FALSE);
hr = MFCreateMediaSession(NULL, &session); ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); @@ -4302,7 +4373,7 @@ static void test_presentation_clock(void) hr = IMFPresentationClock_GetCorrelatedTime(clock, 0, &time, &systime); ok(hr == S_OK, "got hr %#lx.\n", hr);
- callback = create_test_callback(FALSE); + callback = create_test_callback(FALSE, FALSE); timer_callback = impl_from_IMFAsyncCallback(callback); hr = IMFTimer_SetTimer(timer, 0, 100000, callback, NULL, &timer_cancel_key); ok(hr == S_OK, "got hr %#lx.\n", hr); @@ -4968,7 +5039,7 @@ static void test_sample_grabber_orientation(GUID subtype) goto done; }
- callback = create_test_callback(TRUE); + callback = create_test_callback(TRUE, FALSE); grabber_callback = impl_from_IMFSampleGrabberSinkCallback(create_test_grabber_callback());
grabber_callback->ready_event = CreateEventW(NULL, FALSE, FALSE, NULL); @@ -7065,6 +7136,91 @@ static void test_mpeg4_media_sink(void) IMFMediaType_Release(audio_type); }
+static void test_mpeg4_media_sink_process(void) +{ + DWORD width = 96, height = 96, fps = 1, ret; + IMFClockStateSink *clock_sink; + IMFAsyncCallback *callback; + IMFStreamSink *stream_sink; + IMFByteStream *bytestream; + IMFMediaSink *media_sink; + IMFMediaType *input_type; + IMFSample *input_sample; + PROPVARIANT variant; + UINT64 value; + UINT32 size; + HRESULT hr; + GUID guid; + + hr = MFCreateMediaType(&input_type); + ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); + hr = IMFMediaType_SetGUID(input_type, &MF_MT_MAJOR_TYPE, &MFMediaType_Video); + ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); + hr = IMFMediaType_SetGUID(input_type, &MF_MT_SUBTYPE, &MFVideoFormat_H264); + ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); + hr = IMFMediaType_SetUINT64(input_type, &MF_MT_FRAME_SIZE, ((UINT64)width << 32) | height); + ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); + hr = IMFMediaType_SetUINT64(input_type, &MF_MT_FRAME_RATE, ((UINT64)fps << 32) | 1); + ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); + hr = IMFMediaType_SetBlob(input_type, &MF_MT_MPEG_SEQUENCE_HEADER, test_h264_header, sizeof(test_h264_header)); + ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); + + hr = MFCreateTempFile(MF_ACCESSMODE_READWRITE, MF_OPENMODE_DELETE_IF_EXIST, MF_FILEFLAGS_NONE, &bytestream); + ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); + + hr = MFCreateMPEG4MediaSink(bytestream, input_type, NULL, &media_sink); + todo_wine + ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); + IMFMediaType_Release(input_type); + if (hr != S_OK) + { + IMFByteStream_Release(bytestream); + return; + } + hr = IMFMediaSink_QueryInterface(media_sink, &IID_IMFClockStateSink, (void **)&clock_sink); + ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); + + /* Start streaming. */ + callback = create_test_callback(TRUE, FALSE); + hr = IMFMediaSink_GetStreamSinkById(media_sink, 1, &stream_sink); + ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); + hr = IMFClockStateSink_OnClockStart(clock_sink, MFGetSystemTime(), 0); + ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); + wait_media_event(stream_sink, callback, MEStreamSinkStarted, 3000, &variant); + + /* Process sample. */ + input_sample = create_sample(test_h264_frame, sizeof(test_h264_frame)); + hr = IMFSample_SetSampleTime(input_sample, 0); + ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); + hr = IMFSample_SetSampleDuration(input_sample, 10000000); + ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); + hr = IMFStreamSink_ProcessSample(stream_sink, input_sample); + ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); + IMFSample_Release(input_sample); + + /* Wait for stop event to make sure samples have been processed. */ + hr = IMFClockStateSink_OnClockStop(clock_sink, MFGetSystemTime()); + ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); + wait_media_event(stream_sink, callback, MEStreamSinkStopped, 3000, &variant); + + /* Finalize. */ + test_callback_set(callback, FALSE, TRUE); + hr = IMFFinalizableMediaSink_BeginFinalize((IMFFinalizableMediaSink *)media_sink, callback, (IUnknown *)media_sink); + ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); + ret = test_callback_wait_event(callback, 3000); + ok(ret == WAIT_OBJECT_0, "Unexpected ret %#lx\n", ret); + hr = IMFMediaSink_Shutdown(media_sink); + ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); + + IMFClockStateSink_Release(clock_sink); + ret = IMFMediaSink_Release(media_sink); + ok(ret == 0, "Release returned %lu.\n", ret); + + IMFAsyncCallback_Release(callback); + IMFStreamSink_Release(stream_sink); + IMFByteStream_Release(bytestream); +} + START_TEST(mf) { init_functions(); @@ -7099,4 +7255,5 @@ START_TEST(mf) test_MFGetTopoNodeCurrentType(); test_MFRequireProtectedEnvironment(); test_mpeg4_media_sink(); + test_mpeg4_media_sink_process(); }
From: Ziqing Hui zhui@codeweavers.com
--- dlls/mf/tests/mf.c | 15 +++++++++++++++ 1 file changed, 15 insertions(+)
diff --git a/dlls/mf/tests/mf.c b/dlls/mf/tests/mf.c index 2ad3df533a6..677414d9985 100644 --- a/dlls/mf/tests/mf.c +++ b/dlls/mf/tests/mf.c @@ -6844,6 +6844,7 @@ static void test_mpeg4_media_sink(void) DWORD id, count, flags, width = 16, height = 16, fps = 10; IMFMediaType *audio_type, *video_type, *media_type; IMFMediaTypeHandler *type_handler = NULL; + IMFClockStateSink *clock_sink; IMFPresentationClock *clock; IMFStreamSink *stream_sink; HRESULT hr; @@ -7122,6 +7123,20 @@ static void test_mpeg4_media_sink(void) hr = IMFMediaSink_GetCharacteristics(sink, &flags); ok(hr == MF_E_SHUTDOWN, "Unexpected hr %#lx.\n", hr);
+ hr = IMFMediaSink_QueryInterface(sink, &IID_IMFClockStateSink, (void **)&clock_sink); + ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); + hr = IMFClockStateSink_OnClockStart(clock_sink, MFGetSystemTime(), 0); + ok(hr == MF_E_SHUTDOWN, "Unexpected hr %#lx.\n", hr); + hr = IMFClockStateSink_OnClockStop(clock_sink, MFGetSystemTime()); + ok(hr == MF_E_SHUTDOWN, "Unexpected hr %#lx.\n", hr); + hr = IMFClockStateSink_OnClockPause(clock_sink, MFGetSystemTime()); + ok(hr == MF_E_SHUTDOWN, "Unexpected hr %#lx.\n", hr); + hr = IMFClockStateSink_OnClockRestart(clock_sink, MFGetSystemTime()); + ok(hr == MF_E_SHUTDOWN, "Unexpected hr %#lx.\n", hr); + hr = IMFClockStateSink_OnClockSetRate(clock_sink, MFGetSystemTime(), 1.0f); + ok(hr == MF_E_SHUTDOWN, "Unexpected hr %#lx.\n", hr); + IMFClockStateSink_Release(clock_sink); + IMFMediaTypeHandler_Release(type_handler); IMFMediaSink_Release(sink); IMFMediaSink_Release(sink_video);