Commit 7dfc5db1 authored by Nikolay Sivov's avatar Nikolay Sivov Committed by Alexandre Julliard

mfplat: Implement attributes serialization.

parent f3a72d4e
......@@ -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;
......
......@@ -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
......
......@@ -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();
}
......@@ -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,
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment