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:
parent
7dfc5db155
commit
6dc7503b23
|
@ -1509,6 +1509,7 @@ struct attributes_store_item
|
||||||
union
|
union
|
||||||
{
|
{
|
||||||
double f;
|
double f;
|
||||||
|
UINT32 i32;
|
||||||
UINT64 i64;
|
UINT64 i64;
|
||||||
struct
|
struct
|
||||||
{
|
{
|
||||||
|
@ -1587,7 +1588,7 @@ static void attributes_serialize_write(struct attr_serialize_context *context, c
|
||||||
context->ptr += size;
|
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)
|
const void *value)
|
||||||
{
|
{
|
||||||
switch (item->type)
|
switch (item->type)
|
||||||
|
@ -1606,8 +1607,10 @@ static void attributes_serialize_write_item(struct attr_serialize_context *conte
|
||||||
context->size -= item->u.subheader.size;
|
context->size -= item->u.subheader.size;
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
;
|
return FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
/***********************************************************************
|
/***********************************************************************
|
||||||
|
@ -1619,6 +1622,7 @@ HRESULT WINAPI MFGetAttributesAsBlob(IMFAttributes *attributes, UINT8 *buffer, U
|
||||||
struct attr_serialize_context context;
|
struct attr_serialize_context context;
|
||||||
unsigned int required_size, i;
|
unsigned int required_size, i;
|
||||||
PROPVARIANT value;
|
PROPVARIANT value;
|
||||||
|
UINT32 count;
|
||||||
HRESULT hr;
|
HRESULT hr;
|
||||||
|
|
||||||
TRACE("%p, %p, %u.\n", attributes, buffer, size);
|
TRACE("%p, %p, %u.\n", attributes, buffer, size);
|
||||||
|
@ -1636,11 +1640,12 @@ HRESULT WINAPI MFGetAttributesAsBlob(IMFAttributes *attributes, UINT8 *buffer, U
|
||||||
IMFAttributes_LockStore(attributes);
|
IMFAttributes_LockStore(attributes);
|
||||||
|
|
||||||
header.magic = ATTRIBUTES_STORE_MAGIC;
|
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));
|
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;
|
struct attributes_store_item item;
|
||||||
const void *data = NULL;
|
const void *data = NULL;
|
||||||
|
@ -1678,16 +1683,118 @@ HRESULT WINAPI MFGetAttributesAsBlob(IMFAttributes *attributes, UINT8 *buffer, U
|
||||||
WARN("Unknown attribute type %#x.\n", value.vt);
|
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);
|
PropVariantClear(&value);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
memcpy(context.buffer, &header, sizeof(header));
|
||||||
|
|
||||||
IMFAttributes_UnlockStore(attributes);
|
IMFAttributes_UnlockStore(attributes);
|
||||||
|
|
||||||
return S_OK;
|
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
|
typedef struct _mfbytestream
|
||||||
{
|
{
|
||||||
mfattributes attributes;
|
mfattributes attributes;
|
||||||
|
|
|
@ -107,7 +107,7 @@
|
||||||
@ stdcall MFHeapAlloc(long long str long long)
|
@ stdcall MFHeapAlloc(long long str long long)
|
||||||
@ stdcall MFHeapFree(ptr)
|
@ stdcall MFHeapFree(ptr)
|
||||||
@ stub MFInitAMMediaTypeFromMFMediaType
|
@ stub MFInitAMMediaTypeFromMFMediaType
|
||||||
@ stub MFInitAttributesFromBlob
|
@ stdcall MFInitAttributesFromBlob(ptr ptr long)
|
||||||
@ stub MFInitMediaTypeFromAMMediaType
|
@ stub MFInitMediaTypeFromAMMediaType
|
||||||
@ stub MFInitMediaTypeFromMFVideoFormat
|
@ stub MFInitMediaTypeFromMFVideoFormat
|
||||||
@ stub MFInitMediaTypeFromMPEG1VideoInfo
|
@ stub MFInitMediaTypeFromMPEG1VideoInfo
|
||||||
|
|
|
@ -2523,14 +2523,24 @@ static void test_MFCompareFullToPartialMediaType(void)
|
||||||
|
|
||||||
static void test_attributes_serialization(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;
|
UINT8 *buffer;
|
||||||
UINT32 size;
|
IUnknown *obj;
|
||||||
HRESULT hr;
|
HRESULT hr;
|
||||||
|
WCHAR *str;
|
||||||
|
GUID guid;
|
||||||
|
|
||||||
hr = MFCreateAttributes(&attributes, 0);
|
hr = MFCreateAttributes(&attributes, 0);
|
||||||
ok(hr == S_OK, "Failed to create object, hr %#x.\n", hr);
|
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);
|
hr = MFGetAttributesAsBlobSize(attributes, &size);
|
||||||
ok(hr == S_OK, "Failed to get blob size, hr %#x.\n", hr);
|
ok(hr == S_OK, "Failed to get blob size, hr %#x.\n", hr);
|
||||||
ok(size == 8, "Got size %u.\n", size);
|
ok(size == 8, "Got size %u.\n", size);
|
||||||
|
@ -2543,9 +2553,67 @@ static void test_attributes_serialization(void)
|
||||||
hr = MFGetAttributesAsBlob(attributes, buffer, size - 1);
|
hr = MFGetAttributesAsBlob(attributes, buffer, size - 1);
|
||||||
ok(hr == MF_E_BUFFERTOOSMALL, "Unexpected hr %#x.\n", hr);
|
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);
|
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(attributes);
|
||||||
|
IMFAttributes_Release(dest);
|
||||||
}
|
}
|
||||||
|
|
||||||
START_TEST(mfplat)
|
START_TEST(mfplat)
|
||||||
|
|
|
@ -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,
|
HRESULT WINAPI MFTEnumEx(GUID category, UINT32 flags, const MFT_REGISTER_TYPE_INFO *input_type,
|
||||||
const MFT_REGISTER_TYPE_INFO *output_type, IMFActivate ***activate,
|
const MFT_REGISTER_TYPE_INFO *output_type, IMFActivate ***activate,
|
||||||
UINT32 *pcount);
|
UINT32 *pcount);
|
||||||
|
HRESULT WINAPI MFInitAttributesFromBlob(IMFAttributes *attributes, const UINT8 *buffer, UINT size);
|
||||||
HRESULT WINAPI MFInvokeCallback(IMFAsyncResult *result);
|
HRESULT WINAPI MFInvokeCallback(IMFAsyncResult *result);
|
||||||
HRESULT WINAPI MFLockPlatform(void);
|
HRESULT WINAPI MFLockPlatform(void);
|
||||||
HRESULT WINAPI MFPutWorkItem(DWORD queue, IMFAsyncCallback *callback, IUnknown *state);
|
HRESULT WINAPI MFPutWorkItem(DWORD queue, IMFAsyncCallback *callback, IUnknown *state);
|
||||||
|
|
Loading…
Reference in New Issue