[PATCH v2 4/8] mfplat: Implement IMFAttributes::{SetItem,GetItem}.

Jactry Zeng jzeng at codeweavers.com
Fri Jan 4 07:26:25 CST 2019


Signed-off-by: Jactry Zeng <jzeng at 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





More information about the wine-devel mailing list