[PATCH 2/5] wmvcore/tests: Add tests for user-allocated samples.
Zebediah Figura
zfigura at codeweavers.com
Wed Nov 10 19:05:47 CST 2021
Signed-off-by: Zebediah Figura <zfigura at codeweavers.com>
---
dlls/wmvcore/tests/wmvcore.c | 434 +++++++++++++++++++++++++++++++++--
1 file changed, 415 insertions(+), 19 deletions(-)
diff --git a/dlls/wmvcore/tests/wmvcore.c b/dlls/wmvcore/tests/wmvcore.c
index 76586822c84..07a465c7518 100644
--- a/dlls/wmvcore/tests/wmvcore.c
+++ b/dlls/wmvcore/tests/wmvcore.c
@@ -273,6 +273,117 @@ static void test_iscontentprotected(void)
ok(drm == FALSE, "got %0dx\n", drm);
}
+static LONG outstanding_buffers;
+
+struct buffer
+{
+ INSSBuffer INSSBuffer_iface;
+ LONG refcount;
+
+ DWORD capacity, size;
+ BYTE data[1];
+};
+
+static inline 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)
+{
+ if (winetest_debug > 1)
+ trace("%04x: INSSBuffer::QueryInterface(%s)\n", GetCurrentThreadId(), debugstr_guid(iid));
+
+ if (!IsEqualGUID(iid, &IID_INSSBuffer3) && !IsEqualGUID(iid, &IID_IMediaBuffer))
+ ok(0, "Unexpected IID %s.\n", debugstr_guid(iid));
+ return E_NOINTERFACE;
+}
+
+static ULONG WINAPI buffer_AddRef(INSSBuffer *iface)
+{
+ struct buffer *buffer = impl_from_INSSBuffer(iface);
+
+ return InterlockedIncrement(&buffer->refcount);
+}
+
+static ULONG WINAPI buffer_Release(INSSBuffer *iface)
+{
+ struct buffer *buffer = impl_from_INSSBuffer(iface);
+ ULONG refcount = InterlockedDecrement(&buffer->refcount);
+
+ if (!refcount)
+ {
+ InterlockedDecrement(&outstanding_buffers);
+ free(buffer);
+ }
+ return refcount;
+}
+
+static HRESULT WINAPI buffer_GetLength(INSSBuffer *iface, DWORD *size)
+{
+ struct buffer *buffer = impl_from_INSSBuffer(iface);
+
+ if (winetest_debug > 1)
+ trace("%04x: INSSBuffer::GetLength()\n", GetCurrentThreadId());
+
+ *size = buffer->size;
+ return S_OK;
+}
+
+static HRESULT WINAPI buffer_SetLength(INSSBuffer *iface, DWORD size)
+{
+ struct buffer *buffer = impl_from_INSSBuffer(iface);
+
+ if (winetest_debug > 1)
+ trace("%04x: INSSBuffer::SetLength(%u)\n", GetCurrentThreadId(), size);
+
+ ok(size <= buffer->capacity, "Got size %u, buffer capacity %u.\n", size, buffer->capacity);
+
+ buffer->size = size;
+ return S_OK;
+}
+
+static HRESULT WINAPI buffer_GetMaxLength(INSSBuffer *iface, DWORD *size)
+{
+ struct buffer *buffer = impl_from_INSSBuffer(iface);
+
+ if (winetest_debug > 1)
+ trace("%04x: INSSBuffer::GetMaxLength()\n", GetCurrentThreadId());
+
+ *size = buffer->capacity;
+ return S_OK;
+}
+
+static HRESULT WINAPI buffer_GetBuffer(INSSBuffer *iface, BYTE **data)
+{
+ ok(0, "Unexpected call.\n");
+ return E_NOTIMPL;
+}
+
+static HRESULT WINAPI buffer_GetBufferAndLength(INSSBuffer *iface, BYTE **data, DWORD *size)
+{
+ struct buffer *buffer = impl_from_INSSBuffer(iface);
+
+ if (winetest_debug > 1)
+ trace("%04x: INSSBuffer::GetBufferAndLength()\n", GetCurrentThreadId());
+
+ *size = buffer->size;
+ *data = buffer->data;
+ return S_OK;
+}
+
+static const INSSBufferVtbl buffer_vtbl =
+{
+ buffer_QueryInterface,
+ buffer_AddRef,
+ buffer_Release,
+ buffer_GetLength,
+ buffer_SetLength,
+ buffer_GetMaxLength,
+ buffer_GetBuffer,
+ buffer_GetBufferAndLength,
+};
+
struct teststream
{
IStream IStream_iface;
@@ -1230,10 +1341,13 @@ static void test_sync_reader_file(void)
struct callback
{
IWMReaderCallback IWMReaderCallback_iface;
+ IWMReaderCallbackAdvanced IWMReaderCallbackAdvanced_iface;
+ IWMReaderAllocatorEx IWMReaderAllocatorEx_iface;
LONG refcount;
HANDLE got_opened, got_stopped, eof_event;
unsigned int got_closed, got_started, got_sample, got_end_of_streaming, got_eof;
bool all_streams_off;
+ bool allocated_samples;
};
static struct callback *impl_from_IWMReaderCallback(IWMReaderCallback *iface)
@@ -1243,13 +1357,25 @@ static struct callback *impl_from_IWMReaderCallback(IWMReaderCallback *iface)
static HRESULT WINAPI callback_QueryInterface(IWMReaderCallback *iface, REFIID iid, void **out)
{
+ struct callback *callback = impl_from_IWMReaderCallback(iface);
+
if (winetest_debug > 1)
trace("%04x: IWMReaderCallback::QueryInterface(%s)\n", GetCurrentThreadId(), debugstr_guid(iid));
- if (!IsEqualGUID(iid, &IID_IWMReaderCallbackAdvanced) && !IsEqualGUID(iid, &IID_IWMCredentialCallback))
- ok(0, "Unexpected IID %s.\n", debugstr_guid(iid));
+ if (IsEqualGUID(iid, &IID_IWMReaderAllocatorEx))
+ *out = &callback->IWMReaderAllocatorEx_iface;
+ else if (IsEqualGUID(iid, &IID_IWMReaderCallbackAdvanced))
+ *out = &callback->IWMReaderCallbackAdvanced_iface;
+ else
+ {
+ if (!IsEqualGUID(iid, &IID_IWMCredentialCallback))
+ ok(0, "Unexpected IID %s.\n", debugstr_guid(iid));
- return E_NOINTERFACE;
+ return E_NOINTERFACE;
+ }
+
+ IWMReaderCallback_AddRef(iface);
+ return S_OK;
}
static ULONG WINAPI callback_AddRef(IWMReaderCallback *iface)
@@ -1362,27 +1488,39 @@ static HRESULT WINAPI callback_OnSample(IWMReaderCallback *iface, DWORD output,
ok(context == (void *)0xfacade, "Got unexpected context %p.\n", context);
- hr = INSSBuffer_GetBufferAndLength(sample, &data, &size);
- ok(hr == S_OK, "Got hr %#x.\n", hr);
+ if (callback->allocated_samples)
+ {
+ struct buffer *buffer = impl_from_INSSBuffer(sample);
- hr = INSSBuffer_GetBuffer(sample, &data2);
- ok(hr == S_OK, "Got hr %#x.\n", hr);
- ok(data2 == data, "Data pointers didn't match.\n");
+ ok(sample->lpVtbl == &buffer_vtbl, "Buffer vtbl didn't match.\n");
+ ok(buffer->size > 0 && buffer->size <= buffer->capacity, "Got size %d.\n", buffer->size);
+ }
+ else
+ {
+ ok(sample->lpVtbl != &buffer_vtbl, "Buffer vtbl shouldn't match.\n");
- hr = INSSBuffer_GetMaxLength(sample, &capacity);
- ok(hr == S_OK, "Got hr %#x.\n", hr);
- ok(size <= capacity, "Size %u exceeds capacity %u.\n", size, capacity);
+ hr = INSSBuffer_GetBufferAndLength(sample, &data, &size);
+ ok(hr == S_OK, "Got hr %#x.\n", hr);
- hr = INSSBuffer_SetLength(sample, capacity + 1);
- ok(hr == E_INVALIDARG, "Got hr %#x.\n", hr);
+ hr = INSSBuffer_GetBuffer(sample, &data2);
+ ok(hr == S_OK, "Got hr %#x.\n", hr);
+ ok(data2 == data, "Data pointers didn't match.\n");
- hr = INSSBuffer_SetLength(sample, capacity - 1);
- ok(hr == S_OK, "Got hr %#x.\n", hr);
+ hr = INSSBuffer_GetMaxLength(sample, &capacity);
+ ok(hr == S_OK, "Got hr %#x.\n", hr);
+ ok(size <= capacity, "Size %u exceeds capacity %u.\n", size, capacity);
- hr = INSSBuffer_GetBufferAndLength(sample, &data2, &size);
- ok(hr == S_OK, "Got hr %#x.\n", hr);
- ok(data2 == data, "Data pointers didn't match.\n");
- ok(size == capacity - 1, "Expected size %u, got %u.\n", capacity - 1, size);
+ hr = INSSBuffer_SetLength(sample, capacity + 1);
+ ok(hr == E_INVALIDARG, "Got hr %#x.\n", hr);
+
+ hr = INSSBuffer_SetLength(sample, capacity - 1);
+ ok(hr == S_OK, "Got hr %#x.\n", hr);
+
+ hr = INSSBuffer_GetBufferAndLength(sample, &data2, &size);
+ ok(hr == S_OK, "Got hr %#x.\n", hr);
+ ok(data2 == data, "Data pointers didn't match.\n");
+ ok(size == capacity - 1, "Expected size %u, got %u.\n", capacity - 1, size);
+ }
ok(callback->got_started > 0, "Got %u WMT_STARTED callbacks.\n", callback->got_started);
ok(!callback->got_eof, "Got %u WMT_EOF callbacks.\n", callback->got_eof);
@@ -1400,10 +1538,164 @@ static const IWMReaderCallbackVtbl callback_vtbl =
callback_OnSample,
};
+static struct callback *impl_from_IWMReaderCallbackAdvanced(IWMReaderCallbackAdvanced *iface)
+{
+ return CONTAINING_RECORD(iface, struct callback, IWMReaderCallbackAdvanced_iface);
+}
+
+static HRESULT WINAPI callback_advanced_QueryInterface(IWMReaderCallbackAdvanced *iface, REFIID iid, void **out)
+{
+ struct callback *callback = impl_from_IWMReaderCallbackAdvanced(iface);
+ return IWMReaderCallback_QueryInterface(&callback->IWMReaderCallback_iface, iid, out);
+}
+
+static ULONG WINAPI callback_advanced_AddRef(IWMReaderCallbackAdvanced *iface)
+{
+ struct callback *callback = impl_from_IWMReaderCallbackAdvanced(iface);
+ return IWMReaderCallback_AddRef(&callback->IWMReaderCallback_iface);
+}
+
+static ULONG WINAPI callback_advanced_Release(IWMReaderCallbackAdvanced *iface)
+{
+ struct callback *callback = impl_from_IWMReaderCallbackAdvanced(iface);
+ return IWMReaderCallback_Release(&callback->IWMReaderCallback_iface);
+}
+
+static HRESULT WINAPI callback_advanced_OnStreamSample(IWMReaderCallbackAdvanced *iface,
+ WORD stream_number, QWORD pts, QWORD duration, DWORD flags, INSSBuffer *sample, void *context)
+{
+ ok(0, "Unexpected call.\n");
+ return E_NOTIMPL;
+}
+
+static HRESULT WINAPI callback_advanced_OnTime(IWMReaderCallbackAdvanced *iface, QWORD time, void *context)
+{
+ if (winetest_debug > 1)
+ trace("%u: %04x: IWMReaderCallbackAdvanced::OnTime(time %I64u)\n",
+ GetTickCount(), GetCurrentThreadId(), time);
+
+ ok(time == 3000 * 10000, "Got time %I64u.\n", time);
+ ok(context == (void *)0xfacade, "Got unexpected context %p.\n", context);
+ return S_OK;
+}
+
+static HRESULT WINAPI callback_advanced_OnStreamSelection(IWMReaderCallbackAdvanced *iface,
+ WORD count, WORD *stream_numbers, WMT_STREAM_SELECTION *selections, void *context)
+{
+ ok(0, "Unexpected call.\n");
+ return E_NOTIMPL;
+}
+
+static HRESULT WINAPI callback_advanced_OnOutputPropsChanged(IWMReaderCallbackAdvanced *iface,
+ DWORD output, WM_MEDIA_TYPE *mt, void *context)
+{
+ ok(0, "Unexpected call.\n");
+ return E_NOTIMPL;
+}
+
+static HRESULT WINAPI callback_advanced_AllocateForStream(IWMReaderCallbackAdvanced *iface,
+ WORD stream_number, DWORD size, INSSBuffer **sample, void *context)
+{
+ ok(0, "Unexpected call.\n");
+ return E_NOTIMPL;
+}
+
+static HRESULT WINAPI callback_advanced_AllocateForOutput(IWMReaderCallbackAdvanced *iface,
+ DWORD output, DWORD size, INSSBuffer **sample, void *context)
+{
+ struct callback *callback = impl_from_IWMReaderCallbackAdvanced(iface);
+ struct buffer *object;
+
+ if (winetest_debug > 1)
+ trace("%u: %04x: IWMReaderCallbackAdvanced::AllocateForOutput(output %u, size %u)\n",
+ GetTickCount(), GetCurrentThreadId(), output, size);
+
+ ok(callback->allocated_samples, "AllocateForOutput() should only be called when using a custom allocator.\n");
+
+ if (!(object = malloc(offsetof(struct buffer, data[size]))))
+ return E_OUTOFMEMORY;
+
+ size = max(size, 65536);
+
+ object->INSSBuffer_iface.lpVtbl = &buffer_vtbl;
+ object->refcount = 1;
+ object->capacity = size;
+ object->size = 0;
+ *sample = &object->INSSBuffer_iface;
+
+ InterlockedIncrement(&outstanding_buffers);
+
+ ok(!context, "Got unexpected context %p.\n", context);
+ return S_OK;
+}
+
+static const IWMReaderCallbackAdvancedVtbl callback_advanced_vtbl =
+{
+ callback_advanced_QueryInterface,
+ callback_advanced_AddRef,
+ callback_advanced_Release,
+ callback_advanced_OnStreamSample,
+ callback_advanced_OnTime,
+ callback_advanced_OnStreamSelection,
+ callback_advanced_OnOutputPropsChanged,
+ callback_advanced_AllocateForStream,
+ callback_advanced_AllocateForOutput,
+};
+
+static struct callback *impl_from_IWMReaderAllocatorEx(IWMReaderAllocatorEx *iface)
+{
+ return CONTAINING_RECORD(iface, struct callback, IWMReaderAllocatorEx_iface);
+}
+
+static HRESULT WINAPI callback_allocator_QueryInterface(IWMReaderAllocatorEx *iface, REFIID iid, void **out)
+{
+ struct callback *callback = impl_from_IWMReaderAllocatorEx(iface);
+ return IWMReaderCallback_QueryInterface(&callback->IWMReaderCallback_iface, iid, out);
+}
+
+static ULONG WINAPI callback_allocator_AddRef(IWMReaderAllocatorEx *iface)
+{
+ struct callback *callback = impl_from_IWMReaderAllocatorEx(iface);
+ return IWMReaderCallback_AddRef(&callback->IWMReaderCallback_iface);
+}
+
+static ULONG WINAPI callback_allocator_Release(IWMReaderAllocatorEx *iface)
+{
+ struct callback *callback = impl_from_IWMReaderAllocatorEx(iface);
+ return IWMReaderCallback_Release(&callback->IWMReaderCallback_iface);
+}
+
+static HRESULT WINAPI callback_allocator_AllocateForStreamEx(IWMReaderAllocatorEx *iface,
+ WORD stream_number, DWORD size, INSSBuffer **sample, DWORD flags,
+ QWORD pts, QWORD duration, void *context)
+{
+ ok(0, "Unexpected call.\n");
+ return E_NOTIMPL;
+}
+
+static HRESULT WINAPI callback_allocator_AllocateForOutputEx(IWMReaderAllocatorEx *iface,
+ DWORD output, DWORD size, INSSBuffer **sample, DWORD flags,
+ QWORD pts, QWORD duration, void *context)
+{
+ ok(0, "Unexpected call.\n");
+ return E_NOTIMPL;
+}
+
+static const IWMReaderAllocatorExVtbl callback_allocator_vtbl =
+{
+ callback_allocator_QueryInterface,
+ callback_allocator_AddRef,
+ callback_allocator_Release,
+ callback_allocator_AllocateForStreamEx,
+ callback_allocator_AllocateForOutputEx,
+};
+
static void callback_init(struct callback *callback)
{
memset(callback, 0, sizeof(*callback));
callback->IWMReaderCallback_iface.lpVtbl = &callback_vtbl;
+ callback->IWMReaderCallbackAdvanced_iface.lpVtbl = &callback_advanced_vtbl;
+ callback->IWMReaderAllocatorEx_iface.lpVtbl = &callback_allocator_vtbl;
callback->refcount = 1;
callback->got_opened = CreateEventW(NULL, FALSE, FALSE, NULL);
callback->got_stopped = CreateEventW(NULL, FALSE, FALSE, NULL);
@@ -1444,6 +1736,109 @@ static void run_async_reader(IWMReader *reader, IWMReaderAdvanced2 *advanced, st
ok(hr == S_OK, "Got hr %#x.\n", hr);
ret = WaitForSingleObject(callback->got_stopped, 1000);
ok(!ret, "Wait timed out.\n");
+
+ ok(!outstanding_buffers, "Got %d outstanding buffers.\n", outstanding_buffers);
+}
+
+static void test_async_reader_allocate(IWMReader *reader,
+ IWMReaderAdvanced2 *advanced, struct callback *callback)
+{
+ BOOL allocate;
+ HRESULT hr;
+
+ callback->allocated_samples = true;
+
+ hr = IWMReaderAdvanced2_GetAllocateForOutput(advanced, 0, &allocate);
+ todo_wine ok(hr == S_OK, "Got hr %#x.\n", hr);
+ if (hr == S_OK)
+ ok(!allocate, "Got allocate %d.\n", allocate);
+ hr = IWMReaderAdvanced2_GetAllocateForOutput(advanced, 1, &allocate);
+ todo_wine ok(hr == S_OK, "Got hr %#x.\n", hr);
+ if (hr == S_OK)
+ ok(!allocate, "Got allocate %d.\n", allocate);
+ hr = IWMReaderAdvanced2_GetAllocateForOutput(advanced, 2, &allocate);
+ todo_wine ok(hr == E_INVALIDARG, "Got hr %#x.\n", hr);
+
+ hr = IWMReaderAdvanced2_GetAllocateForStream(advanced, 0, &allocate);
+ todo_wine ok(hr == E_INVALIDARG, "Got hr %#x.\n", hr);
+ hr = IWMReaderAdvanced2_GetAllocateForStream(advanced, 1, &allocate);
+ todo_wine ok(hr == S_OK, "Got hr %#x.\n", hr);
+ if (hr == S_OK)
+ ok(!allocate, "Got allocate %d.\n", allocate);
+ hr = IWMReaderAdvanced2_GetAllocateForStream(advanced, 2, &allocate);
+ todo_wine ok(hr == S_OK, "Got hr %#x.\n", hr);
+ if (hr == S_OK)
+ ok(!allocate, "Got allocate %d.\n", allocate);
+ hr = IWMReaderAdvanced2_GetAllocateForStream(advanced, 3, &allocate);
+ todo_wine ok(hr == E_INVALIDARG, "Got hr %#x.\n", hr);
+
+ hr = IWMReaderAdvanced2_SetAllocateForOutput(advanced, 0, TRUE);
+ ok(hr == S_OK, "Got hr %#x.\n", hr);
+ hr = IWMReaderAdvanced2_SetAllocateForOutput(advanced, 1, TRUE);
+ ok(hr == S_OK, "Got hr %#x.\n", hr);
+ hr = IWMReaderAdvanced2_SetAllocateForOutput(advanced, 2, TRUE);
+ ok(hr == E_INVALIDARG, "Got hr %#x.\n", hr);
+
+ hr = IWMReaderAdvanced2_GetAllocateForOutput(advanced, 0, &allocate);
+ todo_wine ok(hr == S_OK, "Got hr %#x.\n", hr);
+ if (hr == S_OK)
+ ok(allocate == TRUE, "Got allocate %d.\n", allocate);
+ hr = IWMReaderAdvanced2_GetAllocateForOutput(advanced, 1, &allocate);
+ todo_wine ok(hr == S_OK, "Got hr %#x.\n", hr);
+ if (hr == S_OK)
+ ok(allocate == TRUE, "Got allocate %d.\n", allocate);
+
+ hr = IWMReaderAdvanced2_GetAllocateForStream(advanced, 1, &allocate);
+ todo_wine ok(hr == S_OK, "Got hr %#x.\n", hr);
+ if (hr == S_OK)
+ ok(!allocate, "Got allocate %d.\n", allocate);
+ hr = IWMReaderAdvanced2_GetAllocateForStream(advanced, 2, &allocate);
+ todo_wine ok(hr == S_OK, "Got hr %#x.\n", hr);
+ if (hr == S_OK)
+ ok(!allocate, "Got allocate %d.\n", allocate);
+
+ run_async_reader(reader, advanced, callback);
+
+ callback->allocated_samples = false;
+
+ hr = IWMReaderAdvanced2_SetAllocateForOutput(advanced, 0, FALSE);
+ ok(hr == S_OK, "Got hr %#x.\n", hr);
+ hr = IWMReaderAdvanced2_SetAllocateForOutput(advanced, 1, FALSE);
+ ok(hr == S_OK, "Got hr %#x.\n", hr);
+
+ hr = IWMReaderAdvanced2_SetAllocateForStream(advanced, 0, TRUE);
+ todo_wine ok(hr == E_INVALIDARG, "Got hr %#x.\n", hr);
+ hr = IWMReaderAdvanced2_SetAllocateForStream(advanced, 1, TRUE);
+ todo_wine ok(hr == S_OK, "Got hr %#x.\n", hr);
+ hr = IWMReaderAdvanced2_SetAllocateForStream(advanced, 2, TRUE);
+ todo_wine ok(hr == S_OK, "Got hr %#x.\n", hr);
+ hr = IWMReaderAdvanced2_SetAllocateForStream(advanced, 3, TRUE);
+ todo_wine ok(hr == E_INVALIDARG, "Got hr %#x.\n", hr);
+
+ hr = IWMReaderAdvanced2_GetAllocateForOutput(advanced, 0, &allocate);
+ todo_wine ok(hr == S_OK, "Got hr %#x.\n", hr);
+ if (hr == S_OK)
+ ok(!allocate, "Got allocate %d.\n", allocate);
+ hr = IWMReaderAdvanced2_GetAllocateForOutput(advanced, 1, &allocate);
+ todo_wine ok(hr == S_OK, "Got hr %#x.\n", hr);
+ if (hr == S_OK)
+ ok(!allocate, "Got allocate %d.\n", allocate);
+
+ hr = IWMReaderAdvanced2_GetAllocateForStream(advanced, 1, &allocate);
+ todo_wine ok(hr == S_OK, "Got hr %#x.\n", hr);
+ if (hr == S_OK)
+ ok(allocate == TRUE, "Got allocate %d.\n", allocate);
+ hr = IWMReaderAdvanced2_GetAllocateForStream(advanced, 2, &allocate);
+ todo_wine ok(hr == S_OK, "Got hr %#x.\n", hr);
+ if (hr == S_OK)
+ ok(allocate == TRUE, "Got allocate %d.\n", allocate);
+
+ run_async_reader(reader, advanced, callback);
+
+ hr = IWMReaderAdvanced2_SetAllocateForStream(advanced, 1, FALSE);
+ todo_wine ok(hr == S_OK, "Got hr %#x.\n", hr);
+ hr = IWMReaderAdvanced2_SetAllocateForStream(advanced, 2, FALSE);
+ todo_wine ok(hr == S_OK, "Got hr %#x.\n", hr);
}
static void test_async_reader_selection(IWMReader *reader,
@@ -1611,6 +2006,7 @@ static void test_async_reader_streaming(void)
test_reader_attributes(profile);
test_async_reader_selection(reader, advanced, &callback);
+ test_async_reader_allocate(reader, advanced, &callback);
hr = IWMReader_Close(reader);
ok(hr == S_OK, "Got hr %#x.\n", hr);
--
2.33.0
More information about the wine-devel
mailing list