mfplat: Implement MFCreateCollection().
Signed-off-by: Nikolay Sivov <nsivov@codeweavers.com> Signed-off-by: Alexandre Julliard <julliard@winehq.org>
This commit is contained in:
parent
d2794fe6b7
commit
a606abf245
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
|
|
Loading…
Reference in New Issue