mfsrcsnk/wave: Add a sink stub.

Signed-off-by: Nikolay Sivov <nsivov@codeweavers.com>
This commit is contained in:
Nikolay Sivov 2022-08-12 16:02:00 +03:00 committed by Alexandre Julliard
parent 73d6ca6e1e
commit ed7762c1fa
6 changed files with 707 additions and 3 deletions

1
configure vendored
View file

@ -21602,6 +21602,7 @@ wine_fn_config_makefile dlls/mfplay/tests enable_tests
wine_fn_config_makefile dlls/mfreadwrite enable_mfreadwrite
wine_fn_config_makefile dlls/mfreadwrite/tests enable_tests
wine_fn_config_makefile dlls/mfsrcsnk enable_mfsrcsnk
wine_fn_config_makefile dlls/mfsrcsnk/tests enable_tests
wine_fn_config_makefile dlls/mgmtapi enable_mgmtapi
wine_fn_config_makefile dlls/midimap enable_midimap
wine_fn_config_makefile dlls/mlang enable_mlang

View file

@ -2741,6 +2741,7 @@ WINE_CONFIG_MAKEFILE(dlls/mfplay/tests)
WINE_CONFIG_MAKEFILE(dlls/mfreadwrite)
WINE_CONFIG_MAKEFILE(dlls/mfreadwrite/tests)
WINE_CONFIG_MAKEFILE(dlls/mfsrcsnk)
WINE_CONFIG_MAKEFILE(dlls/mfsrcsnk/tests)
WINE_CONFIG_MAKEFILE(dlls/mgmtapi)
WINE_CONFIG_MAKEFILE(dlls/midimap)
WINE_CONFIG_MAKEFILE(dlls/mlang)

View file

@ -1,5 +1,6 @@
MODULE = mfsrcsnk.dll
IMPORTLIB = mfsrcsnk
IMPORTS = mfplat mfuuid uuid
EXTRADLLFLAGS = -Wb,--prefer-native

View file

@ -0,0 +1,5 @@
TESTDLL = mfsrcsnk.dll
IMPORTS = ole32 mfsrcsnk mfplat uuid mfuuid
C_SRCS = \
mfsrcsnk.c

View file

@ -0,0 +1,163 @@
/*
* Copyright 2022 Nikolay Sivov for CodeWeavers
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
*/
#include <stdarg.h>
#include <string.h>
#define COBJMACROS
#include "windef.h"
#include "mfapi.h"
#include "mfidl.h"
#include "mferror.h"
#include "wine/test.h"
#define check_interface(a, b, c) check_interface_(__LINE__, a, b, c)
static void check_interface_(unsigned int line, void *iface_ptr, REFIID iid, BOOL supported)
{
IUnknown *iface = iface_ptr;
HRESULT hr, expected_hr;
IUnknown *unk;
expected_hr = supported ? S_OK : E_NOINTERFACE;
hr = IUnknown_QueryInterface(iface, iid, (void **)&unk);
ok_(__FILE__, line)(hr == expected_hr, "Got hr %#lx, expected %#lx.\n", hr, expected_hr);
if (SUCCEEDED(hr))
IUnknown_Release(unk);
}
static void test_wave_sink(void)
{
IMFStreamSink *stream_sink;
IMFMediaSink *sink, *sink2;
IMFByteStream *bytestream;
IMFMediaType *media_type;
DWORD id, count, flags;
HRESULT hr;
hr = MFCreateWAVEMediaSink(NULL, NULL, NULL);
ok(hr == E_POINTER, "Unexpected hr %#lx.\n", hr);
hr = MFCreateWAVEMediaSink(NULL, NULL, &sink);
ok(hr == E_POINTER, "Unexpected hr %#lx.\n", hr);
hr = MFCreateMediaType(&media_type);
ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
hr = IMFMediaType_SetUINT32(media_type, &MF_MT_AUDIO_BLOCK_ALIGNMENT, 2);
ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
hr = IMFMediaType_SetUINT32(media_type, &MF_MT_AUDIO_NUM_CHANNELS, 2);
ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
hr = IMFMediaType_SetGUID(media_type, &MF_MT_MAJOR_TYPE, &MFMediaType_Audio);
ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
hr = IMFMediaType_SetGUID(media_type, &MF_MT_SUBTYPE, &MFAudioFormat_PCM);
ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
hr = IMFMediaType_SetUINT32(media_type, &MF_MT_AUDIO_SAMPLES_PER_SECOND, 44100);
ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
hr = IMFMediaType_SetUINT32(media_type, &MF_MT_AUDIO_BITS_PER_SAMPLE, 8);
ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
hr = MFCreateTempFile(MF_ACCESSMODE_WRITE, MF_OPENMODE_DELETE_IF_EXIST, 0, &bytestream);
ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
hr = MFCreateWAVEMediaSink(bytestream, NULL, &sink);
ok(hr == E_POINTER, "Unexpected hr %#lx.\n", hr);
hr = MFCreateWAVEMediaSink(bytestream, media_type, &sink);
ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
/* Sink tests */
hr = IMFMediaSink_GetCharacteristics(sink, &flags);
ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
ok(flags == (MEDIASINK_FIXED_STREAMS | MEDIASINK_RATELESS), "Unexpected flags %#lx.\n", flags);
hr = IMFMediaSink_GetStreamSinkCount(sink, NULL);
ok(hr == E_POINTER, "Unexpected hr %#lx.\n", hr);
hr = IMFMediaSink_GetStreamSinkCount(sink, &count);
ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
ok(count == 1, "Unexpected count %lu.\n", count);
hr = IMFMediaSink_AddStreamSink(sink, 123, media_type, &stream_sink);
ok(hr == MF_E_STREAMSINKS_FIXED, "Unexpected hr %#lx.\n", hr);
check_interface(sink, &IID_IMFMediaEventGenerator, TRUE);
check_interface(sink, &IID_IMFFinalizableMediaSink, TRUE);
/* Stream tests */
hr = IMFMediaSink_GetStreamSinkByIndex(sink, 0, &stream_sink);
ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
hr = IMFStreamSink_GetIdentifier(stream_sink, &id);
ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
ok(id == 1, "Unexpected id %#lx.\n", id);
IMFStreamSink_Release(stream_sink);
hr = IMFMediaSink_GetStreamSinkById(sink, 0, &stream_sink);
ok(hr == MF_E_INVALIDSTREAMNUMBER, "Unexpected hr %#lx.\n", hr);
hr = IMFMediaSink_GetStreamSinkById(sink, id, &stream_sink);
ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
hr = IMFStreamSink_GetMediaSink(stream_sink, &sink2);
ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
IMFMediaSink_Release(sink2);
/* Shutdown state */
hr = IMFMediaSink_Shutdown(sink);
ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
hr = IMFMediaSink_Shutdown(sink);
ok(hr == MF_E_SHUTDOWN, "Unexpected hr %#lx.\n", hr);
hr = IMFStreamSink_GetMediaSink(stream_sink, &sink2);
ok(hr == MF_E_STREAMSINK_REMOVED, "Unexpected hr %#lx.\n", hr);
hr = IMFStreamSink_GetIdentifier(stream_sink, &id);
ok(hr == MF_E_STREAMSINK_REMOVED, "Unexpected hr %#lx.\n", hr);
IMFStreamSink_Release(stream_sink);
hr = IMFMediaSink_AddStreamSink(sink, 123, media_type, &stream_sink);
ok(hr == MF_E_SHUTDOWN, "Unexpected hr %#lx.\n", hr);
hr = IMFMediaSink_GetStreamSinkByIndex(sink, 0, &stream_sink);
ok(hr == MF_E_SHUTDOWN, "Unexpected hr %#lx.\n", hr);
hr = IMFMediaSink_GetStreamSinkById(sink, 0, &stream_sink);
ok(hr == MF_E_SHUTDOWN, "Unexpected hr %#lx.\n", hr);
hr = IMFMediaSink_GetCharacteristics(sink, &flags);
ok(hr == MF_E_SHUTDOWN, "Unexpected hr %#lx.\n", hr);
IMFMediaSink_Release(sink);
IMFMediaType_Release(media_type);
IMFByteStream_Release(bytestream);
}
START_TEST(mfsrcsnk)
{
HRESULT hr;
hr = MFStartup(MF_VERSION, MFSTARTUP_FULL);
ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
test_wave_sink();
hr = MFShutdown();
ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
}

View file

@ -16,18 +16,551 @@
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
*/
#define COBJMACROS
#include "mfapi.h"
#include "mfidl.h"
#include "mferror.h"
#include "wine/debug.h"
WINE_DEFAULT_DEBUG_CHANNEL(mfplat);
enum wave_sink_flags
{
SINK_SHUT_DOWN = 0x1,
};
struct wave_sink
{
IMFFinalizableMediaSink IMFFinalizableMediaSink_iface;
IMFMediaEventGenerator IMFMediaEventGenerator_iface;
IMFStreamSink IMFStreamSink_iface;
LONG refcount;
IMFMediaEventQueue *event_queue;
IMFMediaEventQueue *stream_event_queue;
IMFByteStream *bytestream;
unsigned int flags;
CRITICAL_SECTION cs;
};
static struct wave_sink *impl_from_IMFFinalizableMediaSink(IMFFinalizableMediaSink *iface)
{
return CONTAINING_RECORD(iface, struct wave_sink, IMFFinalizableMediaSink_iface);
}
static struct wave_sink *impl_from_IMFMediaEventGenerator(IMFMediaEventGenerator *iface)
{
return CONTAINING_RECORD(iface, struct wave_sink, IMFMediaEventGenerator_iface);
}
static struct wave_sink *impl_from_IMFStreamSink(IMFStreamSink *iface)
{
return CONTAINING_RECORD(iface, struct wave_sink, IMFStreamSink_iface);
}
static HRESULT WINAPI wave_sink_QueryInterface(IMFFinalizableMediaSink *iface, REFIID riid, void **obj)
{
struct wave_sink *sink = impl_from_IMFFinalizableMediaSink(iface);
TRACE("%p, %s, %p.\n", iface, debugstr_guid(riid), obj);
if (IsEqualIID(riid, &IID_IMFFinalizableMediaSink) ||
IsEqualIID(riid, &IID_IMFMediaSink) ||
IsEqualIID(riid, &IID_IUnknown))
{
*obj = iface;
}
else if (IsEqualIID(riid, &IID_IMFMediaEventGenerator))
{
*obj = &sink->IMFMediaEventGenerator_iface;
}
else
{
WARN("Unsupported %s.\n", debugstr_guid(riid));
*obj = NULL;
return E_NOINTERFACE;
}
IUnknown_AddRef((IUnknown *)*obj);
return S_OK;
}
static ULONG WINAPI wave_sink_AddRef(IMFFinalizableMediaSink *iface)
{
struct wave_sink *sink = impl_from_IMFFinalizableMediaSink(iface);
ULONG refcount = InterlockedIncrement(&sink->refcount);
TRACE("%p, refcount %lu.\n", iface, refcount);
return refcount;
}
static ULONG WINAPI wave_sink_Release(IMFFinalizableMediaSink *iface)
{
struct wave_sink *sink = impl_from_IMFFinalizableMediaSink(iface);
ULONG refcount = InterlockedDecrement(&sink->refcount);
TRACE("%p, refcount %lu.\n", iface, refcount);
if (!refcount)
{
if (sink->event_queue)
IMFMediaEventQueue_Release(sink->event_queue);
if (sink->stream_event_queue)
IMFMediaEventQueue_Release(sink->stream_event_queue);
IMFByteStream_Release(sink->bytestream);
DeleteCriticalSection(&sink->cs);
free(sink);
}
return refcount;
}
static HRESULT WINAPI wave_sink_GetCharacteristics(IMFFinalizableMediaSink *iface, DWORD *flags)
{
struct wave_sink *sink = impl_from_IMFFinalizableMediaSink(iface);
TRACE("%p, %p.\n", iface, flags);
if (sink->flags & SINK_SHUT_DOWN)
return MF_E_SHUTDOWN;
*flags = MEDIASINK_FIXED_STREAMS | MEDIASINK_RATELESS;
return S_OK;
}
static HRESULT WINAPI wave_sink_AddStreamSink(IMFFinalizableMediaSink *iface, DWORD stream_sink_id,
IMFMediaType *media_type, IMFStreamSink **stream_sink)
{
struct wave_sink *sink = impl_from_IMFFinalizableMediaSink(iface);
TRACE("%p, %#lx, %p, %p.\n", iface, stream_sink_id, media_type, stream_sink);
return sink->flags & SINK_SHUT_DOWN ? MF_E_SHUTDOWN : MF_E_STREAMSINKS_FIXED;
}
static HRESULT WINAPI wave_sink_RemoveStreamSink(IMFFinalizableMediaSink *iface, DWORD stream_sink_id)
{
struct wave_sink *sink = impl_from_IMFFinalizableMediaSink(iface);
TRACE("%p, %#lx.\n", iface, stream_sink_id);
return sink->flags & SINK_SHUT_DOWN ? MF_E_SHUTDOWN : MF_E_STREAMSINKS_FIXED;
}
static HRESULT WINAPI wave_sink_GetStreamSinkCount(IMFFinalizableMediaSink *iface, DWORD *count)
{
struct wave_sink *sink = impl_from_IMFFinalizableMediaSink(iface);
TRACE("%p, %p.\n", iface, count);
if (!count)
return E_POINTER;
if (sink->flags & SINK_SHUT_DOWN)
return MF_E_SHUTDOWN;
*count = 1;
return S_OK;
}
static HRESULT WINAPI wave_sink_GetStreamSinkByIndex(IMFFinalizableMediaSink *iface, DWORD index,
IMFStreamSink **stream)
{
struct wave_sink *sink = impl_from_IMFFinalizableMediaSink(iface);
HRESULT hr = S_OK;
TRACE("%p, %lu, %p.\n", iface, index, stream);
EnterCriticalSection(&sink->cs);
if (sink->flags & SINK_SHUT_DOWN)
hr = MF_E_SHUTDOWN;
else if (index)
hr = MF_E_INVALIDINDEX;
else
{
*stream = &sink->IMFStreamSink_iface;
IMFStreamSink_AddRef(*stream);
}
LeaveCriticalSection(&sink->cs);
return hr;
}
static HRESULT WINAPI wave_sink_GetStreamSinkById(IMFFinalizableMediaSink *iface, DWORD stream_sink_id,
IMFStreamSink **stream)
{
struct wave_sink *sink = impl_from_IMFFinalizableMediaSink(iface);
HRESULT hr = S_OK;
TRACE("%p, %#lx, %p.\n", iface, stream_sink_id, stream);
EnterCriticalSection(&sink->cs);
if (sink->flags & SINK_SHUT_DOWN)
hr = MF_E_SHUTDOWN;
else if (stream_sink_id != 1)
hr = MF_E_INVALIDSTREAMNUMBER;
else
{
*stream = &sink->IMFStreamSink_iface;
IMFStreamSink_AddRef(*stream);
}
LeaveCriticalSection(&sink->cs);
return hr;
}
static HRESULT WINAPI wave_sink_SetPresentationClock(IMFFinalizableMediaSink *iface, IMFPresentationClock *clock)
{
FIXME("%p, %p.\n", iface, clock);
return E_NOTIMPL;
}
static HRESULT WINAPI wave_sink_GetPresentationClock(IMFFinalizableMediaSink *iface, IMFPresentationClock **clock)
{
FIXME("%p, %p.\n", iface, clock);
return E_NOTIMPL;
}
static HRESULT WINAPI wave_sink_Shutdown(IMFFinalizableMediaSink *iface)
{
struct wave_sink *sink = impl_from_IMFFinalizableMediaSink(iface);
HRESULT hr = S_OK;
TRACE("%p.\n", iface);
EnterCriticalSection(&sink->cs);
if (sink->flags & SINK_SHUT_DOWN)
hr = MF_E_SHUTDOWN;
else
{
sink->flags |= SINK_SHUT_DOWN;
IMFMediaEventQueue_Shutdown(sink->event_queue);
IMFMediaEventQueue_Shutdown(sink->stream_event_queue);
}
LeaveCriticalSection(&sink->cs);
return hr;
}
static HRESULT WINAPI wave_sink_BeginFinalize(IMFFinalizableMediaSink *iface, IMFAsyncCallback *callback, IUnknown *state)
{
FIXME("%p, %p, %p.\n", iface, callback, state);
return E_NOTIMPL;
}
static HRESULT WINAPI wave_sink_EndFinalize(IMFFinalizableMediaSink *iface, IMFAsyncResult *result)
{
FIXME("%p, %p.\n", iface, result);
return E_NOTIMPL;
}
static const IMFFinalizableMediaSinkVtbl wave_sink_vtbl =
{
wave_sink_QueryInterface,
wave_sink_AddRef,
wave_sink_Release,
wave_sink_GetCharacteristics,
wave_sink_AddStreamSink,
wave_sink_RemoveStreamSink,
wave_sink_GetStreamSinkCount,
wave_sink_GetStreamSinkByIndex,
wave_sink_GetStreamSinkById,
wave_sink_SetPresentationClock,
wave_sink_GetPresentationClock,
wave_sink_Shutdown,
wave_sink_BeginFinalize,
wave_sink_EndFinalize,
};
static HRESULT WINAPI wave_sink_events_QueryInterface(IMFMediaEventGenerator *iface, REFIID riid, void **obj)
{
struct wave_sink *sink = impl_from_IMFMediaEventGenerator(iface);
return IMFFinalizableMediaSink_QueryInterface(&sink->IMFFinalizableMediaSink_iface, riid, obj);
}
static ULONG WINAPI wave_sink_events_AddRef(IMFMediaEventGenerator *iface)
{
struct wave_sink *sink = impl_from_IMFMediaEventGenerator(iface);
return IMFFinalizableMediaSink_AddRef(&sink->IMFFinalizableMediaSink_iface);
}
static ULONG WINAPI wave_sink_events_Release(IMFMediaEventGenerator *iface)
{
struct wave_sink *sink = impl_from_IMFMediaEventGenerator(iface);
return IMFFinalizableMediaSink_Release(&sink->IMFFinalizableMediaSink_iface);
}
static HRESULT WINAPI wave_sink_events_GetEvent(IMFMediaEventGenerator *iface, DWORD flags, IMFMediaEvent **event)
{
struct wave_sink *sink = impl_from_IMFMediaEventGenerator(iface);
TRACE("%p, %#lx, %p.\n", iface, flags, event);
return IMFMediaEventQueue_GetEvent(sink->event_queue, flags, event);
}
static HRESULT WINAPI wave_sink_events_BeginGetEvent(IMFMediaEventGenerator *iface, IMFAsyncCallback *callback,
IUnknown *state)
{
struct wave_sink *sink = impl_from_IMFMediaEventGenerator(iface);
TRACE("%p, %p, %p.\n", iface, callback, state);
return IMFMediaEventQueue_BeginGetEvent(sink->event_queue, callback, state);
}
static HRESULT WINAPI wave_sink_events_EndGetEvent(IMFMediaEventGenerator *iface, IMFAsyncResult *result,
IMFMediaEvent **event)
{
struct wave_sink *sink = impl_from_IMFMediaEventGenerator(iface);
TRACE("%p, %p, %p.\n", iface, result, event);
return IMFMediaEventQueue_EndGetEvent(sink->event_queue, result, event);
}
static HRESULT WINAPI wave_sink_events_QueueEvent(IMFMediaEventGenerator *iface, MediaEventType event_type,
REFGUID ext_type, HRESULT hr, const PROPVARIANT *value)
{
struct wave_sink *sink = impl_from_IMFMediaEventGenerator(iface);
TRACE("%p, %lu, %s, %#lx, %p.\n", iface, event_type, debugstr_guid(ext_type), hr, value);
return IMFMediaEventQueue_QueueEventParamVar(sink->event_queue, event_type, ext_type, hr, value);
}
static const IMFMediaEventGeneratorVtbl wave_sink_events_vtbl =
{
wave_sink_events_QueryInterface,
wave_sink_events_AddRef,
wave_sink_events_Release,
wave_sink_events_GetEvent,
wave_sink_events_BeginGetEvent,
wave_sink_events_EndGetEvent,
wave_sink_events_QueueEvent,
};
static HRESULT WINAPI wave_stream_sink_QueryInterface(IMFStreamSink *iface, REFIID riid, void **obj)
{
struct wave_sink *sink = impl_from_IMFStreamSink(iface);
TRACE("%p, %s, %p.\n", iface, debugstr_guid(riid), obj);
if (IsEqualIID(riid, &IID_IMFStreamSink) ||
IsEqualIID(riid, &IID_IMFMediaEventGenerator) ||
IsEqualIID(riid, &IID_IUnknown))
{
*obj = &sink->IMFStreamSink_iface;
}
else
{
WARN("Unsupported %s.\n", debugstr_guid(riid));
*obj = NULL;
return E_NOINTERFACE;
}
IUnknown_AddRef((IUnknown *)*obj);
return S_OK;
}
static ULONG WINAPI wave_stream_sink_AddRef(IMFStreamSink *iface)
{
struct wave_sink *sink = impl_from_IMFStreamSink(iface);
return IMFFinalizableMediaSink_AddRef(&sink->IMFFinalizableMediaSink_iface);
}
static ULONG WINAPI wave_stream_sink_Release(IMFStreamSink *iface)
{
struct wave_sink *sink = impl_from_IMFStreamSink(iface);
return IMFFinalizableMediaSink_Release(&sink->IMFFinalizableMediaSink_iface);
}
static HRESULT WINAPI wave_stream_sink_GetEvent(IMFStreamSink *iface, DWORD flags, IMFMediaEvent **event)
{
struct wave_sink *sink = impl_from_IMFStreamSink(iface);
TRACE("%p, %#lx, %p.\n", iface, flags, event);
if (sink->flags & SINK_SHUT_DOWN)
return MF_E_STREAMSINK_REMOVED;
return IMFMediaEventQueue_GetEvent(sink->stream_event_queue, flags, event);
}
static HRESULT WINAPI wave_stream_sink_BeginGetEvent(IMFStreamSink *iface, IMFAsyncCallback *callback,
IUnknown *state)
{
struct wave_sink *sink = impl_from_IMFStreamSink(iface);
TRACE("%p, %p, %p.\n", iface, callback, state);
if (sink->flags & SINK_SHUT_DOWN)
return MF_E_STREAMSINK_REMOVED;
return IMFMediaEventQueue_BeginGetEvent(sink->stream_event_queue, callback, state);
}
static HRESULT WINAPI wave_stream_sink_EndGetEvent(IMFStreamSink *iface, IMFAsyncResult *result,
IMFMediaEvent **event)
{
struct wave_sink *sink = impl_from_IMFStreamSink(iface);
TRACE("%p, %p, %p.\n", iface, result, event);
if (sink->flags & SINK_SHUT_DOWN)
return MF_E_STREAMSINK_REMOVED;
return IMFMediaEventQueue_EndGetEvent(sink->stream_event_queue, result, event);
}
static HRESULT WINAPI wave_stream_sink_QueueEvent(IMFStreamSink *iface, MediaEventType event_type,
REFGUID ext_type, HRESULT hr, const PROPVARIANT *value)
{
struct wave_sink *sink = impl_from_IMFStreamSink(iface);
TRACE("%p, %lu, %s, %#lx, %p.\n", iface, event_type, debugstr_guid(ext_type), hr, value);
if (sink->flags & SINK_SHUT_DOWN)
return MF_E_STREAMSINK_REMOVED;
return IMFMediaEventQueue_QueueEventParamVar(sink->stream_event_queue, event_type, ext_type, hr, value);
}
static HRESULT WINAPI wave_stream_sink_GetMediaSink(IMFStreamSink *iface, IMFMediaSink **ret)
{
struct wave_sink *sink = impl_from_IMFStreamSink(iface);
TRACE("%p, %p.\n", iface, ret);
if (sink->flags & SINK_SHUT_DOWN)
return MF_E_STREAMSINK_REMOVED;
*ret = (IMFMediaSink *)&sink->IMFFinalizableMediaSink_iface;
IMFMediaSink_AddRef(*ret);
return S_OK;
}
static HRESULT WINAPI wave_stream_sink_GetIdentifier(IMFStreamSink *iface, DWORD *identifier)
{
struct wave_sink *sink = impl_from_IMFStreamSink(iface);
TRACE("%p, %p.\n", iface, identifier);
if (sink->flags & SINK_SHUT_DOWN)
return MF_E_STREAMSINK_REMOVED;
*identifier = 1;
return S_OK;
}
static HRESULT WINAPI wave_stream_sink_GetMediaTypeHandler(IMFStreamSink *iface, IMFMediaTypeHandler **handler)
{
FIXME("%p, %p.\n", iface, handler);
return E_NOTIMPL;
}
static HRESULT WINAPI wave_stream_sink_ProcessSample(IMFStreamSink *iface, IMFSample *sample)
{
FIXME("%p, %p.\n", iface, sample);
return E_NOTIMPL;
}
static HRESULT WINAPI wave_stream_sink_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 wave_stream_sink_Flush(IMFStreamSink *iface)
{
FIXME("%p.\n", iface);
return E_NOTIMPL;
}
static const IMFStreamSinkVtbl wave_stream_sink_vtbl =
{
wave_stream_sink_QueryInterface,
wave_stream_sink_AddRef,
wave_stream_sink_Release,
wave_stream_sink_GetEvent,
wave_stream_sink_BeginGetEvent,
wave_stream_sink_EndGetEvent,
wave_stream_sink_QueueEvent,
wave_stream_sink_GetMediaSink,
wave_stream_sink_GetIdentifier,
wave_stream_sink_GetMediaTypeHandler,
wave_stream_sink_ProcessSample,
wave_stream_sink_PlaceMarker,
wave_stream_sink_Flush,
};
/***********************************************************************
* MFCreateWAVEMediaSink (mfplat.@)
* MFCreateWAVEMediaSink (mfsrcsnk.@)
*/
HRESULT WINAPI MFCreateWAVEMediaSink(IMFByteStream *bytestream, IMFMediaType *media_type,
IMFMediaSink **sink)
{
FIXME("%p, %p, %p.\n", bytestream, media_type, sink);
struct wave_sink *object;
DWORD flags = 0;
HRESULT hr;
return E_NOTIMPL;
TRACE("%p, %p, %p.\n", bytestream, media_type, sink);
if (!bytestream || !media_type || !sink)
return E_POINTER;
if (FAILED(hr = IMFByteStream_GetCapabilities(bytestream, &flags))) return hr;
if (!(flags & MFBYTESTREAM_IS_WRITABLE)) return E_INVALIDARG;
/* FIXME: do basic media type validation */
if (!(object = calloc(1, sizeof(*object))))
return E_OUTOFMEMORY;
object->IMFFinalizableMediaSink_iface.lpVtbl = &wave_sink_vtbl;
object->IMFMediaEventGenerator_iface.lpVtbl = &wave_sink_events_vtbl;
object->IMFStreamSink_iface.lpVtbl = &wave_stream_sink_vtbl;
object->refcount = 1;
IMFByteStream_AddRef((object->bytestream = bytestream));
InitializeCriticalSection(&object->cs);
if (FAILED(hr = MFCreateEventQueue(&object->event_queue)))
goto failed;
if (FAILED(hr = MFCreateEventQueue(&object->stream_event_queue)))
goto failed;
*sink = (IMFMediaSink *)&object->IMFFinalizableMediaSink_iface;
return S_OK;
failed:
IMFFinalizableMediaSink_Release(&object->IMFFinalizableMediaSink_iface);
return hr;
}