From: Rémi Bernon rbernon@codeweavers.com
--- dlls/winegstreamer/wm_asyncreader.c | 127 ++++++++++++++++++++++++++++ 1 file changed, 127 insertions(+)
diff --git a/dlls/winegstreamer/wm_asyncreader.c b/dlls/winegstreamer/wm_asyncreader.c index 84742d2f40f..089c96deddf 100644 --- a/dlls/winegstreamer/wm_asyncreader.c +++ b/dlls/winegstreamer/wm_asyncreader.c @@ -70,6 +70,7 @@ struct async_reader CRITICAL_SECTION cs;
IWMReaderCallbackAdvanced *callback_advanced; + IWMReaderAllocatorEx *allocator; IWMReaderCallback *callback; void *context;
@@ -87,6 +88,125 @@ struct async_reader QWORD user_time; };
+struct allocator +{ + IWMReaderAllocatorEx IWMReaderAllocatorEx_iface; + LONG refcount; + + IWMReaderCallbackAdvanced *callback; +}; + +static struct allocator *impl_from_IWMReaderAllocatorEx(IWMReaderAllocatorEx *iface) +{ + return CONTAINING_RECORD(iface, struct allocator, IWMReaderAllocatorEx_iface); +} + +static HRESULT WINAPI allocator_QueryInterface(IWMReaderAllocatorEx *iface, REFIID iid, void **out) +{ + struct allocator *allocator = impl_from_IWMReaderAllocatorEx(iface); + + TRACE("iface %p, iid %s, out %p.\n", iface, debugstr_guid(iid), out); + + if (IsEqualIID(iid, &IID_IUnknown) + || IsEqualIID(iid, &IID_IWMReaderAllocatorEx)) + *out = &allocator->IWMReaderAllocatorEx_iface; + else + { + WARN("%s not implemented, returning E_NOINTERFACE.\n", debugstr_guid(iid)); + return E_NOINTERFACE; + } + + IUnknown_AddRef((IUnknown *)*out); + return S_OK; +} + +static ULONG WINAPI allocator_AddRef(IWMReaderAllocatorEx *iface) +{ + struct allocator *allocator = impl_from_IWMReaderAllocatorEx(iface); + ULONG refcount = InterlockedIncrement(&allocator->refcount); + TRACE("iface %p increasing refcount to %lu.\n", iface, refcount); + return refcount; +} + +static ULONG WINAPI allocator_Release(IWMReaderAllocatorEx *iface) +{ + struct allocator *allocator = impl_from_IWMReaderAllocatorEx(iface); + ULONG refcount = InterlockedDecrement(&allocator->refcount); + + TRACE("iface %p decreasing refcount to %lu.\n", iface, refcount); + + if (!refcount) + { + if (allocator->callback) + IWMReaderCallbackAdvanced_Release(allocator->callback); + free(allocator); + } + + return refcount; +} + +static HRESULT WINAPI allocator_AllocateForStreamEx(IWMReaderAllocatorEx *iface, + WORD stream_number, DWORD size, INSSBuffer **sample, DWORD flags, + QWORD pts, QWORD duration, void *context) +{ + struct allocator *allocator = impl_from_IWMReaderAllocatorEx(iface); + + TRACE("iface %p, stream_number %u, size %#lx, sample %p, flags %#lx, pts %I64d, duration %I64d, context %p.\n", + iface, stream_number, size, sample, flags, pts, duration, context); + + if (allocator->callback) + return IWMReaderCallbackAdvanced_AllocateForStream(allocator->callback, + stream_number, size, sample, context); + + return E_NOTIMPL; +} + +static HRESULT WINAPI allocator_AllocateForOutputEx(IWMReaderAllocatorEx *iface, + DWORD output, DWORD size, INSSBuffer **sample, DWORD flags, + QWORD pts, QWORD duration, void *context) +{ + struct allocator *allocator = impl_from_IWMReaderAllocatorEx(iface); + + TRACE("iface %p, output %lu, size %#lx, sample %p, flags %#lx, pts %I64d, duration %I64d, context %p.\n", + iface, output, size, sample, flags, pts, duration, context); + + if (allocator->callback) + return IWMReaderCallbackAdvanced_AllocateForOutput(allocator->callback, + output, size, sample, context); + + return E_NOTIMPL; +} + +static const IWMReaderAllocatorExVtbl allocator_vtbl = +{ + allocator_QueryInterface, + allocator_AddRef, + allocator_Release, + allocator_AllocateForStreamEx, + allocator_AllocateForOutputEx, +}; + +static HRESULT allocator_create(IWMReaderCallback *callback, IWMReaderAllocatorEx **out) +{ + struct allocator *allocator; + HRESULT hr; + + if (!(allocator = calloc(1, sizeof(*allocator)))) + return E_OUTOFMEMORY; + allocator->IWMReaderAllocatorEx_iface.lpVtbl = &allocator_vtbl; + allocator->refcount = 1; + + if (FAILED(hr = IWMReaderCallback_QueryInterface(callback, + &IID_IWMReaderCallbackAdvanced, (void **)&allocator->callback))) + { + WARN("Failed to retrieve IWMReaderCallbackAdvanced interface, hr %#lx\n", hr); + allocator->callback = NULL; + } + + *out = &allocator->IWMReaderAllocatorEx_iface; + return S_OK; +} + static REFERENCE_TIME get_current_time(const struct async_reader *reader) { LARGE_INTEGER time; @@ -306,6 +426,10 @@ static void async_reader_close(struct async_reader *reader) free(op); }
+ if (reader->allocator) + IWMReaderAllocatorEx_Release(reader->allocator); + reader->allocator = NULL; + if (reader->callback_advanced) IWMReaderCallbackAdvanced_Release(reader->callback_advanced); reader->callback_advanced = NULL; @@ -323,6 +447,9 @@ static HRESULT async_reader_open(struct async_reader *reader, IWMReaderCallback IWMReaderCallback_AddRef((reader->callback = callback)); reader->context = context;
+ if (FAILED(hr = allocator_create(reader->callback, &reader->allocator))) + goto error; + if (FAILED(hr = IWMReaderCallback_QueryInterface(callback, &IID_IWMReaderCallbackAdvanced, (void **)&reader->callback_advanced))) {