mfplat: Implement attributes deserialization.

Signed-off-by: Nikolay Sivov <nsivov@codeweavers.com>
Signed-off-by: Alexandre Julliard <julliard@winehq.org>
This commit is contained in:
Nikolay Sivov 2019-03-21 10:42:58 +03:00 committed by Alexandre Julliard
parent 7dfc5db155
commit 6dc7503b23
4 changed files with 184 additions and 8 deletions

View File

@ -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;

View File

@ -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

View File

@ -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)

View File

@ -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);