[PATCH 7/7] mfplat: Implement attributes deserialization.
Nikolay Sivov
nsivov at codeweavers.com
Thu Mar 21 02:42:58 CDT 2019
Signed-off-by: Nikolay Sivov <nsivov at codeweavers.com>
---
dlls/mfplat/main.c | 117 +++++++++++++++++++++++++++++++++++--
dlls/mfplat/mfplat.spec | 2 +-
dlls/mfplat/tests/mfplat.c | 72 ++++++++++++++++++++++-
include/mfapi.h | 1 +
4 files changed, 184 insertions(+), 8 deletions(-)
diff --git a/dlls/mfplat/main.c b/dlls/mfplat/main.c
index 69746f2a68..899aca73d9 100644
--- a/dlls/mfplat/main.c
+++ b/dlls/mfplat/main.c
@@ -1509,6 +1509,7 @@ struct attributes_store_item
union
{
double f;
+ UINT32 i32;
UINT64 i64;
struct
{
@@ -1587,7 +1588,7 @@ static void attributes_serialize_write(struct attr_serialize_context *context, c
context->ptr += size;
}
-static void attributes_serialize_write_item(struct attr_serialize_context *context, struct attributes_store_item *item,
+static BOOL attributes_serialize_write_item(struct attr_serialize_context *context, struct attributes_store_item *item,
const void *value)
{
switch (item->type)
@@ -1606,8 +1607,10 @@ static void attributes_serialize_write_item(struct attr_serialize_context *conte
context->size -= item->u.subheader.size;
break;
default:
- ;
+ return FALSE;
}
+
+ return TRUE;
}
/***********************************************************************
@@ -1619,6 +1622,7 @@ HRESULT WINAPI MFGetAttributesAsBlob(IMFAttributes *attributes, UINT8 *buffer, U
struct attr_serialize_context context;
unsigned int required_size, i;
PROPVARIANT value;
+ UINT32 count;
HRESULT hr;
TRACE("%p, %p, %u.\n", attributes, buffer, size);
@@ -1636,11 +1640,12 @@ HRESULT WINAPI MFGetAttributesAsBlob(IMFAttributes *attributes, UINT8 *buffer, U
IMFAttributes_LockStore(attributes);
header.magic = ATTRIBUTES_STORE_MAGIC;
- IMFAttributes_GetCount(attributes, &header.count);
+ header.count = 0; /* Will be updated later */
+ IMFAttributes_GetCount(attributes, &count);
attributes_serialize_write(&context, &header, sizeof(header));
- for (i = 0; i < header.count; ++i)
+ for (i = 0; i < count; ++i)
{
struct attributes_store_item item;
const void *data = NULL;
@@ -1678,16 +1683,118 @@ HRESULT WINAPI MFGetAttributesAsBlob(IMFAttributes *attributes, UINT8 *buffer, U
WARN("Unknown attribute type %#x.\n", value.vt);
}
- attributes_serialize_write_item(&context, &item, data);
+ if (attributes_serialize_write_item(&context, &item, data))
+ header.count++;
PropVariantClear(&value);
}
+ memcpy(context.buffer, &header, sizeof(header));
+
IMFAttributes_UnlockStore(attributes);
return S_OK;
}
+static HRESULT attributes_deserialize_read(struct attr_serialize_context *context, void *value, unsigned int size)
+{
+ if (context->size < (context->ptr - context->buffer) + size)
+ return E_INVALIDARG;
+
+ memcpy(value, context->ptr, size);
+ context->ptr += size;
+
+ return S_OK;
+}
+
+/***********************************************************************
+ * MFInitAttributesFromBlob (mfplat.@)
+ */
+HRESULT WINAPI MFInitAttributesFromBlob(IMFAttributes *dest, const UINT8 *buffer, UINT size)
+{
+ struct attr_serialize_context context;
+ struct attributes_store_header header;
+ struct attributes_store_item item;
+ IMFAttributes *attributes;
+ unsigned int i;
+ HRESULT hr;
+
+ TRACE("%p, %p, %u.\n", dest, buffer, size);
+
+ context.buffer = (UINT8 *)buffer;
+ context.ptr = (UINT8 *)buffer;
+ context.size = size;
+
+ /* Validate buffer structure. */
+ if (FAILED(hr = attributes_deserialize_read(&context, &header, sizeof(header))))
+ return hr;
+
+ if (header.magic != ATTRIBUTES_STORE_MAGIC)
+ return E_UNEXPECTED;
+
+ if (FAILED(hr = MFCreateAttributes(&attributes, header.count)))
+ return hr;
+
+ for (i = 0; i < header.count; ++i)
+ {
+ if (FAILED(hr = attributes_deserialize_read(&context, &item, sizeof(item))))
+ break;
+
+ hr = E_UNEXPECTED;
+
+ switch (item.type)
+ {
+ case MF_ATTRIBUTE_UINT32:
+ hr = IMFAttributes_SetUINT32(attributes, &item.key, item.u.i32);
+ break;
+ case MF_ATTRIBUTE_UINT64:
+ hr = IMFAttributes_SetUINT64(attributes, &item.key, item.u.i64);
+ break;
+ case MF_ATTRIBUTE_DOUBLE:
+ hr = IMFAttributes_SetDouble(attributes, &item.key, item.u.f);
+ break;
+ case MF_ATTRIBUTE_GUID:
+ if (item.u.subheader.size == sizeof(GUID) &&
+ item.u.subheader.offset + item.u.subheader.size <= context.size)
+ {
+ hr = IMFAttributes_SetGUID(attributes, &item.key,
+ (const GUID *)(context.buffer + item.u.subheader.offset));
+ }
+ break;
+ case MF_ATTRIBUTE_STRING:
+ if (item.u.subheader.size >= sizeof(WCHAR) &&
+ item.u.subheader.offset + item.u.subheader.size <= context.size)
+ {
+ hr = IMFAttributes_SetString(attributes, &item.key,
+ (const WCHAR *)(context.buffer + item.u.subheader.offset));
+ }
+ break;
+ case MF_ATTRIBUTE_BLOB:
+ if (item.u.subheader.size > 0 && item.u.subheader.offset + item.u.subheader.size <= context.size)
+ {
+ hr = IMFAttributes_SetBlob(attributes, &item.key, context.buffer + item.u.subheader.offset,
+ item.u.subheader.size);
+ }
+ break;
+ default:
+ ;
+ }
+
+ if (FAILED(hr))
+ break;
+ }
+
+ if (SUCCEEDED(hr))
+ {
+ IMFAttributes_DeleteAllItems(dest);
+ hr = IMFAttributes_CopyAllItems(attributes, dest);
+ }
+
+ IMFAttributes_Release(attributes);
+
+ return hr;
+}
+
typedef struct _mfbytestream
{
mfattributes attributes;
diff --git a/dlls/mfplat/mfplat.spec b/dlls/mfplat/mfplat.spec
index 730e64b675..4272a206e6 100644
--- a/dlls/mfplat/mfplat.spec
+++ b/dlls/mfplat/mfplat.spec
@@ -107,7 +107,7 @@
@ stdcall MFHeapAlloc(long long str long long)
@ stdcall MFHeapFree(ptr)
@ stub MFInitAMMediaTypeFromMFMediaType
-@ stub MFInitAttributesFromBlob
+@ stdcall MFInitAttributesFromBlob(ptr ptr long)
@ stub MFInitMediaTypeFromAMMediaType
@ stub MFInitMediaTypeFromMFVideoFormat
@ stub MFInitMediaTypeFromMPEG1VideoInfo
diff --git a/dlls/mfplat/tests/mfplat.c b/dlls/mfplat/tests/mfplat.c
index 258895f3be..85fc176046 100644
--- a/dlls/mfplat/tests/mfplat.c
+++ b/dlls/mfplat/tests/mfplat.c
@@ -2523,14 +2523,24 @@ static void test_MFCompareFullToPartialMediaType(void)
static void test_attributes_serialization(void)
{
- IMFAttributes *attributes;
+ static const WCHAR textW[] = {'T','e','x','t',0};
+ static const UINT8 blob[] = {1,2,3};
+ IMFAttributes *attributes, *dest;
+ UINT32 size, count, value32;
+ double value_dbl;
+ UINT64 value64;
UINT8 *buffer;
- UINT32 size;
+ IUnknown *obj;
HRESULT hr;
+ WCHAR *str;
+ GUID guid;
hr = MFCreateAttributes(&attributes, 0);
ok(hr == S_OK, "Failed to create object, hr %#x.\n", hr);
+ hr = MFCreateAttributes(&dest, 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);
@@ -2543,9 +2553,67 @@ static void test_attributes_serialization(void)
hr = MFGetAttributesAsBlob(attributes, buffer, size - 1);
ok(hr == MF_E_BUFFERTOOSMALL, "Unexpected hr %#x.\n", hr);
+ hr = MFInitAttributesFromBlob(dest, buffer, size - 1);
+ ok(hr == E_INVALIDARG, "Unexpected hr %#x.\n", hr);
+
+ hr = IMFAttributes_SetUINT32(dest, &MF_MT_MAJOR_TYPE, 1);
+ ok(hr == S_OK, "Failed to set attribute, hr %#x.\n", hr);
+
+ hr = MFInitAttributesFromBlob(dest, buffer, size);
+ ok(hr == S_OK, "Failed to deserialize, hr %#x.\n", hr);
+
+ /* Previous items are cleared. */
+ hr = IMFAttributes_GetCount(dest, &count);
+ ok(hr == S_OK, "Failed to get attribute count, hr %#x.\n", hr);
+ ok(count == 0, "Unexpected count %u.\n", count);
+
heap_free(buffer);
+ /* Set some attributes of various types. */
+ IMFAttributes_SetUINT32(attributes, &MF_MT_MAJOR_TYPE, 456);
+ IMFAttributes_SetUINT64(attributes, &MF_MT_SUBTYPE, 123);
+ IMFAttributes_SetDouble(attributes, &IID_IUnknown, 0.5);
+ IMFAttributes_SetUnknown(attributes, &IID_IMFAttributes, (IUnknown *)attributes);
+ IMFAttributes_SetGUID(attributes, &GUID_NULL, &IID_IUnknown);
+ IMFAttributes_SetString(attributes, &DUMMY_CLSID, textW);
+ IMFAttributes_SetBlob(attributes, &DUMMY_GUID1, blob, sizeof(blob));
+
+ hr = MFGetAttributesAsBlobSize(attributes, &size);
+ ok(hr == S_OK, "Failed to get blob size, hr %#x.\n", hr);
+ ok(size > 8, "Got unexpected 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 = MFInitAttributesFromBlob(dest, buffer, size);
+ ok(hr == S_OK, "Failed to deserialize, hr %#x.\n", hr);
+ heap_free(buffer);
+
+ hr = IMFAttributes_GetUINT32(dest, &MF_MT_MAJOR_TYPE, &value32);
+ ok(hr == S_OK, "Failed to get get uint32 value, hr %#x.\n", hr);
+ ok(value32 == 456, "Unexpected value %u.\n", value32);
+ hr = IMFAttributes_GetUINT64(dest, &MF_MT_SUBTYPE, &value64);
+ ok(hr == S_OK, "Failed to get get uint64 value, hr %#x.\n", hr);
+ ok(value64 == 123, "Unexpected value.\n");
+ hr = IMFAttributes_GetDouble(dest, &IID_IUnknown, &value_dbl);
+ ok(hr == S_OK, "Failed to get get double value, hr %#x.\n", hr);
+ ok(value_dbl == 0.5, "Unexpected value.\n");
+ hr = IMFAttributes_GetUnknown(dest, &IID_IMFAttributes, &IID_IUnknown, (void **)&obj);
+ ok(hr == MF_E_ATTRIBUTENOTFOUND, "Unexpected hr %#x.\n", hr);
+ hr = IMFAttributes_GetGUID(dest, &GUID_NULL, &guid);
+ ok(hr == S_OK, "Failed to get guid value, hr %#x.\n", hr);
+ ok(IsEqualGUID(&guid, &IID_IUnknown), "Unexpected guid.\n");
+ hr = IMFAttributes_GetAllocatedString(dest, &DUMMY_CLSID, &str, &size);
+ ok(hr == S_OK, "Failed to get string value, hr %#x.\n", hr);
+ ok(!lstrcmpW(str, textW), "Unexpected string.\n");
+ CoTaskMemFree(str);
+ hr = IMFAttributes_GetAllocatedBlob(dest, &DUMMY_GUID1, &buffer, &size);
+ ok(hr == S_OK, "Failed to get blob value, hr %#x.\n", hr);
+ ok(!memcmp(buffer, blob, sizeof(blob)), "Unexpected blob.\n");
+ CoTaskMemFree(buffer);
+
IMFAttributes_Release(attributes);
+ IMFAttributes_Release(dest);
}
START_TEST(mfplat)
diff --git a/include/mfapi.h b/include/mfapi.h
index 5d6d1e79d7..b082f9c2dd 100644
--- a/include/mfapi.h
+++ b/include/mfapi.h
@@ -213,6 +213,7 @@ HRESULT WINAPI MFTEnum(GUID category, UINT32 flags, MFT_REGISTER_TYPE_INFO *inpu
HRESULT WINAPI MFTEnumEx(GUID category, UINT32 flags, const MFT_REGISTER_TYPE_INFO *input_type,
const MFT_REGISTER_TYPE_INFO *output_type, IMFActivate ***activate,
UINT32 *pcount);
+HRESULT WINAPI MFInitAttributesFromBlob(IMFAttributes *attributes, const UINT8 *buffer, UINT size);
HRESULT WINAPI MFInvokeCallback(IMFAsyncResult *result);
HRESULT WINAPI MFLockPlatform(void);
HRESULT WINAPI MFPutWorkItem(DWORD queue, IMFAsyncCallback *callback, IUnknown *state);
--
2.20.1
More information about the wine-devel
mailing list