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);