Nikolay Sivov : mf/session: Handle shutdown state on GetService().

Alexandre Julliard julliard at winehq.org
Mon Apr 12 16:11:26 CDT 2021


Module: wine
Branch: master
Commit: a2728cdeced4d1ae28f56eb73b822b8e9779a7fa
URL:    https://source.winehq.org/git/wine.git/?a=commit;h=a2728cdeced4d1ae28f56eb73b822b8e9779a7fa

Author: Nikolay Sivov <nsivov at codeweavers.com>
Date:   Mon Apr 12 12:19:53 2021 +0300

mf/session: Handle shutdown state on GetService().

Signed-off-by: Nikolay Sivov <nsivov at codeweavers.com>
Signed-off-by: Alexandre Julliard <julliard at winehq.org>

---

 dlls/mf/session.c  | 110 ++++++++++++++++++++++++++++++-----------------------
 dlls/mf/tests/mf.c |  11 ++++++
 2 files changed, 73 insertions(+), 48 deletions(-)

diff --git a/dlls/mf/session.c b/dlls/mf/session.c
index 20ccdd0535e..7a8c7e9f598 100644
--- a/dlls/mf/session.c
+++ b/dlls/mf/session.c
@@ -2020,15 +2020,66 @@ static ULONG WINAPI session_get_service_Release(IMFGetService *iface)
     return IMFMediaSession_Release(&session->IMFMediaSession_iface);
 }
 
+static HRESULT session_get_video_render_service(struct media_session *session, REFGUID service,
+        REFIID riid, void **obj)
+{
+    IMFStreamSink *stream_sink;
+    IMFTopologyNode *node;
+    IMFCollection *nodes;
+    IMFMediaSink *sink;
+    unsigned int i = 0;
+    IUnknown *vr;
+    HRESULT hr = E_FAIL;
+
+    /* Use first sink to support IMFVideoRenderer. */
+    if (session->presentation.current_topology)
+    {
+        if (SUCCEEDED(IMFTopology_GetOutputNodeCollection(session->presentation.current_topology,
+                &nodes)))
+        {
+            while (IMFCollection_GetElement(nodes, i++, (IUnknown **)&node) == S_OK)
+            {
+                if (SUCCEEDED(topology_node_get_object(node, &IID_IMFStreamSink, (void **)&stream_sink)))
+                {
+                    if (SUCCEEDED(IMFStreamSink_GetMediaSink(stream_sink, &sink)))
+                    {
+                        if (SUCCEEDED(IMFMediaSink_QueryInterface(sink, &IID_IMFVideoRenderer, (void **)&vr)))
+                        {
+                            if (FAILED(hr = MFGetService(vr, service, riid, obj)))
+                                WARN("Failed to get service from video renderer %#x.\n", hr);
+                            IUnknown_Release(vr);
+                        }
+                    }
+                    IMFStreamSink_Release(stream_sink);
+                }
+
+                IMFTopologyNode_Release(node);
+
+                if (*obj)
+                    break;
+            }
+
+            IMFCollection_Release(nodes);
+        }
+    }
+
+    return hr;
+}
+
 static HRESULT WINAPI session_get_service_GetService(IMFGetService *iface, REFGUID service, REFIID riid, void **obj)
 {
     struct media_session *session = impl_from_IMFGetService(iface);
+    HRESULT hr = S_OK;
 
     TRACE("%p, %s, %s, %p.\n", iface, debugstr_guid(service), debugstr_guid(riid), obj);
 
     *obj = NULL;
 
-    if (IsEqualGUID(service, &MF_RATE_CONTROL_SERVICE))
+    EnterCriticalSection(&session->cs);
+    if (FAILED(hr = session_is_shut_down(session)))
+    {
+    }
+    else if (IsEqualGUID(service, &MF_RATE_CONTROL_SERVICE))
     {
         if (IsEqualIID(riid, &IID_IMFRateSupport))
         {
@@ -2038,68 +2089,31 @@ static HRESULT WINAPI session_get_service_GetService(IMFGetService *iface, REFGU
         {
             *obj = &session->IMFRateControl_iface;
         }
+        else
+            hr = E_NOINTERFACE;
+
+        if (*obj)
+            IUnknown_AddRef((IUnknown *)*obj);
     }
     else if (IsEqualGUID(service, &MF_LOCAL_MFT_REGISTRATION_SERVICE))
     {
-        return IMFLocalMFTRegistration_QueryInterface(&local_mft_registration, riid, obj);
+        hr = IMFLocalMFTRegistration_QueryInterface(&local_mft_registration, riid, obj);
     }
     else if (IsEqualGUID(service, &MF_TOPONODE_ATTRIBUTE_EDITOR_SERVICE))
     {
         *obj = &session->IMFTopologyNodeAttributeEditor_iface;
+        IUnknown_AddRef((IUnknown *)*obj);
     }
     else if (IsEqualGUID(service, &MR_VIDEO_RENDER_SERVICE))
     {
-        IMFStreamSink *stream_sink;
-        IMFTopologyNode *node;
-        IMFCollection *nodes;
-        IMFMediaSink *sink;
-        unsigned int i = 0;
-        IUnknown *vr;
-        HRESULT hr;
-
-        EnterCriticalSection(&session->cs);
-
-        /* Use first sink to support IMFVideoRenderer. */
-        if (session->presentation.current_topology)
-        {
-            if (SUCCEEDED(IMFTopology_GetOutputNodeCollection(session->presentation.current_topology,
-                    &nodes)))
-            {
-                while (IMFCollection_GetElement(nodes, i++, (IUnknown **)&node) == S_OK)
-                {
-                    if (SUCCEEDED(topology_node_get_object(node, &IID_IMFStreamSink, (void **)&stream_sink)))
-                    {
-                        if (SUCCEEDED(IMFStreamSink_GetMediaSink(stream_sink, &sink)))
-                        {
-                            if (SUCCEEDED(IMFMediaSink_QueryInterface(sink, &IID_IMFVideoRenderer, (void **)&vr)))
-                            {
-                                if (FAILED(hr = MFGetService(vr, service, riid, obj)))
-                                    WARN("Failed to get service from video renderer %#x.\n", hr);
-                                IUnknown_Release(vr);
-                            }
-                        }
-                        IMFStreamSink_Release(stream_sink);
-                    }
-
-                    IMFTopologyNode_Release(node);
-
-                    if (*obj)
-                        break;
-                }
-
-                IMFCollection_Release(nodes);
-            }
-        }
-
-        LeaveCriticalSection(&session->cs);
+        hr = session_get_video_render_service(session, service, riid, obj);
     }
     else
         FIXME("Unsupported service %s.\n", debugstr_guid(service));
 
-    if (*obj)
-        IUnknown_AddRef((IUnknown *)*obj);
+    LeaveCriticalSection(&session->cs);
 
-    return *obj ? S_OK : E_NOINTERFACE;
+    return hr;
 }
 
 static const IMFGetServiceVtbl session_get_service_vtbl =
diff --git a/dlls/mf/tests/mf.c b/dlls/mf/tests/mf.c
index 20440499227..308c1fae529 100644
--- a/dlls/mf/tests/mf.c
+++ b/dlls/mf/tests/mf.c
@@ -1170,6 +1170,7 @@ static void test_media_session(void)
     IMFShutdown *shutdown;
     PROPVARIANT propvar;
     DWORD status, caps;
+    IMFGetService *gs;
     IMFClock *clock;
     IUnknown *unk;
     HRESULT hr;
@@ -1271,6 +1272,16 @@ todo_wine
     hr = IMFMediaSession_Shutdown(session);
     ok(hr == S_OK, "Failed to shut down, hr %#x.\n", hr);
 
+    check_interface(session, &IID_IMFGetService, TRUE);
+
+    hr = IMFMediaSession_QueryInterface(session, &IID_IMFGetService, (void **)&gs);
+    ok(hr == S_OK, "Unexpected hr %#x.\n", hr);
+
+    hr = IMFGetService_GetService(gs, &MF_RATE_CONTROL_SERVICE, &IID_IMFRateSupport, (void **)&rate_support);
+    ok(hr == MF_E_SHUTDOWN, "Unexpected hr %#x.\n", hr);
+
+    IMFGetService_Release(gs);
+
     hr = IMFShutdown_GetShutdownStatus(shutdown, &status);
     ok(hr == S_OK, "Unexpected hr %#x.\n", hr);
     ok(status == MFSHUTDOWN_COMPLETED, "Unexpected shutdown status %u.\n", status);




More information about the wine-cvs mailing list