mfplat: Implement MFCreateCollection().

Signed-off-by: Nikolay Sivov <nsivov@codeweavers.com>
Signed-off-by: Alexandre Julliard <julliard@winehq.org>
stable
Nikolay Sivov 2019-02-22 10:36:52 +03:00 committed by Alexandre Julliard
parent d2794fe6b7
commit a606abf245
4 changed files with 358 additions and 1 deletions

View File

@ -129,6 +129,33 @@ static BOOL GUIDFromString(LPCWSTR s, GUID *id)
return FALSE;
}
static BOOL mf_array_reserve(void **elements, size_t *capacity, size_t count, size_t size)
{
size_t new_capacity, max_capacity;
void *new_elements;
if (count <= *capacity)
return TRUE;
max_capacity = ~(SIZE_T)0 / size;
if (count > max_capacity)
return FALSE;
new_capacity = max(4, *capacity);
while (new_capacity < count && new_capacity <= max_capacity / 2)
new_capacity *= 2;
if (new_capacity < count)
new_capacity = max_capacity;
if (!(new_elements = heap_realloc(*elements, new_capacity * size)))
return FALSE;
*elements = new_elements;
*capacity = new_capacity;
return TRUE;
}
BOOL WINAPI DllMain(HINSTANCE instance, DWORD reason, LPVOID reserved)
{
switch (reason)
@ -3871,3 +3898,229 @@ HRESULT WINAPI MFCreateSample(IMFSample **sample)
return S_OK;
}
struct collection
{
IMFCollection IMFCollection_iface;
LONG refcount;
IUnknown **elements;
size_t capacity;
size_t count;
};
static struct collection *impl_from_IMFCollection(IMFCollection *iface)
{
return CONTAINING_RECORD(iface, struct collection, IMFCollection_iface);
}
static void collection_clear(struct collection *collection)
{
size_t i;
for (i = 0; i < collection->count; ++i)
{
if (collection->elements[i])
IUnknown_Release(collection->elements[i]);
}
heap_free(collection->elements);
collection->elements = NULL;
collection->count = 0;
collection->capacity = 0;
}
static HRESULT WINAPI collection_QueryInterface(IMFCollection *iface, REFIID riid, void **out)
{
TRACE("%p, %s, %p.\n", iface, debugstr_guid(riid), out);
if (IsEqualIID(riid, &IID_IMFCollection) ||
IsEqualIID(riid, &IID_IUnknown))
{
*out = iface;
IMFCollection_AddRef(iface);
return S_OK;
}
WARN("Unsupported interface %s.\n", debugstr_guid(riid));
*out = NULL;
return E_NOINTERFACE;
}
static ULONG WINAPI collection_AddRef(IMFCollection *iface)
{
struct collection *collection = impl_from_IMFCollection(iface);
ULONG refcount = InterlockedIncrement(&collection->refcount);
TRACE("%p, %d.\n", collection, refcount);
return refcount;
}
static ULONG WINAPI collection_Release(IMFCollection *iface)
{
struct collection *collection = impl_from_IMFCollection(iface);
ULONG refcount = InterlockedDecrement(&collection->refcount);
TRACE("%p, %d.\n", collection, refcount);
if (!refcount)
{
collection_clear(collection);
heap_free(collection->elements);
heap_free(collection);
}
return refcount;
}
static HRESULT WINAPI collection_GetElementCount(IMFCollection *iface, DWORD *count)
{
struct collection *collection = impl_from_IMFCollection(iface);
TRACE("%p, %p.\n", iface, count);
if (!count)
return E_POINTER;
*count = collection->count;
return S_OK;
}
static HRESULT WINAPI collection_GetElement(IMFCollection *iface, DWORD idx, IUnknown **element)
{
struct collection *collection = impl_from_IMFCollection(iface);
TRACE("%p, %u, %p.\n", iface, idx, element);
if (!element)
return E_POINTER;
if (idx >= collection->count)
return E_INVALIDARG;
*element = collection->elements[idx];
if (*element)
IUnknown_AddRef(*element);
return *element ? S_OK : E_UNEXPECTED;
}
static HRESULT WINAPI collection_AddElement(IMFCollection *iface, IUnknown *element)
{
struct collection *collection = impl_from_IMFCollection(iface);
TRACE("%p, %p.\n", iface, element);
if (!mf_array_reserve((void **)&collection->elements, &collection->capacity, collection->count + 1,
sizeof(*collection->elements)))
return E_OUTOFMEMORY;
collection->elements[collection->count++] = element;
if (element)
IUnknown_AddRef(element);
return S_OK;
}
static HRESULT WINAPI collection_RemoveElement(IMFCollection *iface, DWORD idx, IUnknown **element)
{
struct collection *collection = impl_from_IMFCollection(iface);
size_t count;
TRACE("%p, %u, %p.\n", iface, idx, element);
if (!element)
return E_POINTER;
if (idx >= collection->count)
return E_INVALIDARG;
*element = collection->elements[idx];
count = collection->count - idx - 1;
if (count)
memmove(&collection->elements[idx], &collection->elements[idx + 1], count * sizeof(*collection->elements));
collection->count--;
return S_OK;
}
static HRESULT WINAPI collection_InsertElementAt(IMFCollection *iface, DWORD idx, IUnknown *element)
{
struct collection *collection = impl_from_IMFCollection(iface);
size_t i;
TRACE("%p, %u, %p.\n", iface, idx, element);
if (!mf_array_reserve((void **)&collection->elements, &collection->capacity, idx + 1,
sizeof(*collection->elements)))
return E_OUTOFMEMORY;
if (idx < collection->count)
{
memmove(&collection->elements[idx + 1], &collection->elements[idx],
(collection->count - idx) * sizeof(*collection->elements));
collection->count++;
}
else
{
for (i = collection->count; i < idx; ++i)
collection->elements[i] = NULL;
collection->count = idx + 1;
}
collection->elements[idx] = element;
if (collection->elements[idx])
IUnknown_AddRef(collection->elements[idx]);
return S_OK;
}
static HRESULT WINAPI collection_RemoveAllElements(IMFCollection *iface)
{
struct collection *collection = impl_from_IMFCollection(iface);
TRACE("%p.\n", iface);
collection_clear(collection);
return S_OK;
}
static const IMFCollectionVtbl mfcollectionvtbl =
{
collection_QueryInterface,
collection_AddRef,
collection_Release,
collection_GetElementCount,
collection_GetElement,
collection_AddElement,
collection_RemoveElement,
collection_InsertElementAt,
collection_RemoveAllElements,
};
/***********************************************************************
* MFCreateCollection (mfplat.@)
*/
HRESULT WINAPI MFCreateCollection(IMFCollection **collection)
{
struct collection *object;
TRACE("%p\n", collection);
if (!collection)
return E_POINTER;
object = heap_alloc_zero(sizeof(*object));
if (!object)
return E_OUTOFMEMORY;
object->IMFCollection_iface.lpVtbl = &mfcollectionvtbl;
object->refcount = 1;
*collection = &object->IMFCollection_iface;
return S_OK;
}

View File

@ -41,7 +41,7 @@
@ stdcall MFCreateAsyncResult(ptr ptr ptr ptr)
@ stdcall MFCreateAttributes(ptr long)
@ stub MFCreateAudioMediaType
@ stub MFCreateCollection
@ stdcall MFCreateCollection(ptr)
@ stdcall MFCreateEventQueue(ptr)
@ stdcall MFCreateFile(long long long wstr ptr)
@ stub MFCreateLegacyMediaBufferOnMFMediaBuffer

View File

@ -913,6 +913,108 @@ static void test_MFCopyImage(void)
ok(!memcmp(dest, src, 16), "Unexpected buffer contents.\n");
}
static void test_MFCreateCollection(void)
{
IMFCollection *collection;
IUnknown *element;
DWORD count;
HRESULT hr;
hr = MFCreateCollection(NULL);
ok(hr == E_POINTER, "Unexpected hr %#x.\n", hr);
hr = MFCreateCollection(&collection);
ok(hr == S_OK, "Failed to create collection, hr %#x.\n", hr);
hr = IMFCollection_GetElementCount(collection, NULL);
ok(hr == E_POINTER, "Unexpected hr %#x.\n", hr);
count = 1;
hr = IMFCollection_GetElementCount(collection, &count);
ok(hr == S_OK, "Failed to get element count, hr %#x.\n", hr);
ok(count == 0, "Unexpected count %u.\n", count);
hr = IMFCollection_GetElement(collection, 0, NULL);
ok(hr == E_POINTER, "Unexpected hr %#x.\n", hr);
element = (void *)0xdeadbeef;
hr = IMFCollection_GetElement(collection, 0, &element);
ok(hr == E_INVALIDARG, "Unexpected hr %#x.\n", hr);
ok(element == (void *)0xdeadbeef, "Unexpected pointer.\n");
hr = IMFCollection_RemoveElement(collection, 0, NULL);
ok(hr == E_POINTER, "Unexpected hr %#x.\n", hr);
element = (void *)0xdeadbeef;
hr = IMFCollection_RemoveElement(collection, 0, &element);
ok(hr == E_INVALIDARG, "Failed to remove element, hr %#x.\n", hr);
ok(element == (void *)0xdeadbeef, "Unexpected pointer.\n");
hr = IMFCollection_RemoveAllElements(collection);
ok(hr == S_OK, "Failed to clear, hr %#x.\n", hr);
hr = IMFCollection_AddElement(collection, (IUnknown *)collection);
ok(hr == S_OK, "Failed to add element, hr %#x.\n", hr);
count = 0;
hr = IMFCollection_GetElementCount(collection, &count);
ok(hr == S_OK, "Failed to get element count, hr %#x.\n", hr);
ok(count == 1, "Unexpected count %u.\n", count);
hr = IMFCollection_AddElement(collection, NULL);
ok(hr == S_OK, "Failed to add element, hr %#x.\n", hr);
count = 0;
hr = IMFCollection_GetElementCount(collection, &count);
ok(hr == S_OK, "Failed to get element count, hr %#x.\n", hr);
ok(count == 2, "Unexpected count %u.\n", count);
hr = IMFCollection_InsertElementAt(collection, 10, (IUnknown *)collection);
ok(hr == S_OK, "Failed to insert element, hr %#x.\n", hr);
count = 0;
hr = IMFCollection_GetElementCount(collection, &count);
ok(hr == S_OK, "Failed to get element count, hr %#x.\n", hr);
ok(count == 11, "Unexpected count %u.\n", count);
hr = IMFCollection_GetElement(collection, 0, &element);
ok(hr == S_OK, "Failed to get element, hr %#x.\n", hr);
ok(element == (IUnknown *)collection, "Unexpected element.\n");
IUnknown_Release(element);
hr = IMFCollection_GetElement(collection, 1, &element);
ok(hr == E_UNEXPECTED, "Unexpected hr %#x.\n", hr);
ok(!element, "Unexpected element.\n");
hr = IMFCollection_GetElement(collection, 2, &element);
ok(hr == E_UNEXPECTED, "Unexpected hr %#x.\n", hr);
ok(!element, "Unexpected element.\n");
hr = IMFCollection_GetElement(collection, 10, &element);
ok(hr == S_OK, "Failed to get element, hr %#x.\n", hr);
ok(element == (IUnknown *)collection, "Unexpected element.\n");
IUnknown_Release(element);
hr = IMFCollection_InsertElementAt(collection, 0, NULL);
ok(hr == S_OK, "Failed to insert element, hr %#x.\n", hr);
hr = IMFCollection_GetElement(collection, 0, &element);
ok(hr == E_UNEXPECTED, "Unexpected hr %#x.\n", hr);
hr = IMFCollection_RemoveAllElements(collection);
ok(hr == S_OK, "Failed to clear, hr %#x.\n", hr);
count = 1;
hr = IMFCollection_GetElementCount(collection, &count);
ok(hr == S_OK, "Failed to get element count, hr %#x.\n", hr);
ok(count == 0, "Unexpected count %u.\n", count);
hr = IMFCollection_InsertElementAt(collection, 0, NULL);
ok(hr == S_OK, "Failed to insert element, hr %#x.\n", hr);
IMFCollection_Release(collection);
}
START_TEST(mfplat)
{
CoInitialize(NULL);
@ -932,6 +1034,7 @@ START_TEST(mfplat)
test_MFCreateAsyncResult();
test_allocate_queue();
test_MFCopyImage();
test_MFCreateCollection();
CoUninitialize();
}

View File

@ -85,6 +85,7 @@ HRESULT WINAPI MFCancelWorkItem(MFWORKITEM_KEY key);
HRESULT WINAPI MFCopyImage(BYTE *dest, LONG deststride, const BYTE *src, LONG srcstride, DWORD width, DWORD lines);
HRESULT WINAPI MFCreateAttributes(IMFAttributes **attributes, UINT32 size);
HRESULT WINAPI MFCreateAsyncResult(IUnknown *object, IMFAsyncCallback *callback, IUnknown *state, IMFAsyncResult **result);
HRESULT WINAPI MFCreateCollection(IMFCollection **collection);
HRESULT WINAPI MFCreateEventQueue(IMFMediaEventQueue **queue);
HRESULT WINAPI MFCreateFile(MF_FILE_ACCESSMODE accessmode, MF_FILE_OPENMODE openmode, MF_FILE_FLAGS flags,
LPCWSTR url, IMFByteStream **bytestream);