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)