mfplat: Implement attributes serialization.
Signed-off-by: Nikolay Sivov <nsivov@codeweavers.com> Signed-off-by: Alexandre Julliard <julliard@winehq.org>
This commit is contained in:
parent
f3a72d4e91
commit
7dfc5db155
|
@ -1364,6 +1364,7 @@ static HRESULT WINAPI mfattributes_GetItemByIndex(IMFAttributes *iface, UINT32 i
|
|||
if (index < attributes->count)
|
||||
{
|
||||
*key = attributes->attributes[index].key;
|
||||
if (value)
|
||||
PropVariantCopy(value, &attributes->attributes[index].value);
|
||||
}
|
||||
else
|
||||
|
@ -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,
|
||||
|
|
Loading…
Reference in New Issue