[PATCH 6/7] mfplat: Implement attributes serialization.
Nikolay Sivov
nsivov at codeweavers.com
Thu Mar 21 02:42:57 CDT 2019
Signed-off-by: Nikolay Sivov <nsivov at codeweavers.com>
---
dlls/mfplat/main.c | 197 ++++++++++++++++++++++++++++++++++++-
dlls/mfplat/mfplat.spec | 4 +-
dlls/mfplat/tests/mfplat.c | 29 ++++++
include/mfapi.h | 2 +
4 files changed, 229 insertions(+), 3 deletions(-)
diff --git a/dlls/mfplat/main.c b/dlls/mfplat/main.c
index ae94645ef1..69746f2a68 100644
--- a/dlls/mfplat/main.c
+++ b/dlls/mfplat/main.c
@@ -1364,7 +1364,8 @@ static HRESULT WINAPI mfattributes_GetItemByIndex(IMFAttributes *iface, UINT32 i
if (index < attributes->count)
{
*key = attributes->attributes[index].key;
- PropVariantCopy(value, &attributes->attributes[index].value);
+ if (value)
+ PropVariantCopy(value, &attributes->attributes[index].value);
}
else
hr = E_INVALIDARG;
@@ -1493,6 +1494,200 @@ HRESULT WINAPI MFCreateAttributes(IMFAttributes **attributes, UINT32 size)
return S_OK;
}
+#define ATTRIBUTES_STORE_MAGIC 0x494d4641 /* IMFA */
+
+struct attributes_store_header
+{
+ DWORD magic;
+ UINT32 count;
+};
+
+struct attributes_store_item
+{
+ GUID key;
+ QWORD type;
+ union
+ {
+ double f;
+ UINT64 i64;
+ struct
+ {
+ DWORD size;
+ DWORD offset;
+ } subheader;
+ } u;
+};
+
+/***********************************************************************
+ * MFGetAttributesAsBlobSize (mfplat.@)
+ */
+HRESULT WINAPI MFGetAttributesAsBlobSize(IMFAttributes *attributes, UINT32 *size)
+{
+ unsigned int i, count, length;
+ HRESULT hr;
+ GUID key;
+
+ TRACE("%p, %p.\n", attributes, size);
+
+ IMFAttributes_LockStore(attributes);
+
+ hr = IMFAttributes_GetCount(attributes, &count);
+
+ *size = sizeof(struct attributes_store_header);
+
+ for (i = 0; i < count; ++i)
+ {
+ MF_ATTRIBUTE_TYPE type;
+
+ hr = IMFAttributes_GetItemByIndex(attributes, i, &key, NULL);
+ if (FAILED(hr))
+ break;
+
+ *size += sizeof(struct attributes_store_item);
+
+ IMFAttributes_GetItemType(attributes, &key, &type);
+
+ switch (type)
+ {
+ case MF_ATTRIBUTE_GUID:
+ *size += sizeof(GUID);
+ break;
+ case MF_ATTRIBUTE_STRING:
+ IMFAttributes_GetStringLength(attributes, &key, &length);
+ *size += (length + 1) * sizeof(WCHAR);
+ break;
+ case MF_ATTRIBUTE_BLOB:
+ IMFAttributes_GetBlobSize(attributes, &key, &length);
+ *size += length;
+ break;
+ case MF_ATTRIBUTE_UINT32:
+ case MF_ATTRIBUTE_UINT64:
+ case MF_ATTRIBUTE_DOUBLE:
+ case MF_ATTRIBUTE_IUNKNOWN:
+ default:
+ ;
+ }
+ }
+
+ IMFAttributes_UnlockStore(attributes);
+
+ return hr;
+}
+
+struct attr_serialize_context
+{
+ UINT8 *buffer;
+ UINT8 *ptr;
+ UINT32 size;
+};
+
+static void attributes_serialize_write(struct attr_serialize_context *context, const void *value, unsigned int size)
+{
+ memcpy(context->ptr, value, size);
+ context->ptr += size;
+}
+
+static void attributes_serialize_write_item(struct attr_serialize_context *context, struct attributes_store_item *item,
+ const void *value)
+{
+ switch (item->type)
+ {
+ case MF_ATTRIBUTE_UINT32:
+ case MF_ATTRIBUTE_UINT64:
+ case MF_ATTRIBUTE_DOUBLE:
+ attributes_serialize_write(context, item, sizeof(*item));
+ break;
+ case MF_ATTRIBUTE_GUID:
+ case MF_ATTRIBUTE_STRING:
+ case MF_ATTRIBUTE_BLOB:
+ item->u.subheader.offset = context->size - item->u.subheader.size;
+ attributes_serialize_write(context, item, sizeof(*item));
+ memcpy(context->buffer + item->u.subheader.offset, value, item->u.subheader.size);
+ context->size -= item->u.subheader.size;
+ break;
+ default:
+ ;
+ }
+}
+
+/***********************************************************************
+ * MFGetAttributesAsBlob (mfplat.@)
+ */
+HRESULT WINAPI MFGetAttributesAsBlob(IMFAttributes *attributes, UINT8 *buffer, UINT size)
+{
+ struct attributes_store_header header;
+ struct attr_serialize_context context;
+ unsigned int required_size, i;
+ PROPVARIANT value;
+ HRESULT hr;
+
+ TRACE("%p, %p, %u.\n", attributes, buffer, size);
+
+ if (FAILED(hr = MFGetAttributesAsBlobSize(attributes, &required_size)))
+ return hr;
+
+ if (required_size > size)
+ return MF_E_BUFFERTOOSMALL;
+
+ context.buffer = buffer;
+ context.ptr = buffer;
+ context.size = required_size;
+
+ IMFAttributes_LockStore(attributes);
+
+ header.magic = ATTRIBUTES_STORE_MAGIC;
+ IMFAttributes_GetCount(attributes, &header.count);
+
+ attributes_serialize_write(&context, &header, sizeof(header));
+
+ for (i = 0; i < header.count; ++i)
+ {
+ struct attributes_store_item item;
+ const void *data = NULL;
+
+ hr = IMFAttributes_GetItemByIndex(attributes, i, &item.key, &value);
+ if (FAILED(hr))
+ break;
+
+ item.type = value.vt;
+
+ switch (value.vt)
+ {
+ case MF_ATTRIBUTE_UINT32:
+ case MF_ATTRIBUTE_UINT64:
+ item.u.i64 = value.u.uhVal.QuadPart;
+ break;
+ case MF_ATTRIBUTE_DOUBLE:
+ item.u.f = value.u.dblVal;
+ break;
+ case MF_ATTRIBUTE_GUID:
+ item.u.subheader.size = sizeof(*value.u.puuid);
+ data = value.u.puuid;
+ break;
+ case MF_ATTRIBUTE_STRING:
+ item.u.subheader.size = (strlenW(value.u.pwszVal) + 1) * sizeof(WCHAR);
+ data = value.u.pwszVal;
+ break;
+ case MF_ATTRIBUTE_BLOB:
+ item.u.subheader.size = value.u.caub.cElems;
+ data = value.u.caub.pElems;
+ break;
+ case MF_ATTRIBUTE_IUNKNOWN:
+ break;
+ default:
+ WARN("Unknown attribute type %#x.\n", value.vt);
+ }
+
+ attributes_serialize_write_item(&context, &item, data);
+
+ PropVariantClear(&value);
+ }
+
+ IMFAttributes_UnlockStore(attributes);
+
+ return S_OK;
+}
+
typedef struct _mfbytestream
{
mfattributes attributes;
diff --git a/dlls/mfplat/mfplat.spec b/dlls/mfplat/mfplat.spec
index 8b340a2136..730e64b675 100644
--- a/dlls/mfplat/mfplat.spec
+++ b/dlls/mfplat/mfplat.spec
@@ -85,8 +85,8 @@
@ stub MFFrameRateToAverageTimePerFrame
@ stub MFFreeAdaptersAddresses
@ stub MFGetAdaptersAddresses
-@ stub MFGetAttributesAsBlob
-@ stub MFGetAttributesAsBlobSize
+@ stdcall MFGetAttributesAsBlob(ptr ptr long)
+@ stdcall MFGetAttributesAsBlobSize(ptr ptr)
@ stub MFGetConfigurationDWORD
@ stub MFGetConfigurationPolicy
@ stub MFGetConfigurationStore
diff --git a/dlls/mfplat/tests/mfplat.c b/dlls/mfplat/tests/mfplat.c
index 2f8b1aaa3e..258895f3be 100644
--- a/dlls/mfplat/tests/mfplat.c
+++ b/dlls/mfplat/tests/mfplat.c
@@ -47,6 +47,7 @@ DEFINE_GUID(DUMMY_GUID3, 0x12345678,0x1234,0x1234,0x23,0x23,0x23,0x23,0x23,0x23,
#include "strsafe.h"
#include "wine/test.h"
+#include "wine/heap.h"
static BOOL is_win8_plus;
@@ -2520,6 +2521,33 @@ static void test_MFCompareFullToPartialMediaType(void)
IMFMediaType_Release(partial_type);
}
+static void test_attributes_serialization(void)
+{
+ IMFAttributes *attributes;
+ UINT8 *buffer;
+ UINT32 size;
+ HRESULT hr;
+
+ hr = MFCreateAttributes(&attributes, 0);
+ ok(hr == S_OK, "Failed to create object, hr %#x.\n", hr);
+
+ hr = MFGetAttributesAsBlobSize(attributes, &size);
+ ok(hr == S_OK, "Failed to get blob size, hr %#x.\n", hr);
+ ok(size == 8, "Got size %u.\n", size);
+
+ buffer = heap_alloc(size);
+
+ hr = MFGetAttributesAsBlob(attributes, buffer, size);
+ ok(hr == S_OK, "Failed to serialize, hr %#x.\n", hr);
+
+ hr = MFGetAttributesAsBlob(attributes, buffer, size - 1);
+ ok(hr == MF_E_BUFFERTOOSMALL, "Unexpected hr %#x.\n", hr);
+
+ heap_free(buffer);
+
+ IMFAttributes_Release(attributes);
+}
+
START_TEST(mfplat)
{
CoInitialize(NULL);
@@ -2551,6 +2579,7 @@ START_TEST(mfplat)
test_stream_descriptor();
test_MFCalculateImageSize();
test_MFCompareFullToPartialMediaType();
+ test_attributes_serialization();
CoUninitialize();
}
diff --git a/include/mfapi.h b/include/mfapi.h
index d8738d5ae1..5d6d1e79d7 100644
--- a/include/mfapi.h
+++ b/include/mfapi.h
@@ -204,6 +204,8 @@ HRESULT WINAPI MFCreateSample(IMFSample **sample);
HRESULT WINAPI MFCreateMemoryBuffer(DWORD max_length, IMFMediaBuffer **buffer);
void * WINAPI MFHeapAlloc(SIZE_T size, ULONG flags, char *file, int line, EAllocationType type);
void WINAPI MFHeapFree(void *ptr);
+HRESULT WINAPI MFGetAttributesAsBlob(IMFAttributes *attributes, UINT8 *buffer, UINT size);
+HRESULT WINAPI MFGetAttributesAsBlobSize(IMFAttributes *attributes, UINT32 *size);
HRESULT WINAPI MFGetTimerPeriodicity(DWORD *periodicity);
HRESULT WINAPI MFTEnum(GUID category, UINT32 flags, MFT_REGISTER_TYPE_INFO *input_type,
MFT_REGISTER_TYPE_INFO *output_type, IMFAttributes *attributes,
--
2.20.1
More information about the wine-devel
mailing list