[PATCH 4/7] mf: Add stream sink stub for SAR.

Nikolay Sivov nsivov at codeweavers.com
Wed Apr 8 09:21:25 CDT 2020


Signed-off-by: Nikolay Sivov <nsivov at codeweavers.com>
---
 dlls/mf/sar.c      | 249 ++++++++++++++++++++++++++++++++++++++++++++-
 dlls/mf/tests/mf.c |  60 ++++++++++-
 2 files changed, 304 insertions(+), 5 deletions(-)

diff --git a/dlls/mf/sar.c b/dlls/mf/sar.c
index 5d74238a91..77025fdc7c 100644
--- a/dlls/mf/sar.c
+++ b/dlls/mf/sar.c
@@ -30,6 +30,16 @@
 
 WINE_DEFAULT_DEBUG_CHANNEL(mfplat);
 
+struct audio_renderer;
+
+struct audio_renderer_stream
+{
+    IMFStreamSink IMFStreamSink_iface;
+    LONG refcount;
+    struct audio_renderer *sink;
+    CRITICAL_SECTION cs;
+};
+
 struct audio_renderer
 {
     IMFMediaSink IMFMediaSink_iface;
@@ -40,6 +50,7 @@ struct audio_renderer
     IMFMediaEventQueue *event_queue;
     IMFPresentationClock *clock;
     BOOL is_shut_down;
+    struct audio_renderer_stream *stream;
     CRITICAL_SECTION cs;
 };
 
@@ -63,6 +74,11 @@ static struct audio_renderer *impl_from_IMFMediaEventGenerator(IMFMediaEventGene
     return CONTAINING_RECORD(iface, struct audio_renderer, IMFMediaEventGenerator_iface);
 }
 
+static struct audio_renderer_stream *impl_from_IMFStreamSink(IMFStreamSink *iface)
+{
+    return CONTAINING_RECORD(iface, struct audio_renderer_stream, IMFStreamSink_iface);
+}
+
 static HRESULT WINAPI audio_renderer_sink_QueryInterface(IMFMediaSink *iface, REFIID riid, void **obj)
 {
     struct audio_renderer *renderer = impl_from_IMFMediaSink(iface);
@@ -179,17 +195,54 @@ static HRESULT WINAPI audio_renderer_sink_GetStreamSinkCount(IMFMediaSink *iface
 static HRESULT WINAPI audio_renderer_sink_GetStreamSinkByIndex(IMFMediaSink *iface, DWORD index,
         IMFStreamSink **stream)
 {
-    FIXME("%p, %u, %p.\n", iface, index, stream);
+    struct audio_renderer *renderer = impl_from_IMFMediaSink(iface);
+    HRESULT hr = S_OK;
 
-    return E_NOTIMPL;
+    TRACE("%p, %u, %p.\n", iface, index, stream);
+
+    if (renderer->is_shut_down)
+        return MF_E_SHUTDOWN;
+
+    EnterCriticalSection(&renderer->cs);
+
+    if (renderer->is_shut_down)
+        hr = MF_E_SHUTDOWN;
+    else if (index > 0)
+        hr = MF_E_INVALIDINDEX;
+    else
+    {
+       *stream = &renderer->stream->IMFStreamSink_iface;
+       IMFStreamSink_AddRef(*stream);
+    }
+
+    LeaveCriticalSection(&renderer->cs);
+
+    return hr;
 }
 
 static HRESULT WINAPI audio_renderer_sink_GetStreamSinkById(IMFMediaSink *iface, DWORD stream_sink_id,
         IMFStreamSink **stream)
 {
-    FIXME("%p, %#x, %p.\n", iface, stream_sink_id, stream);
+    struct audio_renderer *renderer = impl_from_IMFMediaSink(iface);
+    HRESULT hr = S_OK;
 
-    return E_NOTIMPL;
+    TRACE("%p, %#x, %p.\n", iface, stream_sink_id, stream);
+
+    EnterCriticalSection(&renderer->cs);
+
+    if (renderer->is_shut_down)
+        hr = MF_E_SHUTDOWN;
+    else if (stream_sink_id > 0)
+        hr = MF_E_INVALIDSTREAMNUMBER;
+    else
+    {
+        *stream = &renderer->stream->IMFStreamSink_iface;
+        IMFStreamSink_AddRef(*stream);
+    }
+
+    LeaveCriticalSection(&renderer->cs);
+
+    return hr;
 }
 
 static HRESULT WINAPI audio_renderer_sink_SetPresentationClock(IMFMediaSink *iface, IMFPresentationClock *clock)
@@ -260,8 +313,19 @@ static HRESULT WINAPI audio_renderer_sink_Shutdown(IMFMediaSink *iface)
         return MF_E_SHUTDOWN;
 
     EnterCriticalSection(&renderer->cs);
+
     renderer->is_shut_down = TRUE;
     IMFMediaEventQueue_Shutdown(renderer->event_queue);
+
+    /* Detach stream. */
+    IMFMediaSink_Release(&renderer->stream->sink->IMFMediaSink_iface);
+    EnterCriticalSection(&renderer->stream->cs);
+    renderer->stream->sink = NULL;
+    LeaveCriticalSection(&renderer->stream->cs);
+
+    IMFStreamSink_Release(&renderer->stream->IMFStreamSink_iface);
+    renderer->stream = NULL;
+
     LeaveCriticalSection(&renderer->cs);
 
     return S_OK;
@@ -494,6 +558,180 @@ static HRESULT sar_create_mmdevice(IMFAttributes *attributes, IMMDevice **device
     return hr;
 }
 
+static HRESULT WINAPI audio_renderer_stream_QueryInterface(IMFStreamSink *iface, REFIID riid, void **obj)
+{
+    TRACE("%p, %s, %p.\n", iface, debugstr_guid(riid), obj);
+
+    if (IsEqualIID(riid, &IID_IMFStreamSink) ||
+            IsEqualIID(riid, &IID_IUnknown))
+    {
+        *obj = iface;
+    }
+    else
+    {
+        WARN("Unsupported %s.\n", debugstr_guid(riid));
+        *obj = NULL;
+        return E_NOINTERFACE;
+    }
+
+    IUnknown_AddRef((IUnknown *)*obj);
+
+    return S_OK;
+}
+
+static ULONG WINAPI audio_renderer_stream_AddRef(IMFStreamSink *iface)
+{
+    struct audio_renderer_stream *stream = impl_from_IMFStreamSink(iface);
+    ULONG refcount = InterlockedIncrement(&stream->refcount);
+
+    TRACE("%p, refcount %u.\n", iface, refcount);
+
+    return refcount;
+}
+
+static ULONG WINAPI audio_renderer_stream_Release(IMFStreamSink *iface)
+{
+    struct audio_renderer_stream *stream = impl_from_IMFStreamSink(iface);
+    ULONG refcount = InterlockedDecrement(&stream->refcount);
+
+    TRACE("%p, refcount %u.\n", iface, refcount);
+
+    if (!refcount)
+    {
+        if (stream->sink)
+            IMFMediaSink_Release(&stream->sink->IMFMediaSink_iface);
+        DeleteCriticalSection(&stream->cs);
+        heap_free(stream);
+    }
+
+    return refcount;
+}
+
+static HRESULT WINAPI audio_renderer_stream_GetEvent(IMFStreamSink *iface, DWORD flags, IMFMediaEvent **event)
+{
+    FIXME("%p, %#x, %p.\n", iface, flags, event);
+
+    return E_NOTIMPL;
+}
+
+static HRESULT WINAPI audio_renderer_stream_BeginGetEvent(IMFStreamSink *iface, IMFAsyncCallback *callback,
+        IUnknown *state)
+{
+    FIXME("%p, %p, %p.\n", iface, callback, state);
+
+    return E_NOTIMPL;
+}
+
+static HRESULT WINAPI audio_renderer_stream_EndGetEvent(IMFStreamSink *iface, IMFAsyncResult *result,
+        IMFMediaEvent **event)
+{
+    FIXME("%p, %p, %p.\n", iface, result, event);
+
+    return E_NOTIMPL;
+}
+
+static HRESULT WINAPI audio_renderer_stream_QueueEvent(IMFStreamSink *iface, MediaEventType event_type,
+        REFGUID ext_type, HRESULT hr, const PROPVARIANT *value)
+{
+    FIXME("%p, %u, %s, %#x, %p.\n", iface, event_type, debugstr_guid(ext_type), hr, value);
+
+    return E_NOTIMPL;
+}
+
+static HRESULT WINAPI audio_renderer_stream_GetMediaSink(IMFStreamSink *iface, IMFMediaSink **sink)
+{
+    struct audio_renderer_stream *stream = impl_from_IMFStreamSink(iface);
+
+    TRACE("%p, %p.\n", iface, sink);
+
+    if (!stream->sink)
+        return MF_E_STREAMSINK_REMOVED;
+
+    *sink = &stream->sink->IMFMediaSink_iface;
+    IMFMediaSink_AddRef(*sink);
+
+    return S_OK;
+}
+
+static HRESULT WINAPI audio_renderer_stream_GetIdentifier(IMFStreamSink *iface, DWORD *identifier)
+{
+    struct audio_renderer_stream *stream = impl_from_IMFStreamSink(iface);
+
+    TRACE("%p, %p.\n", iface, identifier);
+
+    if (!stream->sink)
+        return MF_E_STREAMSINK_REMOVED;
+
+    *identifier = 0;
+
+    return S_OK;
+}
+
+static HRESULT WINAPI audio_renderer_stream_GetMediaTypeHandler(IMFStreamSink *iface, IMFMediaTypeHandler **handler)
+{
+    FIXME("%p, %p.\n", iface, handler);
+
+    return E_NOTIMPL;
+}
+
+static HRESULT WINAPI audio_renderer_stream_ProcessSample(IMFStreamSink *iface, IMFSample *sample)
+{
+    FIXME("%p, %p.\n", iface, sample);
+
+    return E_NOTIMPL;
+}
+
+static HRESULT WINAPI audio_renderer_stream_PlaceMarker(IMFStreamSink *iface, MFSTREAMSINK_MARKER_TYPE marker_type,
+        const PROPVARIANT *marker_value, const PROPVARIANT *context_value)
+{
+    FIXME("%p, %d, %p, %p.\n", iface, marker_type, marker_value, context_value);
+
+    return E_NOTIMPL;
+}
+
+static HRESULT WINAPI audio_renderer_stream_Flush(IMFStreamSink *iface)
+{
+    FIXME("%p.\n", iface);
+
+    return E_NOTIMPL;
+}
+
+static const IMFStreamSinkVtbl audio_renderer_stream_vtbl =
+{
+    audio_renderer_stream_QueryInterface,
+    audio_renderer_stream_AddRef,
+    audio_renderer_stream_Release,
+    audio_renderer_stream_GetEvent,
+    audio_renderer_stream_BeginGetEvent,
+    audio_renderer_stream_EndGetEvent,
+    audio_renderer_stream_QueueEvent,
+    audio_renderer_stream_GetMediaSink,
+    audio_renderer_stream_GetIdentifier,
+    audio_renderer_stream_GetMediaTypeHandler,
+    audio_renderer_stream_ProcessSample,
+    audio_renderer_stream_PlaceMarker,
+    audio_renderer_stream_Flush,
+};
+
+static HRESULT audio_renderer_create_stream(struct audio_renderer *sink, struct audio_renderer_stream **stream)
+{
+    struct audio_renderer_stream *object;
+
+    object = heap_alloc_zero(sizeof(*object));
+    if (!object)
+        return E_OUTOFMEMORY;
+
+    object->IMFStreamSink_iface.lpVtbl = &audio_renderer_stream_vtbl;
+    object->refcount = 1;
+    object->sink = sink;
+    IMFMediaSink_AddRef(&object->sink->IMFMediaSink_iface);
+    InitializeCriticalSection(&object->cs);
+
+    *stream = object;
+
+    return S_OK;
+}
+
 static HRESULT sar_create_object(IMFAttributes *attributes, void *user_context, IUnknown **obj)
 {
     struct audio_renderer *renderer;
@@ -512,6 +750,9 @@ static HRESULT sar_create_object(IMFAttributes *attributes, void *user_context,
     renderer->refcount = 1;
     InitializeCriticalSection(&renderer->cs);
 
+    if (FAILED(hr = audio_renderer_create_stream(renderer, &renderer->stream)))
+        goto failed;
+
     if (FAILED(hr = MFCreateEventQueue(&renderer->event_queue)))
         goto failed;
 
diff --git a/dlls/mf/tests/mf.c b/dlls/mf/tests/mf.c
index 4f29362102..3b919d536a 100644
--- a/dlls/mf/tests/mf.c
+++ b/dlls/mf/tests/mf.c
@@ -38,7 +38,9 @@ DEFINE_GUID(MFVideoFormat_ABGR32, 0x00000020, 0x0000, 0x0010, 0x80, 0x00, 0x00,
 #include "mfapi.h"
 #include "mferror.h"
 #include "mfidl.h"
+#include "initguid.h"
 #include "mmdeviceapi.h"
+#include "audioclient.h"
 
 #include "wine/test.h"
 
@@ -2634,16 +2636,19 @@ static void test_sar(void)
 {
     IMFPresentationClock *present_clock, *present_clock2;
     IMFPresentationTimeSource *time_source;
+    IMFMediaType *mediatype, *mediatype2;
     IMFClockStateSink *state_sink;
+    IMFMediaTypeHandler *handler;
     IMFMediaSink *sink, *sink2;
     IMFStreamSink *stream_sink;
     IMFAttributes *attributes;
+    DWORD id, flags, count;
     IMFActivate *activate;
     MFCLOCK_STATE state;
-    DWORD flags, count;
     IMFClock *clock;
     IUnknown *unk;
     HRESULT hr;
+    GUID guid;
 
     hr = CoInitialize(NULL);
     ok(hr == S_OK, "Failed to initialize, hr %#x.\n", hr);
@@ -2746,6 +2751,59 @@ todo_wine
     ok(present_clock == present_clock2, "Unexpected instance.\n");
     IMFPresentationClock_Release(present_clock2);
 
+    /* Stream */
+    hr = IMFMediaSink_GetStreamSinkByIndex(sink, 0, &stream_sink);
+    ok(hr == S_OK, "Failed to get a stream, hr %#x.\n", hr);
+
+    hr = IMFStreamSink_GetIdentifier(stream_sink, &id);
+    ok(hr == S_OK, "Unexpected hr %#x.\n", hr);
+    ok(!id, "Unexpected id.\n");
+
+    hr = IMFStreamSink_GetMediaSink(stream_sink, &sink2);
+    ok(hr == S_OK, "Unexpected hr %#x.\n", hr);
+    ok(sink == sink2, "Unexpected object.\n");
+    IMFMediaSink_Release(sink2);
+
+    hr = IMFStreamSink_GetMediaTypeHandler(stream_sink, &handler);
+todo_wine
+    ok(hr == S_OK, "Unexpected hr %#x.\n", hr);
+
+if (SUCCEEDED(hr))
+{
+    hr = IMFMediaTypeHandler_GetMajorType(handler, &guid);
+    ok(hr == S_OK, "Failed to get major type, hr %#x.\n", hr);
+    ok(IsEqualGUID(&guid, &MFMediaType_Audio), "Unexpected type %s.\n", wine_dbgstr_guid(&guid));
+
+    hr = IMFMediaTypeHandler_GetMediaTypeCount(handler, &count);
+    ok(hr == S_OK, "Failed to get type count, hr %#x.\n", hr);
+    ok(count > 0, "Unexpected type count %u.\n", count);
+
+    hr = IMFMediaTypeHandler_GetCurrentMediaType(handler, &mediatype);
+    ok(hr == MF_E_NOT_INITIALIZED, "Unexpected hr %#x.\n", hr);
+
+    hr = MFCreateMediaType(&mediatype);
+    ok(hr == S_OK, "Failed to create media type, hr %#x.\n", hr);
+
+    hr = IMFMediaTypeHandler_IsMediaTypeSupported(handler, mediatype, NULL);
+    ok(hr == MF_E_ATTRIBUTENOTFOUND, "Unexpected hr %#x.\n", hr);
+
+    IMFMediaType_SetGUID(mediatype, &MF_MT_MAJOR_TYPE, &MFMediaType_Audio);
+    hr = IMFMediaTypeHandler_IsMediaTypeSupported(handler, mediatype, NULL);
+    ok(hr == MF_E_INVALIDMEDIATYPE, "Unexpected hr %#x.\n", hr);
+
+    hr = IMFMediaTypeHandler_GetMediaTypeByIndex(handler, 0, &mediatype2);
+    ok(hr == S_OK, "Failed to get media type, hr %#x.\n", hr);
+
+    hr = IMFMediaTypeHandler_IsMediaTypeSupported(handler, mediatype2, NULL);
+    ok(hr == MF_E_INVALIDMEDIATYPE, "Unexpected hr %#x.\n", hr);
+
+    IMFMediaType_Release(mediatype2);
+    IMFMediaType_Release(mediatype);
+
+    IMFMediaTypeHandler_Release(handler);
+}
+    IMFStreamSink_Release(stream_sink);
+
     /* Shutdown */
     hr = IMFMediaSink_Shutdown(sink);
     ok(hr == S_OK, "Failed to shut down, hr %#x.\n", hr);
-- 
2.25.1




More information about the wine-devel mailing list