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,7 +1364,8 @@ static HRESULT WINAPI mfattributes_GetItemByIndex(IMFAttributes *iface, UINT32 i
|
||||||
if (index < attributes->count)
|
if (index < attributes->count)
|
||||||
{
|
{
|
||||||
*key = attributes->attributes[index].key;
|
*key = attributes->attributes[index].key;
|
||||||
PropVariantCopy(value, &attributes->attributes[index].value);
|
if (value)
|
||||||
|
PropVariantCopy(value, &attributes->attributes[index].value);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
hr = E_INVALIDARG;
|
hr = E_INVALIDARG;
|
||||||
|
@ -1493,6 +1494,200 @@ HRESULT WINAPI MFCreateAttributes(IMFAttributes **attributes, UINT32 size)
|
||||||
return S_OK;
|
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
|
typedef struct _mfbytestream
|
||||||
{
|
{
|
||||||
mfattributes attributes;
|
mfattributes attributes;
|
||||||
|
|
|
@ -85,8 +85,8 @@
|
||||||
@ stub MFFrameRateToAverageTimePerFrame
|
@ stub MFFrameRateToAverageTimePerFrame
|
||||||
@ stub MFFreeAdaptersAddresses
|
@ stub MFFreeAdaptersAddresses
|
||||||
@ stub MFGetAdaptersAddresses
|
@ stub MFGetAdaptersAddresses
|
||||||
@ stub MFGetAttributesAsBlob
|
@ stdcall MFGetAttributesAsBlob(ptr ptr long)
|
||||||
@ stub MFGetAttributesAsBlobSize
|
@ stdcall MFGetAttributesAsBlobSize(ptr ptr)
|
||||||
@ stub MFGetConfigurationDWORD
|
@ stub MFGetConfigurationDWORD
|
||||||
@ stub MFGetConfigurationPolicy
|
@ stub MFGetConfigurationPolicy
|
||||||
@ stub MFGetConfigurationStore
|
@ stub MFGetConfigurationStore
|
||||||
|
|
|
@ -47,6 +47,7 @@ DEFINE_GUID(DUMMY_GUID3, 0x12345678,0x1234,0x1234,0x23,0x23,0x23,0x23,0x23,0x23,
|
||||||
#include "strsafe.h"
|
#include "strsafe.h"
|
||||||
|
|
||||||
#include "wine/test.h"
|
#include "wine/test.h"
|
||||||
|
#include "wine/heap.h"
|
||||||
|
|
||||||
static BOOL is_win8_plus;
|
static BOOL is_win8_plus;
|
||||||
|
|
||||||
|
@ -2520,6 +2521,33 @@ static void test_MFCompareFullToPartialMediaType(void)
|
||||||
IMFMediaType_Release(partial_type);
|
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)
|
START_TEST(mfplat)
|
||||||
{
|
{
|
||||||
CoInitialize(NULL);
|
CoInitialize(NULL);
|
||||||
|
@ -2551,6 +2579,7 @@ START_TEST(mfplat)
|
||||||
test_stream_descriptor();
|
test_stream_descriptor();
|
||||||
test_MFCalculateImageSize();
|
test_MFCalculateImageSize();
|
||||||
test_MFCompareFullToPartialMediaType();
|
test_MFCompareFullToPartialMediaType();
|
||||||
|
test_attributes_serialization();
|
||||||
|
|
||||||
CoUninitialize();
|
CoUninitialize();
|
||||||
}
|
}
|
||||||
|
|
|
@ -204,6 +204,8 @@ HRESULT WINAPI MFCreateSample(IMFSample **sample);
|
||||||
HRESULT WINAPI MFCreateMemoryBuffer(DWORD max_length, IMFMediaBuffer **buffer);
|
HRESULT WINAPI MFCreateMemoryBuffer(DWORD max_length, IMFMediaBuffer **buffer);
|
||||||
void * WINAPI MFHeapAlloc(SIZE_T size, ULONG flags, char *file, int line, EAllocationType type);
|
void * WINAPI MFHeapAlloc(SIZE_T size, ULONG flags, char *file, int line, EAllocationType type);
|
||||||
void WINAPI MFHeapFree(void *ptr);
|
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 MFGetTimerPeriodicity(DWORD *periodicity);
|
||||||
HRESULT WINAPI MFTEnum(GUID category, UINT32 flags, MFT_REGISTER_TYPE_INFO *input_type,
|
HRESULT WINAPI MFTEnum(GUID category, UINT32 flags, MFT_REGISTER_TYPE_INFO *input_type,
|
||||||
MFT_REGISTER_TYPE_INFO *output_type, IMFAttributes *attributes,
|
MFT_REGISTER_TYPE_INFO *output_type, IMFAttributes *attributes,
|
||||||
|
|
Loading…
Reference in New Issue