[PATCH] mf: Implement type handler methods for sample grabber stream.

Nikolay Sivov nsivov at codeweavers.com
Mon May 27 09:07:37 CDT 2019


Signed-off-by: Nikolay Sivov <nsivov at codeweavers.com>
---
 dlls/mf/samplegrabber.c |  81 +++++++++++++++++++++-------
 dlls/mf/tests/mf.c      | 117 +++++++++++++++++++++++++++++++++++++---
 2 files changed, 172 insertions(+), 26 deletions(-)

diff --git a/dlls/mf/samplegrabber.c b/dlls/mf/samplegrabber.c
index b62502f4f1..86dcb13a6c 100644
--- a/dlls/mf/samplegrabber.c
+++ b/dlls/mf/samplegrabber.c
@@ -28,12 +28,14 @@
 
 WINE_DEFAULT_DEBUG_CHANNEL(mfplat);
 
+struct sample_grabber;
+
 struct sample_grabber_stream
 {
     IMFStreamSink IMFStreamSink_iface;
     IMFMediaTypeHandler IMFMediaTypeHandler_iface;
     LONG refcount;
-    IMFMediaSink *sink;
+    struct sample_grabber *sink;
     IMFMediaEventQueue *event_queue;
 };
 
@@ -136,7 +138,7 @@ static ULONG WINAPI sample_grabber_stream_Release(IMFStreamSink *iface)
 
     if (!refcount)
     {
-        IMFMediaSink_Release(stream->sink);
+        IMFMediaSink_Release(&stream->sink->IMFMediaSink_iface);
         if (stream->event_queue)
         {
             IMFMediaEventQueue_Shutdown(stream->event_queue);
@@ -193,7 +195,7 @@ static HRESULT WINAPI sample_grabber_stream_GetMediaSink(IMFStreamSink *iface, I
 
     TRACE("%p, %p.\n", iface, sink);
 
-    *sink = stream->sink;
+    *sink = &stream->sink->IMFMediaSink_iface;
     IMFMediaSink_AddRef(*sink);
 
     return S_OK;
@@ -281,47 +283,81 @@ static ULONG WINAPI sample_grabber_stream_type_handler_Release(IMFMediaTypeHandl
 static HRESULT WINAPI sample_grabber_stream_type_handler_IsMediaTypeSupported(IMFMediaTypeHandler *iface,
         IMFMediaType *in_type, IMFMediaType **out_type)
 {
-    FIXME("%p, %p, %p.\n", iface, in_type, out_type);
+    struct sample_grabber_stream *stream = impl_from_IMFMediaTypeHandler(iface);
+    const DWORD supported_flags = MF_MEDIATYPE_EQUAL_MAJOR_TYPES | MF_MEDIATYPE_EQUAL_FORMAT_TYPES;
+    DWORD flags;
 
-    return E_NOTIMPL;
+    TRACE("%p, %p, %p.\n", iface, in_type, out_type);
+
+    if (!in_type)
+        return E_POINTER;
+
+    if (IMFMediaType_IsEqual(stream->sink->media_type, in_type, &flags) == S_OK)
+        return S_OK;
+
+    return (flags & supported_flags) == supported_flags ? S_OK : MF_E_INVALIDMEDIATYPE;
 }
 
 static HRESULT WINAPI sample_grabber_stream_type_handler_GetMediaTypeCount(IMFMediaTypeHandler *iface, DWORD *count)
 {
-    FIXME("%p, %p.\n", iface, count);
+    TRACE("%p, %p.\n", iface, count);
 
-    return E_NOTIMPL;
+    if (!count)
+        return E_POINTER;
+
+    *count = 0;
+
+    return S_OK;
 }
 
 static HRESULT WINAPI sample_grabber_stream_type_handler_GetMediaTypeByIndex(IMFMediaTypeHandler *iface, DWORD index,
-        IMFMediaType **type)
+        IMFMediaType **media_type)
 {
-    FIXME("%p, %u, %p.\n", iface, index, type);
+    TRACE("%p, %u, %p.\n", iface, index, media_type);
 
-    return E_NOTIMPL;
+    if (!media_type)
+        return E_POINTER;
+
+    return MF_E_NO_MORE_TYPES;
 }
 
 static HRESULT WINAPI sample_grabber_stream_type_handler_SetCurrentMediaType(IMFMediaTypeHandler *iface,
-        IMFMediaType *type)
+        IMFMediaType *media_type)
 {
-    FIXME("%p, %p.\n", iface, type);
+    struct sample_grabber_stream *stream = impl_from_IMFMediaTypeHandler(iface);
 
-    return E_NOTIMPL;
+    TRACE("%p, %p.\n", iface, media_type);
+
+    if (!media_type)
+        return E_POINTER;
+
+    IMFMediaType_Release(stream->sink->media_type);
+    stream->sink->media_type = media_type;
+    IMFMediaType_AddRef(stream->sink->media_type);
+
+    return S_OK;
 }
 
 static HRESULT WINAPI sample_grabber_stream_type_handler_GetCurrentMediaType(IMFMediaTypeHandler *iface,
         IMFMediaType **type)
 {
-    FIXME("%p, %p.\n", iface, type);
+    struct sample_grabber_stream *stream = impl_from_IMFMediaTypeHandler(iface);
 
-    return E_NOTIMPL;
+    TRACE("%p, %p.\n", iface, type);
+
+    *type = stream->sink->media_type;
+    IMFMediaType_AddRef(*type);
+
+    return S_OK;
 }
 
 static HRESULT WINAPI sample_grabber_stream_type_handler_GetMajorType(IMFMediaTypeHandler *iface, GUID *type)
 {
-    FIXME("%p, %p.\n", iface, type);
+    struct sample_grabber_stream *stream = impl_from_IMFMediaTypeHandler(iface);
 
-    return E_NOTIMPL;
+    TRACE("%p, %p.\n", iface, type);
+
+    return IMFMediaType_GetMajorType(stream->sink->media_type, type);
 }
 
 static const IMFMediaTypeHandlerVtbl sample_grabber_stream_type_handler_vtbl =
@@ -682,7 +718,7 @@ static const IMFClockStateSinkVtbl sample_grabber_clock_sink_vtbl =
     sample_grabber_clock_sink_OnClockSetRate,
 };
 
-static HRESULT sample_grabber_create_stream(IMFMediaSink *sink, IMFStreamSink **stream)
+static HRESULT sample_grabber_create_stream(struct sample_grabber *sink, IMFStreamSink **stream)
 {
     struct sample_grabber_stream *object;
     HRESULT hr;
@@ -695,7 +731,7 @@ static HRESULT sample_grabber_create_stream(IMFMediaSink *sink, IMFStreamSink **
     object->IMFMediaTypeHandler_iface.lpVtbl = &sample_grabber_stream_type_handler_vtbl;
     object->refcount = 1;
     object->sink = sink;
-    IMFMediaSink_AddRef(object->sink);
+    IMFMediaSink_AddRef(&object->sink->IMFMediaSink_iface);
 
     if (FAILED(hr = MFCreateEventQueue(&object->event_queue)))
         goto failed;
@@ -715,9 +751,14 @@ static HRESULT sample_grabber_create_object(IMFAttributes *attributes, void *use
     struct sample_grabber_activate_context *context = user_context;
     struct sample_grabber *object;
     HRESULT hr;
+    GUID guid;
 
     TRACE("%p, %p, %p.\n", attributes, user_context, obj);
 
+    /* At least major type is required. */
+    if (FAILED(IMFMediaType_GetMajorType(context->media_type, &guid)))
+        return MF_E_INVALIDMEDIATYPE;
+
     object = heap_alloc_zero(sizeof(*object));
     if (!object)
         return E_OUTOFMEMORY;
@@ -732,7 +773,7 @@ static HRESULT sample_grabber_create_object(IMFAttributes *attributes, void *use
     IMFMediaType_AddRef(object->media_type);
     InitializeCriticalSection(&object->cs);
 
-    if (FAILED(hr = sample_grabber_create_stream(&object->IMFMediaSink_iface, &object->stream)))
+    if (FAILED(hr = sample_grabber_create_stream(object, &object->stream)))
         goto failed;
 
     if (FAILED(hr = MFCreateEventQueue(&object->event_queue)))
diff --git a/dlls/mf/tests/mf.c b/dlls/mf/tests/mf.c
index 317d611c2f..b381daf882 100644
--- a/dlls/mf/tests/mf.c
+++ b/dlls/mf/tests/mf.c
@@ -1638,17 +1638,23 @@ static IMFSampleGrabberSinkCallback grabber_callback = { &grabber_callback_vtbl
 
 static void test_sample_grabber(void)
 {
+    IMFMediaType *media_type, *media_type2, *media_type3;
     IMFMediaTypeHandler *handler, *handler2;
+    IMFPresentationTimeSource *time_source;
     IMFStreamSink *stream, *stream2;
     IMFClockStateSink *clocksink;
+    IMFPresentationClock *clock;
     IMFMediaEventGenerator *eg;
     IMFMediaSink *sink, *sink2;
-    IMFMediaType *media_type;
     DWORD flags, count, id;
     IMFActivate *activate;
     ULONG refcount;
     IUnknown *unk;
     HRESULT hr;
+    GUID guid;
+
+    hr = MFStartup(MF_VERSION, MFSTARTUP_FULL);
+    ok(hr == S_OK, "Failed to start up, hr %#x.\n", hr);
 
     hr = MFCreateMediaType(&media_type);
     ok(hr == S_OK, "Failed to create media type, hr %#x.\n", hr);
@@ -1725,15 +1731,32 @@ static void test_sample_grabber(void)
     hr = IMFStreamSink_GetMediaTypeHandler(stream, &handler);
     ok(hr == S_OK, "Failed to get type handler, hr %#x.\n", hr);
     hr = IMFMediaTypeHandler_GetMediaTypeCount(handler, &count);
-todo_wine {
     ok(hr == S_OK, "Failed to get media type count, hr %#x.\n", hr);
     ok(count == 0, "Unexpected count %u.\n", count);
-}
     ok(handler == handler2, "Unexpected handler.\n");
 
     IMFMediaTypeHandler_Release(handler);
     IMFMediaTypeHandler_Release(handler2);
 
+    /* Set clock. */
+    hr = MFCreatePresentationClock(&clock);
+    ok(hr == S_OK, "Failed to create clock object, hr %#x.\n", hr);
+
+    hr = IMFMediaSink_SetPresentationClock(sink, clock);
+    ok(hr == E_NOTIMPL, "Unexpected hr %#x.\n", hr);
+
+    hr = MFCreateSystemTimeSource(&time_source);
+    ok(hr == S_OK, "Failed to create time source, hr %#x.\n", hr);
+
+    hr = IMFPresentationClock_SetTimeSource(clock, time_source);
+    ok(hr == S_OK, "Failed to set time source, hr %#x.\n", hr);
+    IMFPresentationTimeSource_Release(time_source);
+
+    hr = IMFMediaSink_SetPresentationClock(sink, clock);
+    ok(hr == E_NOTIMPL, "Unexpected hr %#x.\n", hr);
+
+    IMFPresentationClock_Release(clock);
+
     hr = IMFActivate_ShutdownObject(activate);
 todo_wine
     ok(hr == S_OK, "Failed to shut down, hr %#x.\n", hr);
@@ -1768,20 +1791,102 @@ todo_wine
     hr = IMFStreamSink_GetMediaTypeHandler(stream, &handler);
     ok(hr == S_OK, "Failed to get type handler, hr %#x.\n", hr);
 
+    /* On Win8+ this initialization happens automatically. */
+    hr = IMFMediaTypeHandler_SetCurrentMediaType(handler, media_type);
+    ok(hr == S_OK, "Failed to set media type, hr %#x.\n", hr);
+
+    hr = IMFMediaTypeHandler_GetMediaTypeCount(handler, NULL);
+    ok(hr == E_POINTER, "Unexpected hr %#x.\n", hr);
+
     hr = IMFMediaTypeHandler_GetMediaTypeCount(handler, &count);
-todo_wine {
     ok(hr == S_OK, "Failed to get media type count, hr %#x.\n", hr);
     ok(count == 0, "Unexpected count %u.\n", count);
-}
+
+    hr = IMFMediaTypeHandler_GetMajorType(handler, &guid);
+    ok(hr == S_OK, "Failed to get major type, hr %#x.\n", hr);
+    ok(IsEqualGUID(&guid, &MFMediaType_Audio), "Unexpected major type %s.\n", wine_dbgstr_guid(&guid));
+
+    hr = IMFMediaTypeHandler_GetCurrentMediaType(handler, &media_type2);
+    ok(hr == S_OK, "Failed to get current type, hr %#x.\n", hr);
+    ok(media_type2 == media_type, "Unexpected media type.\n");
+    IMFMediaType_Release(media_type2);
+
+    hr = MFCreateMediaType(&media_type2);
+    ok(hr == S_OK, "Failed to create media type, hr %#x.\n", hr);
+
+    hr = IMFMediaType_SetGUID(media_type2, &MF_MT_MAJOR_TYPE, &MFMediaType_Audio);
+    ok(hr == S_OK, "Failed to set attribute, hr %#x.\n", hr);
+    hr = IMFMediaType_SetGUID(media_type2, &MF_MT_SUBTYPE, &MFAudioFormat_PCM);
+    ok(hr == S_OK, "Failed to set attribute, hr %#x.\n", hr);
+
+    hr = IMFMediaTypeHandler_SetCurrentMediaType(handler, media_type2);
+    ok(hr == S_OK, "Failed to get current type, hr %#x.\n", hr);
+    IMFMediaType_Release(media_type);
+
+    hr = IMFMediaTypeHandler_SetCurrentMediaType(handler, NULL);
+    ok(hr == E_POINTER, "Unexpected hr %#x.\n", hr);
+
+    hr = IMFMediaTypeHandler_GetCurrentMediaType(handler, &media_type);
+    ok(hr == S_OK, "Failed to get current type, hr %#x.\n", hr);
+    ok(media_type2 == media_type, "Unexpected media type.\n");
+    IMFMediaType_Release(media_type);
+
+    hr = IMFMediaTypeHandler_GetMediaTypeByIndex(handler, 0, &media_type);
+    ok(hr == MF_E_NO_MORE_TYPES, "Unexpected hr %#x.\n", hr);
+
+    hr = IMFMediaTypeHandler_GetMediaTypeByIndex(handler, 0, NULL);
+    ok(hr == E_POINTER, "Unexpected hr %#x.\n", hr);
+
+    hr = IMFMediaTypeHandler_IsMediaTypeSupported(handler, media_type2, NULL);
+    ok(hr == S_OK, "Unexpected hr %#x.\n", hr);
+
+    hr = MFCreateMediaType(&media_type);
+    ok(hr == S_OK, "Failed to create media type, hr %#x.\n", hr);
+
+    hr = IMFMediaType_SetGUID(media_type, &MF_MT_MAJOR_TYPE, &MFMediaType_Audio);
+    ok(hr == S_OK, "Failed to set attribute, hr %#x.\n", hr);
+
+    hr = IMFMediaTypeHandler_IsMediaTypeSupported(handler, media_type, NULL);
+    ok(hr == MF_E_INVALIDMEDIATYPE, "Unexpected hr %#x.\n", hr);
+
+    hr = IMFMediaTypeHandler_IsMediaTypeSupported(handler, media_type, &media_type3);
+    ok(hr == MF_E_INVALIDMEDIATYPE, "Unexpected hr %#x.\n", hr);
+
+    hr = IMFMediaType_SetGUID(media_type, &MF_MT_SUBTYPE, &MFAudioFormat_PCM);
+    ok(hr == S_OK, "Failed to set attribute, hr %#x.\n", hr);
+
+    media_type3 = (void *)0xdeadbeef;
+    hr = IMFMediaTypeHandler_IsMediaTypeSupported(handler, media_type, &media_type3);
+    ok(hr == S_OK, "Unexpected hr %#x.\n", hr);
+    ok(media_type3 == (void *)0xdeadbeef, "Unexpected media type %p.\n", media_type3);
+
+    hr = IMFMediaType_SetUINT32(media_type, &MF_MT_FIXED_SIZE_SAMPLES, 1);
+    ok(hr == S_OK, "Failed to set attribute, hr %#x.\n", hr);
+
+    hr = IMFMediaType_SetUINT32(media_type, &MF_MT_SAMPLE_SIZE, 1024);
+    ok(hr == S_OK, "Failed to set attribute, hr %#x.\n", hr);
+
+    media_type3 = (void *)0xdeadbeef;
+    hr = IMFMediaTypeHandler_IsMediaTypeSupported(handler, media_type, &media_type3);
+    ok(hr == S_OK, "Unexpected hr %#x.\n", hr);
+    ok(media_type3 == (void *)0xdeadbeef, "Unexpected media type %p.\n", media_type3);
+
+    hr = IMFMediaTypeHandler_IsMediaTypeSupported(handler, NULL, NULL);
+    ok(hr == E_POINTER, "Unexpected hr %#x.\n", hr);
+
     IMFMediaTypeHandler_Release(handler);
 
+    IMFMediaType_Release(media_type2);
+    IMFMediaType_Release(media_type);
+
     IMFMediaSink_Release(sink);
     IMFStreamSink_Release(stream);
 
     refcount = IMFActivate_Release(activate);
     ok(!refcount, "Unexpected refcount %u.\n", refcount);
 
-    IMFMediaType_Release(media_type);
+    hr = MFShutdown();
+    ok(hr == S_OK, "Failed to shut down, hr %#x.\n", hr);
 }
 
 START_TEST(mf)
-- 
2.20.1




More information about the wine-devel mailing list