[PATCH v4 1/5] mfplat: Implement IMFAttributes::{SetItem,GetItem}.

Jactry Zeng jzeng at codeweavers.com
Thu Mar 7 20:42:50 CST 2019


Signed-off-by: Jactry Zeng <jzeng at codeweavers.com>
---
 dlls/mfplat/buffer.c          |   7 +-
 dlls/mfplat/main.c            | 161 +++++++++++++++++++++++++++++++---
 dlls/mfplat/mediatype.c       |  17 +++-
 dlls/mfplat/mfplat_private.h  |  13 ++-
 dlls/mfplat/tests/Makefile.in |   2 +-
 dlls/mfplat/tests/mfplat.c    |  89 +++++++++++++++++++
 6 files changed, 272 insertions(+), 17 deletions(-)

diff --git a/dlls/mfplat/buffer.c b/dlls/mfplat/buffer.c
index 833ec041a9..afdb525dea 100644
--- a/dlls/mfplat/buffer.c
+++ b/dlls/mfplat/buffer.c
@@ -273,6 +273,7 @@ static ULONG WINAPI sample_Release(IMFSample *iface)
             IMFMediaBuffer_Release(sample->buffers[i]);
         DeleteCriticalSection(&sample->cs);
         heap_free(sample->buffers);
+        clear_attributes_object(&sample->attributes);
         heap_free(sample);
     }
 
@@ -706,7 +707,11 @@ HRESULT WINAPI MFCreateSample(IMFSample **sample)
     if (!object)
         return E_OUTOFMEMORY;
 
-    init_attribute_object(&object->attributes, 0);
+    if (FAILED(init_attributes_object(&object->attributes, 0)))
+    {
+        heap_free(object);
+        return E_OUTOFMEMORY;
+    }
     object->IMFSample_iface.lpVtbl = &samplevtbl;
     InitializeCriticalSection(&object->cs);
 
diff --git a/dlls/mfplat/main.c b/dlls/mfplat/main.c
index 6bec41884e..22803dc1b4 100644
--- a/dlls/mfplat/main.c
+++ b/dlls/mfplat/main.c
@@ -577,19 +577,48 @@ static ULONG WINAPI mfattributes_Release(IMFAttributes *iface)
 
     if (!ref)
     {
+        clear_attributes_object(This);
         HeapFree(GetProcessHeap(), 0, This);
     }
 
     return ref;
 }
 
+static struct mfattribute *mfattributes_find_item(mfattributes *object, REFGUID key, size_t *item_index)
+{
+    size_t index;
+
+    for (index = 0; index < object->count; index++)
+    {
+        if (IsEqualGUID(key, &object->attributes[index].key))
+        {
+            if (item_index)
+                *item_index = index;
+            return &object->attributes[index];
+        }
+    }
+    return NULL;
+}
+
 static HRESULT WINAPI mfattributes_GetItem(IMFAttributes *iface, REFGUID key, PROPVARIANT *value)
 {
     mfattributes *This = impl_from_IMFAttributes(iface);
+    HRESULT hr;
+    struct mfattribute *attribute = NULL;
 
-    FIXME("%p, %s, %p\n", This, debugstr_guid(key), value);
+    TRACE("(%p, %s, %p)\n", This, debugstr_guid(key), value);
 
-    return E_NOTIMPL;
+    EnterCriticalSection(&This->lock);
+
+    attribute = mfattributes_find_item(This, key, NULL);
+    if (!attribute)
+        hr = MF_E_ATTRIBUTENOTFOUND;
+    else
+        hr = PropVariantCopy(value, &attribute->value);
+
+    LeaveCriticalSection(&This->lock);
+
+    return hr;
 }
 
 static HRESULT WINAPI mfattributes_GetItemType(IMFAttributes *iface, REFGUID key, MF_ATTRIBUTE_TYPE *type)
@@ -722,13 +751,68 @@ 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_set_item(mfattributes *object, REFGUID key, REFPROPVARIANT value)
+{
+    struct mfattribute *attribute = NULL;
+
+    EnterCriticalSection(&object->lock);
+
+    attribute = mfattributes_find_item(object, key, NULL);
+    if (!attribute)
+    {
+        if (!mf_array_reserve((void **)&object->attributes, &object->capacity, object->count + 1,
+                              sizeof(*object->attributes)))
+        {
+            LeaveCriticalSection(&object->lock);
+            return E_OUTOFMEMORY;
+        }
+        object->attributes[object->count].key = *key;
+        attribute = &object->attributes[object->count];
+        object->count++;
+    }
+    else
+        PropVariantClear(&attribute->value);
+
+    PropVariantCopy(&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_set_item(This, key, &empty_value);
+        return MF_E_INVALIDTYPE;
+    }
+    else
+        return mfattributes_set_item(This, key, value);
 }
 
 static HRESULT WINAPI mfattributes_DeleteItem(IMFAttributes *iface, REFGUID key)
@@ -897,10 +981,42 @@ static const IMFAttributesVtbl mfattributes_vtbl =
     mfattributes_CopyAllItems
 };
 
-void init_attribute_object(mfattributes *object, UINT32 size)
+HRESULT init_attributes_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");
+
+    object->attributes = NULL;
+    object->count = 0;
+    object->capacity = 0;
+    if (!mf_array_reserve((void **)&object->attributes, &object->capacity, size,
+                          sizeof(*object->attributes)))
+    {
+        object->lock.DebugInfo->Spare[0] = 0;
+        DeleteCriticalSection(&object->lock);
+        return E_OUTOFMEMORY;
+    }
+
+    return S_OK;
+}
+
+void clear_attributes_object(mfattributes *object)
+{
+    size_t i;
+
+    EnterCriticalSection(&object->lock);
+
+    for (i = 0; i < object->count; i++)
+        PropVariantClear(&object->attributes[i].value);
+
+    heap_free(object->attributes);
+
+    LeaveCriticalSection(&object->lock);
+
+    object->lock.DebugInfo->Spare[0] = 0;
+    DeleteCriticalSection(&object->lock);
 }
 
 /***********************************************************************
@@ -916,7 +1032,11 @@ HRESULT WINAPI MFCreateAttributes(IMFAttributes **attributes, UINT32 size)
     if(!object)
         return E_OUTOFMEMORY;
 
-    init_attribute_object(object, size);
+    if (FAILED(init_attributes_object(object, size)))
+    {
+        heap_free(object);
+        return E_OUTOFMEMORY;
+    }
     *attributes = &object->IMFAttributes_iface;
 
     return S_OK;
@@ -978,6 +1098,7 @@ static ULONG WINAPI mfbytestream_Release(IMFByteStream *iface)
 
     if (!ref)
     {
+        clear_attributes_object(&This->attributes);
         HeapFree(GetProcessHeap(), 0, This);
     }
 
@@ -1218,7 +1339,11 @@ HRESULT WINAPI MFCreateMFByteStreamOnStream(IStream *stream, IMFByteStream **byt
     if(!object)
         return E_OUTOFMEMORY;
 
-    init_attribute_object(&object->attributes, 0);
+    if (FAILED(init_attributes_object(&object->attributes, 0)))
+    {
+        heap_free(object);
+        return E_OUTOFMEMORY;
+    }
     object->IMFByteStream_iface.lpVtbl = &mfbytestream_vtbl;
     object->attributes.IMFAttributes_iface.lpVtbl = &mfbytestream_attributes_vtbl;
 
@@ -1289,7 +1414,11 @@ HRESULT WINAPI MFCreateFile(MF_FILE_ACCESSMODE accessmode, MF_FILE_OPENMODE open
     if(!object)
         return E_OUTOFMEMORY;
 
-    init_attribute_object(&object->attributes, 0);
+    if (FAILED(init_attributes_object(&object->attributes, 0)))
+    {
+        heap_free(object);
+        return E_OUTOFMEMORY;
+    }
     object->IMFByteStream_iface.lpVtbl = &mfbytestream_vtbl;
     object->attributes.IMFAttributes_iface.lpVtbl = &mfbytestream_attributes_vtbl;
 
@@ -1445,6 +1574,7 @@ static ULONG WINAPI mfpresentationdescriptor_Release(IMFPresentationDescriptor *
 
     if (!ref)
     {
+        clear_attributes_object(&This->attributes);
         HeapFree(GetProcessHeap(), 0, This);
     }
 
@@ -1843,7 +1973,11 @@ static HRESULT WINAPI mfsource_CreatePresentationDescriptor(IMFMediaSource *ifac
     if (!object)
         return E_OUTOFMEMORY;
 
-    init_attribute_object(&object->attributes, 0);
+    if (FAILED(init_attributes_object(&object->attributes, 0)))
+    {
+        heap_free(object);
+        return E_OUTOFMEMORY;
+    }
     object->IMFPresentationDescriptor_iface.lpVtbl = &mfpresentationdescriptor_vtbl;
 
     *descriptor = &object->IMFPresentationDescriptor_iface;
@@ -2146,6 +2280,7 @@ static ULONG WINAPI mfmediaevent_Release(IMFMediaEvent *iface)
 
     if (!ref)
     {
+        clear_attributes_object(&This->attributes);
         HeapFree(GetProcessHeap(), 0, This);
     }
 
@@ -2436,7 +2571,11 @@ HRESULT WINAPI MFCreateMediaEvent(MediaEventType type, REFGUID extended_type, HR
     if(!object)
         return E_OUTOFMEMORY;
 
-    init_attribute_object(&object->attributes, 0);
+    if (FAILED(init_attributes_object(&object->attributes, 0)))
+    {
+        heap_free(object);
+        return E_OUTOFMEMORY;
+    }
     object->IMFMediaEvent_iface.lpVtbl = &mfmediaevent_vtbl;
 
     object->type = type;
diff --git a/dlls/mfplat/mediatype.c b/dlls/mfplat/mediatype.c
index 7abbf31796..88e34e23e2 100644
--- a/dlls/mfplat/mediatype.c
+++ b/dlls/mfplat/mediatype.c
@@ -116,6 +116,7 @@ static ULONG WINAPI mediatype_Release(IMFMediaType *iface)
 
     if (!refcount)
     {
+        clear_attributes_object(&media_type->attributes);
         heap_free(media_type);
     }
 
@@ -400,7 +401,11 @@ HRESULT WINAPI MFCreateMediaType(IMFMediaType **media_type)
     if (!object)
         return E_OUTOFMEMORY;
 
-    init_attribute_object(&object->attributes, 0);
+    if (FAILED(init_attributes_object(&object->attributes, 0)))
+    {
+        heap_free(object);
+        return E_OUTOFMEMORY;
+    }
     object->IMFMediaType_iface.lpVtbl = &mediatypevtbl;
 
     *media_type = &object->IMFMediaType_iface;
@@ -456,6 +461,7 @@ static ULONG WINAPI stream_descriptor_Release(IMFStreamDescriptor *iface)
         if (stream_desc->current_type)
             IMFMediaType_Release(stream_desc->current_type);
         DeleteCriticalSection(&stream_desc->cs);
+        clear_attributes_object(&stream_desc->attributes);
         heap_free(stream_desc);
     }
 
@@ -855,7 +861,11 @@ HRESULT WINAPI MFCreateStreamDescriptor(DWORD identifier, DWORD count,
     if (!object)
         return E_OUTOFMEMORY;
 
-    init_attribute_object(&object->attributes, 0);
+    if (FAILED(init_attributes_object(&object->attributes, 0)))
+    {
+        heap_free(object);
+        return E_OUTOFMEMORY;
+    }
     object->IMFStreamDescriptor_iface.lpVtbl = &streamdescriptorvtbl;
     object->IMFMediaTypeHandler_iface.lpVtbl = &mediatypehandlervtbl;
     object->identifier = identifier;
@@ -1264,7 +1274,8 @@ static const IMFPresentationDescriptorVtbl presentationdescriptorvtbl =
 
 static HRESULT presentation_descriptor_init(struct presentation_desc *object, DWORD count)
 {
-    init_attribute_object(&object->attributes, 0);
+    if (FAILED(init_attributes_object(&object->attributes, 0)))
+        return E_OUTOFMEMORY;
     object->IMFPresentationDescriptor_iface.lpVtbl = &presentationdescriptorvtbl;
     object->descriptors = heap_alloc_zero(count * sizeof(*object->descriptors));
     if (!object->descriptors)
diff --git a/dlls/mfplat/mfplat_private.h b/dlls/mfplat/mfplat_private.h
index 72f8f684f6..4ad71e225d 100644
--- a/dlls/mfplat/mfplat_private.h
+++ b/dlls/mfplat/mfplat_private.h
@@ -22,13 +22,24 @@
 
 #include "wine/heap.h"
 
+struct mfattribute
+{
+    GUID key;
+    PROPVARIANT value;
+};
+
 typedef struct attributes
 {
     IMFAttributes IMFAttributes_iface;
     LONG ref;
+    CRITICAL_SECTION lock;
+    struct mfattribute *attributes;
+    size_t capacity;
+    size_t count;
 } mfattributes;
 
-extern void init_attribute_object(mfattributes *object, UINT32 size) DECLSPEC_HIDDEN;
+extern HRESULT init_attributes_object(mfattributes *object, UINT32 size) DECLSPEC_HIDDEN;
+extern void clear_attributes_object(mfattributes *object) DECLSPEC_HIDDEN;
 
 extern void init_system_queues(void) DECLSPEC_HIDDEN;
 extern void shutdown_system_queues(void) DECLSPEC_HIDDEN;
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 2f4db9b219..95f13725bf 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"
 
@@ -58,6 +59,7 @@ DEFINE_GUID(MF_READWRITE_ENABLE_HARDWARE_TRANSFORMS, 0xa634a91c, 0x822b, 0x41b9,
 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};
 
@@ -419,6 +421,8 @@ static void test_MFCreateAttributes(void)
     IMFAttributes *attributes;
     HRESULT hr;
     UINT32 count;
+    PROPVARIANT propvar, ret_propvar;
+    GUID key;
 
     hr = MFCreateAttributes( &attributes, 3 );
     ok(hr == S_OK, "got 0x%08x\n", hr);
@@ -436,6 +440,91 @@ static void test_MFCreateAttributes(void)
     todo_wine ok(count == 1, "got %d\n", count);
 
     IMFAttributes_Release(attributes);
+
+    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);
+    key = GUID_NULL;
+    if (is_win8_plus)
+        hr = IMFAttributes_GetItemByIndex(attributes, 0, &key, &ret_propvar);
+    else
+        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_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;
+    key = GUID_NULL;
+    if (is_win8_plus)
+        hr = IMFAttributes_GetItemByIndex(attributes, 1, &key, &ret_propvar);
+    else
+        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_GUID1), "got wrong key: %s.\n", wine_dbgstr_guid(&key));
+
+    IMFAttributes_Release(attributes);
 }
 
 static void test_MFCreateMFByteStreamOnStream(void)
-- 
2.20.1





More information about the wine-devel mailing list