[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