Signed-off-by: Nikolay Sivov nsivov@codeweavers.com --- dlls/mfplat/main.c | 101 +++++++++++++++-- dlls/mfplat/tests/mfplat.c | 223 ++++++++++++++++++++++++++++++++++++- 2 files changed, 315 insertions(+), 9 deletions(-)
diff --git a/dlls/mfplat/main.c b/dlls/mfplat/main.c index 88945f6724..4589840c21 100644 --- a/dlls/mfplat/main.c +++ b/dlls/mfplat/main.c @@ -724,9 +724,24 @@ static HRESULT WINAPI mfattributes_GetItem(IMFAttributes *iface, REFGUID key, PR
static HRESULT WINAPI mfattributes_GetItemType(IMFAttributes *iface, REFGUID key, MF_ATTRIBUTE_TYPE *type) { - FIXME("%p, %s, %p.\n", iface, debugstr_attr(key), type); + struct attributes *attributes = impl_from_IMFAttributes(iface); + struct attribute *attribute; + HRESULT hr = S_OK;
- return E_NOTIMPL; + TRACE("%p, %s, %p.\n", iface, debugstr_attr(key), type); + + EnterCriticalSection(&attributes->cs); + + if ((attribute = attributes_find_item(attributes, key, NULL))) + { + *type = attribute->value.vt; + } + else + hr = MF_E_ATTRIBUTENOTFOUND; + + LeaveCriticalSection(&attributes->cs); + + return hr; }
static HRESULT WINAPI mfattributes_CompareItem(IMFAttributes *iface, REFGUID key, REFPROPVARIANT value, BOOL *result) @@ -748,14 +763,86 @@ static HRESULT WINAPI mfattributes_CompareItem(IMFAttributes *iface, REFGUID key return S_OK; }
-static HRESULT WINAPI mfattributes_Compare(IMFAttributes *iface, IMFAttributes *theirs, MF_ATTRIBUTES_MATCH_TYPE type, - BOOL *result) +static HRESULT WINAPI mfattributes_Compare(IMFAttributes *iface, IMFAttributes *theirs, + MF_ATTRIBUTES_MATCH_TYPE match_type, BOOL *ret) { - mfattributes *This = impl_from_IMFAttributes(iface); + struct attributes *attributes = impl_from_IMFAttributes(iface); + IMFAttributes *smaller, *other; + MF_ATTRIBUTE_TYPE type; + HRESULT hr = S_OK; + UINT32 count; + BOOL result; + size_t i;
- FIXME("%p, %p, %d, %p\n", This, theirs, type, result); + TRACE("%p, %p, %d, %p.\n", iface, theirs, match_type, ret);
- return E_NOTIMPL; + if (FAILED(hr = IMFAttributes_GetCount(theirs, &count))) + return hr; + + EnterCriticalSection(&attributes->cs); + + result = TRUE; + + switch (match_type) + { + case MF_ATTRIBUTES_MATCH_OUR_ITEMS: + for (i = 0; i < attributes->count; ++i) + { + if (FAILED(hr = IMFAttributes_CompareItem(theirs, &attributes->attributes[i].key, + &attributes->attributes[i].value, &result))) + break; + if (!result) + break; + } + break; + case MF_ATTRIBUTES_MATCH_THEIR_ITEMS: + hr = IMFAttributes_Compare(theirs, iface, MF_ATTRIBUTES_MATCH_OUR_ITEMS, &result); + break; + case MF_ATTRIBUTES_MATCH_ALL_ITEMS: + if (count != attributes->count) + { + result = FALSE; + break; + } + for (i = 0; i < count; ++i) + { + if (FAILED(hr = IMFAttributes_CompareItem(theirs, &attributes->attributes[i].key, + &attributes->attributes[i].value, &result))) + break; + if (!result) + break; + } + break; + case MF_ATTRIBUTES_MATCH_INTERSECTION: + for (i = 0; i < attributes->count; ++i) + { + if (FAILED(IMFAttributes_GetItemType(theirs, &attributes->attributes[i].key, &type))) + continue; + + if (FAILED(hr = IMFAttributes_CompareItem(theirs, &attributes->attributes[i].key, + &attributes->attributes[i].value, &result))) + break; + + if (!result) + break; + } + break; + case MF_ATTRIBUTES_MATCH_SMALLER: + smaller = attributes->count > count ? theirs : iface; + other = attributes->count > count ? iface : theirs; + hr = IMFAttributes_Compare(smaller, other, MF_ATTRIBUTES_MATCH_OUR_ITEMS, &result); + break; + default: + WARN("Unknown match type %d.\n", match_type); + hr = E_INVALIDARG; + } + + LeaveCriticalSection(&attributes->cs); + + if (SUCCEEDED(hr)) + *ret = result; + + return hr; }
static HRESULT WINAPI mfattributes_GetUINT32(IMFAttributes *iface, REFGUID key, UINT32 *value) diff --git a/dlls/mfplat/tests/mfplat.c b/dlls/mfplat/tests/mfplat.c index 38151d9020..d012acc524 100644 --- a/dlls/mfplat/tests/mfplat.c +++ b/dlls/mfplat/tests/mfplat.c @@ -496,14 +496,27 @@ static void check_attr_count(IMFAttributes* obj, UINT32 expected, int line) ok_(__FILE__, line)(count == expected, "Unexpected count %u, expected %u.\n", count, expected); }
-static void test_MFCreateAttributes(void) +#define CHECK_ATTR_TYPE(obj, key, expected) check_attr_type(obj, key, expected, __LINE__) +static void check_attr_type(IMFAttributes *obj, const GUID *key, MF_ATTRIBUTE_TYPE expected, int line) +{ + MF_ATTRIBUTE_TYPE type; + HRESULT hr; + + hr = IMFAttributes_GetItemType(obj, key, &type); + ok_(__FILE__, line)(hr == S_OK, "Failed to get item type, hr %#x.\n", hr); + ok_(__FILE__, line)(type == expected, "Unexpected item type %d, expected %d.\n", type, expected); +} + +static void test_attributes(void) { static const WCHAR stringW[] = {'W','i','n','e',0}; static const UINT8 blob[] = {0,1,2,3,4,5}; IMFAttributes *attributes, *attributes1; UINT8 blob_value[256], *blob_buf = NULL; + MF_ATTRIBUTES_MATCH_TYPE match_type; UINT32 value, string_length, size; PROPVARIANT propvar, ret_propvar; + MF_ATTRIBUTE_TYPE type; double double_value; IUnknown *unk_value; WCHAR bufferW[256]; @@ -516,10 +529,14 @@ static void test_MFCreateAttributes(void) hr = MFCreateAttributes( &attributes, 3 ); ok(hr == S_OK, "got 0x%08x\n", hr);
+ hr = IMFAttributes_GetItemType(attributes, &GUID_NULL, &type); + ok(hr == MF_E_ATTRIBUTENOTFOUND, "Unexpected hr %#x.\n", hr); + CHECK_ATTR_COUNT(attributes, 0); hr = IMFAttributes_SetUINT32(attributes, &MF_READWRITE_ENABLE_HARDWARE_TRANSFORMS, 123); ok(hr == S_OK, "Failed to set UINT32 value, hr %#x.\n", hr); CHECK_ATTR_COUNT(attributes, 1); + CHECK_ATTR_TYPE(attributes, &MF_READWRITE_ENABLE_HARDWARE_TRANSFORMS, MF_ATTRIBUTE_UINT32);
value = 0xdeadbeef; hr = IMFAttributes_GetUINT32(attributes, &MF_READWRITE_ENABLE_HARDWARE_TRANSFORMS, &value); @@ -534,6 +551,7 @@ static void test_MFCreateAttributes(void) hr = IMFAttributes_SetUINT64(attributes, &MF_READWRITE_ENABLE_HARDWARE_TRANSFORMS, 65536); ok(hr == S_OK, "Failed to set UINT64 value, hr %#x.\n", hr); CHECK_ATTR_COUNT(attributes, 1); + CHECK_ATTR_TYPE(attributes, &MF_READWRITE_ENABLE_HARDWARE_TRANSFORMS, MF_ATTRIBUTE_UINT64);
hr = IMFAttributes_GetUINT64(attributes, &MF_READWRITE_ENABLE_HARDWARE_TRANSFORMS, &value64); ok(hr == S_OK, "Failed to get UINT64 value, hr %#x.\n", hr); @@ -643,6 +661,7 @@ static void test_MFCreateAttributes(void) hr = IMFAttributes_SetDouble(attributes, &GUID_NULL, 22.0); ok(hr == S_OK, "Failed to set double value, hr %#x.\n", hr); CHECK_ATTR_COUNT(attributes, 3); + CHECK_ATTR_TYPE(attributes, &GUID_NULL, MF_ATTRIBUTE_DOUBLE);
double_value = 0xdeadbeef; hr = IMFAttributes_GetDouble(attributes, &GUID_NULL, &double_value); @@ -664,6 +683,7 @@ static void test_MFCreateAttributes(void) hr = IMFAttributes_SetString(attributes, &DUMMY_GUID1, stringW); ok(hr == S_OK, "Failed to set string attribute, hr %#x.\n", hr); CHECK_ATTR_COUNT(attributes, 3); + CHECK_ATTR_TYPE(attributes, &DUMMY_GUID1, MF_ATTRIBUTE_STRING);
hr = IMFAttributes_GetStringLength(attributes, &DUMMY_GUID1, &string_length); ok(hr == S_OK, "Failed to get string length, hr %#x.\n", hr); @@ -701,6 +721,7 @@ static void test_MFCreateAttributes(void) hr = IMFAttributes_SetUnknown(attributes, &DUMMY_GUID2, (IUnknown *)attributes); ok(hr == S_OK, "Failed to set value, hr %#x.\n", hr); CHECK_ATTR_COUNT(attributes, 4); + CHECK_ATTR_TYPE(attributes, &DUMMY_GUID2, MF_ATTRIBUTE_IUNKNOWN);
hr = IMFAttributes_GetUnknown(attributes, &DUMMY_GUID2, &IID_IUnknown, (void **)&unk_value); ok(hr == S_OK, "Failed to get value, hr %#x.\n", hr); @@ -747,6 +768,7 @@ static void test_MFCreateAttributes(void) hr = IMFAttributes_SetBlob(attributes, &DUMMY_GUID1, blob, sizeof(blob)); ok(hr == S_OK, "Failed to set blob attribute, hr %#x.\n", hr); CHECK_ATTR_COUNT(attributes, 1); + CHECK_ATTR_TYPE(attributes, &DUMMY_GUID1, MF_ATTRIBUTE_BLOB); hr = IMFAttributes_GetBlobSize(attributes, &DUMMY_GUID1, &size); ok(hr == S_OK, "Failed to get blob size, hr %#x.\n", hr); ok(size == sizeof(blob), "Unexpected blob size %u.\n", size); @@ -779,6 +801,203 @@ static void test_MFCreateAttributes(void)
IMFAttributes_Release(attributes); IMFAttributes_Release(attributes1); + + /* Compare() */ + hr = MFCreateAttributes(&attributes, 0); + ok(hr == S_OK, "Failed to create attributes object, hr %#x.\n", hr); + hr = MFCreateAttributes(&attributes1, 0); + ok(hr == S_OK, "Failed to create attributes object, hr %#x.\n", hr); + + hr = IMFAttributes_Compare(attributes, attributes, MF_ATTRIBUTES_MATCH_SMALLER + 1, &result); + ok(hr == E_INVALIDARG, "Unexpected hr %#x.\n", hr); + + for (match_type = MF_ATTRIBUTES_MATCH_OUR_ITEMS; match_type <= MF_ATTRIBUTES_MATCH_SMALLER; ++match_type) + { + result = FALSE; + hr = IMFAttributes_Compare(attributes, attributes, match_type, &result); + ok(hr == S_OK, "Failed to compare, hr %#x.\n", hr); + ok(result, "Unexpected result %d.\n", result); + + result = FALSE; + hr = IMFAttributes_Compare(attributes, attributes1, match_type, &result); + ok(hr == S_OK, "Failed to compare, hr %#x.\n", hr); + ok(result, "Unexpected result %d.\n", result); + } + + hr = IMFAttributes_SetUINT32(attributes, &DUMMY_GUID1, 1); + ok(hr == S_OK, "Failed to set value, hr %#x.\n", hr); + + result = TRUE; + hr = IMFAttributes_Compare(attributes, attributes1, MF_ATTRIBUTES_MATCH_OUR_ITEMS, &result); + ok(hr == S_OK, "Failed to compare, hr %#x.\n", hr); + ok(!result, "Unexpected result %d.\n", result); + + result = TRUE; + hr = IMFAttributes_Compare(attributes, attributes1, MF_ATTRIBUTES_MATCH_ALL_ITEMS, &result); + ok(hr == S_OK, "Failed to compare, hr %#x.\n", hr); + ok(!result, "Unexpected result %d.\n", result); + + result = FALSE; + hr = IMFAttributes_Compare(attributes, attributes1, MF_ATTRIBUTES_MATCH_INTERSECTION, &result); + ok(hr == S_OK, "Failed to compare, hr %#x.\n", hr); + ok(result, "Unexpected result %d.\n", result); + + result = FALSE; + hr = IMFAttributes_Compare(attributes, attributes1, MF_ATTRIBUTES_MATCH_SMALLER, &result); + ok(hr == S_OK, "Failed to compare, hr %#x.\n", hr); + ok(result, "Unexpected result %d.\n", result); + + hr = IMFAttributes_SetUINT32(attributes1, &DUMMY_GUID1, 2); + ok(hr == S_OK, "Failed to set value, hr %#x.\n", hr); + + result = TRUE; + hr = IMFAttributes_Compare(attributes, attributes1, MF_ATTRIBUTES_MATCH_ALL_ITEMS, &result); + ok(hr == S_OK, "Failed to compare, hr %#x.\n", hr); + ok(!result, "Unexpected result %d.\n", result); + + result = TRUE; + hr = IMFAttributes_Compare(attributes, attributes1, MF_ATTRIBUTES_MATCH_OUR_ITEMS, &result); + ok(hr == S_OK, "Failed to compare, hr %#x.\n", hr); + ok(!result, "Unexpected result %d.\n", result); + + result = TRUE; + hr = IMFAttributes_Compare(attributes, attributes1, MF_ATTRIBUTES_MATCH_THEIR_ITEMS, &result); + ok(hr == S_OK, "Failed to compare, hr %#x.\n", hr); + ok(!result, "Unexpected result %d.\n", result); + + result = TRUE; + hr = IMFAttributes_Compare(attributes, attributes1, MF_ATTRIBUTES_MATCH_INTERSECTION, &result); + ok(hr == S_OK, "Failed to compare, hr %#x.\n", hr); + ok(!result, "Unexpected result %d.\n", result); + + result = TRUE; + hr = IMFAttributes_Compare(attributes, attributes1, MF_ATTRIBUTES_MATCH_SMALLER, &result); + ok(hr == S_OK, "Failed to compare, hr %#x.\n", hr); + ok(!result, "Unexpected result %d.\n", result); + + result = TRUE; + hr = IMFAttributes_Compare(attributes1, attributes, MF_ATTRIBUTES_MATCH_ALL_ITEMS, &result); + ok(hr == S_OK, "Failed to compare, hr %#x.\n", hr); + ok(!result, "Unexpected result %d.\n", result); + + result = TRUE; + hr = IMFAttributes_Compare(attributes1, attributes, MF_ATTRIBUTES_MATCH_OUR_ITEMS, &result); + ok(hr == S_OK, "Failed to compare, hr %#x.\n", hr); + ok(!result, "Unexpected result %d.\n", result); + + result = TRUE; + hr = IMFAttributes_Compare(attributes1, attributes, MF_ATTRIBUTES_MATCH_THEIR_ITEMS, &result); + ok(hr == S_OK, "Failed to compare, hr %#x.\n", hr); + ok(!result, "Unexpected result %d.\n", result); + + result = TRUE; + hr = IMFAttributes_Compare(attributes1, attributes, MF_ATTRIBUTES_MATCH_INTERSECTION, &result); + ok(hr == S_OK, "Failed to compare, hr %#x.\n", hr); + ok(!result, "Unexpected result %d.\n", result); + + result = TRUE; + hr = IMFAttributes_Compare(attributes1, attributes, MF_ATTRIBUTES_MATCH_SMALLER, &result); + ok(hr == S_OK, "Failed to compare, hr %#x.\n", hr); + ok(!result, "Unexpected result %d.\n", result); + + hr = IMFAttributes_SetUINT32(attributes1, &DUMMY_GUID1, 1); + ok(hr == S_OK, "Failed to set value, hr %#x.\n", hr); + + result = FALSE; + hr = IMFAttributes_Compare(attributes, attributes1, MF_ATTRIBUTES_MATCH_ALL_ITEMS, &result); + ok(hr == S_OK, "Failed to compare, hr %#x.\n", hr); + ok(result, "Unexpected result %d.\n", result); + + result = FALSE; + hr = IMFAttributes_Compare(attributes, attributes1, MF_ATTRIBUTES_MATCH_THEIR_ITEMS, &result); + ok(hr == S_OK, "Failed to compare, hr %#x.\n", hr); + ok(result, "Unexpected result %d.\n", result); + + result = FALSE; + hr = IMFAttributes_Compare(attributes, attributes1, MF_ATTRIBUTES_MATCH_INTERSECTION, &result); + ok(hr == S_OK, "Failed to compare, hr %#x.\n", hr); + ok(result, "Unexpected result %d.\n", result); + + result = FALSE; + hr = IMFAttributes_Compare(attributes, attributes1, MF_ATTRIBUTES_MATCH_SMALLER, &result); + ok(hr == S_OK, "Failed to compare, hr %#x.\n", hr); + ok(result, "Unexpected result %d.\n", result); + + result = FALSE; + hr = IMFAttributes_Compare(attributes1, attributes, MF_ATTRIBUTES_MATCH_ALL_ITEMS, &result); + ok(hr == S_OK, "Failed to compare, hr %#x.\n", hr); + ok(result, "Unexpected result %d.\n", result); + + result = FALSE; + hr = IMFAttributes_Compare(attributes1, attributes, MF_ATTRIBUTES_MATCH_THEIR_ITEMS, &result); + ok(hr == S_OK, "Failed to compare, hr %#x.\n", hr); + ok(result, "Unexpected result %d.\n", result); + + result = FALSE; + hr = IMFAttributes_Compare(attributes1, attributes, MF_ATTRIBUTES_MATCH_INTERSECTION, &result); + ok(hr == S_OK, "Failed to compare, hr %#x.\n", hr); + ok(result, "Unexpected result %d.\n", result); + + result = FALSE; + hr = IMFAttributes_Compare(attributes1, attributes, MF_ATTRIBUTES_MATCH_SMALLER, &result); + ok(hr == S_OK, "Failed to compare, hr %#x.\n", hr); + ok(result, "Unexpected result %d.\n", result); + + hr = IMFAttributes_SetUINT32(attributes1, &DUMMY_GUID2, 2); + ok(hr == S_OK, "Failed to set value, hr %#x.\n", hr); + + result = TRUE; + hr = IMFAttributes_Compare(attributes, attributes1, MF_ATTRIBUTES_MATCH_ALL_ITEMS, &result); + ok(hr == S_OK, "Failed to compare, hr %#x.\n", hr); + ok(!result, "Unexpected result %d.\n", result); + + result = TRUE; + hr = IMFAttributes_Compare(attributes, attributes1, MF_ATTRIBUTES_MATCH_THEIR_ITEMS, &result); + ok(hr == S_OK, "Failed to compare, hr %#x.\n", hr); + ok(!result, "Unexpected result %d.\n", result); + + result = FALSE; + hr = IMFAttributes_Compare(attributes, attributes1, MF_ATTRIBUTES_MATCH_OUR_ITEMS, &result); + ok(hr == S_OK, "Failed to compare, hr %#x.\n", hr); + ok(result, "Unexpected result %d.\n", result); + + result = FALSE; + hr = IMFAttributes_Compare(attributes, attributes1, MF_ATTRIBUTES_MATCH_INTERSECTION, &result); + ok(hr == S_OK, "Failed to compare, hr %#x.\n", hr); + ok(result, "Unexpected result %d.\n", result); + + result = FALSE; + hr = IMFAttributes_Compare(attributes, attributes1, MF_ATTRIBUTES_MATCH_SMALLER, &result); + ok(hr == S_OK, "Failed to compare, hr %#x.\n", hr); + ok(result, "Unexpected result %d.\n", result); + + result = TRUE; + hr = IMFAttributes_Compare(attributes1, attributes, MF_ATTRIBUTES_MATCH_ALL_ITEMS, &result); + ok(hr == S_OK, "Failed to compare, hr %#x.\n", hr); + ok(!result, "Unexpected result %d.\n", result); + + result = FALSE; + hr = IMFAttributes_Compare(attributes1, attributes, MF_ATTRIBUTES_MATCH_THEIR_ITEMS, &result); + ok(hr == S_OK, "Failed to compare, hr %#x.\n", hr); + ok(result, "Unexpected result %d.\n", result); + + result = TRUE; + hr = IMFAttributes_Compare(attributes1, attributes, MF_ATTRIBUTES_MATCH_OUR_ITEMS, &result); + ok(hr == S_OK, "Failed to compare, hr %#x.\n", hr); + ok(!result, "Unexpected result %d.\n", result); + + result = FALSE; + hr = IMFAttributes_Compare(attributes1, attributes, MF_ATTRIBUTES_MATCH_INTERSECTION, &result); + ok(hr == S_OK, "Failed to compare, hr %#x.\n", hr); + ok(result, "Unexpected result %d.\n", result); + + result = FALSE; + hr = IMFAttributes_Compare(attributes1, attributes, MF_ATTRIBUTES_MATCH_SMALLER, &result); + ok(hr == S_OK, "Failed to compare, hr %#x.\n", hr); + ok(result, "Unexpected result %d.\n", result); + + IMFAttributes_Release(attributes); + IMFAttributes_Release(attributes1); }
static void test_MFCreateMFByteStreamOnStream(void) @@ -2112,7 +2331,7 @@ START_TEST(mfplat) test_register(); test_media_type(); test_MFCreateMediaEvent(); - test_MFCreateAttributes(); + test_attributes(); test_sample(); test_MFCreateFile(); test_MFCreateMFByteStreamOnStream();
Signed-off-by: Nikolay Sivov nsivov@codeweavers.com --- dlls/mfplat/main.c | 72 ++++++++++++++++++++++++++------------ dlls/mfplat/tests/mfplat.c | 4 ++- 2 files changed, 53 insertions(+), 23 deletions(-)
diff --git a/dlls/mfplat/main.c b/dlls/mfplat/main.c index 4589840c21..7481b77f48 100644 --- a/dlls/mfplat/main.c +++ b/dlls/mfplat/main.c @@ -37,6 +37,7 @@ #include "mfplat_private.h" #include "mfreadwrite.h" #include "propvarutil.h" +#include "strsafe.h"
WINE_DEFAULT_DEBUG_CHANNEL(mfplat);
@@ -857,7 +858,8 @@ static HRESULT WINAPI mfattributes_GetUINT32(IMFAttributes *iface, REFGUID key, attrval.vt = VT_UI4; hr = attributes_get_item(attributes, key, &attrval); if (SUCCEEDED(hr)) - hr = PropVariantToUInt32(&attrval, value); + *value = attrval.u.ulVal; + return hr; }
@@ -873,7 +875,8 @@ static HRESULT WINAPI mfattributes_GetUINT64(IMFAttributes *iface, REFGUID key, attrval.vt = VT_UI8; hr = attributes_get_item(attributes, key, &attrval); if (SUCCEEDED(hr)) - hr = PropVariantToUInt64(&attrval, value); + *value = attrval.u.uhVal.QuadPart; + return hr; }
@@ -889,7 +892,8 @@ static HRESULT WINAPI mfattributes_GetDouble(IMFAttributes *iface, REFGUID key, attrval.vt = VT_R8; hr = attributes_get_item(attributes, key, &attrval); if (SUCCEEDED(hr)) - hr = PropVariantToDouble(&attrval, value); + *value = attrval.u.dblVal; + return hr; }
@@ -905,7 +909,7 @@ static HRESULT WINAPI mfattributes_GetGUID(IMFAttributes *iface, REFGUID key, GU attrval.vt = VT_CLSID; hr = attributes_get_item(attributes, key, &attrval); if (SUCCEEDED(hr)) - hr = PropVariantToGUID(&attrval, value); + *value = *attrval.u.puuid;
return hr; } @@ -913,17 +917,25 @@ static HRESULT WINAPI mfattributes_GetGUID(IMFAttributes *iface, REFGUID key, GU static HRESULT WINAPI mfattributes_GetStringLength(IMFAttributes *iface, REFGUID key, UINT32 *length) { struct attributes *attributes = impl_from_IMFAttributes(iface); - PROPVARIANT attrval; - HRESULT hr; + struct attribute *attribute; + HRESULT hr = S_OK;
TRACE("%p, %s, %p.\n", iface, debugstr_attr(key), length);
- PropVariantInit(&attrval); - attrval.vt = VT_LPWSTR; - hr = attributes_get_item(attributes, key, &attrval); - if (SUCCEEDED(hr) && length) - *length = lstrlenW(attrval.u.pwszVal); - PropVariantClear(&attrval); + EnterCriticalSection(&attributes->cs); + + attribute = attributes_find_item(attributes, key, NULL); + if (attribute) + { + if (attribute->value.vt == MF_ATTRIBUTE_STRING) + *length = strlenW(attribute->value.u.pwszVal); + else + hr = MF_E_INVALIDTYPE; + } + else + hr = MF_E_ATTRIBUTENOTFOUND; + + LeaveCriticalSection(&attributes->cs);
return hr; } @@ -932,19 +944,35 @@ static HRESULT WINAPI mfattributes_GetString(IMFAttributes *iface, REFGUID key, UINT32 size, UINT32 *length) { struct attributes *attributes = impl_from_IMFAttributes(iface); - PROPVARIANT attrval; - HRESULT hr; + struct attribute *attribute; + HRESULT hr = S_OK;
TRACE("%p, %s, %p, %d, %p.\n", iface, debugstr_attr(key), value, size, length);
- PropVariantInit(&attrval); - attrval.vt = VT_LPWSTR; - hr = attributes_get_item(attributes, key, &attrval); - if (SUCCEEDED(hr)) - hr = PropVariantToString(&attrval, value, size); - if (SUCCEEDED(hr) && length) - *length = lstrlenW(value); - PropVariantClear(&attrval); + EnterCriticalSection(&attributes->cs); + + attribute = attributes_find_item(attributes, key, NULL); + if (attribute) + { + if (attribute->value.vt == MF_ATTRIBUTE_STRING) + { + int len = strlenW(attribute->value.u.pwszVal); + + if (length) + *length = len; + + if (size <= len) + return STRSAFE_E_INSUFFICIENT_BUFFER; + + memcpy(value, attribute->value.u.pwszVal, (len + 1) * sizeof(WCHAR)); + } + else + hr = MF_E_INVALIDTYPE; + } + else + hr = MF_E_ATTRIBUTENOTFOUND; + + LeaveCriticalSection(&attributes->cs);
return hr; } diff --git a/dlls/mfplat/tests/mfplat.c b/dlls/mfplat/tests/mfplat.c index d012acc524..90c0afcdba 100644 --- a/dlls/mfplat/tests/mfplat.c +++ b/dlls/mfplat/tests/mfplat.c @@ -708,9 +708,11 @@ static void test_attributes(void) ok(!lstrcmpW(bufferW, stringW), "Unexpected string %s.\n", wine_dbgstr_w(bufferW)); memset(bufferW, 0, sizeof(bufferW));
- hr = IMFAttributes_GetString(attributes, &DUMMY_GUID1, bufferW, 1, NULL); + string_length = 0; + hr = IMFAttributes_GetString(attributes, &DUMMY_GUID1, bufferW, 1, &string_length); ok(hr == STRSAFE_E_INSUFFICIENT_BUFFER, "Unexpected hr %#x.\n", hr); ok(!bufferW[0], "Unexpected string %s.\n", wine_dbgstr_w(bufferW)); + ok(string_length, "Unexpected length.\n");
string_length = 0xdeadbeef; hr = IMFAttributes_GetStringLength(attributes, &GUID_NULL, &string_length);
Hi,
While running your changed tests, I think I found new failures. Being a bot and all I'm not very good at pattern recognition, so I might be wrong, but could you please double-check?
Full results can be found at: https://testbot.winehq.org/JobDetails.pl?Key=49527
Your paranoid android.
=== wxppro (32 bit report) ===
mfplat: 0b40:mfplat: unhandled exception c0000005 at 2F2E2E2F
=== debian9 (32 bit Japanese:Japan report) ===
mfplat: mfplat.c:2320: Test failed: Unexpected refcount 1. Unhandled exception: page fault on read access to 0x00000009 in 32-bit code (0x7e7f1d7a).
Report errors: mfplat:mfplat crashed (c0000005)
Signed-off-by: Nikolay Sivov nsivov@codeweavers.com --- dlls/mfplat/main.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-)
diff --git a/dlls/mfplat/main.c b/dlls/mfplat/main.c index 7481b77f48..00245314fe 100644 --- a/dlls/mfplat/main.c +++ b/dlls/mfplat/main.c @@ -757,7 +757,10 @@ static HRESULT WINAPI mfattributes_CompareItem(IMFAttributes *iface, REFGUID key EnterCriticalSection(&attributes->cs);
if ((attribute = attributes_find_item(attributes, key, NULL))) - *result = !PropVariantCompareEx(&attribute->value, value, PVCU_DEFAULT, PVCF_DEFAULT); + { + *result = attribute->value.vt == value->vt && + !PropVariantCompareEx(&attribute->value, value, PVCU_DEFAULT, PVCF_DEFAULT); + }
LeaveCriticalSection(&attributes->cs);
Signed-off-by: Nikolay Sivov nsivov@codeweavers.com --- dlls/mfplat/buffer.c | 63 ++++++++++++++++++++++++++++++++------ dlls/mfplat/tests/mfplat.c | 25 +++++++++++++-- 2 files changed, 76 insertions(+), 12 deletions(-)
diff --git a/dlls/mfplat/buffer.c b/dlls/mfplat/buffer.c index b07ec875f9..de08b1b5be 100644 --- a/dlls/mfplat/buffer.c +++ b/dlls/mfplat/buffer.c @@ -34,6 +34,12 @@ struct memory_buffer DWORD current_length; };
+enum sample_prop_flags +{ + SAMPLE_PROP_HAS_DURATION = 1 << 0, + SAMPLE_PROP_HAS_TIMESTAMP = 1 << 1, +}; + struct sample { struct attributes attributes; @@ -44,6 +50,9 @@ struct sample size_t capacity; DWORD flags; CRITICAL_SECTION cs; + DWORD prop_flags; + LONGLONG duration; + LONGLONG timestamp; };
static inline struct memory_buffer *impl_from_IMFMediaBuffer(IMFMediaBuffer *iface) @@ -487,32 +496,66 @@ static HRESULT WINAPI sample_SetSampleFlags(IMFSample *iface, DWORD flags) return S_OK; }
-static HRESULT WINAPI sample_GetSampleTime(IMFSample *iface, LONGLONG *sampletime) +static HRESULT WINAPI sample_GetSampleTime(IMFSample *iface, LONGLONG *timestamp) { - FIXME("%p, %p.\n", iface, sampletime); + struct sample *sample = impl_from_IMFSample(iface); + HRESULT hr = S_OK;
- return E_NOTIMPL; + TRACE("%p, %p.\n", iface, timestamp); + + EnterCriticalSection(&sample->cs); + if (sample->prop_flags & SAMPLE_PROP_HAS_TIMESTAMP) + *timestamp = sample->timestamp; + else + hr = MF_E_NO_SAMPLE_TIMESTAMP; + LeaveCriticalSection(&sample->cs); + + return hr; }
-static HRESULT WINAPI sample_SetSampleTime(IMFSample *iface, LONGLONG sampletime) +static HRESULT WINAPI sample_SetSampleTime(IMFSample *iface, LONGLONG timestamp) { - FIXME("%p, %s.\n", iface, wine_dbgstr_longlong(sampletime)); + struct sample *sample = impl_from_IMFSample(iface);
- return E_NOTIMPL; + TRACE("%p, %s.\n", iface, wine_dbgstr_longlong(timestamp)); + + EnterCriticalSection(&sample->cs); + sample->timestamp = timestamp; + sample->prop_flags |= SAMPLE_PROP_HAS_TIMESTAMP; + LeaveCriticalSection(&sample->cs); + + return S_OK; }
static HRESULT WINAPI sample_GetSampleDuration(IMFSample *iface, LONGLONG *duration) { - FIXME("%p, %p.\n", iface, duration); + struct sample *sample = impl_from_IMFSample(iface); + HRESULT hr = S_OK;
- return E_NOTIMPL; + TRACE("%p, %p.\n", iface, duration); + + EnterCriticalSection(&sample->cs); + if (sample->prop_flags & SAMPLE_PROP_HAS_DURATION) + *duration = sample->duration; + else + hr = MF_E_NO_SAMPLE_DURATION; + LeaveCriticalSection(&sample->cs); + + return hr; }
static HRESULT WINAPI sample_SetSampleDuration(IMFSample *iface, LONGLONG duration) { - FIXME("%p, %s.\n", iface, wine_dbgstr_longlong(duration)); + struct sample *sample = impl_from_IMFSample(iface);
- return E_NOTIMPL; + TRACE("%p, %s.\n", iface, wine_dbgstr_longlong(duration)); + + EnterCriticalSection(&sample->cs); + sample->duration = duration; + sample->prop_flags |= SAMPLE_PROP_HAS_DURATION; + LeaveCriticalSection(&sample->cs); + + return S_OK; }
static HRESULT WINAPI sample_GetBufferCount(IMFSample *iface, DWORD *count) diff --git a/dlls/mfplat/tests/mfplat.c b/dlls/mfplat/tests/mfplat.c index 90c0afcdba..b66c54a374 100644 --- a/dlls/mfplat/tests/mfplat.c +++ b/dlls/mfplat/tests/mfplat.c @@ -1280,6 +1280,7 @@ static void test_sample(void) { IMFMediaBuffer *buffer, *buffer2; DWORD count, flags, length; + IMFAttributes *attributes; IMFSample *sample; LONGLONG time; HRESULT hr; @@ -1287,6 +1288,11 @@ static void test_sample(void) hr = MFCreateSample( &sample ); ok(hr == S_OK, "got 0x%08x\n", hr);
+ hr = IMFSample_QueryInterface(sample, &IID_IMFAttributes, (void **)&attributes); + ok(hr == S_OK, "Failed to get attributes interface, hr %#x.\n", hr); + + CHECK_ATTR_COUNT(attributes, 0); + hr = IMFSample_GetBufferCount(sample, NULL); ok(hr == E_INVALIDARG, "Unexpected hr %#x.\n", hr);
@@ -1305,11 +1311,9 @@ static void test_sample(void) ok(flags == 0x123, "Unexpected flags %#x.\n", flags);
hr = IMFSample_GetSampleTime(sample, &time); -todo_wine ok(hr == MF_E_NO_SAMPLE_TIMESTAMP, "Unexpected hr %#x.\n", hr);
hr = IMFSample_GetSampleDuration(sample, &time); -todo_wine ok(hr == MF_E_NO_SAMPLE_DURATION, "Unexpected hr %#x.\n", hr);
hr = IMFSample_GetBufferByIndex(sample, 0, &buffer); @@ -1363,6 +1367,23 @@ todo_wine
IMFMediaBuffer_Release(buffer);
+ /* Duration */ + hr = IMFSample_SetSampleDuration(sample, 10); + ok(hr == S_OK, "Failed to set duration, hr %#x.\n", hr); + CHECK_ATTR_COUNT(attributes, 0); + hr = IMFSample_GetSampleDuration(sample, &time); + ok(hr == S_OK, "Failed to get sample duration, hr %#x.\n", hr); + ok(time == 10, "Unexpected duration.\n"); + + /* Timestamp */ + hr = IMFSample_SetSampleTime(sample, 1); + ok(hr == S_OK, "Failed to set timestamp, hr %#x.\n", hr); + CHECK_ATTR_COUNT(attributes, 0); + hr = IMFSample_GetSampleTime(sample, &time); + ok(hr == S_OK, "Failed to get sample time, hr %#x.\n", hr); + ok(time == 1, "Unexpected timestamp.\n"); + + IMFAttributes_Release(attributes); IMFSample_Release(sample); }
Hi,
While running your changed tests, I think I found new failures. Being a bot and all I'm not very good at pattern recognition, so I might be wrong, but could you please double-check?
Full results can be found at: https://testbot.winehq.org/JobDetails.pl?Key=49529
Your paranoid android.
=== wxppro (32 bit report) ===
mfplat: 0b40:mfplat: unhandled exception c0000005 at 2F2E2E2F
Signed-off-by: Nikolay Sivov nsivov@codeweavers.com --- dlls/mfplat/main.c | 3 +++ include/mfapi.h | 4 ++++ 2 files changed, 7 insertions(+)
diff --git a/dlls/mfplat/main.c b/dlls/mfplat/main.c index 00245314fe..ccd0a03b0b 100644 --- a/dlls/mfplat/main.c +++ b/dlls/mfplat/main.c @@ -575,6 +575,7 @@ static const char *debugstr_attr(const GUID *guid) X(MF_MT_FRAME_RATE_RANGE_MAX), X(MF_MT_USER_DATA), X(MF_READWRITE_DISABLE_CONVERTERS), + X(MFSampleExtension_Token), X(MF_PD_SAMI_STYLELIST), X(MF_SD_LANGUAGE), X(MF_SD_PROTECTED), @@ -589,12 +590,14 @@ static const char *debugstr_attr(const GUID *guid) X(MF_BYTESTREAM_DLNA_PROFILE_ID), X(MF_MT_MAJOR_TYPE), X(MF_PD_ADAPTIVE_STREAMING), + X(MFSampleExtension_Timestamp), X(MF_MT_SUBTYPE), X(MF_SD_MUTUALLY_EXCLUSIVE), X(MF_SD_STREAM_NAME), X(MF_SINK_WRITER_D3D_MANAGER), X(MF_MT_INTERLACE_MODE), X(MF_READWRITE_MMCSS_PRIORITY), + X(MFSampleExtension_DecodeTimestamp), X(MF_SINK_WRITER_DISABLE_THROTTLING), X(MF_READWRITE_D3D_OPTIONAL), X(MF_READWRITE_MMCSS_CLASS_AUDIO), diff --git a/include/mfapi.h b/include/mfapi.h index 21876fe574..a58699179e 100644 --- a/include/mfapi.h +++ b/include/mfapi.h @@ -118,6 +118,10 @@ DEFINE_GUID(MFMediaType_Stream, 0xe436eb83, 0x524f, 0x11ce, 0x9f, 0x5 DEFINE_GUID(MFMediaType_Subtitle, 0xa6d13581, 0xed50, 0x4e65, 0xae, 0x08, 0x26, 0x06, 0x55, 0x76, 0xaa, 0xcc); DEFINE_GUID(MFMediaType_Video, 0x73646976, 0x0000, 0x0010, 0x80, 0x00, 0x00, 0xaa, 0x00, 0x38, 0x9b, 0x71);
+DEFINE_GUID(MFSampleExtension_DecodeTimestamp, 0x73a954d4, 0x09e2, 0x4861, 0xbe, 0xfc, 0x94, 0xbd, 0x97, 0xc0, 0x8e, 0x6e); +DEFINE_GUID(MFSampleExtension_Timestamp, 0x1e436999, 0x69be, 0x4c7a, 0x93, 0x69, 0x70, 0x06, 0x8c, 0x02, 0x60, 0xcb); +DEFINE_GUID(MFSampleExtension_Token, 0x8294da66, 0xf328, 0x4805, 0xb5, 0x51, 0x00, 0xde, 0xb4, 0xc5, 0x7a, 0x61); + typedef unsigned __int64 MFWORKITEM_KEY;
typedef enum
Signed-off-by: Nikolay Sivov nsivov@codeweavers.com --- dlls/mfreadwrite/main.c | 8 ++++++++ 1 file changed, 8 insertions(+)
diff --git a/dlls/mfreadwrite/main.c b/dlls/mfreadwrite/main.c index 034d5f8960..df8f89a9d0 100644 --- a/dlls/mfreadwrite/main.c +++ b/dlls/mfreadwrite/main.c @@ -76,6 +76,7 @@ typedef struct source_reader IMFSourceReader IMFSourceReader_iface; LONG refcount; IMFMediaSource *source; + IMFPresentationDescriptor *descriptor; } srcreader;
struct sink_writer @@ -135,6 +136,8 @@ static ULONG WINAPI src_reader_Release(IMFSourceReader *iface)
if (!refcount) { + if (reader->descriptor) + IMFPresentationDescriptor_Release(reader->descriptor); IMFMediaSource_Release(reader->source); heap_free(reader); } @@ -279,7 +282,12 @@ static HRESULT create_source_reader_from_source(IMFMediaSource *source, IMFAttri object->source = source; IMFMediaSource_AddRef(object->source);
+ if (FAILED(hr = IMFMediaSource_CreatePresentationDescriptor(object->source, &object->descriptor))) + goto failed; + hr = IMFSourceReader_QueryInterface(&object->IMFSourceReader_iface, riid, out); + +failed: IMFSourceReader_Release(&object->IMFSourceReader_iface); return hr; }
Hi,
While running your changed tests, I think I found new failures. Being a bot and all I'm not very good at pattern recognition, so I might be wrong, but could you please double-check?
Full results can be found at: https://testbot.winehq.org/JobDetails.pl?Key=49526
Your paranoid android.
=== wxppro (32 bit report) ===
mfplat: 0b40:mfplat: unhandled exception c0000005 at 2F2E2E2F