-- v6: mf/tests: Test IMFClockStateSink in shutdown state. mf/tests: Add initial tests for MPEG4 media sink sample processing. 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 84f5e69ac25..bfd39103e2d 100644 --- a/dlls/mf/tests/mf.c +++ b/dlls/mf/tests/mf.c @@ -1972,18 +1972,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); @@ -1991,6 +1996,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); @@ -2007,18 +2014,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; @@ -2026,6 +2038,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 | 168 +++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 161 insertions(+), 7 deletions(-)
diff --git a/dlls/mf/tests/mf.c b/dlls/mf/tests/mf.c index bfd39103e2d..5319183f9fd 100644 --- a/dlls/mf/tests/mf.c +++ b/dlls/mf/tests/mf.c @@ -82,6 +82,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; @@ -1867,7 +1905,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) @@ -1941,6 +1979,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; @@ -1955,7 +2005,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;
@@ -1964,6 +2014,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()); @@ -1971,6 +2022,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) @@ -2147,8 +2218,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); @@ -2203,7 +2274,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); @@ -4303,7 +4374,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); @@ -4975,7 +5046,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); @@ -7208,6 +7279,88 @@ 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; + HRESULT hr; + + 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); + 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); + todo_wine + ok(ret == 0, "Release returned %lu.\n", ret); + + IMFAsyncCallback_Release(callback); + IMFStreamSink_Release(stream_sink); + IMFByteStream_Release(bytestream); +} + static void test_MFCreateSequencerSegmentOffset(void) { PROPVARIANT propvar; @@ -7259,5 +7412,6 @@ START_TEST(mf) test_MFGetTopoNodeCurrentType(); test_MFRequireProtectedEnvironment(); test_mpeg4_media_sink(); + test_mpeg4_media_sink_process(); test_MFCreateSequencerSegmentOffset(); }
From: Ziqing Hui zhui@codeweavers.com
--- dlls/mf/tests/mf.c | 16 ++++++++++++++++ 1 file changed, 16 insertions(+)
diff --git a/dlls/mf/tests/mf.c b/dlls/mf/tests/mf.c index 5319183f9fd..4311e21647b 100644 --- a/dlls/mf/tests/mf.c +++ b/dlls/mf/tests/mf.c @@ -6979,6 +6979,7 @@ static void test_mpeg4_media_sink(void) DWORD id, count, flags, width = 96, height = 96; IMFMediaType *audio_type, *video_type, *media_type; IMFMediaTypeHandler *type_handler = NULL; + IMFClockStateSink *clock_sink; IMFPresentationClock *clock; IMFStreamSink *stream_sink; HRESULT hr; @@ -7265,6 +7266,21 @@ static void test_mpeg4_media_sink(void) todo_wine 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); + todo_wine + 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);
@nsivov, since we have mp4 muxer implemented now, I think these tests should be needed.
Nikolay Sivov (@nsivov) commented about dlls/mf/tests/mf.c:
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[] =
Do we need this? Maybe it's enough to check the header or some elements of it actually being h264 stream, but full frame, it seems too much. Maybe we could use media foundation itself to check that output file type is detected as h264 when played back.
In my opinion this is a good example that tests are getting out of hand, when test callback is made to handle every possible case we need. I think it's fine to have a new mpeg4.c for tests.
Nikolay Sivov (@nsivov) commented about dlls/mf/tests/mf.c:
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);
This should query and not cast.
Nikolay Sivov (@nsivov) commented about dlls/mf/tests/mf.c:
- 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);
Same here, IMFFinalizableMediaSink is optional.
Do we need this? Maybe it's enough to check the header or some elements of it actually being h264 stream, but full frame, it seems too much. Maybe we could use media foundation itself to check that output file type is detected as h264 when played back.
The frame data must be used when testing `IMFStreamSink_ProcessSample()`, this data is the input for generating the output file.
The header data is set as a media type field. So, to test ProcessSample(), we should have a frame data.