Signed-off-by: Nikolay Sivov nsivov@codeweavers.com --- dlls/mf/samplegrabber.c | 127 ++++++++++++++++++++++++++++++++++++++++ dlls/mf/tests/mf.c | 66 +++++++++++++++++++++ 2 files changed, 193 insertions(+)
diff --git a/dlls/mf/samplegrabber.c b/dlls/mf/samplegrabber.c index 566ee2f2930..54e28b466c5 100644 --- a/dlls/mf/samplegrabber.c +++ b/dlls/mf/samplegrabber.c @@ -18,6 +18,8 @@
#define COBJMACROS
+#include <float.h> + #include "mfidl.h" #include "mf_private.h"
@@ -61,6 +63,8 @@ struct sample_grabber IMFMediaSink IMFMediaSink_iface; IMFClockStateSink IMFClockStateSink_iface; IMFMediaEventGenerator IMFMediaEventGenerator_iface; + IMFGetService IMFGetService_iface; + IMFRateSupport IMFRateSupport_iface; IMFStreamSink IMFStreamSink_iface; IMFMediaTypeHandler IMFMediaTypeHandler_iface; IMFAsyncCallback timer_callback; @@ -117,6 +121,16 @@ static struct sample_grabber *impl_from_IMFMediaEventGenerator(IMFMediaEventGene return CONTAINING_RECORD(iface, struct sample_grabber, IMFMediaEventGenerator_iface); }
+static struct sample_grabber *impl_from_IMFGetService(IMFGetService *iface) +{ + return CONTAINING_RECORD(iface, struct sample_grabber, IMFGetService_iface); +} + +static struct sample_grabber *impl_from_IMFRateSupport(IMFRateSupport *iface) +{ + return CONTAINING_RECORD(iface, struct sample_grabber, IMFRateSupport_iface); +} + static struct sample_grabber *impl_from_IMFStreamSink(IMFStreamSink *iface) { return CONTAINING_RECORD(iface, struct sample_grabber, IMFStreamSink_iface); @@ -773,6 +787,14 @@ static HRESULT WINAPI sample_grabber_sink_QueryInterface(IMFMediaSink *iface, RE { *obj = &grabber->IMFMediaEventGenerator_iface; } + else if (IsEqualIID(riid, &IID_IMFGetService)) + { + *obj = &grabber->IMFGetService_iface; + } + else if (IsEqualIID(riid, &IID_IMFRateSupport)) + { + *obj = &grabber->IMFRateSupport_iface; + } else { WARN("Unsupported %s.\n", debugstr_guid(riid)); @@ -1249,6 +1271,109 @@ static const IMFClockStateSinkVtbl sample_grabber_clock_sink_vtbl = sample_grabber_clock_sink_OnClockSetRate, };
+static HRESULT WINAPI sample_grabber_getservice_QueryInterface(IMFGetService *iface, REFIID riid, void **obj) +{ + struct sample_grabber *grabber = impl_from_IMFGetService(iface); + return IMFMediaSink_QueryInterface(&grabber->IMFMediaSink_iface, riid, obj); +} + +static ULONG WINAPI sample_grabber_getservice_AddRef(IMFGetService *iface) +{ + struct sample_grabber *grabber = impl_from_IMFGetService(iface); + return IMFMediaSink_AddRef(&grabber->IMFMediaSink_iface); +} + +static ULONG WINAPI sample_grabber_getservice_Release(IMFGetService *iface) +{ + struct sample_grabber *grabber = impl_from_IMFGetService(iface); + return IMFMediaSink_Release(&grabber->IMFMediaSink_iface); +} + +static HRESULT WINAPI sample_grabber_getservice_GetService(IMFGetService *iface, REFGUID service, + REFIID riid, void **obj) +{ + TRACE("%p, %s, %s, %p.\n", iface, debugstr_guid(service), debugstr_guid(riid), obj); + + if (IsEqualGUID(service, &MF_RATE_CONTROL_SERVICE)) + { + if (IsEqualIID(riid, &IID_IMFRateSupport)) + return IMFGetService_QueryInterface(iface, riid, obj); + + return E_NOINTERFACE; + } + + FIXME("Unsupported service %s, riid %s.\n", debugstr_guid(service), debugstr_guid(riid)); + + return MF_E_UNSUPPORTED_SERVICE; +} + +static const IMFGetServiceVtbl sample_grabber_getservice_vtbl = +{ + sample_grabber_getservice_QueryInterface, + sample_grabber_getservice_AddRef, + sample_grabber_getservice_Release, + sample_grabber_getservice_GetService, +}; + +static HRESULT WINAPI sample_grabber_rate_support_QueryInterface(IMFRateSupport *iface, REFIID riid, void **obj) +{ + struct sample_grabber *grabber = impl_from_IMFRateSupport(iface); + return IMFMediaSink_QueryInterface(&grabber->IMFMediaSink_iface, riid, obj); +} + +static ULONG WINAPI sample_grabber_rate_support_AddRef(IMFRateSupport *iface) +{ + struct sample_grabber *grabber = impl_from_IMFRateSupport(iface); + return IMFMediaSink_AddRef(&grabber->IMFMediaSink_iface); +} + +static ULONG WINAPI sample_grabber_rate_support_Release(IMFRateSupport *iface) +{ + struct sample_grabber *grabber = impl_from_IMFRateSupport(iface); + return IMFMediaSink_Release(&grabber->IMFMediaSink_iface); +} + +static HRESULT WINAPI sample_grabber_rate_support_GetSlowestRate(IMFRateSupport *iface, MFRATE_DIRECTION direction, + BOOL thin, float *rate) +{ + TRACE("%p, %d, %d, %p.\n", iface, direction, thin, rate); + + *rate = 0.0f; + + return S_OK; +} + +static HRESULT WINAPI sample_grabber_rate_support_GetFastestRate(IMFRateSupport *iface, MFRATE_DIRECTION direction, + BOOL thin, float *rate) +{ + TRACE("%p, %d, %d, %p.\n", iface, direction, thin, rate); + + *rate = direction == MFRATE_REVERSE ? -FLT_MAX : FLT_MAX; + + return S_OK; +} + +static HRESULT WINAPI sample_grabber_rate_support_IsRateSupported(IMFRateSupport *iface, BOOL thin, float rate, + float *ret_rate) +{ + TRACE("%p, %d, %f, %p.\n", iface, thin, rate, ret_rate); + + if (ret_rate) + *ret_rate = rate; + + return S_OK; +} + +static const IMFRateSupportVtbl sample_grabber_rate_support_vtbl = +{ + sample_grabber_rate_support_QueryInterface, + sample_grabber_rate_support_AddRef, + sample_grabber_rate_support_Release, + sample_grabber_rate_support_GetSlowestRate, + sample_grabber_rate_support_GetFastestRate, + sample_grabber_rate_support_IsRateSupported, +}; + static HRESULT sample_grabber_create_object(IMFAttributes *attributes, void *user_context, IUnknown **obj) { struct sample_grabber_activate_context *context = user_context; @@ -1272,6 +1397,8 @@ static HRESULT sample_grabber_create_object(IMFAttributes *attributes, void *use object->IMFMediaSink_iface.lpVtbl = &sample_grabber_sink_vtbl; object->IMFClockStateSink_iface.lpVtbl = &sample_grabber_clock_sink_vtbl; object->IMFMediaEventGenerator_iface.lpVtbl = &sample_grabber_sink_events_vtbl; + object->IMFGetService_iface.lpVtbl = &sample_grabber_getservice_vtbl; + object->IMFRateSupport_iface.lpVtbl = &sample_grabber_rate_support_vtbl; object->IMFStreamSink_iface.lpVtbl = &sample_grabber_stream_vtbl; object->IMFMediaTypeHandler_iface.lpVtbl = &sample_grabber_stream_type_handler_vtbl; object->timer_callback.lpVtbl = &sample_grabber_stream_timer_callback_vtbl; diff --git a/dlls/mf/tests/mf.c b/dlls/mf/tests/mf.c index 78a3d75e0a7..2a671225a11 100644 --- a/dlls/mf/tests/mf.c +++ b/dlls/mf/tests/mf.c @@ -20,6 +20,7 @@
#include <stdarg.h> #include <string.h> +#include <float.h>
#define COBJMACROS
@@ -71,6 +72,21 @@ static void check_interface_(unsigned int line, void *iface_ptr, REFIID iid, BOO IUnknown_Release(unk); }
+#define check_service_interface(a, b, c, d) check_service_interface_(__LINE__, a, b, c, d) +static void check_service_interface_(unsigned int line, void *iface_ptr, REFGUID service, REFIID iid, BOOL supported) +{ + IUnknown *iface = iface_ptr; + HRESULT hr, expected_hr; + IUnknown *unk; + + expected_hr = supported ? S_OK : E_NOINTERFACE; + + hr = MFGetService(iface, service, iid, (void **)&unk); + ok_(__FILE__, line)(hr == expected_hr, "Got hr %#x, expected %#x.\n", hr, expected_hr); + if (SUCCEEDED(hr)) + IUnknown_Release(unk); +} + static HWND create_window(void) { RECT r = {0, 0, 640, 480}; @@ -2097,6 +2113,7 @@ static void test_sample_grabber(void) IMFPresentationTimeSource *time_source; IMFPresentationClock *clock, *clock2; IMFStreamSink *stream, *stream2; + IMFRateSupport *rate_support; IMFMediaEventGenerator *eg; IMFMediaSink *sink, *sink2; DWORD flags, count, id; @@ -2104,6 +2121,7 @@ static void test_sample_grabber(void) IMFMediaEvent *event; ULONG refcount; IUnknown *unk; + float rate; HRESULT hr; GUID guid;
@@ -2136,6 +2154,53 @@ static void test_sample_grabber(void) hr = IMFActivate_ActivateObject(activate, &IID_IMFMediaSink, (void **)&sink); ok(hr == S_OK, "Failed to activate object, hr %#x.\n", hr);
+ check_interface(sink, &IID_IMFClockStateSink, TRUE); + check_interface(sink, &IID_IMFMediaEventGenerator, TRUE); + check_interface(sink, &IID_IMFGetService, TRUE); + check_interface(sink, &IID_IMFRateSupport, TRUE); + check_service_interface(sink, &MF_RATE_CONTROL_SERVICE, &IID_IMFRateSupport, TRUE); + + if (SUCCEEDED(MFGetService((IUnknown *)sink, &MF_RATE_CONTROL_SERVICE, &IID_IMFRateSupport, (void **)&rate_support))) + { + hr = IMFRateSupport_GetFastestRate(rate_support, MFRATE_FORWARD, FALSE, &rate); + ok(hr == S_OK, "Unexpected hr %#x.\n", hr); + ok(rate == FLT_MAX, "Unexpected rate %f.\n", rate); + + hr = IMFRateSupport_GetFastestRate(rate_support, MFRATE_FORWARD, TRUE, &rate); + ok(hr == S_OK, "Unexpected hr %#x.\n", hr); + ok(rate == FLT_MAX, "Unexpected rate %f.\n", rate); + + hr = IMFRateSupport_GetFastestRate(rate_support, MFRATE_REVERSE, FALSE, &rate); + ok(hr == S_OK, "Unexpected hr %#x.\n", hr); + ok(rate == -FLT_MAX, "Unexpected rate %f.\n", rate); + + hr = IMFRateSupport_GetFastestRate(rate_support, MFRATE_REVERSE, TRUE, &rate); + ok(hr == S_OK, "Unexpected hr %#x.\n", hr); + ok(rate == -FLT_MAX, "Unexpected rate %f.\n", rate); + + hr = IMFRateSupport_GetSlowestRate(rate_support, MFRATE_FORWARD, FALSE, &rate); + ok(hr == S_OK, "Unexpected hr %#x.\n", hr); + ok(rate == 0.0f, "Unexpected rate %f.\n", rate); + + hr = IMFRateSupport_GetSlowestRate(rate_support, MFRATE_FORWARD, TRUE, &rate); + ok(hr == S_OK, "Unexpected hr %#x.\n", hr); + ok(rate == 0.0f, "Unexpected rate %f.\n", rate); + + hr = IMFRateSupport_GetSlowestRate(rate_support, MFRATE_REVERSE, FALSE, &rate); + ok(hr == S_OK, "Unexpected hr %#x.\n", hr); + ok(rate == 0.0f, "Unexpected rate %f.\n", rate); + + hr = IMFRateSupport_GetSlowestRate(rate_support, MFRATE_REVERSE, TRUE, &rate); + ok(hr == S_OK, "Unexpected hr %#x.\n", hr); + ok(rate == 0.0f, "Unexpected rate %f.\n", rate); + + hr = IMFRateSupport_IsRateSupported(rate_support, TRUE, 1.0f, &rate); + ok(hr == S_OK, "Unexpected hr %#x.\n", hr); + ok(rate == 1.0f, "Unexpected rate %f.\n", rate); + + IMFRateSupport_Release(rate_support); + } + hr = IMFMediaSink_GetCharacteristics(sink, &flags); ok(hr == S_OK, "Failed to get sink flags, hr %#x.\n", hr); ok(flags & MEDIASINK_FIXED_STREAMS, "Unexpected flags %#x.\n", flags); @@ -2148,6 +2213,7 @@ static void test_sample_grabber(void) ok(hr == S_OK, "Failed to get sink stream, hr %#x.\n", hr);
check_interface(stream, &IID_IMFMediaEventGenerator, TRUE); + check_interface(stream, &IID_IMFMediaTypeHandler, TRUE);
hr = IMFStreamSink_GetIdentifier(stream, &id); ok(hr == S_OK, "Failed to get stream id, hr %#x.\n", hr);