[PATCH 3/7] mf: Improve ShutdownObject() behavior for sample grabber activation object.

Nikolay Sivov nsivov at codeweavers.com
Wed Mar 11 06:19:41 CDT 2020


Signed-off-by: Nikolay Sivov <nsivov at 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)
-- 
2.25.1




More information about the wine-devel mailing list