Signed-off-by: Nikolay Sivov nsivov@codeweavers.com --- dlls/mf/samplegrabber.c | 6 +++--- dlls/mf/tests/mf.c | 20 +++++++++++++++++++- 2 files changed, 22 insertions(+), 4 deletions(-)
diff --git a/dlls/mf/samplegrabber.c b/dlls/mf/samplegrabber.c index f44df9f32b..f4dbe4f283 100644 --- a/dlls/mf/samplegrabber.c +++ b/dlls/mf/samplegrabber.c @@ -849,10 +849,7 @@ static ULONG WINAPI sample_grabber_sink_Release(IMFMediaSink *iface) IMFSampleGrabberSinkCallback2_Release(grabber->callback2); IMFMediaType_Release(grabber->media_type); if (grabber->event_queue) - { - IMFMediaEventQueue_Shutdown(grabber->event_queue); IMFMediaEventQueue_Release(grabber->event_queue); - } if (grabber->clock) IMFPresentationClock_Release(grabber->clock); if (grabber->timer) @@ -1045,12 +1042,15 @@ static HRESULT WINAPI sample_grabber_sink_Shutdown(IMFMediaSink *iface) grabber->is_shut_down = TRUE; if (SUCCEEDED(hr = IMFSampleGrabberSinkCallback_OnShutdown(sample_grabber_get_callback(grabber)))) { + /* Detach stream. */ IMFMediaSink_Release(&grabber->stream->sink->IMFMediaSink_iface); EnterCriticalSection(&grabber->stream->cs); grabber->stream->sink = NULL; LeaveCriticalSection(&grabber->stream->cs); IMFStreamSink_Release(&grabber->stream->IMFStreamSink_iface); grabber->stream = NULL; + + IMFMediaEventQueue_Shutdown(grabber->event_queue); } LeaveCriticalSection(&grabber->cs);
diff --git a/dlls/mf/tests/mf.c b/dlls/mf/tests/mf.c index da533d05d3..ebab86aab6 100644 --- a/dlls/mf/tests/mf.c +++ b/dlls/mf/tests/mf.c @@ -1925,6 +1925,7 @@ static void test_sample_grabber(void) IMFMediaSink *sink, *sink2; DWORD flags, count, id; IMFActivate *activate; + IMFMediaEvent *event; ULONG refcount; IUnknown *unk; HRESULT hr; @@ -1995,9 +1996,12 @@ static void test_sample_grabber(void) ok(hr == S_OK, "Failed to get interface, hr %#x.\n", hr); IMFClockStateSink_Release(clocksink);
+ /* Event generator. */ hr = IMFMediaSink_QueryInterface(sink, &IID_IMFMediaEventGenerator, (void **)&eg); ok(hr == S_OK, "Failed to get interface, hr %#x.\n", hr); - IMFMediaEventGenerator_Release(eg); + + hr = IMFMediaEventGenerator_GetEvent(eg, MF_EVENT_FLAG_NO_WAIT, &event); + ok(hr == MF_E_NO_EVENTS_AVAILABLE, "Unexpected hr %#x.\n", hr);
hr = IMFMediaSink_QueryInterface(sink, &IID_IMFPresentationTimeSource, (void **)&unk); ok(hr == E_NOINTERFACE, "Unexpected hr %#x.\n", hr); @@ -2130,9 +2134,18 @@ todo_wine hr = IMFMediaTypeHandler_IsMediaTypeSupported(handler, NULL, NULL); ok(hr == E_POINTER, "Unexpected hr %#x.\n", hr);
+ hr = IMFMediaEventGenerator_GetEvent(eg, MF_EVENT_FLAG_NO_WAIT, &event); + ok(hr == MF_E_NO_EVENTS_AVAILABLE, "Unexpected hr %#x.\n", hr); + + hr = IMFStreamSink_GetEvent(stream, MF_EVENT_FLAG_NO_WAIT, &event); + ok(hr == MF_E_NO_EVENTS_AVAILABLE, "Unexpected hr %#x.\n", hr); + hr = IMFMediaSink_Shutdown(sink); ok(hr == S_OK, "Failed to shut down, hr %#x.\n", hr);
+ hr = IMFMediaEventGenerator_GetEvent(eg, MF_EVENT_FLAG_NO_WAIT, &event); + ok(hr == MF_E_SHUTDOWN, "Unexpected hr %#x.\n", hr); + hr = IMFMediaSink_Shutdown(sink); ok(hr == MF_E_SHUTDOWN, "Unexpected hr %#x.\n", hr);
@@ -2148,6 +2161,10 @@ todo_wine hr = IMFMediaSink_GetStreamSinkByIndex(sink, 0, &stream2); ok(hr == MF_E_SHUTDOWN, "Unexpected hr %#x.\n", hr);
+ hr = IMFStreamSink_GetEvent(stream, MF_EVENT_FLAG_NO_WAIT, &event); +todo_wine + ok(hr == MF_E_STREAMSINK_REMOVED, "Unexpected hr %#x.\n", hr); + hr = IMFStreamSink_GetMediaSink(stream, &sink2); ok(hr == MF_E_STREAMSINK_REMOVED, "Unexpected hr %#x.\n", hr);
@@ -2195,6 +2212,7 @@ todo_wine hr = IMFStreamSink_GetMediaTypeHandler(stream, NULL); ok(hr == E_POINTER, "Unexpected hr %#x.\n", hr);
+ IMFMediaEventGenerator_Release(eg); IMFMediaSink_Release(sink); IMFStreamSink_Release(stream);
Signed-off-by: Nikolay Sivov nsivov@codeweavers.com --- dlls/mf/samplegrabber.c | 13 +++++++++++++ dlls/mf/tests/mf.c | 1 - 2 files changed, 13 insertions(+), 1 deletion(-)
diff --git a/dlls/mf/samplegrabber.c b/dlls/mf/samplegrabber.c index f4dbe4f283..82febf236d 100644 --- a/dlls/mf/samplegrabber.c +++ b/dlls/mf/samplegrabber.c @@ -235,6 +235,9 @@ static HRESULT WINAPI sample_grabber_stream_GetEvent(IMFStreamSink *iface, DWORD
TRACE("%p, %#x, %p.\n", iface, flags, event);
+ if (!stream->sink) + return MF_E_STREAMSINK_REMOVED; + return IMFMediaEventQueue_GetEvent(stream->event_queue, flags, event); }
@@ -245,6 +248,9 @@ static HRESULT WINAPI sample_grabber_stream_BeginGetEvent(IMFStreamSink *iface,
TRACE("%p, %p, %p.\n", iface, callback, state);
+ if (!stream->sink) + return MF_E_STREAMSINK_REMOVED; + return IMFMediaEventQueue_BeginGetEvent(stream->event_queue, callback, state); }
@@ -255,6 +261,9 @@ static HRESULT WINAPI sample_grabber_stream_EndGetEvent(IMFStreamSink *iface, IM
TRACE("%p, %p, %p.\n", iface, result, event);
+ if (!stream->sink) + return MF_E_STREAMSINK_REMOVED; + return IMFMediaEventQueue_EndGetEvent(stream->event_queue, result, event); }
@@ -265,6 +274,9 @@ static HRESULT WINAPI sample_grabber_stream_QueueEvent(IMFStreamSink *iface, Med
TRACE("%p, %u, %s, %#x, %p.\n", iface, event_type, debugstr_guid(ext_type), hr, value);
+ if (!stream->sink) + return MF_E_STREAMSINK_REMOVED; + return IMFMediaEventQueue_QueueEventParamVar(stream->event_queue, event_type, ext_type, hr, value); }
@@ -1046,6 +1058,7 @@ static HRESULT WINAPI sample_grabber_sink_Shutdown(IMFMediaSink *iface) IMFMediaSink_Release(&grabber->stream->sink->IMFMediaSink_iface); EnterCriticalSection(&grabber->stream->cs); grabber->stream->sink = NULL; + IMFMediaEventQueue_Shutdown(grabber->stream->event_queue); LeaveCriticalSection(&grabber->stream->cs); IMFStreamSink_Release(&grabber->stream->IMFStreamSink_iface); grabber->stream = NULL; diff --git a/dlls/mf/tests/mf.c b/dlls/mf/tests/mf.c index ebab86aab6..0593ed8868 100644 --- a/dlls/mf/tests/mf.c +++ b/dlls/mf/tests/mf.c @@ -2162,7 +2162,6 @@ todo_wine ok(hr == MF_E_SHUTDOWN, "Unexpected hr %#x.\n", hr);
hr = IMFStreamSink_GetEvent(stream, MF_EVENT_FLAG_NO_WAIT, &event); -todo_wine ok(hr == MF_E_STREAMSINK_REMOVED, "Unexpected hr %#x.\n", hr);
hr = IMFStreamSink_GetMediaSink(stream, &sink2);
Hi,
While running your changed tests, I think I found new failures. Being a bot and all I'm not very good at pattern recognition, so I might be wrong, but could you please double-check?
Full results can be found at: https://testbot.winehq.org/JobDetails.pl?Key=66909
Your paranoid android.
=== w1064v1507 (32 bit report) ===
mf: mf.c:1007: Test failed: Unexpected return value 0x102. mf.c:931: Test failed: Failed to finalize GetEvent, hr 0xc00d3e85. 0c94:mf: unhandled exception c0000005 at 0040297F
Signed-off-by: Nikolay Sivov nsivov@codeweavers.com --- dlls/mf/main.c | 23 +++++++- dlls/mf/mf_private.h | 1 + dlls/mf/samplegrabber.c | 11 ++++ dlls/mf/sar.c | 6 ++ dlls/mf/tests/mf.c | 122 +++++++++++++++++++++++++++++++++++++++- 5 files changed, 158 insertions(+), 5 deletions(-)
diff --git a/dlls/mf/main.c b/dlls/mf/main.c index f16e3e8aba..ecf7de23b6 100644 --- a/dlls/mf/main.c +++ b/dlls/mf/main.c @@ -402,14 +402,23 @@ static HRESULT WINAPI activate_object_ActivateObject(IMFActivate *iface, REFIID
static HRESULT WINAPI activate_object_ShutdownObject(IMFActivate *iface) { - FIXME("%p.\n", iface); + struct activate_object *activate = impl_from_IMFActivate(iface); + IUnknown *object;
- return E_NOTIMPL; + TRACE("%p.\n", iface); + + if ((object = InterlockedCompareExchangePointer((void **)&activate->object, NULL, activate->object))) + { + activate->funcs->shutdown_object(activate->context, object); + IUnknown_Release(object); + } + + return S_OK; }
static HRESULT WINAPI activate_object_DetachObject(IMFActivate *iface) { - FIXME("%p.\n", iface); + TRACE("%p.\n", iface);
return E_NOTIMPL; } @@ -1265,6 +1274,10 @@ static HRESULT evr_create_object(IMFAttributes *attributes, void *user_context, return E_NOTIMPL; }
+static void evr_shutdown_object(void *user_context, IUnknown *obj) +{ +} + static void evr_free_private(void *user_context) { } @@ -1272,6 +1285,7 @@ static void evr_free_private(void *user_context) static const struct activate_funcs evr_activate_funcs = { evr_create_object, + evr_shutdown_object, evr_free_private, };
@@ -1279,6 +1293,9 @@ HRESULT WINAPI MFCreateVideoRendererActivate(HWND hwnd, IMFActivate **activate) { TRACE("%p, %p.\n", hwnd, activate);
+ if (!activate) + return E_POINTER; + return create_activation_object(hwnd, &evr_activate_funcs, activate); }
diff --git a/dlls/mf/mf_private.h b/dlls/mf/mf_private.h index 0b7d1c65fa..f68c7d8d4c 100644 --- a/dlls/mf/mf_private.h +++ b/dlls/mf/mf_private.h @@ -50,6 +50,7 @@ static inline BOOL mf_array_reserve(void **elements, size_t *capacity, size_t co struct activate_funcs { HRESULT (*create_object)(IMFAttributes *attributes, void *context, IUnknown **object); + void (*shutdown_object)(void *context, IUnknown *object); void (*free_private)(void *context); };
diff --git a/dlls/mf/samplegrabber.c b/dlls/mf/samplegrabber.c index 82febf236d..ea0d596f7e 100644 --- a/dlls/mf/samplegrabber.c +++ b/dlls/mf/samplegrabber.c @@ -101,6 +101,7 @@ struct sample_grabber_activate_context { IMFMediaType *media_type; IMFSampleGrabberSinkCallback *callback; + BOOL shut_down; };
static void sample_grabber_free_private(void *user_context) @@ -1320,6 +1321,9 @@ static HRESULT sample_grabber_create_object(IMFAttributes *attributes, void *use
TRACE("%p, %p, %p.\n", attributes, user_context, obj);
+ if (context->shut_down) + return MF_E_SHUTDOWN; + /* At least major type is required. */ if (FAILED(IMFMediaType_GetMajorType(context->media_type, &guid))) return MF_E_INVALIDMEDIATYPE; @@ -1363,9 +1367,16 @@ failed: return hr; }
+static void sample_grabber_shutdown_object(void *user_context, IUnknown *obj) +{ + struct sample_grabber_activate_context *context = user_context; + context->shut_down = TRUE; +} + static const struct activate_funcs sample_grabber_activate_funcs = { sample_grabber_create_object, + sample_grabber_shutdown_object, sample_grabber_free_private, };
diff --git a/dlls/mf/sar.c b/dlls/mf/sar.c index c0c1803df1..4f20472748 100644 --- a/dlls/mf/sar.c +++ b/dlls/mf/sar.c @@ -33,6 +33,11 @@ static HRESULT sar_create_object(IMFAttributes *attributes, void *user_context, return E_NOTIMPL; }
+static void sar_shutdown_object(void *user_context, IUnknown *obj) +{ + /* FIXME: shut down sink */ +} + static void sar_free_private(void *user_context) { } @@ -40,6 +45,7 @@ static void sar_free_private(void *user_context) static const struct activate_funcs sar_activate_funcs = { sar_create_object, + sar_shutdown_object, sar_free_private, };
diff --git a/dlls/mf/tests/mf.c b/dlls/mf/tests/mf.c index 0593ed8868..5742da1620 100644 --- a/dlls/mf/tests/mf.c +++ b/dlls/mf/tests/mf.c @@ -2044,10 +2044,15 @@ static void test_sample_grabber(void)
IMFPresentationClock_Release(clock);
+ hr = IMFMediaSink_GetCharacteristics(sink, &flags); + ok(hr == S_OK, "Failed to get sink flags, hr %#x.\n", hr); + hr = IMFActivate_ShutdownObject(activate); -todo_wine ok(hr == S_OK, "Failed to shut down, hr %#x.\n", hr);
+ hr = IMFMediaSink_GetCharacteristics(sink, &flags); + ok(hr == S_OK, "Failed to get sink flags, hr %#x.\n", hr); + hr = IMFStreamSink_GetMediaTypeHandler(stream, &handler); ok(hr == S_OK, "Failed to get type handler, hr %#x.\n", hr);
@@ -2240,8 +2245,36 @@ todo_wine ok(hr == S_OK, "Failed to get sink flags, hr %#x.\n", hr); ok(flags & MEDIASINK_RATELESS, "Unexpected flags %#x.\n", flags);
+ hr = IMFActivate_ShutdownObject(activate); + ok(hr == S_OK, "Failed to shut down, hr %#x.\n", hr); + + hr = IMFMediaSink_Shutdown(sink); + ok(hr == S_OK, "Failed to shut down, hr %#x.\n", hr); + IMFMediaSink_Release(sink); + + /* Detaching */ + hr = MFCreateSampleGrabberSinkActivate(media_type, &grabber_callback, &activate); + ok(hr == S_OK, "Failed to create grabber activate, hr %#x.\n", hr); + + hr = IMFActivate_ActivateObject(activate, &IID_IMFMediaSink, (void **)&sink); + ok(hr == S_OK, "Failed to activate object, hr %#x.\n", hr); + IMFMediaSink_Release(sink); + + hr = IMFActivate_ShutdownObject(activate); + ok(hr == S_OK, "Failed to shut down, hr %#x.\n", hr); + + hr = IMFActivate_ActivateObject(activate, &IID_IMFMediaSink, (void **)&sink); + ok(hr == MF_E_SHUTDOWN, "Unexpected hr %#x.\n", hr); + + hr = IMFActivate_GetCount(activate, &count); + ok(hr == S_OK, "Unexpected hr %#x.\n", hr); + + hr = IMFActivate_DetachObject(activate); + ok(hr == E_NOTIMPL, "Unexpected hr %#x.\n", hr); + IMFActivate_Release(activate); + IMFMediaType_Release(media_type);
hr = MFShutdown(); @@ -2608,8 +2641,9 @@ static void test_sar(void) { IMFPresentationTimeSource *time_source; IMFClockStateSink *state_sink; + IMFMediaSink *sink, *sink2; + IMFActivate *activate; MFCLOCK_STATE state; - IMFMediaSink *sink; IMFClock *clock; DWORD flags; HRESULT hr; @@ -2656,19 +2690,103 @@ if (SUCCEEDED(hr))
IMFMediaSink_Release(sink); } + /* Activation */ + hr = MFCreateAudioRendererActivate(&activate); + ok(hr == S_OK, "Failed to create activation object, hr %#x.\n", hr); + + hr = IMFActivate_ActivateObject(activate, &IID_IMFMediaSink, (void **)&sink); +todo_wine + ok(hr == S_OK, "Failed to activate, hr %#x.\n", hr); + +if (hr == S_OK) +{ + hr = IMFActivate_ActivateObject(activate, &IID_IMFMediaSink, (void **)&sink2); + ok(hr == S_OK, "Failed to activate, hr %#x.\n", hr); + ok(sink == sink2, "Unexpected instance.\n"); + IMFMediaSink_Release(sink2); + + hr = IMFMediaSink_GetCharacteristics(sink, &flags); + ok(hr == S_OK, "Failed to get sink flags, hr %#x.\n", hr); + + hr = IMFActivate_ShutdownObject(activate); + ok(hr == S_OK, "Failed to shut down, hr %#x.\n", hr); + + hr = IMFMediaSink_GetCharacteristics(sink, &flags); + ok(hr == MF_E_SHUTDOWN, "Unexpected hr %#x.\n", hr); + + IMFMediaSink_Release(sink); + + hr = IMFActivate_ActivateObject(activate, &IID_IMFMediaSink, (void **)&sink); + ok(hr == S_OK, "Failed to activate, hr %#x.\n", hr); + + hr = IMFMediaSink_GetCharacteristics(sink, &flags); + ok(hr == MF_E_SHUTDOWN, "Unexpected hr %#x.\n", hr); + + IMFMediaSink_Release(sink); + + hr = IMFActivate_DetachObject(activate); + ok(hr == E_NOTIMPL, "Unexpected hr %#x.\n", hr); +} + IMFActivate_Release(activate);
CoUninitialize(); }
static void test_evr(void) { + IMFMediaSink *sink, *sink2; IMFActivate *activate; + DWORD flags; HRESULT hr;
+ hr = CoInitialize(NULL); + ok(hr == S_OK, "Failed to initialize, hr %#x.\n", hr); + + hr = MFCreateVideoRendererActivate(NULL, NULL); + ok(hr == E_POINTER, "Unexpected hr %#x.\n", hr); + hr = MFCreateVideoRendererActivate(NULL, &activate); ok(hr == S_OK, "Failed to create activate object, hr %#x.\n", hr);
+ hr = IMFActivate_ActivateObject(activate, &IID_IMFMediaSink, (void **)&sink); +todo_wine + ok(hr == S_OK, "Failed to activate, hr %#x.\n", hr); + +if (hr == S_OK) +{ + hr = IMFMediaSink_GetCharacteristics(sink, &flags); + ok(hr == S_OK, "Unexpected hr %#x.\n", hr); + + hr = IMFActivate_ShutdownObject(activate); + ok(hr == S_OK, "Failed to shut down, hr %#x.\n", hr); + + hr = IMFMediaSink_GetCharacteristics(sink, &flags); + ok(hr == MF_E_SHUTDOWN, "Unexpected hr %#x.\n", hr); + + /* Activate again. */ + hr = IMFActivate_ActivateObject(activate, &IID_IMFMediaSink, (void **)&sink2); + ok(hr == S_OK, "Failed to activate, hr %#x.\n", hr); + ok(sink == sink2, "Unexpected instance.\n"); + IMFMediaSink_Release(sink2); + + hr = IMFActivate_DetachObject(activate); + ok(hr == E_NOTIMPL, "Unexpected hr %#x.\n", hr); + + hr = IMFMediaSink_GetCharacteristics(sink, &flags); + ok(hr == MF_E_SHUTDOWN, "Unexpected hr %#x.\n", hr); + + hr = IMFActivate_ActivateObject(activate, &IID_IMFMediaSink, (void **)&sink2); + ok(hr == S_OK, "Failed to activate, hr %#x.\n", hr); + + hr = IMFActivate_ShutdownObject(activate); + ok(hr == S_OK, "Failed to shut down, hr %#x.\n", hr); + + IMFMediaSink_Release(sink2); + IMFMediaSink_Release(sink); +} IMFActivate_Release(activate); + + CoUninitialize(); }
static void test_MFCreateSimpleTypeHandler(void)
Hi,
While running your changed tests, I think I found new failures. Being a bot and all I'm not very good at pattern recognition, so I might be wrong, but could you please double-check?
Full results can be found at: https://testbot.winehq.org/JobDetails.pl?Key=66910
Your paranoid android.
=== w1064v1809_zh_CN (32 bit report) ===
mf: mf.c:1007: Test failed: Unexpected return value 0x102. mf.c:931: Test failed: Failed to finalize GetEvent, hr 0xc00d3e85. 11b0:mf: unhandled exception c0000005 at 0040297F
Signed-off-by: Nikolay Sivov nsivov@codeweavers.com --- dlls/mf/session.c | 28 ++++++++++++++++++++++++---- dlls/mf/tests/mf.c | 31 +++++++++++++++++++++++++++---- 2 files changed, 51 insertions(+), 8 deletions(-)
diff --git a/dlls/mf/session.c b/dlls/mf/session.c index 29f366a34e..91fcce57ca 100644 --- a/dlls/mf/session.c +++ b/dlls/mf/session.c @@ -239,6 +239,7 @@ struct presentation_clock float rate; LONGLONG frequency; CRITICAL_SECTION cs; + BOOL is_shut_down; };
struct quality_manager @@ -3332,16 +3333,35 @@ static ULONG WINAPI present_clock_shutdown_Release(IMFShutdown *iface)
static HRESULT WINAPI present_clock_shutdown_Shutdown(IMFShutdown *iface) { - FIXME("%p.\n", iface); + struct presentation_clock *clock = impl_from_IMFShutdown(iface);
- return E_NOTIMPL; + TRACE("%p.\n", iface); + + EnterCriticalSection(&clock->cs); + clock->is_shut_down = TRUE; + LeaveCriticalSection(&clock->cs); + + return S_OK; }
static HRESULT WINAPI present_clock_shutdown_GetShutdownStatus(IMFShutdown *iface, MFSHUTDOWN_STATUS *status) { - FIXME("%p, %p.\n", iface, status); + struct presentation_clock *clock = impl_from_IMFShutdown(iface); + HRESULT hr = S_OK;
- return E_NOTIMPL; + TRACE("%p, %p.\n", iface, status); + + if (!status) + return E_INVALIDARG; + + EnterCriticalSection(&clock->cs); + if (clock->is_shut_down) + *status = MFSHUTDOWN_COMPLETED; + else + hr = MF_E_INVALIDREQUEST; + LeaveCriticalSection(&clock->cs); + + return hr; }
static const IMFShutdownVtbl presentclockshutdownvtbl = diff --git a/dlls/mf/tests/mf.c b/dlls/mf/tests/mf.c index 5742da1620..a86a8ecdbb 100644 --- a/dlls/mf/tests/mf.c +++ b/dlls/mf/tests/mf.c @@ -1776,6 +1776,10 @@ static void test_presentation_clock(void) ok(rate == 1.0f, "Unexpected rate.\n"); ok(!thin, "Unexpected thinning.\n");
+ hr = IMFPresentationClock_GetState(clock, 0, &state); + ok(hr == S_OK, "Failed to get clock state, hr %#x.\n", hr); + ok(state == MFCLOCK_STATE_PAUSED, "Unexpected state %d.\n", state); + hr = IMFPresentationClock_Start(clock, 0); ok(hr == S_OK, "Failed to stop, hr %#x.\n", hr);
@@ -1809,18 +1813,37 @@ static void test_presentation_clock(void)
/* Shutdown behavior. */ hr = IMFShutdown_GetShutdownStatus(shutdown, NULL); -todo_wine ok(hr == E_INVALIDARG, "Unexpected hr %#x.\n", hr);
+ hr = IMFShutdown_GetShutdownStatus(shutdown, &status); + ok(hr == MF_E_INVALIDREQUEST, "Unexpected hr %#x.\n", hr); + hr = IMFShutdown_Shutdown(shutdown); -todo_wine ok(hr == S_OK, "Failed to shut down, hr %#x.\n", hr);
+ time_source = NULL; + hr = IMFPresentationClock_GetTimeSource(clock, &time_source); + ok(hr == S_OK, "Unexpected hr %#x.\n", hr); + ok(!!time_source, "Unexpected instance %p.\n", time_source); + IMFPresentationTimeSource_Release(time_source); + + hr = IMFPresentationClock_GetTime(clock, &time); + ok(hr == S_OK, "Failed to get time, hr %#x.\n", hr); + hr = IMFShutdown_GetShutdownStatus(shutdown, &status); -todo_wine { ok(hr == S_OK, "Failed to get status, hr %#x.\n", hr); ok(status == MFSHUTDOWN_COMPLETED, "Unexpected status.\n"); -} + + hr = IMFPresentationClock_Start(clock, 0); + ok(hr == S_OK, "Failed to start the clock, hr %#x.\n", hr); + + hr = IMFShutdown_GetShutdownStatus(shutdown, &status); + ok(hr == S_OK, "Failed to get status, hr %#x.\n", hr); + ok(status == MFSHUTDOWN_COMPLETED, "Unexpected status.\n"); + + hr = IMFShutdown_Shutdown(shutdown); + ok(hr == S_OK, "Unexpected hr %#x.\n", hr); + IMFShutdown_Release(shutdown);
IMFPresentationClock_Release(clock);
Signed-off-by: Nikolay Sivov nsivov@codeweavers.com --- dlls/mf/session.c | 176 +++++++++++++++++++++++++--------------------- 1 file changed, 95 insertions(+), 81 deletions(-)
diff --git a/dlls/mf/session.c b/dlls/mf/session.c index 91fcce57ca..933cdf5c93 100644 --- a/dlls/mf/session.c +++ b/dlls/mf/session.c @@ -234,6 +234,7 @@ struct presentation_clock IMFPresentationTimeSource *time_source; IMFClockStateSink *time_source_sink; MFCLOCK_STATE state; + LONGLONG start_offset; struct list sinks; struct list timers; float rate; @@ -2504,6 +2505,81 @@ failed: return hr; }
+static HRESULT WINAPI sink_notification_QueryInterface(IUnknown *iface, REFIID riid, void **out) +{ + if (IsEqualIID(riid, &IID_IUnknown)) + { + *out = iface; + IUnknown_AddRef(iface); + return S_OK; + } + + WARN("Unsupported %s.\n", debugstr_guid(riid)); + *out = NULL; + return E_NOINTERFACE; +} + +static ULONG WINAPI sink_notification_AddRef(IUnknown *iface) +{ + struct sink_notification *notification = impl_sink_notification_from_IUnknown(iface); + ULONG refcount = InterlockedIncrement(¬ification->refcount); + + TRACE("%p, refcount %u.\n", iface, refcount); + + return refcount; +} + +static ULONG WINAPI sink_notification_Release(IUnknown *iface) +{ + struct sink_notification *notification = impl_sink_notification_from_IUnknown(iface); + ULONG refcount = InterlockedDecrement(¬ification->refcount); + + TRACE("%p, refcount %u.\n", iface, refcount); + + if (!refcount) + { + IMFClockStateSink_Release(notification->sink); + heap_free(notification); + } + + return refcount; +} + +static const IUnknownVtbl sinknotificationvtbl = +{ + sink_notification_QueryInterface, + sink_notification_AddRef, + sink_notification_Release, +}; + +static void clock_notify_async_sink(struct presentation_clock *clock, MFTIME system_time, + struct clock_state_change_param param, enum clock_notification notification, IMFClockStateSink *sink) +{ + struct sink_notification *object; + IMFAsyncResult *result; + HRESULT hr; + + object = heap_alloc(sizeof(*object)); + if (!object) + return; + + object->IUnknown_iface.lpVtbl = &sinknotificationvtbl; + object->refcount = 1; + object->system_time = system_time; + object->param = param; + object->notification = notification; + object->sink = sink; + IMFClockStateSink_AddRef(object->sink); + + hr = MFCreateAsyncResult(&object->IUnknown_iface, &clock->sink_callback, NULL, &result); + IUnknown_Release(&object->IUnknown_iface); + if (SUCCEEDED(hr)) + { + MFPutWorkItemEx(MFASYNC_CALLBACK_QUEUE_STANDARD, result); + IMFAsyncResult_Release(result); + } +} + static HRESULT WINAPI present_clock_QueryInterface(IMFPresentationClock *iface, REFIID riid, void **out) { struct presentation_clock *clock = impl_from_IMFPresentationClock(iface); @@ -2762,7 +2838,24 @@ static HRESULT WINAPI present_clock_AddClockStateSink(IMFPresentationClock *ifac } } if (SUCCEEDED(hr)) + { + static const enum clock_notification notifications[MFCLOCK_STATE_PAUSED + 1] = + { + /* MFCLOCK_STATE_INVALID */ 0, /* Does not apply */ + /* MFCLOCK_STATE_RUNNING */ CLOCK_NOTIFY_START, + /* MFCLOCK_STATE_STOPPED */ CLOCK_NOTIFY_STOP, + /* MFCLOCK_STATE_PAUSED */ CLOCK_NOTIFY_PAUSE, + }; + struct clock_state_change_param param; + + if (!clock->is_shut_down && clock->state != MFCLOCK_STATE_INVALID) + { + param.u.offset = clock->start_offset; + clock_notify_async_sink(clock, MFGetSystemTime(), param, notifications[clock->state], sink->state_sink); + } + list_add_tail(&clock->sinks, &sink->entry); + } LeaveCriticalSection(&clock->cs);
if (FAILED(hr)) @@ -2801,75 +2894,6 @@ static HRESULT WINAPI present_clock_RemoveClockStateSink(IMFPresentationClock *i return S_OK; }
-static HRESULT WINAPI sink_notification_QueryInterface(IUnknown *iface, REFIID riid, void **out) -{ - if (IsEqualIID(riid, &IID_IUnknown)) - { - *out = iface; - IUnknown_AddRef(iface); - return S_OK; - } - - WARN("Unsupported %s.\n", debugstr_guid(riid)); - *out = NULL; - return E_NOINTERFACE; -} - -static ULONG WINAPI sink_notification_AddRef(IUnknown *iface) -{ - struct sink_notification *notification = impl_sink_notification_from_IUnknown(iface); - ULONG refcount = InterlockedIncrement(¬ification->refcount); - - TRACE("%p, refcount %u.\n", iface, refcount); - - return refcount; -} - -static ULONG WINAPI sink_notification_Release(IUnknown *iface) -{ - struct sink_notification *notification = impl_sink_notification_from_IUnknown(iface); - ULONG refcount = InterlockedDecrement(¬ification->refcount); - - TRACE("%p, refcount %u.\n", iface, refcount); - - if (!refcount) - { - IMFClockStateSink_Release(notification->sink); - heap_free(notification); - } - - return refcount; -} - -static const IUnknownVtbl sinknotificationvtbl = -{ - sink_notification_QueryInterface, - sink_notification_AddRef, - sink_notification_Release, -}; - -static HRESULT create_sink_notification(MFTIME system_time, struct clock_state_change_param param, - enum clock_notification notification, IMFClockStateSink *sink, IUnknown **out) -{ - struct sink_notification *object; - - object = heap_alloc(sizeof(*object)); - if (!object) - return E_OUTOFMEMORY; - - object->IUnknown_iface.lpVtbl = &sinknotificationvtbl; - object->refcount = 1; - object->system_time = system_time; - object->param = param; - object->notification = notification; - object->sink = sink; - IMFClockStateSink_AddRef(object->sink); - - *out = &object->IUnknown_iface; - - return S_OK; -} - static HRESULT clock_call_state_change(MFTIME system_time, struct clock_state_change_param param, enum clock_notification notification, IMFClockStateSink *sink) { @@ -2926,7 +2950,6 @@ static HRESULT clock_change_state(struct presentation_clock *clock, enum clock_c }; enum clock_notification notification; struct clock_sink *sink; - IUnknown *notify_object; MFCLOCK_STATE old_state; IMFAsyncResult *result; MFTIME system_time; @@ -2992,16 +3015,7 @@ static HRESULT clock_change_state(struct presentation_clock *clock, enum clock_c
LIST_FOR_EACH_ENTRY(sink, &clock->sinks, struct clock_sink, entry) { - if (SUCCEEDED(create_sink_notification(system_time, param, notification, sink->state_sink, ¬ify_object))) - { - hr = MFCreateAsyncResult(notify_object, &clock->sink_callback, NULL, &result); - IUnknown_Release(notify_object); - if (SUCCEEDED(hr)) - { - MFPutWorkItemEx(MFASYNC_CALLBACK_QUEUE_STANDARD, result); - IMFAsyncResult_Release(result); - } - } + clock_notify_async_sink(clock, system_time, param, notification, sink->state_sink); }
return S_OK; @@ -3016,7 +3030,7 @@ static HRESULT WINAPI present_clock_Start(IMFPresentationClock *iface, LONGLONG TRACE("%p, %s.\n", iface, wine_dbgstr_longlong(start_offset));
EnterCriticalSection(&clock->cs); - param.u.offset = start_offset; + clock->start_offset = param.u.offset = start_offset; hr = clock_change_state(clock, CLOCK_CMD_START, param); LeaveCriticalSection(&clock->cs);
Hi,
While running your changed tests, I think I found new failures. Being a bot and all I'm not very good at pattern recognition, so I might be wrong, but could you please double-check?
Full results can be found at: https://testbot.winehq.org/JobDetails.pl?Key=66912
Your paranoid android.
=== debiant (32 bit report) ===
mf: Unhandled exception: page fault on execute access to 0x00000003 in 32-bit code (0x00000003).
Signed-off-by: Nikolay Sivov nsivov@codeweavers.com --- dlls/mf/session.c | 3 ++- dlls/mf/tests/mf.c | 4 ++++ 2 files changed, 6 insertions(+), 1 deletion(-)
diff --git a/dlls/mf/session.c b/dlls/mf/session.c index 933cdf5c93..cc014f548a 100644 --- a/dlls/mf/session.c +++ b/dlls/mf/session.c @@ -2978,7 +2978,8 @@ static HRESULT clock_change_state(struct presentation_clock *clock, enum clock_c return hr;
old_state = clock->state; - clock->state = states[command]; + if (command != CLOCK_CMD_SET_RATE) + clock->state = states[command];
/* Dump all pending timer requests immediately on start; otherwise try to cancel scheduled items when transitioning from running state. */ diff --git a/dlls/mf/tests/mf.c b/dlls/mf/tests/mf.c index a86a8ecdbb..a9b0ee34a3 100644 --- a/dlls/mf/tests/mf.c +++ b/dlls/mf/tests/mf.c @@ -1797,6 +1797,10 @@ static void test_presentation_clock(void) hr = IMFRateControl_SetRate(rate_control, TRUE, -1.0f); ok(hr == MF_E_THINNING_UNSUPPORTED, "Unexpected hr %#x.\n", hr);
+ hr = IMFPresentationClock_GetState(clock, 0, &state); + ok(hr == S_OK, "Failed to get clock state, hr %#x.\n", hr); + ok(state == MFCLOCK_STATE_RUNNING, "Unexpected state %d.\n", state); + hr = IMFRateControl_GetRate(rate_control, &thin, &rate); ok(hr == S_OK, "Failed to get clock rate, hr %#x.\n", hr); ok(rate == 0.5f, "Unexpected rate.\n");
Hi,
While running your changed tests, I think I found new failures. Being a bot and all I'm not very good at pattern recognition, so I might be wrong, but could you please double-check?
Full results can be found at: https://testbot.winehq.org/JobDetails.pl?Key=66913
Your paranoid android.
=== w1064v1809_zh_CN (32 bit report) ===
mf: mf.c:1007: Test failed: Unexpected return value 0x102. mf.c:931: Test failed: Failed to finalize GetEvent, hr 0xc00d3e85. 18ac:mf: unhandled exception c0000005 at 0040297F
Signed-off-by: Nikolay Sivov nsivov@codeweavers.com --- dlls/mf/tests/mf.c | 44 -------------------------------------------- 1 file changed, 44 deletions(-)
diff --git a/dlls/mf/tests/mf.c b/dlls/mf/tests/mf.c index a9b0ee34a3..8ebfd0ddee 100644 --- a/dlls/mf/tests/mf.c +++ b/dlls/mf/tests/mf.c @@ -875,14 +875,8 @@ static void test_sequencer_source(void) struct test_callback { IMFAsyncCallback IMFAsyncCallback_iface; - HANDLE event; };
-static struct test_callback *impl_from_IMFAsyncCallback(IMFAsyncCallback *iface) -{ - return CONTAINING_RECORD(iface, struct test_callback, IMFAsyncCallback_iface); -} - static HRESULT WINAPI testcallback_QueryInterface(IMFAsyncCallback *iface, REFIID riid, void **obj) { if (IsEqualIID(riid, &IID_IMFAsyncCallback) || @@ -915,34 +909,8 @@ static HRESULT WINAPI testcallback_GetParameters(IMFAsyncCallback *iface, DWORD
static HRESULT WINAPI testcallback_Invoke(IMFAsyncCallback *iface, IMFAsyncResult *result) { - struct test_callback *callback = impl_from_IMFAsyncCallback(iface); - IMFMediaSession *session; - IUnknown *state, *obj; - HRESULT hr; - ok(result != NULL, "Unexpected result object.\n");
- state = IMFAsyncResult_GetStateNoAddRef(result); - if (state && SUCCEEDED(IUnknown_QueryInterface(state, &IID_IMFMediaSession, (void **)&session))) - { - IMFMediaEvent *event; - - hr = IMFMediaSession_EndGetEvent(session, result, &event); - ok(hr == S_OK, "Failed to finalize GetEvent, hr %#x.\n", hr); - - hr = IMFAsyncResult_GetObject(result, &obj); - ok(hr == E_POINTER, "Unexpected hr %#x.\n", hr); - - IMFMediaEvent_Release(event); - - hr = IMFMediaSession_EndGetEvent(session, result, &event); - ok(hr == E_FAIL, "Unexpected result, hr %#x.\n", hr); - - IMFMediaSession_Release(session); - - SetEvent(callback->event); - } - return E_NOTIMPL; }
@@ -958,7 +926,6 @@ static const IMFAsyncCallbackVtbl testcallbackvtbl = static void init_test_callback(struct test_callback *callback) { callback->IMFAsyncCallback_iface.lpVtbl = &testcallbackvtbl; - callback->event = NULL; }
static void test_session_events(IMFMediaSession *session) @@ -967,7 +934,6 @@ static void test_session_events(IMFMediaSession *session) IMFAsyncResult *result; IMFMediaEvent *event; HRESULT hr; - DWORD ret;
init_test_callback(&callback); init_test_callback(&callback2); @@ -998,16 +964,6 @@ static void test_session_events(IMFMediaSession *session) hr = IMFMediaSession_BeginGetEvent(session, &callback2.IMFAsyncCallback_iface, (IUnknown *)&callback.IMFAsyncCallback_iface); ok(hr == MF_E_MULTIPLE_SUBSCRIBERS, "Unexpected hr %#x.\n", hr);
- callback.event = CreateEventA(NULL, FALSE, FALSE, NULL); - - hr = IMFMediaSession_QueueEvent(session, MEError, &GUID_NULL, E_FAIL, NULL); - ok(hr == S_OK, "Failed to queue event, hr %#x.\n", hr); - - ret = WaitForSingleObject(callback.event, 100); - ok(ret == WAIT_OBJECT_0, "Unexpected return value %#x.\n", ret); - - CloseHandle(callback.event); - hr = MFCreateAsyncResult(NULL, &callback.IMFAsyncCallback_iface, NULL, &result); ok(hr == S_OK, "Failed to create result, hr %#x.\n", hr);
Hi,
While running your changed tests, I think I found new failures. Being a bot and all I'm not very good at pattern recognition, so I might be wrong, but could you please double-check?
Full results can be found at: https://testbot.winehq.org/JobDetails.pl?Key=66914
Your paranoid android.
=== w1064v1809_2scr (32 bit report) ===
mf: mf: Timeout
Hi,
While running your changed tests, I think I found new failures. Being a bot and all I'm not very good at pattern recognition, so I might be wrong, but could you please double-check?
Full results can be found at: https://testbot.winehq.org/JobDetails.pl?Key=66908
Your paranoid android.
=== w1064v1809_he (32 bit report) ===
mf: mf.c:1007: Test failed: Unexpected return value 0x102. mf.c:931: Test failed: Failed to finalize GetEvent, hr 0xc00d3e85. 1898:mf: unhandled exception c0000005 at 0040297F
=== w864 (64 bit report) ===
mf: mf.c:1007: Test failed: Unexpected return value 0x102.