Rémi Bernon : qasf: Implement ASF Reader filter buffer allocation.
Alexandre Julliard
julliard at winehq.org
Tue Aug 16 16:02:12 CDT 2022
Module: wine
Branch: master
Commit: a3ad00da09697d4ca631d399b878cbd2a6bc5dd2
URL: https://gitlab.winehq.org/wine/wine/-/commit/a3ad00da09697d4ca631d399b878cbd2a6bc5dd2
Author: Rémi Bernon <rbernon at codeweavers.com>
Date: Wed Aug 10 20:13:37 2022 +0200
qasf: Implement ASF Reader filter buffer allocation.
---
dlls/qasf/asfreader.c | 157 +++++++++++++++++++++++++++++++++++++++++++++++++-
1 file changed, 155 insertions(+), 2 deletions(-)
diff --git a/dlls/qasf/asfreader.c b/dlls/qasf/asfreader.c
index ea9647accf2..0fdf4a23e12 100644
--- a/dlls/qasf/asfreader.c
+++ b/dlls/qasf/asfreader.c
@@ -27,6 +27,129 @@
WINE_DEFAULT_DEBUG_CHANNEL(quartz);
+struct buffer
+{
+ INSSBuffer INSSBuffer_iface;
+ LONG refcount;
+ IMediaSample *sample;
+};
+
+static struct buffer *impl_from_INSSBuffer(INSSBuffer *iface)
+{
+ return CONTAINING_RECORD(iface, struct buffer, INSSBuffer_iface);
+}
+
+static HRESULT WINAPI buffer_QueryInterface(INSSBuffer *iface, REFIID iid, void **out)
+{
+ struct buffer *impl = impl_from_INSSBuffer(iface);
+
+ TRACE("iface %p, iid %s, out %p.\n", iface, debugstr_guid(iid), out);
+
+ if (IsEqualGUID(iid, &IID_IUnknown)
+ || IsEqualGUID(iid, &IID_INSSBuffer))
+ *out = &impl->INSSBuffer_iface;
+ else
+ {
+ *out = NULL;
+ WARN("%s not implemented, returning E_NOINTERFACE.\n", debugstr_guid(iid));
+ return E_NOINTERFACE;
+ }
+
+ IUnknown_AddRef((IUnknown *)*out);
+ return S_OK;
+}
+
+static ULONG WINAPI buffer_AddRef(INSSBuffer *iface)
+{
+ struct buffer *impl = impl_from_INSSBuffer(iface);
+ ULONG ref = InterlockedIncrement(&impl->refcount);
+ TRACE("iface %p increasing refcount to %lu.\n", iface, ref);
+ return ref;
+}
+
+static ULONG WINAPI buffer_Release(INSSBuffer *iface)
+{
+ struct buffer *impl = impl_from_INSSBuffer(iface);
+ ULONG ref = InterlockedDecrement(&impl->refcount);
+
+ TRACE("iface %p decreasing refcount to %lu.\n", iface, ref);
+
+ if (!ref)
+ {
+ IMediaSample_Release(impl->sample);
+ free(impl);
+ }
+
+ return ref;
+}
+
+static HRESULT WINAPI buffer_GetLength(INSSBuffer *iface, DWORD *size)
+{
+ struct buffer *impl = impl_from_INSSBuffer(iface);
+ TRACE("iface %p, size %p.\n", iface, size);
+ *size = IMediaSample_GetActualDataLength(impl->sample);
+ return S_OK;
+}
+
+static HRESULT WINAPI buffer_SetLength(INSSBuffer *iface, DWORD size)
+{
+ struct buffer *impl = impl_from_INSSBuffer(iface);
+ TRACE("iface %p, size %lu.\n", iface, size);
+ return IMediaSample_SetActualDataLength(impl->sample, size);
+}
+
+static HRESULT WINAPI buffer_GetMaxLength(INSSBuffer *iface, DWORD *size)
+{
+ struct buffer *impl = impl_from_INSSBuffer(iface);
+ TRACE("iface %p, size %p.\n", iface, size);
+ *size = IMediaSample_GetSize(impl->sample);
+ return S_OK;
+}
+
+static HRESULT WINAPI buffer_GetBuffer(INSSBuffer *iface, BYTE **data)
+{
+ struct buffer *impl = impl_from_INSSBuffer(iface);
+ TRACE("iface %p, data %p.\n", iface, data);
+ return IMediaSample_GetPointer(impl->sample, data);
+}
+
+static HRESULT WINAPI buffer_GetBufferAndLength(INSSBuffer *iface, BYTE **data, DWORD *size)
+{
+ struct buffer *impl = impl_from_INSSBuffer(iface);
+ TRACE("iface %p, data %p, size %p.\n", iface, data, size);
+ *size = IMediaSample_GetSize(impl->sample);
+ return IMediaSample_GetPointer(impl->sample, data);
+}
+
+static const INSSBufferVtbl buffer_vtbl =
+{
+ buffer_QueryInterface,
+ buffer_AddRef,
+ buffer_Release,
+ buffer_GetLength,
+ buffer_SetLength,
+ buffer_GetMaxLength,
+ buffer_GetBuffer,
+ buffer_GetBufferAndLength,
+};
+
+static HRESULT buffer_create(IMediaSample *sample, INSSBuffer **out)
+{
+ struct buffer *buffer;
+
+ if (!(buffer = calloc(1, sizeof(struct buffer))))
+ return E_OUTOFMEMORY;
+
+ buffer->INSSBuffer_iface.lpVtbl = &buffer_vtbl;
+ buffer->refcount = 1;
+ buffer->sample = sample;
+
+ *out = &buffer->INSSBuffer_iface;
+ TRACE("Created buffer %p for sample %p\n", *out, sample);
+
+ return S_OK;
+}
+
struct asf_stream
{
struct strmbase_source source;
@@ -228,6 +351,12 @@ static HRESULT asf_reader_init_stream(struct strmbase_filter *iface)
break;
}
+ if (FAILED(hr = IWMReaderAdvanced_SetAllocateForOutput(reader_advanced, i, TRUE)))
+ {
+ WARN("Failed to enable allocation for stream %u, hr %#lx\n", i, hr);
+ break;
+ }
+
if (FAILED(hr = IWMReader_GetOutputFormat(filter->reader, stream->index, 0, &props)))
{
WARN("Failed to get stream %u output format, hr %#lx\n", i, hr);
@@ -693,8 +822,32 @@ static HRESULT WINAPI reader_callback_advanced_AllocateForStream(IWMReaderCallba
static HRESULT WINAPI reader_callback_advanced_AllocateForOutput(IWMReaderCallbackAdvanced *iface,
DWORD output, DWORD size, INSSBuffer **out, void *context)
{
- FIXME("iface %p, output %lu, size %lu, out %p, context %p stub!\n", iface, output, size, out, context);
- return E_NOTIMPL;
+ struct asf_reader *filter = impl_from_IWMReaderCallbackAdvanced(iface)->filter;
+ struct asf_stream *stream = filter->streams + output;
+ IMediaSample *sample;
+ HRESULT hr;
+
+ TRACE("iface %p, output %lu, size %lu, out %p, context %p.\n", iface, output, size, out, context);
+
+ *out = NULL;
+
+ if (!stream->source.pin.peer)
+ return VFW_E_NOT_CONNECTED;
+
+ if (FAILED(hr = IMemAllocator_GetBuffer(stream->source.pAllocator, &sample, NULL, NULL, 0)))
+ {
+ WARN("Failed to get a sample, hr %#lx.\n", hr);
+ return hr;
+ }
+
+ if (size > IMediaSample_GetSize(sample))
+ {
+ WARN("Allocated media sample is too small, size %lu.\n", size);
+ IMediaSample_Release(sample);
+ return VFW_E_BUFFER_OVERFLOW;
+ }
+
+ return buffer_create(sample, out);
}
static const IWMReaderCallbackAdvancedVtbl reader_callback_advanced_vtbl =
More information about the wine-cvs
mailing list