Goes atop !9294
-- v2: mf/session: Shut down all topologies on session shutdown. mf/session: Ensure the session object is shut down on release. mf/tests: Add tests for sample grabber sink shutdown.
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);
From: Conor McCarthy cmccarthy@codeweavers.com
--- dlls/mf/tests/mf.c | 38 +++++++++++++++++++++++++------------- 1 file changed, 25 insertions(+), 13 deletions(-)
diff --git a/dlls/mf/tests/mf.c b/dlls/mf/tests/mf.c index 464e95cfc45..a0600dd4b04 100644 --- a/dlls/mf/tests/mf.c +++ b/dlls/mf/tests/mf.c @@ -3247,6 +3247,27 @@ static IMFSampleGrabberSinkCallback *create_test_grabber_callback(void) return &grabber->IMFSampleGrabberSinkCallback_iface; }
+static struct test_grabber_callback *create_activated_test_grabber_callback(IMFMediaType *output_type, + IMFStreamSink **stream_sink) +{ + struct test_grabber_callback *grabber_callback; + IMFActivate *sink_activate; + IMFMediaSink *sink; + HRESULT hr; + + grabber_callback = impl_from_IMFSampleGrabberSinkCallback(create_test_grabber_callback()); + hr = MFCreateSampleGrabberSinkActivate(output_type, &grabber_callback->IMFSampleGrabberSinkCallback_iface, &sink_activate); + ok(hr == S_OK, "Failed to create grabber sink, hr %#lx.\n", hr); + hr = IMFActivate_ActivateObject(sink_activate, &IID_IMFMediaSink, (void **)&sink); + ok(hr == S_OK, "Failed to activate, hr %#lx.\n", hr); + IMFActivate_Release(sink_activate); + hr = IMFMediaSink_GetStreamSinkByIndex(sink, 0, stream_sink); + ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); + IMFMediaSink_Release(sink); + + return grabber_callback; +} + static HRESULT WINAPI testshutdown_QueryInterface(IMFShutdown *iface, REFIID riid, void **obj) { if (IsEqualIID(riid, &IID_IMFShutdown) || @@ -6828,13 +6849,11 @@ static void test_h264_output_alignment(void) IMFTopology *topology, *resolved_topology; struct test_callback *test_callback; IMFMediaTypeHandler *handler; - IMFActivate *sink_activate; IMFTopoLoader *topo_loader; IMFStreamSink *stream_sink; IMFAsyncCallback *callback; IMFMediaType *output_type; IMFMediaSession *session; - IMFMediaSink *media_sink; IMFTransform *transform; IMFMediaSource *source; PROPVARIANT propvar; @@ -6854,21 +6873,15 @@ static void test_h264_output_alignment(void) return; }
- 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); init_media_type(output_type, video_nv12_desc, -1); - hr = MFCreateSampleGrabberSinkActivate(output_type, &grabber_callback->IMFSampleGrabberSinkCallback_iface, &sink_activate); - ok(hr == S_OK, "Failed to create grabber sink, hr %#lx.\n", hr); + + grabber_callback = create_activated_test_grabber_callback(output_type, &stream_sink); IMFMediaType_Release(output_type); + grabber_callback->ready_event = CreateEventW(NULL, FALSE, FALSE, NULL); + ok(!!grabber_callback->ready_event, "CreateEventW failed, error %lu\n", GetLastError());
- IMFActivate_ActivateObject(sink_activate, &IID_IMFMediaSink, (void **)&media_sink); - hr = IMFMediaSink_GetStreamSinkByIndex(media_sink, 0, &stream_sink); - ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); - IMFActivate_Release(sink_activate); topology = create_test_topology_unk(source, (IUnknown *)stream_sink, NULL, NULL); hr = MFCreateTopoLoader(&topo_loader); ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); @@ -6941,7 +6954,6 @@ static void test_h264_output_alignment(void) IMFAsyncCallback_Release(callback); IMFMediaSession_Release(session); IMFStreamSink_Release(stream_sink); - IMFMediaSink_Release(media_sink); IMFSampleGrabberSinkCallback_Release(&grabber_callback->IMFSampleGrabberSinkCallback_iface); IMFMediaSource_Release(source);
From: Conor McCarthy cmccarthy@codeweavers.com
--- dlls/mf/tests/mf.c | 17 +++++++++++++++++ 1 file changed, 17 insertions(+)
diff --git a/dlls/mf/tests/mf.c b/dlls/mf/tests/mf.c index a0600dd4b04..f2dc8bfd91e 100644 --- a/dlls/mf/tests/mf.c +++ b/dlls/mf/tests/mf.c @@ -3099,6 +3099,8 @@ struct test_grabber_callback IMFCollection *samples; HANDLE ready_event; HANDLE done_event; + + BOOL shutdown; };
static struct test_grabber_callback *impl_from_IMFSampleGrabberSinkCallback(IMFSampleGrabberSinkCallback *iface) @@ -3213,6 +3215,8 @@ static HRESULT WINAPI test_grabber_callback_OnProcessSample(IMFSampleGrabberSink
static HRESULT WINAPI test_grabber_callback_OnShutdown(IMFSampleGrabberSinkCallback *iface) { + struct test_grabber_callback *grabber = impl_from_IMFSampleGrabberSinkCallback(iface); + grabber->shutdown = TRUE; return S_OK; }
@@ -4481,6 +4485,8 @@ static void test_sample_grabber_orientation(GUID subtype)
hr = IMFMediaSession_Shutdown(session); ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); + todo_wine + ok(grabber_callback->shutdown, "Media sink is not shut down.\n"); hr = IMFMediaSource_Shutdown(source); ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); hr = IMFActivate_ShutdownObject(sink_activate); @@ -7102,12 +7108,15 @@ static void test_media_session_Start(void) ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); hr = wait_media_event(session, callback, MESessionClosed, 1000, &propvar); ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); + ok(!grabber_callback->shutdown, "Media sink was shut down.\n");
/* Media session is shut down */ hr = IMFMediaSource_Shutdown(source); ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); hr = IMFMediaSession_Shutdown(session); ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); + todo_wine + ok(grabber_callback->shutdown, "Media sink is not shut down.\n");
propvar.vt = VT_I8; propvar.hVal.QuadPart = 10000000; @@ -7186,8 +7195,11 @@ static void test_media_session_Start(void) ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); hr = wait_media_event(session, callback, MESessionClosed, 1000, &propvar); ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); + ok(!grabber_callback->shutdown, "Media sink was shut down.\n"); hr = IMFMediaSession_Shutdown(session); ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); + todo_wine + ok(grabber_callback->shutdown, "Media sink is not shut down.\n"); hr = IMFMediaSource_Shutdown(source); ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
@@ -7399,6 +7411,7 @@ static void test_media_session_source_shutdown(void)
IMFMediaSource_Release(source);
+ ok(!grabber_callback->shutdown, "Media sink was shut down.\n"); IMFActivate_ShutdownObject(sink_activate); IMFActivate_Release(sink_activate); IMFSampleGrabberSinkCallback_Release(&grabber_callback->IMFSampleGrabberSinkCallback_iface); @@ -7632,6 +7645,8 @@ static void test_media_session_Close(void)
hr = IMFMediaSession_Shutdown(session); ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); + todo_wine + ok(grabber_callback->shutdown, "Media sink is not shut down.\n");
IMFPresentationClock_Release(presentation_clock); IMFAsyncCallback_Release(callback); @@ -7774,6 +7789,8 @@ static void test_media_session_thinning(void) ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); hr = IMFMediaSession_Shutdown(session); ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); + todo_wine + ok(grabber_callback->shutdown, "Media sink is not shut down.\n"); hr = IMFMediaSource_Shutdown(source); ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
From: Conor McCarthy cmccarthy@codeweavers.com
--- dlls/mf/tests/mf.c | 247 ++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 246 insertions(+), 1 deletion(-)
diff --git a/dlls/mf/tests/mf.c b/dlls/mf/tests/mf.c index f2dc8bfd91e..515a98f9aa6 100644 --- a/dlls/mf/tests/mf.c +++ b/dlls/mf/tests/mf.c @@ -4317,7 +4317,8 @@ static void test_sample_grabber_is_mediatype_supported(void) }
/* create a test topology with the specified source, sink, and option MFT. Return duration if required */ -static IMFTopology *create_test_topology_unk(IMFMediaSource *source, IUnknown *sink, IUnknown *mft, UINT64 *duration) +static IMFTopology *create_test_topology_unk_noshutdown(IMFMediaSource *source, IUnknown *sink, IUnknown *mft, + UINT64 *duration, UINT noshutdown_on_remove) { IMFTopologyNode *src_node, *sink_node, *mft_node; IMFPresentationDescriptor *pd; @@ -4369,6 +4370,11 @@ static IMFTopology *create_test_topology_unk(IMFMediaSource *source, IUnknown *s ok(hr == S_OK, "Failed to set object, hr %#lx.\n", hr); hr = IMFTopologyNode_SetUINT32(sink_node, &MF_TOPONODE_CONNECT_METHOD, MF_CONNECT_ALLOW_DECODER); ok(hr == S_OK, "Failed to set connect method, hr %#lx.\n", hr); + if (noshutdown_on_remove != UINT_MAX) + { + hr = IMFTopologyNode_SetUINT32(sink_node, &MF_TOPONODE_NOSHUTDOWN_ON_REMOVE, noshutdown_on_remove); + ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); + } hr = IMFTopology_SetUINT32(topology, &MF_TOPOLOGY_ENUMERATE_SOURCE_TYPES, TRUE); ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
@@ -4379,6 +4385,11 @@ static IMFTopology *create_test_topology_unk(IMFMediaSource *source, IUnknown *s return topology; }
+static IMFTopology *create_test_topology_unk(IMFMediaSource *source, IUnknown *sink, IUnknown *mft, UINT64 *duration) +{ + return create_test_topology_unk_noshutdown(source, (IUnknown*)sink, mft, duration, UINT_MAX); +} + static IMFTopology *create_test_topology(IMFMediaSource *source, IMFActivate *sink_activate, UINT64 *duration) { return create_test_topology_unk(source, (IUnknown*)sink_activate, NULL, duration); @@ -8451,6 +8462,239 @@ static void test_media_session_seek(void) ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); }
+static void test_media_session_sink_shutdown(void) +{ + media_type_desc video_rgb32_desc = + { + ATTR_GUID(MF_MT_MAJOR_TYPE, MFMediaType_Video), + ATTR_GUID(MF_MT_SUBTYPE, MFVideoFormat_RGB32), + }; + struct test_grabber_callback *grabber_callback, *grabber_callbacks[3]; + IMFAsyncCallback *callback; + IMFStreamSink *stream_sink; + IMFActivate *sink_activate; + IMFMediaType *output_type; + IMFMediaSession *session; + IMFMediaSource *source; + IMFTopology *topology; + PROPVARIANT propvar; + HRESULT hr; + LONG ref; + UINT i; + + hr = MFStartup(MF_VERSION, MFSTARTUP_FULL); + ok(hr == S_OK, "Failed to start up, hr %#lx.\n", hr); + + hr = MFCreateMediaType(&output_type); + ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); + init_media_type(output_type, video_rgb32_desc, -1); + + callback = create_test_callback(TRUE); + + /* Sinks are always shut down on session shutdown, but never before. + * MF_TOPONODE_NOSHUTDOWN_ON_REMOVE is ignored. */ + + for (i = 0; i < 4; ++i) + { + winetest_push_context("Test %u", i); + + if (!(source = create_media_source(L"test.mp4", L"video/mp4"))) + { + todo_wine /* Gitlab CI Debian runner */ + win_skip("MP4 media source is not supported, skipping tests.\n"); + goto done; + } + + hr = MFCreateMediaSession(NULL, &session); + ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); + + if (i & 2) + { + grabber_callback = impl_from_IMFSampleGrabberSinkCallback(create_test_grabber_callback()); + hr = MFCreateSampleGrabberSinkActivate(output_type, &grabber_callback->IMFSampleGrabberSinkCallback_iface, &sink_activate); + ok(hr == S_OK, "Failed to create grabber sink, hr %#lx.\n", hr); + topology = create_test_topology_unk_noshutdown(source, (IUnknown *)sink_activate, NULL, NULL, i & 1); + IMFActivate_Release(sink_activate); + } + else + { + grabber_callback = create_activated_test_grabber_callback(output_type, &stream_sink); + topology = create_test_topology_unk_noshutdown(source, (IUnknown *)stream_sink, NULL, NULL, i & 1); + IMFStreamSink_Release(stream_sink); + } + + hr = IMFMediaSession_SetTopology(session, 0, topology); + ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); + IMFTopology_Release(topology); + + propvar.vt = VT_EMPTY; + hr = IMFMediaSession_Start(session, &GUID_NULL, &propvar); + ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); + + hr = wait_media_event(session, callback, MESessionStarted, 5000, &propvar); + ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); + + hr = IMFMediaSession_Stop(session); + ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); + hr = wait_media_event_until_blocking(session, callback, MESessionStopped, 1000, &propvar); + ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); + + hr = IMFMediaSession_SetTopology(session, MFSESSION_SETTOPOLOGY_CLEAR_CURRENT, NULL); + ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); + hr = wait_media_event(session, callback, MESessionTopologySet, 1000, &propvar); + ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); + PropVariantClear(&propvar); + todo_wine_if(i == 1) + ok(!grabber_callback->shutdown, "Media sink was shut down.\n"); + + hr = IMFMediaSession_ClearTopologies(session); + ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); + hr = wait_media_event(session, callback, MESessionTopologiesCleared, 1000, &propvar); + ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); + todo_wine_if(i == 1) + ok(!grabber_callback->shutdown, "Media sink was shut down.\n"); + + hr = IMFMediaSession_Close(session); + ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); + hr = wait_media_event(session, callback, MESessionClosed, 1000, &propvar); + ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); + todo_wine_if(i == 1) + ok(!grabber_callback->shutdown, "Media sink was shut down.\n"); + + hr = IMFMediaSession_Shutdown(session); + ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); + todo_wine_if(i != 1) + ok(grabber_callback->shutdown, "Media sink is not shut down.\n"); + IMFSampleGrabberSinkCallback_Release(&grabber_callback->IMFSampleGrabberSinkCallback_iface); + + hr = IMFMediaSource_Shutdown(source); + ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); + + Sleep(20); + ref = IMFMediaSession_Release(session); + todo_wine_if(i != 1) + ok(!ref, "Unexpected refcount %ld.\n", ref); + ref = IMFMediaSource_Release(source); + ok(!ref, "Unexpected refcount %ld.\n", ref); + + winetest_pop_context(); + } + + if (!(source = create_media_source(L"test.mp4", L"video/mp4"))) + { + todo_wine /* Gitlab CI Debian runner */ + win_skip("MP4 media source is not supported, skipping tests.\n"); + goto done; + } + + /* Sinks in queued topologies are not shut down until session shutdown. */ + + hr = MFCreateMediaSession(NULL, &session); + ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); + + for (i = 0; i < 2; ++i) + { + grabber_callbacks[i] = create_activated_test_grabber_callback(output_type, &stream_sink); + topology = create_test_topology_unk_noshutdown(source, (IUnknown *)stream_sink, NULL, NULL, 0); + IMFStreamSink_Release(stream_sink); + + hr = IMFMediaSession_SetTopology(session, 0, topology); + ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); + IMFTopology_Release(topology); + } + + grabber_callbacks[2] = impl_from_IMFSampleGrabberSinkCallback(create_test_grabber_callback()); + hr = MFCreateSampleGrabberSinkActivate(output_type, &grabber_callbacks[2]->IMFSampleGrabberSinkCallback_iface, &sink_activate); + ok(hr == S_OK, "Failed to create grabber sink, hr %#lx.\n", hr); + topology = create_test_topology_unk_noshutdown(source, (IUnknown *)sink_activate, NULL, NULL, 0); + IMFActivate_Release(sink_activate); + + hr = IMFMediaSession_SetTopology(session, 0, topology); + ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); + IMFTopology_Release(topology); + + propvar.vt = VT_EMPTY; + hr = IMFMediaSession_Start(session, &GUID_NULL, &propvar); + ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); + + hr = wait_media_event(session, callback, MESessionStarted, 5000, &propvar); + ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); + + hr = IMFMediaSession_Close(session); + ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); + hr = wait_media_event(session, callback, MESessionClosed, 1000, &propvar); + ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); + for (i = 0; i < ARRAY_SIZE(grabber_callbacks); ++i) + ok(!grabber_callbacks[i]->shutdown, "Media sink %u was shut down.\n", i); + + hr = IMFMediaSession_Shutdown(session); + ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); + for (i = 0; i < ARRAY_SIZE(grabber_callbacks); ++i) + { + todo_wine_if(i) + ok(grabber_callbacks[i]->shutdown, "Media sink %u is not shut down.\n", i); + IMFSampleGrabberSinkCallback_Release(&grabber_callbacks[i]->IMFSampleGrabberSinkCallback_iface); + } + + hr = IMFMediaSource_Shutdown(source); + ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); + + Sleep(20); + ref = IMFMediaSession_Release(session); + ok(!ref, "Unexpected refcount %ld.\n", ref); + + ref = IMFMediaSource_Release(source); + ok(!ref, "Unexpected refcount %ld.\n", ref); + + /* Unexpected source shutdown does not shut down sinks. + * NOTE: Source re-use is broken in Wine, for more reasons than + * just errors from multiple event subscription. */ + + if (!(source = create_media_source(L"test.mp4", L"video/mp4"))) + { + todo_wine /* Gitlab CI Debian runner */ + win_skip("MP4 media source is not supported, skipping tests.\n"); + goto done; + } + + hr = MFCreateMediaSession(NULL, &session); + ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); + + grabber_callback = create_activated_test_grabber_callback(output_type, &stream_sink); + topology = create_test_topology_unk(source, (IUnknown *)stream_sink, NULL, NULL); + IMFStreamSink_Release(stream_sink); + + hr = IMFMediaSession_SetTopology(session, 0, topology); + ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); + IMFTopology_Release(topology); + + propvar.vt = VT_EMPTY; + hr = IMFMediaSession_Start(session, &GUID_NULL, &propvar); + ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); + + hr = wait_media_event(session, callback, MESessionStarted, 5000, &propvar); + ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); + + hr = IMFMediaSource_Shutdown(source); + ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); + ok(!grabber_callback->shutdown, "Media sink was shut down.\n"); + + hr = IMFMediaSession_Shutdown(session); + ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); + ok(grabber_callback->shutdown, "Media sink is not shut down.\n"); + IMFSampleGrabberSinkCallback_Release(&grabber_callback->IMFSampleGrabberSinkCallback_iface); + + IMFMediaSession_Release(session); + IMFMediaSource_Release(source); + +done: + IMFAsyncCallback_Release(callback); + IMFMediaType_Release(output_type); + + hr = MFShutdown(); + ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); +} + START_TEST(mf) { init_functions(); @@ -8490,4 +8734,5 @@ START_TEST(mf) test_media_session_source_shutdown(); test_media_session_thinning(); test_media_session_seek(); + test_media_session_sink_shutdown(); }
From: Conor McCarthy cmccarthy@codeweavers.com
--- dlls/mf/session.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-)
diff --git a/dlls/mf/session.c b/dlls/mf/session.c index abc77d9f143..062f415364e 100644 --- a/dlls/mf/session.c +++ b/dlls/mf/session.c @@ -2198,8 +2198,8 @@ static ULONG WINAPI mfsession_Release(IMFMediaSession *iface)
if (!refcount) { - session_clear_queued_topologies(session); - session_clear_presentation(session); + if (SUCCEEDED(session_is_shut_down(session))) + IMFMediaSession_Shutdown(iface); session_clear_command_list(session); if (session->presentation.current_topology) IMFTopology_Release(session->presentation.current_topology); @@ -2477,8 +2477,6 @@ static HRESULT WINAPI mfsession_Shutdown(IMFMediaSession *iface) if (session->quality_manager) IMFQualityManager_Shutdown(session->quality_manager); MFShutdownObject((IUnknown *)session->clock); - IMFPresentationClock_Release(session->clock); - session->clock = NULL; session_clear_presentation(session); session_clear_queued_topologies(session); session_submit_simple_command(session, SESSION_CMD_SHUTDOWN);
From: Conor McCarthy cmccarthy@codeweavers.com
--- dlls/mf/session.c | 58 +++++++++++++++++++++++++--------------------- dlls/mf/tests/mf.c | 11 --------- 2 files changed, 31 insertions(+), 38 deletions(-)
diff --git a/dlls/mf/session.c b/dlls/mf/session.c index 062f415364e..109ce6ccfbe 100644 --- a/dlls/mf/session.c +++ b/dlls/mf/session.c @@ -277,6 +277,7 @@ struct media_session BOOL thin_committed; } presentation; struct list topologies; + struct list removed_topologies; struct list commands; enum session_state state; enum command_state command_state; @@ -522,8 +523,7 @@ static void session_clear_queued_topologies(struct media_session *session) LIST_FOR_EACH_ENTRY_SAFE(ptr, next, &session->topologies, struct queued_topology, entry) { list_remove(&ptr->entry); - IMFTopology_Release(ptr->topology); - free(ptr); + list_add_tail(&session->removed_topologies, &ptr->entry); } }
@@ -819,21 +819,16 @@ static void release_topo_node(struct topo_node *node) free(node); }
-static void session_shutdown_current_topology(struct media_session *session) +static void topology_shutdown(IMFTopology *topology) { - unsigned int shutdown, force_shutdown; MF_TOPOLOGY_TYPE node_type; IMFStreamSink *stream_sink; - IMFTopology *topology; IMFTopologyNode *node; IMFActivate *activate; IMFMediaSink *sink; WORD idx = 0; HRESULT hr;
- topology = session->presentation.current_topology; - force_shutdown = session->state == SESSION_STATE_SHUT_DOWN; - /* FIXME: should handle async MFTs, but these are not supported by the rest of the pipeline currently. */
while (SUCCEEDED(IMFTopology_GetNode(topology, idx++, &node))) @@ -841,28 +836,24 @@ static void session_shutdown_current_topology(struct media_session *session) if (SUCCEEDED(IMFTopologyNode_GetNodeType(node, &node_type)) && node_type == MF_TOPOLOGY_OUTPUT_NODE) { - shutdown = 1; - IMFTopologyNode_GetUINT32(node, &MF_TOPONODE_NOSHUTDOWN_ON_REMOVE, &shutdown); + /* MF_TOPONODE_NOSHUTDOWN_ON_REMOVE is ignored, at least for sinks. */
- if (force_shutdown || shutdown) + if (SUCCEEDED(IMFTopologyNode_GetUnknown(node, &_MF_TOPONODE_IMFActivate, &IID_IMFActivate, + (void **)&activate))) { - if (SUCCEEDED(IMFTopologyNode_GetUnknown(node, &_MF_TOPONODE_IMFActivate, &IID_IMFActivate, - (void **)&activate))) + if (FAILED(hr = IMFActivate_ShutdownObject(activate))) + WARN("Failed to shut down activation object for the sink, hr %#lx.\n", hr); + IMFActivate_Release(activate); + } + if (SUCCEEDED(topology_node_get_object(node, &IID_IMFStreamSink, (void **)&stream_sink))) + { + if (SUCCEEDED(IMFStreamSink_GetMediaSink(stream_sink, &sink))) { - if (FAILED(hr = IMFActivate_ShutdownObject(activate))) - WARN("Failed to shut down activation object for the sink, hr %#lx.\n", hr); - IMFActivate_Release(activate); + IMFMediaSink_Shutdown(sink); + IMFMediaSink_Release(sink); } - else if (SUCCEEDED(topology_node_get_object(node, &IID_IMFStreamSink, (void **)&stream_sink))) - { - if (SUCCEEDED(IMFStreamSink_GetMediaSink(stream_sink, &sink))) - { - IMFMediaSink_Shutdown(sink); - IMFMediaSink_Release(sink); - }
- IMFStreamSink_Release(stream_sink); - } + IMFStreamSink_Release(stream_sink); } }
@@ -870,6 +861,19 @@ static void session_shutdown_current_topology(struct media_session *session) } }
+static void session_clear_removed_topologies(struct media_session *session) +{ + struct queued_topology *ptr, *next; + + LIST_FOR_EACH_ENTRY_SAFE(ptr, next, &session->removed_topologies, struct queued_topology, entry) + { + list_remove(&ptr->entry); + topology_shutdown(ptr->topology); + IMFTopology_Release(ptr->topology); + free(ptr); + } +} + static void session_clear_command_list(struct media_session *session) { struct session_op *op, *op2; @@ -891,8 +895,6 @@ static void session_clear_presentation(struct media_session *session) struct media_sink *sink, *sink2; struct topo_node *node, *node2;
- session_shutdown_current_topology(session); - IMFTopology_Clear(session->presentation.current_topology); session->presentation.topo_status = MF_TOPOSTATUS_INVALID; session->presentation.flags = 0; @@ -2479,6 +2481,7 @@ static HRESULT WINAPI mfsession_Shutdown(IMFMediaSession *iface) MFShutdownObject((IUnknown *)session->clock); session_clear_presentation(session); session_clear_queued_topologies(session); + session_clear_removed_topologies(session); session_submit_simple_command(session, SESSION_CMD_SHUTDOWN); } LeaveCriticalSection(&session->cs); @@ -4850,6 +4853,7 @@ HRESULT WINAPI MFCreateMediaSession(IMFAttributes *config, IMFMediaSession **ses object->sink_finalizer_callback.lpVtbl = &session_sink_finalizer_callback_vtbl; object->refcount = 1; list_init(&object->topologies); + list_init(&object->removed_topologies); list_init(&object->commands); list_init(&object->presentation.sources); list_init(&object->presentation.sinks); diff --git a/dlls/mf/tests/mf.c b/dlls/mf/tests/mf.c index 515a98f9aa6..61535cbdec9 100644 --- a/dlls/mf/tests/mf.c +++ b/dlls/mf/tests/mf.c @@ -4496,7 +4496,6 @@ static void test_sample_grabber_orientation(GUID subtype)
hr = IMFMediaSession_Shutdown(session); ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); - todo_wine ok(grabber_callback->shutdown, "Media sink is not shut down.\n"); hr = IMFMediaSource_Shutdown(source); ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); @@ -7126,7 +7125,6 @@ static void test_media_session_Start(void) ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); hr = IMFMediaSession_Shutdown(session); ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); - todo_wine ok(grabber_callback->shutdown, "Media sink is not shut down.\n");
propvar.vt = VT_I8; @@ -7209,7 +7207,6 @@ static void test_media_session_Start(void) ok(!grabber_callback->shutdown, "Media sink was shut down.\n"); hr = IMFMediaSession_Shutdown(session); ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); - todo_wine ok(grabber_callback->shutdown, "Media sink is not shut down.\n"); hr = IMFMediaSource_Shutdown(source); ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); @@ -7656,7 +7653,6 @@ static void test_media_session_Close(void)
hr = IMFMediaSession_Shutdown(session); ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); - todo_wine ok(grabber_callback->shutdown, "Media sink is not shut down.\n");
IMFPresentationClock_Release(presentation_clock); @@ -7800,7 +7796,6 @@ static void test_media_session_thinning(void) ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); hr = IMFMediaSession_Shutdown(session); ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); - todo_wine ok(grabber_callback->shutdown, "Media sink is not shut down.\n"); hr = IMFMediaSource_Shutdown(source); ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); @@ -8544,26 +8539,22 @@ static void test_media_session_sink_shutdown(void) hr = wait_media_event(session, callback, MESessionTopologySet, 1000, &propvar); ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); PropVariantClear(&propvar); - todo_wine_if(i == 1) ok(!grabber_callback->shutdown, "Media sink was shut down.\n");
hr = IMFMediaSession_ClearTopologies(session); ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); hr = wait_media_event(session, callback, MESessionTopologiesCleared, 1000, &propvar); ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); - todo_wine_if(i == 1) ok(!grabber_callback->shutdown, "Media sink was shut down.\n");
hr = IMFMediaSession_Close(session); ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); hr = wait_media_event(session, callback, MESessionClosed, 1000, &propvar); ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); - todo_wine_if(i == 1) ok(!grabber_callback->shutdown, "Media sink was shut down.\n");
hr = IMFMediaSession_Shutdown(session); ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); - todo_wine_if(i != 1) ok(grabber_callback->shutdown, "Media sink is not shut down.\n"); IMFSampleGrabberSinkCallback_Release(&grabber_callback->IMFSampleGrabberSinkCallback_iface);
@@ -8572,7 +8563,6 @@ static void test_media_session_sink_shutdown(void)
Sleep(20); ref = IMFMediaSession_Release(session); - todo_wine_if(i != 1) ok(!ref, "Unexpected refcount %ld.\n", ref); ref = IMFMediaSource_Release(source); ok(!ref, "Unexpected refcount %ld.\n", ref); @@ -8631,7 +8621,6 @@ static void test_media_session_sink_shutdown(void) ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); for (i = 0; i < ARRAY_SIZE(grabber_callbacks); ++i) { - todo_wine_if(i) ok(grabber_callbacks[i]->shutdown, "Media sink %u is not shut down.\n", i); IMFSampleGrabberSinkCallback_Release(&grabber_callbacks[i]->IMFSampleGrabberSinkCallback_iface); }