The last commit in particular fixes the crashes in Windows.
From: Conor McCarthy cmccarthy@codeweavers.com
The size update always occurs before sample delivery, but not always before MESessionStarted. --- dlls/mf/tests/mf.c | 15 ++++++++++++--- 1 file changed, 12 insertions(+), 3 deletions(-)
diff --git a/dlls/mf/tests/mf.c b/dlls/mf/tests/mf.c index fab0e4e86e1..f3093293d6b 100644 --- a/dlls/mf/tests/mf.c +++ b/dlls/mf/tests/mf.c @@ -3048,6 +3048,12 @@ static HRESULT WINAPI test_grabber_callback_OnProcessSample(IMFSampleGrabberSink HRESULT hr; DWORD res;
+ if (grabber->ready_event && !grabber->done_event) + { + SetEvent(grabber->ready_event); + return S_OK; + } + if (!grabber->ready_event) return E_NOTIMPL;
@@ -6698,6 +6704,7 @@ static void test_h264_output_alignment(void) UINT64 frame_size; UINT32 status; HRESULT hr; + DWORD ret;
hr = MFStartup(MF_VERSION, MFSTARTUP_FULL); ok(hr == S_OK, "Failed to start up, hr %#lx.\n", hr); @@ -6711,6 +6718,8 @@ static void test_h264_output_alignment(void) }
grabber_callback = impl_from_IMFSampleGrabberSinkCallback(create_test_grabber_callback()); + grabber_callback->ready_event = CreateEventW(NULL, FALSE, FALSE, NULL); + ok(!!grabber_callback->ready_event, "CreateEventW failed, error %lu\n", GetLastError());
hr = MFCreateMediaType(&output_type); ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); @@ -6767,9 +6776,9 @@ static void test_h264_output_alignment(void) hr = IMFMediaSession_Start(session, &GUID_NULL, &propvar); ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
- /* frame size change occurs before MESessionStarted */ - hr = wait_media_event(session, callback, MESessionStarted, 5000, &propvar); - ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); + /* frame size change occurs before the first sample is delivered */ + ret = WaitForSingleObject(grabber_callback->ready_event, 1000); + ok(ret == WAIT_OBJECT_0, "WaitForSingleObject returned %lu\n", ret); frame_size = get_current_media_type_frame_size(transform); todo_wine ok(frame_size == (((UINT64)64 << 32) | 80), "Unexpected frame size %#llx\n", frame_size);
From: Conor McCarthy cmccarthy@codeweavers.com
Events can be dropped, and a multiple begin can occur while 'timed_out' is false, because an expected timeout leaves an active subscription, so it's possible to resubscribe and then handle an existing event while the subscription again remains active. --- dlls/mf/tests/mf.c | 65 ++++++++++++++++++++++++++++++++++++---------- 1 file changed, 51 insertions(+), 14 deletions(-)
diff --git a/dlls/mf/tests/mf.c b/dlls/mf/tests/mf.c index f3093293d6b..adeb0aba538 100644 --- a/dlls/mf/tests/mf.c +++ b/dlls/mf/tests/mf.c @@ -1168,7 +1168,9 @@ struct test_callback HANDLE event; IMFMediaEvent *media_event; BOOL check_media_event; - BOOL timed_out; + + CRITICAL_SECTION cs; + BOOL subscribed; };
static struct test_callback *impl_from_IMFAsyncCallback(IMFAsyncCallback *iface) @@ -1206,6 +1208,7 @@ static ULONG WINAPI testcallback_Release(IMFAsyncCallback *iface) if (callback->media_event) IMFMediaEvent_Release(callback->media_event); CloseHandle(callback->event); + DeleteCriticalSection(&callback->cs); free(callback); }
@@ -1236,13 +1239,23 @@ static HRESULT WINAPI testcallback_Invoke(IMFAsyncCallback *iface, IMFAsyncResul
hr = IMFAsyncResult_GetState(result, &object); ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); + + EnterCriticalSection(&callback->cs); + hr = IMFMediaEventGenerator_EndGetEvent((IMFMediaEventGenerator *)object, result, &callback->media_event); + callback->subscribed = FALSE; + SetEvent(callback->event); + + LeaveCriticalSection(&callback->cs); + ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); IUnknown_Release(object); } - - SetEvent(callback->event); + else + { + SetEvent(callback->event); + }
return S_OK; } @@ -1266,6 +1279,7 @@ static IMFAsyncCallback *create_test_callback(BOOL check_media_event) callback->refcount = 1; callback->check_media_event = check_media_event; callback->IMFAsyncCallback_iface.lpVtbl = &testcallbackvtbl; + InitializeCriticalSection(&callback->cs); callback->event = CreateEventW(NULL, FALSE, FALSE, NULL); ok(!!callback->event, "CreateEventW failed, error %lu\n", GetLastError());
@@ -1284,10 +1298,22 @@ static HRESULT gen_wait_media_event_(int line, IMFMediaEventGenerator *event_gen
do { - hr = IMFMediaEventGenerator_BeginGetEvent(event_generator, &impl->IMFAsyncCallback_iface, (IUnknown *)event_generator); - ok_(__FILE__, line)(hr == S_OK || (impl->timed_out && (hr == MF_E_MULTIPLE_SUBSCRIBERS || hr == MF_S_MULTIPLE_BEGIN)), "Unexpected hr %#lx.\n", hr); - ret = WaitForSingleObject(impl->event, timeout); - impl->timed_out = FALSE; + ret = WAIT_TIMEOUT; + EnterCriticalSection(&impl->cs); + if (!impl->subscribed && (ret = WaitForSingleObject(impl->event, 0)) != WAIT_OBJECT_0) + { + impl->subscribed = TRUE; + hr = IMFMediaEventGenerator_BeginGetEvent(event_generator, &impl->IMFAsyncCallback_iface, (IUnknown *)event_generator); + LeaveCriticalSection(&impl->cs); + ok_(__FILE__, line)(hr == S_OK, "Unexpected hr %#lx.\n", hr); + ret = WaitForSingleObject(impl->event, timeout); + } + else + { + LeaveCriticalSection(&impl->cs); + if (ret != WAIT_OBJECT_0) + ret = WaitForSingleObject(impl->event, timeout); + } ok_(__FILE__, line)(ret == WAIT_OBJECT_0, "WaitForSingleObject returned %lu\n", ret); hr = IMFMediaEvent_GetType(impl->media_event, &type); ok_(__FILE__, line)(hr == S_OK, "Unexpected hr %#lx.\n", hr); @@ -1327,15 +1353,26 @@ static HRESULT gen_wait_media_event_until_blocking_(int line, IMFMediaEventGener
do { - hr = IMFMediaEventGenerator_BeginGetEvent(event_generator, &impl->IMFAsyncCallback_iface, (IUnknown *)event_generator); - ok_(__FILE__, line)(hr == S_OK || (impl->timed_out && (hr == MF_E_MULTIPLE_SUBSCRIBERS || hr == MF_S_MULTIPLE_BEGIN)), "Unexpected hr %#lx.\n", hr); - ret = WaitForSingleObject(impl->event, timeout); - if (ret == WAIT_TIMEOUT) + ret = WAIT_TIMEOUT; + EnterCriticalSection(&impl->cs); + if (!impl->subscribed && (ret = WaitForSingleObject(impl->event, 0)) != WAIT_OBJECT_0) { - impl->timed_out = TRUE; - return WAIT_TIMEOUT; + impl->subscribed = TRUE; + hr = IMFMediaEventGenerator_BeginGetEvent(event_generator, &impl->IMFAsyncCallback_iface, (IUnknown *)event_generator); + LeaveCriticalSection(&impl->cs); + ok_(__FILE__, line)(hr == S_OK, "Unexpected hr %#lx.\n", hr); + ret = WaitForSingleObject(impl->event, timeout); + } + else + { + LeaveCriticalSection(&impl->cs); + if (ret != WAIT_OBJECT_0) + ret = WaitForSingleObject(impl->event, timeout); } - impl->timed_out = FALSE; + + if (ret == WAIT_TIMEOUT) + return WAIT_TIMEOUT; + hr = IMFMediaEvent_GetType(impl->media_event, &type); ok_(__FILE__, line)(hr == S_OK, "Unexpected hr %#lx.\n", hr); } while (type != expect_type);
From: Conor McCarthy cmccarthy@codeweavers.com
New failure codes keep turning up here in Windows. --- dlls/mf/tests/mf.c | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-)
diff --git a/dlls/mf/tests/mf.c b/dlls/mf/tests/mf.c index adeb0aba538..d98be2fa6d0 100644 --- a/dlls/mf/tests/mf.c +++ b/dlls/mf/tests/mf.c @@ -7281,7 +7281,8 @@ static void test_media_session_source_shutdown(void) break; }
- if (shutdown_point == TEST_CLOSE) + /* Skip tests where the results in Windows are too uncertain to be worth checking. */ + if (shutdown_point >= TEST_PAUSE) goto done;
IMFMediaSource_Release(source); @@ -7323,10 +7324,7 @@ static void test_media_session_source_shutdown(void) hr = IMFMediaSession_Close(session); ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); hr = wait_media_event_until_blocking(session, callback, MESessionClosed, 1000, &propvar); - if (shutdown_point >= TEST_PAUSE) - ok(hr == MF_E_SHUTDOWN || hr == S_OK || hr == WAIT_TIMEOUT, "Unexpected hr %#lx.\n", hr); - else - ok(hr == MF_E_SHUTDOWN || hr == S_OK, "Unexpected hr %#lx.\n", hr); + ok(hr == MF_E_SHUTDOWN || hr == S_OK, "Unexpected hr %#lx.\n", hr);
done: hr = IMFMediaSession_Shutdown(session);
From: Conor McCarthy cmccarthy@codeweavers.com
Windows times out here on rare occasions. --- dlls/mf/tests/mf.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/dlls/mf/tests/mf.c b/dlls/mf/tests/mf.c index d98be2fa6d0..85c7a61c58e 100644 --- a/dlls/mf/tests/mf.c +++ b/dlls/mf/tests/mf.c @@ -7516,7 +7516,7 @@ static void test_media_session_Close(void) hr = IMFMediaSource_Shutdown(source); ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); hr = wait_media_event_until_blocking(session, callback, MESessionClosed, 5000, &propvar); - ok(hr == MF_E_SHUTDOWN, "Unexpected hr %#lx.\n", hr); + ok(hr == MF_E_SHUTDOWN || hr == WAIT_TIMEOUT, "Unexpected hr %#lx.\n", hr);
hr = IMFMediaSession_Shutdown(session); ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
From: Conor McCarthy cmccarthy@codeweavers.com
Windows has matching count but mismatching states here on rare occasions. --- dlls/mf/tests/mf.c | 2 ++ 1 file changed, 2 insertions(+)
diff --git a/dlls/mf/tests/mf.c b/dlls/mf/tests/mf.c index 85c7a61c58e..44a66d918d2 100644 --- a/dlls/mf/tests/mf.c +++ b/dlls/mf/tests/mf.c @@ -8238,6 +8238,7 @@ static void test_media_session_seek(void) CHECK_CALLED(test_stream_sink_Flush); CHECK_CALLED(test_transform_ProcessMessage_FLUSH);
+ flaky compare_object_states(&actual_object_state_record, &expected_seek_start_no_pending_request_records);
/* Test a sample request only (i.e. with no sample delivery), then pause and then start with a seek */ @@ -8300,6 +8301,7 @@ static void test_media_session_seek(void) CHECK_CALLED(test_transform_ProcessOutput); CHECK_CALLED(test_media_stream_RequestSample);
+ flaky compare_object_states(&actual_object_state_record, &expected_seek_start_pending_request_records);
IMFPresentationClock_RemoveClockStateSink(presentation_clock, &test_seek_clock_sink);
From: Conor McCarthy cmccarthy@codeweavers.com
--- dlls/mf/tests/mf.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/dlls/mf/tests/mf.c b/dlls/mf/tests/mf.c index 44a66d918d2..e69cbf108eb 100644 --- a/dlls/mf/tests/mf.c +++ b/dlls/mf/tests/mf.c @@ -798,7 +798,7 @@ static HRESULT WINAPI test_media_sink_GetStreamSinkCount(IMFMediaSink *iface, DW static HRESULT WINAPI test_media_sink_GetStreamSinkByIndex(IMFMediaSink *iface, DWORD index, IMFStreamSink **sink) { struct test_media_sink *sink_impl = impl_from_IMFMediaSink(iface); - if (sink_impl->stream) + if (!index && sink_impl->stream) { IMFStreamSink_AddRef(*sink = sink_impl->stream); return S_OK;
From: Conor McCarthy cmccarthy@codeweavers.com
--- dlls/mf/tests/mf.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-)
diff --git a/dlls/mf/tests/mf.c b/dlls/mf/tests/mf.c index e69cbf108eb..b9b8f690ead 100644 --- a/dlls/mf/tests/mf.c +++ b/dlls/mf/tests/mf.c @@ -8311,9 +8311,13 @@ static void test_media_session_seek(void)
hr = IMFMediaSession_Shutdown(session); ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); + ok(media_sink.shutdown, "Media sink didn't shutdown.\n");
- IMFMediaSession_Release(session); + hr = IMFMediaSource_Shutdown(source); + ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
+ IMFMediaSession_Release(session); + IMFMediaSource_Release(source); IMFMediaEventQueue_Release(stream_sink.event_queue); if (media_sink.clock) IMFPresentationClock_Release(media_sink.clock);
From: Conor McCarthy cmccarthy@codeweavers.com
Windows provides no guarantee about when the last reference will be released, and crashes occur when the test function returns before the session's current topology is shut down. --- dlls/mf/tests/mf.c | 291 ++++++++++++++++++++++++++++++--------------- 1 file changed, 194 insertions(+), 97 deletions(-)
diff --git a/dlls/mf/tests/mf.c b/dlls/mf/tests/mf.c index b9b8f690ead..464e95cfc45 100644 --- a/dlls/mf/tests/mf.c +++ b/dlls/mf/tests/mf.c @@ -576,6 +576,7 @@ static void test_sequencer_source(void) struct test_handler { IMFMediaTypeHandler IMFMediaTypeHandler_iface; + LONG refcount;
ULONG set_current_count; IMFMediaType *current_type; @@ -606,12 +607,25 @@ static HRESULT WINAPI test_handler_QueryInterface(IMFMediaTypeHandler *iface, RE
static ULONG WINAPI test_handler_AddRef(IMFMediaTypeHandler *iface) { - return 2; + struct test_handler *impl = impl_from_IMFMediaTypeHandler(iface); + return InterlockedIncrement(&impl->refcount); }
static ULONG WINAPI test_handler_Release(IMFMediaTypeHandler *iface) { - return 1; + struct test_handler *impl = impl_from_IMFMediaTypeHandler(iface); + ULONG refcount = InterlockedDecrement(&impl->refcount); + + if (!refcount) + { + if (impl->current_type) + IMFMediaType_Release(impl->current_type); + /* references to invalid_type and media_types are not held. */ + + free(impl); + } + + return refcount; }
static HRESULT WINAPI test_handler_IsMediaTypeSupported(IMFMediaTypeHandler *iface, IMFMediaType *in_type, @@ -718,11 +732,31 @@ static const IMFMediaTypeHandlerVtbl test_handler_vtbl = test_handler_GetMajorType, };
-static const struct test_handler test_handler = {.IMFMediaTypeHandler_iface.lpVtbl = &test_handler_vtbl}; +static struct test_handler *create_test_handler(void) +{ + struct test_handler *handler; + + handler = calloc(1, sizeof(*handler)); + handler->IMFMediaTypeHandler_iface.lpVtbl = &test_handler_vtbl; + handler->refcount = 1; + + return handler; +}; + +static void test_handler_clear_current_type(struct test_handler *handler) +{ + if (handler->current_type) + { + IMFMediaType_Release(handler->current_type); + handler->current_type = NULL; + } +}
struct test_media_sink { IMFMediaSink IMFMediaSink_iface; + LONG refcount; + IMFMediaTypeHandler *handler; IMFPresentationClock *clock; IMFStreamSink *stream; BOOL shutdown; @@ -748,12 +782,25 @@ static HRESULT WINAPI test_media_sink_QueryInterface(IMFMediaSink *iface, REFIID
static ULONG WINAPI test_media_sink_AddRef(IMFMediaSink *iface) { - return 2; + struct test_media_sink *sink = impl_from_IMFMediaSink(iface); + return InterlockedIncrement(&sink->refcount); }
static ULONG WINAPI test_media_sink_Release(IMFMediaSink *iface) { - return 1; + struct test_media_sink *sink = impl_from_IMFMediaSink(iface); + ULONG refcount = InterlockedDecrement(&sink->refcount); + + if (!refcount) + { + if (!sink->shutdown) + IMFMediaSink_Shutdown(iface); + if (sink->handler) + IMFMediaTypeHandler_Release(sink->handler); + free(sink); + } + + return refcount; }
static HRESULT WINAPI test_media_sink_GetCharacteristics(IMFMediaSink *iface, DWORD *characteristics) @@ -852,6 +899,18 @@ static HRESULT WINAPI test_media_sink_GetPresentationClock(IMFMediaSink *iface, static HRESULT WINAPI test_media_sink_Shutdown(IMFMediaSink *iface) { struct test_media_sink *sink = impl_from_IMFMediaSink(iface); + + if (sink->clock) + { + IMFPresentationClock_Release(sink->clock); + sink->clock = NULL; + } + if (sink->stream) + { + IMFStreamSink_Release(sink->stream); + sink->stream = NULL; + } + ok(!sink->shutdown, "Unexpected call.\n"); sink->shutdown = TRUE; return S_OK; @@ -921,12 +980,11 @@ static const IMFMediaSinkVtbl test_media_sink_vtbl = test_media_sink_Shutdown, };
-static const struct test_media_sink test_media_sink = {.IMFMediaSink_iface.lpVtbl = &test_media_sink_vtbl}; - struct test_stream_sink { IMFStreamSink IMFStreamSink_iface; IMFGetService IMFGetService_iface; + LONG refcount; IMFMediaTypeHandler *handler; IMFMediaSink *media_sink;
@@ -972,12 +1030,30 @@ static HRESULT WINAPI test_stream_sink_QueryInterface(IMFStreamSink *iface, REFI
static ULONG WINAPI test_stream_sink_AddRef(IMFStreamSink *iface) { - return 2; + struct test_stream_sink *sink = impl_from_IMFStreamSink(iface); + return InterlockedIncrement(&sink->refcount); }
static ULONG WINAPI test_stream_sink_Release(IMFStreamSink *iface) { - return 1; + struct test_stream_sink *sink = impl_from_IMFStreamSink(iface); + ULONG refcount = InterlockedDecrement(&sink->refcount); + + if (!refcount) + { + if (sink->handler) + IMFMediaTypeHandler_Release(sink->handler); + if (sink->media_sink) + IMFMediaSink_Release(sink->media_sink); + if (sink->event_queue) + { + IMFMediaEventQueue_Shutdown(sink->event_queue); + IMFMediaEventQueue_Release(sink->event_queue); + } + free(sink); + } + + return refcount; }
static HRESULT WINAPI test_stream_sink_GetEvent(IMFStreamSink *iface, DWORD flags, IMFMediaEvent **event) @@ -1154,11 +1230,47 @@ static const IMFGetServiceVtbl test_stream_sink_get_service_vtbl = test_stream_sink_get_service_GetService, };
-static const struct test_stream_sink test_stream_sink = +static struct test_stream_sink *create_test_stream_sink(IMFMediaSink *media_sink, + IMFMediaTypeHandler *handler, BOOL create_queue) { - .IMFStreamSink_iface.lpVtbl = &test_stream_sink_vtbl, - .IMFGetService_iface.lpVtbl = &test_stream_sink_get_service_vtbl, -}; + struct test_stream_sink *sink; + + sink = calloc(1, sizeof(*sink)); + sink->IMFStreamSink_iface.lpVtbl = &test_stream_sink_vtbl, + sink->IMFGetService_iface.lpVtbl = &test_stream_sink_get_service_vtbl, + sink->refcount = 1; + if (handler) + IMFMediaTypeHandler_AddRef(sink->handler = handler); + if (media_sink) + IMFMediaSink_AddRef(sink->media_sink = media_sink); + if (create_queue) + MFCreateEventQueue(&sink->event_queue); + + return sink; +} + +static void reset_test_media_sink(struct test_media_sink *sink) +{ + if (sink->shutdown) + { + sink->stream = &create_test_stream_sink(&sink->IMFMediaSink_iface, sink->handler, TRUE)->IMFStreamSink_iface; + sink->shutdown = FALSE; + } +} + +static struct test_media_sink *create_test_media_sink(IMFMediaTypeHandler *handler) +{ + struct test_media_sink *sink; + + sink = calloc(1, sizeof(*sink)); + sink->IMFMediaSink_iface.lpVtbl = &test_media_sink_vtbl; + sink->refcount = 1; + if (handler) + IMFMediaTypeHandler_AddRef(sink->handler = handler); + sink->stream = &create_test_stream_sink(&sink->IMFMediaSink_iface, handler, TRUE)->IMFStreamSink_iface; + + return sink; +}
struct test_callback { @@ -2264,14 +2376,13 @@ static void test_media_session_events(void) ATTR_UINT32(MF_MT_AUDIO_BITS_PER_SAMPLE, 2 * 8), };
- struct test_stream_sink stream_sink = test_stream_sink; - struct test_media_sink media_sink = test_media_sink; - struct test_handler handler = test_handler; struct test_stub_source *source_impl; IMFAsyncCallback *callback, *callback2; IMFMediaType *input_type, *output_type; IMFTopologyNode *src_node, *sink_node; + struct test_media_sink *media_sink; IMFPresentationDescriptor *pd; + struct test_handler *handler; IMFMediaSession *session; IMFStreamDescriptor *sd; IMFAsyncResult *result; @@ -2282,8 +2393,8 @@ static void test_media_session_events(void) HRESULT hr; ULONG ref;
- stream_sink.handler = &handler.IMFMediaTypeHandler_iface; - stream_sink.media_sink = &media_sink.IMFMediaSink_iface; + handler = create_test_handler(); + media_sink = create_test_media_sink(&handler->IMFMediaTypeHandler_iface);
hr = MFStartup(MF_VERSION, MFSTARTUP_FULL); ok(hr == S_OK, "Startup failure, hr %#lx.\n", hr); @@ -2411,13 +2522,13 @@ static void test_media_session_events(void)
hr = MFCreateTopologyNode(MF_TOPOLOGY_OUTPUT_NODE, &sink_node); ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); - init_sink_node(&stream_sink.IMFStreamSink_iface, -1, sink_node); + init_sink_node(media_sink->stream, -1, sink_node);
hr = MFCreateMediaType(&output_type); ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); init_media_type(output_type, audio_pcm_48000, -1); - handler.media_types_count = 1; - handler.media_types = &output_type; + handler->media_types_count = 1; + handler->media_types = &output_type;
hr = MFCreateTopologyNode(MF_TOPOLOGY_SOURCESTREAM_NODE, &src_node); ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); @@ -2449,15 +2560,13 @@ static void test_media_session_events(void)
hr = IMFMediaSession_Shutdown(session); ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); - ok(!media_sink.shutdown, "media sink is shutdown.\n"); - media_sink.shutdown = FALSE; + ok(!media_sink->shutdown, "media sink is shutdown.\n"); + reset_test_media_sink(media_sink);
/* sometimes briefly leaking */ IMFMediaSession_Release(session);
- if (handler.current_type) - IMFMediaType_Release(handler.current_type); - handler.current_type = NULL; + test_handler_clear_current_type(handler);
/* SetTopology without a current output type */ @@ -2475,9 +2584,9 @@ static void test_media_session_events(void) ok(propvar.punkVal == (IUnknown *)topology, "got punkVal %p\n", propvar.punkVal); PropVariantClear(&propvar);
- ok(!handler.enum_count, "got %lu GetMediaTypeByIndex\n", handler.enum_count); - ok(!handler.set_current_count, "got %lu SetCurrentMediaType\n", handler.set_current_count); - handler.enum_count = handler.set_current_count = 0; + ok(!handler->enum_count, "got %lu GetMediaTypeByIndex\n", handler->enum_count); + ok(!handler->set_current_count, "got %lu SetCurrentMediaType\n", handler->set_current_count); + handler->enum_count = handler->set_current_count = 0;
hr = IMFMediaSession_ClearTopologies(session); ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); @@ -2487,15 +2596,13 @@ static void test_media_session_events(void)
hr = IMFMediaSession_Shutdown(session); ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); - ok(media_sink.shutdown, "media sink didn't shutdown.\n"); - media_sink.shutdown = FALSE; + ok(media_sink->shutdown, "media sink didn't shutdown.\n"); + reset_test_media_sink(media_sink);
/* sometimes briefly leaking */ IMFMediaSession_Release(session);
- if (handler.current_type) - IMFMediaType_Release(handler.current_type); - handler.current_type = NULL; + test_handler_clear_current_type(handler);
/* SetTopology without a current output type */ @@ -2517,9 +2624,9 @@ static void test_media_session_events(void) PropVariantClear(&propvar);
todo_wine - ok(!handler.enum_count, "got %lu GetMediaTypeByIndex\n", handler.enum_count); - ok(handler.set_current_count, "got %lu SetCurrentMediaType\n", handler.set_current_count); - handler.enum_count = handler.set_current_count = 0; + ok(!handler->enum_count, "got %lu GetMediaTypeByIndex\n", handler->enum_count); + ok(handler->set_current_count, "got %lu SetCurrentMediaType\n", handler->set_current_count); + handler->enum_count = handler->set_current_count = 0;
hr = IMFMediaSession_ClearTopologies(session); ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); @@ -2529,20 +2636,18 @@ static void test_media_session_events(void)
hr = IMFMediaSession_Shutdown(session); ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); - ok(media_sink.shutdown, "media sink didn't shutdown.\n"); - media_sink.shutdown = FALSE; + ok(media_sink->shutdown, "media sink didn't shutdown.\n"); + reset_test_media_sink(media_sink);
/* sometimes briefly leaking */ IMFMediaSession_Release(session);
- if (handler.current_type) - IMFMediaType_Release(handler.current_type); - handler.current_type = NULL; + test_handler_clear_current_type(handler);
/* SetTopology without a current output type, refusing input type */
- handler.invalid_type = input_type; + handler->invalid_type = input_type;
hr = MFCreateMediaSession(NULL, &session); ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); @@ -2555,9 +2660,9 @@ static void test_media_session_events(void) ok(propvar.punkVal != (IUnknown *)topology, "got punkVal %p\n", propvar.punkVal); PropVariantClear(&propvar);
- ok(handler.enum_count, "got %lu GetMediaTypeByIndex\n", handler.enum_count); - ok(handler.set_current_count, "got %lu SetCurrentMediaType\n", handler.set_current_count); - handler.enum_count = handler.set_current_count = 0; + ok(handler->enum_count, "got %lu GetMediaTypeByIndex\n", handler->enum_count); + ok(handler->set_current_count, "got %lu SetCurrentMediaType\n", handler->set_current_count); + handler->enum_count = handler->set_current_count = 0;
hr = IMFMediaSession_ClearTopologies(session); ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); @@ -2567,21 +2672,19 @@ static void test_media_session_events(void)
hr = IMFMediaSession_Shutdown(session); ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); - ok(media_sink.shutdown, "media sink didn't shutdown.\n"); - media_sink.shutdown = FALSE; + ok(media_sink->shutdown, "media sink didn't shutdown.\n"); + reset_test_media_sink(media_sink);
/* sometimes briefly leaking */ IMFMediaSession_Release(session);
- if (handler.current_type) - IMFMediaType_Release(handler.current_type); - handler.current_type = NULL; + test_handler_clear_current_type(handler);
/* SetTopology without a current output type, refusing input type, requiring a converter */
- handler.media_types_count = 0; - handler.invalid_type = input_type; + handler->media_types_count = 0; + handler->invalid_type = input_type;
hr = MFCreateMediaSession(NULL, &session); ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); @@ -2594,9 +2697,9 @@ static void test_media_session_events(void) ok(propvar.punkVal != (IUnknown *)topology, "got punkVal %p\n", propvar.punkVal); PropVariantClear(&propvar);
- ok(!handler.enum_count, "got %lu GetMediaTypeByIndex\n", handler.enum_count); - ok(handler.set_current_count, "got %lu SetCurrentMediaType\n", handler.set_current_count); - handler.enum_count = handler.set_current_count = 0; + ok(!handler->enum_count, "got %lu GetMediaTypeByIndex\n", handler->enum_count); + ok(handler->set_current_count, "got %lu SetCurrentMediaType\n", handler->set_current_count); + handler->enum_count = handler->set_current_count = 0;
hr = IMFMediaSession_ClearTopologies(session); ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); @@ -2606,21 +2709,19 @@ static void test_media_session_events(void)
hr = IMFMediaSession_Shutdown(session); ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); - ok(media_sink.shutdown, "media sink didn't shutdown.\n"); - media_sink.shutdown = FALSE; + ok(media_sink->shutdown, "media sink didn't shutdown.\n"); + reset_test_media_sink(media_sink);
/* sometimes briefly leaking */ IMFMediaSession_Release(session);
- if (handler.current_type) - IMFMediaType_Release(handler.current_type); - handler.current_type = NULL; + test_handler_clear_current_type(handler);
/* SetTopology with a current output type */
- handler.media_types_count = 1; - IMFMediaType_AddRef((handler.current_type = output_type)); + handler->media_types_count = 1; + IMFMediaType_AddRef((handler->current_type = output_type));
hr = MFCreateMediaSession(NULL, &session); ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); @@ -2633,9 +2734,9 @@ static void test_media_session_events(void) ok(propvar.punkVal != (IUnknown *)topology, "got punkVal %p\n", propvar.punkVal); PropVariantClear(&propvar);
- ok(!handler.enum_count, "got %lu GetMediaTypeByIndex\n", handler.enum_count); - ok(handler.set_current_count, "got %lu SetCurrentMediaType\n", handler.set_current_count); - handler.enum_count = handler.set_current_count = 0; + ok(!handler->enum_count, "got %lu GetMediaTypeByIndex\n", handler->enum_count); + ok(handler->set_current_count, "got %lu SetCurrentMediaType\n", handler->set_current_count); + handler->enum_count = handler->set_current_count = 0;
hr = IMFMediaSession_ClearTopologies(session); ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); @@ -2645,8 +2746,8 @@ static void test_media_session_events(void)
hr = IMFMediaSession_Shutdown(session); ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); - ok(media_sink.shutdown, "media sink didn't shutdown.\n"); - media_sink.shutdown = FALSE; + ok(media_sink->shutdown, "media sink didn't shutdown.\n"); + reset_test_media_sink(media_sink);
/* sometimes briefly leaking */ IMFMediaSession_Release(session); @@ -2689,8 +2790,8 @@ static void test_media_session_events(void)
hr = IMFMediaSession_Shutdown(session); ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); - ok(media_sink.shutdown, "media sink didn't shutdown.\n"); - media_sink.shutdown = FALSE; + ok(media_sink->shutdown, "media sink didn't shutdown.\n"); + reset_test_media_sink(media_sink);
source_impl->begin_get_event_res = E_NOTIMPL;
@@ -2738,8 +2839,7 @@ static void test_media_session_events(void)
hr = IMFMediaSession_Shutdown(session); ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); - ok(media_sink.shutdown, "media sink didn't shutdown.\n"); - media_sink.shutdown = FALSE; + ok(media_sink->shutdown, "media sink didn't shutdown.\n");
source_impl->begin_get_event_res = E_NOTIMPL;
@@ -2748,15 +2848,14 @@ static void test_media_session_events(void) CLEAR_CALLED(test_stub_source_Start);
skip_invalid: + IMFMediaTypeHandler_Release(&handler->IMFMediaTypeHandler_iface); + IMFMediaSink_Release(&media_sink->IMFMediaSink_iface); + /* sometimes briefly leaking */ IMFMediaSession_Release(session);
IMFAsyncCallback_Release(callback);
- if (handler.current_type) - IMFMediaType_Release(handler.current_type); - handler.current_type = NULL; - hr = IMFTopology_Clear(topology); ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); ref = IMFTopologyNode_Release(src_node); @@ -6015,7 +6114,7 @@ static void test_MFGetTopoNodeCurrentType(void) }; IMFMediaType *media_type, *input_types[2], *output_types[2]; IMFStreamDescriptor *input_descriptor, *output_descriptor; - struct test_stream_sink stream_sink = test_stream_sink; + struct test_stream_sink *stream_sink; IMFMediaTypeHandler *input_handler, *output_handler; IMFTransform *transform; IMFTopologyNode *node; @@ -6170,8 +6269,8 @@ static void test_MFGetTopoNodeCurrentType(void) hr = pMFGetTopoNodeCurrentType(node, 0, TRUE, &media_type); ok(hr == MF_E_INVALIDSTREAMNUMBER, "Unexpected hr %#lx.\n", hr);
- stream_sink.handler = output_handler; - hr = IMFTopologyNode_SetObject(node, (IUnknown *)&stream_sink.IMFStreamSink_iface); + stream_sink = create_test_stream_sink(NULL, output_handler, FALSE); + hr = IMFTopologyNode_SetObject(node, (IUnknown *)&stream_sink->IMFStreamSink_iface); ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); hr = pMFGetTopoNodeCurrentType(node, 0, FALSE, &media_type); ok(hr == MF_E_NOT_INITIALIZED, "Unexpected hr %#lx.\n", hr); @@ -6185,6 +6284,7 @@ static void test_MFGetTopoNodeCurrentType(void)
ref = IMFTopologyNode_Release(node); ok(ref == 0, "Release returned %ld\n", ref); + IMFStreamSink_Release(&stream_sink->IMFStreamSink_iface);
/* Transform node. */ @@ -8060,13 +8160,12 @@ static void test_media_session_seek(void) static const struct object_state_record expected_seek_start_pending_request_records = {{SOURCE_STOP, MFT_FLUSH, SOURCE_START, MFT_PROCESS_OUTPUT, SOURCE_REQUEST_SAMPLE, SINK_FLUSH, SINK_ON_CLOCK_START}, 7};
IMFClockStateSink test_seek_clock_sink = {&test_seek_clock_sink_vtbl}; - struct test_stream_sink stream_sink = test_stream_sink; - struct test_media_sink media_sink = test_media_sink; MFT_OUTPUT_STREAM_INFO output_stream_info = {0}; - struct test_handler handler = test_handler; IMFPresentationClock *presentation_clock; struct test_callback *test_callback; + struct test_media_sink *media_sink; struct test_source *media_source; + struct test_handler *handler; IMFAsyncCallback *callback; IMFMediaSession *session; IMFMediaSource *source; @@ -8079,10 +8178,9 @@ static void test_media_session_seek(void) HRESULT hr; INT i;
- stream_sink.handler = &handler.IMFMediaTypeHandler_iface; - stream_sink.media_sink = &media_sink.IMFMediaSink_iface; - media_sink.stream = &stream_sink.IMFStreamSink_iface; - MFCreateEventQueue(&stream_sink.event_queue); + handler = create_test_handler(); + media_sink = create_test_media_sink(&handler->IMFMediaTypeHandler_iface); + IMFMediaTypeHandler_Release(&handler->IMFMediaTypeHandler_iface);
hr = MFStartup(MF_VERSION, MFSTARTUP_FULL); ok(hr == S_OK, "Failed to start up, hr %#lx.\n", hr); @@ -8110,7 +8208,7 @@ static void test_media_session_seek(void) IMFMediaType_Release(type);
SET_EXPECT(test_transform_ProcessMessage_BEGIN_STREAMING); - topology = create_test_topology_unk(source, (IUnknown*)&stream_sink.IMFStreamSink_iface, (IUnknown*) mft, NULL); + topology = create_test_topology_unk(source, (IUnknown*)media_sink->stream, (IUnknown*) mft, NULL); hr = IMFMediaSession_SetTopology(session, 0, topology); ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); IMFTopology_Release(topology); @@ -8149,7 +8247,7 @@ static void test_media_session_seek(void) ok(status == MF_TOPOSTATUS_STARTED_SOURCE, "Unexpected status %d.\n", status); PropVariantClear(&propvar);
- hr = IMFStreamSink_QueueEvent(&stream_sink.IMFStreamSink_iface, MEStreamSinkStarted, &GUID_NULL, S_OK, &propvar); + hr = IMFStreamSink_QueueEvent(media_sink->stream, MEStreamSinkStarted, &GUID_NULL, S_OK, &propvar); ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
hr = wait_media_event(session, callback, MESessionStarted, 1000, &propvar); @@ -8172,7 +8270,7 @@ static void test_media_session_seek(void) SET_EXPECT(test_transform_ProcessOutput); SET_EXPECT(test_transform_ProcessInput); SET_EXPECT(test_stream_sink_ProcessSample); - IMFStreamSink_QueueEvent(&stream_sink.IMFStreamSink_iface, MEStreamSinkRequestSample, &GUID_NULL, S_OK, &propvar); + IMFStreamSink_QueueEvent(media_sink->stream, MEStreamSinkRequestSample, &GUID_NULL, S_OK, &propvar);
Sleep(20);
@@ -8204,7 +8302,7 @@ static void test_media_session_seek(void)
Sleep(20);
- hr = IMFStreamSink_QueueEvent(&stream_sink.IMFStreamSink_iface, MEStreamSinkPaused, &GUID_NULL, S_OK, &propvar); + hr = IMFStreamSink_QueueEvent(media_sink->stream, MEStreamSinkPaused, &GUID_NULL, S_OK, &propvar); ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
hr = wait_media_event(session, callback, MESessionPaused, 1000, &propvar); @@ -8225,7 +8323,7 @@ static void test_media_session_seek(void)
Sleep(20);
- hr = IMFStreamSink_QueueEvent(&stream_sink.IMFStreamSink_iface, MEStreamSinkStarted, &GUID_NULL, S_OK, &propvar); + hr = IMFStreamSink_QueueEvent(media_sink->stream, MEStreamSinkStarted, &GUID_NULL, S_OK, &propvar); ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
hr = wait_media_event(session, callback, MESessionStarted, 1000, &propvar); @@ -8248,7 +8346,7 @@ static void test_media_session_seek(void) memset(&actual_object_state_record, 0, sizeof(actual_object_state_record)); SET_EXPECT(test_media_stream_RequestSample); SET_EXPECT(test_transform_ProcessOutput); - IMFStreamSink_QueueEvent(&stream_sink.IMFStreamSink_iface, MEStreamSinkRequestSample, &GUID_NULL, S_OK, &propvar); + IMFStreamSink_QueueEvent(media_sink->stream, MEStreamSinkRequestSample, &GUID_NULL, S_OK, &propvar);
Sleep(20);
@@ -8263,7 +8361,7 @@ static void test_media_session_seek(void)
Sleep(20);
- hr = IMFStreamSink_QueueEvent(&stream_sink.IMFStreamSink_iface, MEStreamSinkPaused, &GUID_NULL, S_OK, &propvar); + hr = IMFStreamSink_QueueEvent(media_sink->stream, MEStreamSinkPaused, &GUID_NULL, S_OK, &propvar); ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
hr = wait_media_event(session, callback, MESessionPaused, 1000, &propvar); @@ -8286,7 +8384,7 @@ static void test_media_session_seek(void)
Sleep(20);
- hr = IMFStreamSink_QueueEvent(&stream_sink.IMFStreamSink_iface, MEStreamSinkStarted, &GUID_NULL, S_OK, &propvar); + hr = IMFStreamSink_QueueEvent(media_sink->stream, MEStreamSinkStarted, &GUID_NULL, S_OK, &propvar); ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
hr = wait_media_event(session, callback, MESessionStarted, 1000, &propvar); @@ -8311,15 +8409,14 @@ static void test_media_session_seek(void)
hr = IMFMediaSession_Shutdown(session); ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); - ok(media_sink.shutdown, "Media sink didn't shutdown.\n"); + ok(media_sink->shutdown, "Media sink didn't shutdown.\n");
hr = IMFMediaSource_Shutdown(source); ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
IMFMediaSession_Release(session); IMFMediaSource_Release(source); - IMFMediaEventQueue_Release(stream_sink.event_queue); - if (media_sink.clock) IMFPresentationClock_Release(media_sink.clock); + IMFMediaSink_Release(&media_sink->IMFMediaSink_iface);
hr = MFShutdown(); ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);