Signed-off-by: Jactry Zeng <jzeng(a)codeweavers.com>
---
dlls/mfplat/main.c | 158 ++++++++++++++++++++++++++++++++--
dlls/mfplat/tests/Makefile.in | 2 +-
dlls/mfplat/tests/mfplat.c | 88 +++++++++++++++++++
3 files changed, 242 insertions(+), 6 deletions(-)
diff --git a/dlls/mfplat/main.c b/dlls/mfplat/main.c
index c7c346512f..2877e9a929 100644
--- a/dlls/mfplat/main.c
+++ b/dlls/mfplat/main.c
@@ -35,6 +35,7 @@
#include "wine/heap.h"
#include "wine/debug.h"
#include "wine/unicode.h"
+#include "wine/list.h"
WINE_DEFAULT_DEBUG_CHANNEL(mfplat);
@@ -448,10 +449,20 @@ HRESULT WINAPI MFCopyImage(BYTE *dest, LONG deststride, const BYTE *src, LONG sr
return E_NOTIMPL;
}
+struct mfattribute
+{
+ GUID key;
+ PROPVARIANT value;
+};
+
typedef struct _mfattributes
{
IMFAttributes IMFAttributes_iface;
LONG ref;
+ CRITICAL_SECTION lock;
+ struct mfattribute **attributes;
+ int count;
+ int allocated;
} mfattributes;
static inline mfattributes *impl_from_IMFAttributes(IMFAttributes *iface)
@@ -491,6 +502,8 @@ static ULONG WINAPI mfattributes_AddRef(IMFAttributes *iface)
return ref;
}
+static void free_attribute_object(mfattributes *object);
+
static ULONG WINAPI mfattributes_Release(IMFAttributes *iface)
{
mfattributes *This = impl_from_IMFAttributes(iface);
@@ -500,19 +513,54 @@ static ULONG WINAPI mfattributes_Release(IMFAttributes *iface)
if (!ref)
{
+ free_attribute_object(This);
HeapFree(GetProcessHeap(), 0, This);
}
return ref;
}
+static int mfattributes_finditem(mfattributes *object, REFGUID key, struct mfattribute **attribute)
+{
+ int index;
+
+ *attribute = NULL;
+ for(index = 0; index < object->count; index++)
+ {
+ if(IsEqualGUID(key, &object->attributes[index]->key))
+ {
+ *attribute = object->attributes[index];
+ break;
+ }
+ }
+ return index;
+}
+
+static HRESULT mfattributes_getitem(mfattributes *object, REFGUID key, PROPVARIANT *value)
+{
+ HRESULT hres;
+ struct mfattribute *attribute = NULL;
+
+ EnterCriticalSection(&object->lock);
+
+ mfattributes_finditem(object, key, &attribute);
+ if(!attribute)
+ hres = MF_E_ATTRIBUTENOTFOUND;
+ else
+ hres = PropVariantCopy(value, &attribute->value);
+
+ LeaveCriticalSection(&object->lock);
+
+ return hres;
+}
+
static HRESULT WINAPI mfattributes_GetItem(IMFAttributes *iface, REFGUID key, PROPVARIANT *value)
{
mfattributes *This = impl_from_IMFAttributes(iface);
- FIXME("%p, %s, %p\n", This, debugstr_guid(key), value);
+ TRACE("(%p, %s, %p)\n", This, debugstr_guid(key), value);
- return E_NOTIMPL;
+ return mfattributes_getitem(This, key, value);
}
static HRESULT WINAPI mfattributes_GetItemType(IMFAttributes *iface, REFGUID key, MF_ATTRIBUTE_TYPE *type)
@@ -645,13 +693,82 @@ static HRESULT WINAPI mfattributes_GetUnknown(IMFAttributes *iface, REFGUID key,
return E_NOTIMPL;
}
-static HRESULT WINAPI mfattributes_SetItem(IMFAttributes *iface, REFGUID key, REFPROPVARIANT Value)
+static HRESULT mfattributes_setitem(mfattributes *object, REFGUID key, REFPROPVARIANT value)
+{
+ struct mfattribute *new_attribute = NULL;
+ int index;
+
+ EnterCriticalSection(&object->lock);
+
+ index = mfattributes_finditem(object, key, &new_attribute);
+
+ if(!new_attribute)
+ {
+ if(index == object->allocated)
+ {
+ object->allocated *= 2;
+ object->attributes = heap_realloc(object->attributes, sizeof(struct mfattribute *) * object->allocated);
+ if(!object->attributes)
+ {
+ LeaveCriticalSection(&object->lock);
+ return E_OUTOFMEMORY;
+ }
+ }
+
+ new_attribute = heap_alloc(sizeof(struct mfattribute));
+ if(!new_attribute)
+ {
+ LeaveCriticalSection(&object->lock);
+ return E_OUTOFMEMORY;
+ }
+ new_attribute->key = *key;
+
+ object->attributes[index] = new_attribute;
+ object->count++;
+ }
+ else
+ PropVariantClear(&new_attribute->value);
+
+ PropVariantCopy(&new_attribute->value, value);
+
+ LeaveCriticalSection(&object->lock);
+
+ return S_OK;
+ }
+
+static BOOL is_type_valid(DWORD type)
+{
+ switch(type)
+ {
+ case MF_ATTRIBUTE_UINT32:
+ case MF_ATTRIBUTE_UINT64:
+ case MF_ATTRIBUTE_DOUBLE:
+ case MF_ATTRIBUTE_GUID:
+ case MF_ATTRIBUTE_STRING:
+ case MF_ATTRIBUTE_BLOB:
+ case MF_ATTRIBUTE_IUNKNOWN:
+ return TRUE;
+ default:
+ return FALSE;
+ }
+}
+
+static HRESULT WINAPI mfattributes_SetItem(IMFAttributes *iface, REFGUID key, REFPROPVARIANT value)
{
mfattributes *This = impl_from_IMFAttributes(iface);
- FIXME("%p, %s, %p\n", This, debugstr_guid(key), Value);
+ TRACE("(%p, %s, %p)\n", This, debugstr_guid(key), value);
- return E_NOTIMPL;
+ if(!is_type_valid(value->vt))
+ {
+ PROPVARIANT empty_value;
+
+ PropVariantClear(&empty_value);
+ mfattributes_setitem(This, key, &empty_value);
+ return MF_E_INVALIDTYPE;
+ }
+ else
+ return mfattributes_setitem(This, key, value);
}
static HRESULT WINAPI mfattributes_DeleteItem(IMFAttributes *iface, REFGUID key)
@@ -824,6 +941,31 @@ static void init_attribute_object(mfattributes *object, UINT32 size)
{
object->ref = 1;
object->IMFAttributes_iface.lpVtbl = &mfattributes_vtbl;
+ InitializeCriticalSection(&object->lock);
+ object->lock.DebugInfo->Spare[0] = (DWORD_PTR)(__FILE__ ": IMFAttributes.lock");
+ if(!size)
+ size = 3;
+ object->attributes = heap_alloc_zero(sizeof(struct mfattribute*) * size);
+ object->count = 0;
+ object->allocated = size;
+}
+
+static void free_attribute_object(mfattributes *object)
+{
+ int i;
+
+ EnterCriticalSection(&object->lock);
+
+ for(i = 0; i < object->count; i++)
+ {
+ PropVariantClear(&object->attributes[i]->value);
+ heap_free(object->attributes[i]);
+ }
+
+ LeaveCriticalSection(&object->lock);
+
+ object->lock.DebugInfo->Spare[0] = 0;
+ DeleteCriticalSection(&object->lock);
}
/***********************************************************************
@@ -901,6 +1043,7 @@ static ULONG WINAPI mfbytestream_Release(IMFByteStream *iface)
if (!ref)
{
+ free_attribute_object(&This->attributes);
HeapFree(GetProcessHeap(), 0, This);
}
@@ -1368,6 +1511,7 @@ static ULONG WINAPI mfpresentationdescriptor_Release(IMFPresentationDescriptor *
if (!ref)
{
+ free_attribute_object(&This->attributes);
HeapFree(GetProcessHeap(), 0, This);
}
@@ -2064,6 +2208,7 @@ static ULONG WINAPI mediatype_Release(IMFMediaType *iface)
if (!ref)
{
+ free_attribute_object(&This->attributes);
HeapFree(GetProcessHeap(), 0, This);
}
@@ -2426,6 +2571,7 @@ static ULONG WINAPI mfmediaevent_Release(IMFMediaEvent *iface)
if (!ref)
{
+ free_attribute_object(&This->attributes);
HeapFree(GetProcessHeap(), 0, This);
}
@@ -2940,6 +3086,7 @@ static ULONG WINAPI mfdescriptor_Release(IMFStreamDescriptor *iface)
if (!ref)
{
+ free_attribute_object(&This->attributes);
heap_free(This);
}
@@ -3437,6 +3584,7 @@ static ULONG WINAPI mfsample_Release(IMFSample *iface)
if (!ref)
{
+ free_attribute_object(&This->attributes);
heap_free(This);
}
diff --git a/dlls/mfplat/tests/Makefile.in b/dlls/mfplat/tests/Makefile.in
index 07cf328ad2..e80a3b7cfc 100644
--- a/dlls/mfplat/tests/Makefile.in
+++ b/dlls/mfplat/tests/Makefile.in
@@ -1,5 +1,5 @@
TESTDLL = mfplat.dll
-IMPORTS = ole32 mfplat
+IMPORTS = ole32 mfplat propsys
C_SRCS = \
mfplat.c
diff --git a/dlls/mfplat/tests/mfplat.c b/dlls/mfplat/tests/mfplat.c
index 3fa59f4816..13c1d3cb2f 100644
--- a/dlls/mfplat/tests/mfplat.c
+++ b/dlls/mfplat/tests/mfplat.c
@@ -33,6 +33,7 @@
#include "mfidl.h"
#include "mferror.h"
#include "mfreadwrite.h"
+#include "propvarutil.h"
#include "wine/test.h"
@@ -51,6 +52,7 @@ DEFINE_GUID(MFT_CATEGORY_OTHER, 0x90175d57,0xb7ea,0x4901,0xae,0xb3,0x93,0x3a,0x8
DEFINE_GUID(DUMMY_CLSID, 0x12345678,0x1234,0x1234,0x12,0x13,0x14,0x15,0x16,0x17,0x18,0x19);
DEFINE_GUID(DUMMY_GUID1, 0x12345678,0x1234,0x1234,0x21,0x21,0x21,0x21,0x21,0x21,0x21,0x21);
DEFINE_GUID(DUMMY_GUID2, 0x12345678,0x1234,0x1234,0x22,0x22,0x22,0x22,0x22,0x22,0x22,0x22);
+DEFINE_GUID(DUMMY_GUID3, 0x12345678,0x1234,0x1234,0x23,0x23,0x23,0x23,0x23,0x23,0x23,0x23);
static const WCHAR mp4file[] = {'t','e','s','t','.','m','p','4',0};
@@ -693,6 +695,91 @@ static void test_MFSample(void)
IMFSample_Release(sample);
}
+static void test_IMFAttributes_item(void)
+{
+ IMFAttributes *attributes;
+ HRESULT hr;
+ PROPVARIANT propvar, ret_propvar;
+ GUID key;
+
+ hr = MFCreateAttributes(&attributes, 0);
+ ok(hr == S_OK, "MFCreateAttributes failed: 0x%08x.\n", hr);
+
+ PropVariantInit(&propvar);
+ propvar.vt = MF_ATTRIBUTE_UINT32;
+ U(propvar).ulVal = 123;
+ hr = IMFAttributes_SetItem(attributes, &DUMMY_GUID1, &propvar);
+ ok(hr == S_OK, "IMFAttributes_SetItem failed: 0x%08x.\n", hr);
+ PropVariantInit(&ret_propvar);
+ ret_propvar.vt = MF_ATTRIBUTE_UINT32;
+ U(ret_propvar).ulVal = 0xdeadbeef;
+ hr = IMFAttributes_GetItem(attributes, &DUMMY_GUID1, &ret_propvar);
+ ok(hr == S_OK, "IMFAttributes_GetItem failed: 0x%08x.\n", hr);
+ ok(!PropVariantCompareEx(&propvar, &ret_propvar, 0, 0), "got wrong property.\n");
+ PropVariantClear(&ret_propvar);
+
+ PropVariantInit(&ret_propvar);
+ ret_propvar.vt = MF_ATTRIBUTE_STRING;
+ U(ret_propvar).pwszVal = NULL;
+ hr = IMFAttributes_GetItem(attributes, &DUMMY_GUID1, &ret_propvar);
+ ok(hr == S_OK, "IMFAttributes_GetItem failed: 0x%08x.\n", hr);
+ ok(!PropVariantCompareEx(&propvar, &ret_propvar, 0, 0), "got wrong property.\n");
+ PropVariantClear(&ret_propvar);
+
+ PropVariantClear(&propvar);
+
+ PropVariantInit(&propvar);
+ propvar.vt = MF_ATTRIBUTE_UINT64;
+ U(propvar).uhVal.QuadPart = 65536;
+ hr = IMFAttributes_SetItem(attributes, &DUMMY_GUID1, &propvar);
+ ok(hr == S_OK, "IMFAttributes_SetItem failed: 0x%08x.\n", hr);
+ PropVariantInit(&ret_propvar);
+ ret_propvar.vt = MF_ATTRIBUTE_UINT32;
+ U(ret_propvar).ulVal = 0xdeadbeef;
+ hr = IMFAttributes_GetItem(attributes, &DUMMY_GUID1, &ret_propvar);
+ ok(hr == S_OK, "IMFAttributes_GetItem failed: 0x%08x.\n", hr);
+ ok(!PropVariantCompareEx(&propvar, &ret_propvar, 0, 0), "got wrong property.\n");
+ PropVariantClear(&ret_propvar);
+ PropVariantClear(&propvar);
+
+ PropVariantInit(&propvar);
+ propvar.vt = VT_I4;
+ U(propvar).lVal = 123;
+ hr = IMFAttributes_SetItem(attributes, &DUMMY_GUID2, &propvar);
+ ok(hr == MF_E_INVALIDTYPE, "IMFAttributes_SetItem should failed: 0x%08x.\n", hr);
+ PropVariantInit(&ret_propvar);
+ ret_propvar.vt = MF_ATTRIBUTE_UINT32;
+ U(ret_propvar).lVal = 0xdeadbeef;
+ hr = IMFAttributes_GetItem(attributes, &DUMMY_GUID2, &ret_propvar);
+ ok(hr == S_OK, "IMFAttributes_GetItem failed: 0x%08x.\n", hr);
+ PropVariantClear(&propvar);
+ ok(!PropVariantCompareEx(&propvar, &ret_propvar, 0, 0), "got wrong property.\n");
+ PropVariantClear(&ret_propvar);
+
+ PropVariantInit(&propvar);
+ propvar.vt = MF_ATTRIBUTE_UINT32;
+ U(propvar).ulVal = 123;
+ hr = IMFAttributes_SetItem(attributes, &DUMMY_GUID3, &propvar);
+ ok(hr == S_OK, "IMFAttributes_SetItem failed: 0x%08x.\n", hr);
+
+ hr = IMFAttributes_DeleteItem(attributes, &DUMMY_GUID2);
+ todo_wine ok(hr == S_OK, "IMFAttributes_DeleteItem failed: 0x%08x.\n", hr);
+ hr = IMFAttributes_GetItemByIndex(attributes, 0, &key, &ret_propvar);
+ todo_wine ok(hr == S_OK, "IMFAttributes_GetItemByIndex failed: 0x%08x.\n", hr);
+ todo_wine ok(!PropVariantCompareEx(&propvar, &ret_propvar, 0, 0), "got wrong property.\n");
+ todo_wine ok(IsEqualIID(&key, &DUMMY_GUID3), "got wrong key: %s.\n", wine_dbgstr_guid(&key));
+ PropVariantClear(&ret_propvar);
+ PropVariantClear(&propvar);
+ propvar.vt = MF_ATTRIBUTE_UINT64;
+ U(propvar).uhVal.QuadPart = 65536;
+ hr = IMFAttributes_GetItemByIndex(attributes, 1, &key, &ret_propvar);
+ todo_wine ok(hr == S_OK, "IMFAttributes_GetItemByIndex failed: 0x%08x.\n", hr);
+ todo_wine ok(!PropVariantCompareEx(&propvar, &ret_propvar, 0, 0), "got wrong property.\n");
+ todo_wine ok(IsEqualIID(&key, &DUMMY_GUID1), "got wrong key: %s.\n", wine_dbgstr_guid(&key));
+
+ IMFAttributes_Release(attributes);
+}
+
START_TEST(mfplat)
{
CoInitialize(NULL);
@@ -708,6 +795,7 @@ START_TEST(mfplat)
test_MFCreateMFByteStreamOnStream();
test_MFCreateMemoryBuffer();
test_source_resolver();
+ test_IMFAttributes_item();
CoUninitialize();
}
--
2.20.1