diff --git a/dlls/mf/session.c b/dlls/mf/session.c index 7923581f131..e33a5ce7e9b 100644 --- a/dlls/mf/session.c +++ b/dlls/mf/session.c @@ -55,6 +55,8 @@ struct media_session { IMFMediaSession IMFMediaSession_iface; IMFGetService IMFGetService_iface; + IMFRateSupport IMFRateSupport_iface; + IMFRateControl IMFRateControl_iface; IMFAsyncCallback commands_callback; LONG refcount; IMFMediaEventQueue *event_queue; @@ -124,6 +126,16 @@ static struct media_session *impl_from_IMFGetService(IMFGetService *iface) return CONTAINING_RECORD(iface, struct media_session, IMFGetService_iface); } +static struct media_session *impl_session_from_IMFRateSupport(IMFRateSupport *iface) +{ + return CONTAINING_RECORD(iface, struct media_session, IMFRateSupport_iface); +} + +static struct media_session *impl_session_from_IMFRateControl(IMFRateControl *iface) +{ + return CONTAINING_RECORD(iface, struct media_session, IMFRateControl_iface); +} + static struct session_op *impl_op_from_IUnknown(IUnknown *iface) { return CONTAINING_RECORD(iface, struct session_op, IUnknown_iface); @@ -467,7 +479,30 @@ static ULONG WINAPI session_get_service_Release(IMFGetService *iface) static HRESULT WINAPI session_get_service_GetService(IMFGetService *iface, REFGUID service, REFIID riid, void **obj) { - FIXME("%p, %s, %s, %p.\n", iface, debugstr_guid(service), debugstr_guid(riid), obj); + struct media_session *session = impl_from_IMFGetService(iface); + + TRACE("%p, %s, %s, %p.\n", iface, debugstr_guid(service), debugstr_guid(riid), obj); + + *obj = NULL; + + if (IsEqualGUID(service, &MF_RATE_CONTROL_SERVICE)) + { + if (IsEqualIID(riid, &IID_IMFRateSupport)) + { + *obj = &session->IMFRateSupport_iface; + } + else if (IsEqualIID(riid, &IID_IMFRateControl)) + { + *obj = &session->IMFRateControl_iface; + } + + if (*obj) + IUnknown_AddRef((IUnknown *)*obj); + + return *obj ? S_OK : E_NOINTERFACE; + } + else + FIXME("Unsupported service %s.\n", debugstr_guid(service)); return E_NOTIMPL; } @@ -543,6 +578,99 @@ static const IMFAsyncCallbackVtbl session_commands_callback_vtbl = session_commands_callback_Invoke, }; +static HRESULT WINAPI session_rate_support_QueryInterface(IMFRateSupport *iface, REFIID riid, void **obj) +{ + struct media_session *session = impl_session_from_IMFRateSupport(iface); + return IMFMediaSession_QueryInterface(&session->IMFMediaSession_iface, riid, obj); +} + +static ULONG WINAPI session_rate_support_AddRef(IMFRateSupport *iface) +{ + struct media_session *session = impl_session_from_IMFRateSupport(iface); + return IMFMediaSession_AddRef(&session->IMFMediaSession_iface); +} + +static ULONG WINAPI session_rate_support_Release(IMFRateSupport *iface) +{ + struct media_session *session = impl_session_from_IMFRateSupport(iface); + return IMFMediaSession_Release(&session->IMFMediaSession_iface); +} + +static HRESULT WINAPI session_rate_support_GetSlowestRate(IMFRateSupport *iface, MFRATE_DIRECTION direction, + BOOL thin, float *rate) +{ + FIXME("%p, %d, %d, %p.\n", iface, direction, thin, rate); + + return E_NOTIMPL; +} + +static HRESULT WINAPI session_rate_support_GetFastestRate(IMFRateSupport *iface, MFRATE_DIRECTION direction, + BOOL thin, float *rate) +{ + FIXME("%p, %d, %d, %p.\n", iface, direction, thin, rate); + + return E_NOTIMPL; +} + +static HRESULT WINAPI session_rate_support_IsSupported(IMFRateSupport *iface, BOOL thin, float rate, + float *nearest_supported_rate) +{ + FIXME("%p, %d, %f, %p.\n", iface, thin, rate, nearest_supported_rate); + + return E_NOTIMPL; +} + +static const IMFRateSupportVtbl session_rate_support_vtbl = +{ + session_rate_support_QueryInterface, + session_rate_support_AddRef, + session_rate_support_Release, + session_rate_support_GetSlowestRate, + session_rate_support_GetFastestRate, + session_rate_support_IsSupported, +}; + +static HRESULT WINAPI session_rate_control_QueryInterface(IMFRateControl *iface, REFIID riid, void **obj) +{ + struct media_session *session = impl_session_from_IMFRateControl(iface); + return IMFMediaSession_QueryInterface(&session->IMFMediaSession_iface, riid, obj); +} + +static ULONG WINAPI session_rate_control_AddRef(IMFRateControl *iface) +{ + struct media_session *session = impl_session_from_IMFRateControl(iface); + return IMFMediaSession_AddRef(&session->IMFMediaSession_iface); +} + +static ULONG WINAPI session_rate_control_Release(IMFRateControl *iface) +{ + struct media_session *session = impl_session_from_IMFRateControl(iface); + return IMFMediaSession_Release(&session->IMFMediaSession_iface); +} + +static HRESULT WINAPI session_rate_control_SetRate(IMFRateControl *iface, BOOL thin, float rate) +{ + FIXME("%p, %d, %f.\n", iface, thin, rate); + + return E_NOTIMPL; +} + +static HRESULT WINAPI session_rate_control_GetRate(IMFRateControl *iface, BOOL *thin, float *rate) +{ + FIXME("%p, %p, %p.\n", iface, thin, rate); + + return E_NOTIMPL; +} + +static const IMFRateControlVtbl session_rate_control_vtbl = +{ + session_rate_control_QueryInterface, + session_rate_control_AddRef, + session_rate_control_Release, + session_rate_control_SetRate, + session_rate_control_GetRate, +}; + /*********************************************************************** * MFCreateMediaSession (mf.@) */ @@ -562,6 +690,8 @@ HRESULT WINAPI MFCreateMediaSession(IMFAttributes *config, IMFMediaSession **ses object->IMFMediaSession_iface.lpVtbl = &mfmediasessionvtbl; object->IMFGetService_iface.lpVtbl = &session_get_service_vtbl; + object->IMFRateSupport_iface.lpVtbl = &session_rate_support_vtbl; + object->IMFRateControl_iface.lpVtbl = &session_rate_control_vtbl; object->commands_callback.lpVtbl = &session_commands_callback_vtbl; object->refcount = 1; if (FAILED(hr = MFCreateEventQueue(&object->event_queue))) diff --git a/dlls/mf/tests/mf.c b/dlls/mf/tests/mf.c index fc068a93cc1..b64d3f9088e 100644 --- a/dlls/mf/tests/mf.c +++ b/dlls/mf/tests/mf.c @@ -943,8 +943,12 @@ todo_wine static void test_media_session(void) { + MFCLOCK_PROPERTIES clock_props; IMFMediaSession *session; + IMFRateControl *rc, *rc2; + IMFRateSupport *rs; IMFGetService *gs; + IMFClock *clock; IUnknown *unk; HRESULT hr; @@ -959,6 +963,35 @@ static void test_media_session(void) hr = IMFMediaSession_QueryInterface(session, &IID_IMFGetService, (void **)&gs); ok(hr == S_OK, "Failed to get interface, hr %#x.\n", hr); + + hr = IMFGetService_GetService(gs, &MF_RATE_CONTROL_SERVICE, &IID_IMFRateSupport, (void **)&rs); + ok(hr == S_OK, "Failed to get rate support interface, hr %#x.\n", hr); + + hr = IMFGetService_GetService(gs, &MF_RATE_CONTROL_SERVICE, &IID_IMFRateControl, (void **)&rc); + ok(hr == S_OK, "Failed to get rate control interface, hr %#x.\n", hr); + + hr = IMFRateSupport_QueryInterface(rs, &IID_IMFMediaSession, (void **)&unk); + ok(hr == S_OK, "Failed to get session interface, hr %#x.\n", hr); + ok(unk == (IUnknown *)session, "Unexpected pointer.\n"); + IUnknown_Release(unk); + + hr = IMFMediaSession_GetClock(session, &clock); +todo_wine + ok(hr == S_OK, "Failed to get clock, hr %#x.\n", hr); + +if (SUCCEEDED(hr)) +{ + hr = IMFClock_QueryInterface(clock, &IID_IMFRateControl, (void **)&rc2); + ok(hr == S_OK, "Failed to get rate control, hr %#x.\n", hr); + IMFRateControl_Release(rc2); + + hr = IMFClock_GetProperties(clock, &clock_props); + ok(hr == MF_E_CLOCK_NO_TIME_SOURCE, "Unexpected hr %#x.\n", hr); + +} + IMFRateControl_Release(rc); + IMFRateSupport_Release(rs); + IMFGetService_Release(gs); test_session_events(session); diff --git a/include/mfidl.idl b/include/mfidl.idl index 5db737e68da..fac3bcf5b66 100644 --- a/include/mfidl.idl +++ b/include/mfidl.idl @@ -89,6 +89,34 @@ interface IMFClock : IUnknown HRESULT GetProperties([out] MFCLOCK_PROPERTIES *props); } +typedef enum _MFRATE_DIRECTION +{ + MFRATE_FORWARD, + MFRATE_REVERSE +} MFRATE_DIRECTION; + +[ + object, + uuid(0a9ccdbc-d797-4563-9667-94ec5d79292d), +] +interface IMFRateSupport : IUnknown +{ + HRESULT GetSlowestRate( + [in] MFRATE_DIRECTION direction, + [in] BOOL thin, + [out] float *rate); + + HRESULT GetFastestRate( + [in] MFRATE_DIRECTION direction, + [in] BOOL thin, + [out] float *rate); + + HRESULT IsRateSupported( + [in] BOOL thin, + [in] float rate, + [in, out, unique] float *nearest_supported_rate); +} + [ object, uuid(88ddcd21-03c3-4275-91ed-55ee3929328f) @@ -745,3 +773,5 @@ cpp_quote("EXTERN_GUID(MF_TOPOLOGY_PROJECTSTOP, 0x7ed3f803, 0x86bb, 0x4b3f, 0xb7 cpp_quote("EXTERN_GUID(MF_TOPOLOGY_RESOLUTION_STATUS, 0x494bbcde, 0xb031, 0x4e38, 0x97, 0xc4, 0xd5, 0x42, 0x2d, 0xd6, 0x18, 0xdc);") cpp_quote("EXTERN_GUID(MF_TOPOLOGY_START_TIME_ON_PRESENTATION_SWITCH, 0xc8cc113f, 0x7951, 0x4548, 0xaa, 0xd6, 0x9e, 0xd6, 0x20, 0x2e, 0x62, 0xb3);") cpp_quote("EXTERN_GUID(MF_TOPOLOGY_STATIC_PLAYBACK_OPTIMIZATIONS, 0xb86cac42, 0x41a6, 0x4b79, 0x89, 0x7a, 0x1a, 0xb0, 0xe5, 0x2b, 0x4a, 0x1b);") + +cpp_quote("EXTERN_GUID(MF_RATE_CONTROL_SERVICE, 0x866fa297, 0xb802, 0x4bf8, 0x9d, 0xc9, 0x5e, 0x3b, 0x6a, 0x9f, 0x53, 0xc9);")