From: Rémi Bernon rbernon@codeweavers.com
--- dlls/mfsrcsnk/media_source.c | 217 ++++++++++++++++++++++++++++++- dlls/mfsrcsnk/mfsrcsnk_private.h | 35 +++++ 2 files changed, 247 insertions(+), 5 deletions(-)
diff --git a/dlls/mfsrcsnk/media_source.c b/dlls/mfsrcsnk/media_source.c index 86095119d19..8b6a015073f 100644 --- a/dlls/mfsrcsnk/media_source.c +++ b/dlls/mfsrcsnk/media_source.c @@ -18,11 +18,185 @@
#include "mfsrcsnk_private.h"
+#include "wine/list.h" #include "wine/debug.h" #include "wine/winedmo.h"
WINE_DEFAULT_DEBUG_CHANNEL(mfplat);
+struct media_source +{ + IMFMediaSource IMFMediaSource_iface; + LONG refcount; + + IMFMediaEventQueue *queue; + IMFByteStream *stream; +}; + +static struct media_source *media_source_from_IMFMediaSource(IMFMediaSource *iface) +{ + return CONTAINING_RECORD(iface, struct media_source, IMFMediaSource_iface); +} + +static HRESULT WINAPI media_source_QueryInterface(IMFMediaSource *iface, REFIID riid, void **out) +{ + struct media_source *source = media_source_from_IMFMediaSource(iface); + + TRACE("source %p, riid %s, out %p\n", source, debugstr_guid(riid), out); + + if (IsEqualIID(riid, &IID_IUnknown) + || IsEqualIID(riid, &IID_IMFMediaEventGenerator) + || IsEqualIID(riid, &IID_IMFMediaSource)) + { + IMFMediaSource_AddRef(&source->IMFMediaSource_iface); + *out = &source->IMFMediaSource_iface; + return S_OK; + } + + FIXME("Unsupported interface %s\n", debugstr_guid(riid)); + *out = NULL; + return E_NOINTERFACE; +} + +static ULONG WINAPI media_source_AddRef(IMFMediaSource *iface) +{ + struct media_source *source = media_source_from_IMFMediaSource(iface); + ULONG refcount = InterlockedIncrement(&source->refcount); + TRACE("source %p, refcount %ld\n", source, refcount); + return refcount; +} + +static ULONG WINAPI media_source_Release(IMFMediaSource *iface) +{ + struct media_source *source = media_source_from_IMFMediaSource(iface); + ULONG refcount = InterlockedDecrement(&source->refcount); + + TRACE("source %p, refcount %ld\n", source, refcount); + + if (!refcount) + { + IMFMediaEventQueue_Release(source->queue); + free(source); + } + + return refcount; +} + +static HRESULT WINAPI media_source_GetEvent(IMFMediaSource *iface, DWORD flags, IMFMediaEvent **event) +{ + struct media_source *source = media_source_from_IMFMediaSource(iface); + TRACE("source %p, flags %#lx, event %p\n", source, flags, event); + return IMFMediaEventQueue_GetEvent(source->queue, flags, event); +} + +static HRESULT WINAPI media_source_BeginGetEvent(IMFMediaSource *iface, IMFAsyncCallback *callback, IUnknown *state) +{ + struct media_source *source = media_source_from_IMFMediaSource(iface); + TRACE("source %p, callback %p, state %p\n", source, callback, state); + return IMFMediaEventQueue_BeginGetEvent(source->queue, callback, state); +} + +static HRESULT WINAPI media_source_EndGetEvent(IMFMediaSource *iface, IMFAsyncResult *result, + IMFMediaEvent **event) +{ + struct media_source *source = media_source_from_IMFMediaSource(iface); + TRACE("source %p, result %p, event %p\n", source, result, event); + return IMFMediaEventQueue_EndGetEvent(source->queue, result, event); +} + +static HRESULT WINAPI media_source_QueueEvent(IMFMediaSource *iface, MediaEventType event_type, + REFGUID ext_type, HRESULT hr, const PROPVARIANT *value) +{ + struct media_source *source = media_source_from_IMFMediaSource(iface); + TRACE("source %p, event_type %#lx, ext_type %s, hr %#lx, value %p\n", source, event_type, + debugstr_guid(ext_type), hr, debugstr_propvar(value)); + return IMFMediaEventQueue_QueueEventParamVar(source->queue, event_type, ext_type, hr, value); +} + +static HRESULT WINAPI media_source_GetCharacteristics(IMFMediaSource *iface, DWORD *characteristics) +{ + struct media_source *source = media_source_from_IMFMediaSource(iface); + FIXME("source %p, characteristics %p\n", source, characteristics); + return E_NOTIMPL; +} + +static HRESULT WINAPI media_source_CreatePresentationDescriptor(IMFMediaSource *iface, IMFPresentationDescriptor **descriptor) +{ + struct media_source *source = media_source_from_IMFMediaSource(iface); + FIXME("source %p, descriptor %p, stub!\n", source, descriptor); + return E_NOTIMPL; +} + +static HRESULT WINAPI media_source_Start(IMFMediaSource *iface, IMFPresentationDescriptor *descriptor, const GUID *format, + const PROPVARIANT *position) +{ + struct media_source *source = media_source_from_IMFMediaSource(iface); + FIXME("source %p, descriptor %p, format %s, position %s, stub!\n", source, descriptor, + debugstr_guid(format), debugstr_propvar(position)); + return E_NOTIMPL; +} + +static HRESULT WINAPI media_source_Stop(IMFMediaSource *iface) +{ + struct media_source *source = media_source_from_IMFMediaSource(iface); + FIXME("source %p, stub!\n", source); + return E_NOTIMPL; +} + +static HRESULT WINAPI media_source_Pause(IMFMediaSource *iface) +{ + struct media_source *source = media_source_from_IMFMediaSource(iface); + FIXME("source %p, stub!\n", source); + return E_NOTIMPL; +} + +static HRESULT WINAPI media_source_Shutdown(IMFMediaSource *iface) +{ + struct media_source *source = media_source_from_IMFMediaSource(iface); + FIXME("source %p\n", source); + return E_NOTIMPL; +} + +static const IMFMediaSourceVtbl media_source_vtbl = +{ + media_source_QueryInterface, + media_source_AddRef, + media_source_Release, + media_source_GetEvent, + media_source_BeginGetEvent, + media_source_EndGetEvent, + media_source_QueueEvent, + media_source_GetCharacteristics, + media_source_CreatePresentationDescriptor, + media_source_Start, + media_source_Stop, + media_source_Pause, + media_source_Shutdown, +}; + +static HRESULT media_source_create(const WCHAR *url, IMFByteStream *stream, IMFMediaSource **out) +{ + struct media_source *source; + HRESULT hr; + + TRACE("url %s, stream %p, out %p\n", debugstr_w(url), stream, out); + + if (!(source = calloc(1, sizeof(*source)))) + return E_OUTOFMEMORY; + source->IMFMediaSource_iface.lpVtbl = &media_source_vtbl; + source->refcount = 1; + + if (FAILED(hr = MFCreateEventQueue(&source->queue))) + { + free(source); + return hr; + } + + *out = &source->IMFMediaSource_iface; + TRACE("created source %p\n", source); + return S_OK; +} + struct byte_stream_handler { IMFByteStreamHandler IMFByteStreamHandler_iface; @@ -75,17 +249,50 @@ static HRESULT WINAPI byte_stream_handler_BeginCreateObject(IMFByteStreamHandler IPropertyStore *props, IUnknown **cookie, IMFAsyncCallback *callback, IUnknown *state) { struct byte_stream_handler *handler = byte_stream_handler_from_IMFByteStreamHandler(iface); - FIXME("handler %p, stream %p, url %s, flags %#lx, props %p, cookie %p, callback %p, state %p stub!\n", handler, stream, debugstr_w(url), - flags, props, cookie, callback, state); - return E_NOTIMPL; + IMFAsyncResult *result; + IMFMediaSource *source; + HRESULT hr; + + TRACE("handler %p, stream %p, url %s, flags %#lx, props %p, cookie %p, callback %p, state %p\n", + handler, stream, debugstr_w(url), flags, props, cookie, callback, state); + + if (cookie) + *cookie = NULL; + if (!stream) + return E_INVALIDARG; + if (flags != MF_RESOLUTION_MEDIASOURCE) + FIXME("Unimplemented flags %#lx\n", flags); + + if (FAILED(hr = media_source_create(url, stream, &source))) + return hr; + if (SUCCEEDED(hr = MFCreateAsyncResult((IUnknown *)source, callback, state, &result))) + { + hr = MFPutWorkItemEx(MFASYNC_CALLBACK_QUEUE_IO, result); + IMFAsyncResult_Release(result); + } + IMFMediaSource_Release(source); + + return hr; }
static HRESULT WINAPI byte_stream_handler_EndCreateObject(IMFByteStreamHandler *iface, IMFAsyncResult *result, MF_OBJECT_TYPE *type, IUnknown **object) { struct byte_stream_handler *handler = byte_stream_handler_from_IMFByteStreamHandler(iface); - FIXME("handler %p, result %p, type %p, object %p stub!\n", handler, result, type, object); - return E_NOTIMPL; + HRESULT hr; + + TRACE("handler %p, result %p, type %p, object %p\n", handler, result, type, object); + + *object = NULL; + *type = MF_OBJECT_INVALID; + + if (SUCCEEDED(hr = IMFAsyncResult_GetStatus(result))) + { + hr = IMFAsyncResult_GetObject(result, object); + *type = MF_OBJECT_MEDIASOURCE; + } + + return hr; }
static HRESULT WINAPI byte_stream_handler_CancelObjectCreation(IMFByteStreamHandler *iface, IUnknown *cookie) diff --git a/dlls/mfsrcsnk/mfsrcsnk_private.h b/dlls/mfsrcsnk/mfsrcsnk_private.h index 6d4ef560d5b..1f0e027f358 100644 --- a/dlls/mfsrcsnk/mfsrcsnk_private.h +++ b/dlls/mfsrcsnk/mfsrcsnk_private.h @@ -20,6 +20,7 @@
#include "mfapi.h" #include "mfidl.h" +#include "mfapi.h" #include "mferror.h"
#include "wine/mfinternal.h" @@ -91,3 +92,37 @@ static inline const char *debugstr_time(LONGLONG time)
return wine_dbg_sprintf("%s", rev); } + +static inline const char *debugstr_propvar(const PROPVARIANT *v) +{ + if (!v) + return "(null)"; + + switch (v->vt) + { + case VT_EMPTY: + return wine_dbg_sprintf("%p {VT_EMPTY}", v); + case VT_NULL: + return wine_dbg_sprintf("%p {VT_NULL}", v); + case VT_UI4: + return wine_dbg_sprintf("%p {VT_UI4: %ld}", v, v->ulVal); + case VT_UI8: + return wine_dbg_sprintf("%p {VT_UI8: %s}", v, wine_dbgstr_longlong(v->uhVal.QuadPart)); + case VT_I8: + return wine_dbg_sprintf("%p {VT_I8: %s}", v, wine_dbgstr_longlong(v->hVal.QuadPart)); + case VT_R4: + return wine_dbg_sprintf("%p {VT_R4: %.8e}", v, v->fltVal); + case VT_R8: + return wine_dbg_sprintf("%p {VT_R8: %lf}", v, v->dblVal); + case VT_CLSID: + return wine_dbg_sprintf("%p {VT_CLSID: %s}", v, debugstr_guid(v->puuid)); + case VT_LPWSTR: + return wine_dbg_sprintf("%p {VT_LPWSTR: %s}", v, wine_dbgstr_w(v->pwszVal)); + case VT_VECTOR | VT_UI1: + return wine_dbg_sprintf("%p {VT_VECTOR|VT_UI1: %p}", v, v->caub.pElems); + case VT_UNKNOWN: + return wine_dbg_sprintf("%p {VT_UNKNOWN: %p}", v, v->punkVal); + default: + return wine_dbg_sprintf("%p {vt %#x}", v, v->vt); + } +}