[PATCH] mf/samplegrabber: Implement IMFRateSupport.

Nikolay Sivov nsivov at codeweavers.com
Thu Nov 19 06:21:40 CST 2020


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




More information about the wine-devel mailing list