From: "Rémi Bernon" Subject: [PATCH 3/6] mfreadwrite/tests: Add some audio media type attributes tests. Message-Id: <20211108140820.458487-3-rbernon@codeweavers.com> Date: Mon, 8 Nov 2021 15:08:17 +0100 In-Reply-To: <20211108140820.458487-1-rbernon@codeweavers.com> References: <20211108140820.458487-1-rbernon@codeweavers.com> Signed-off-by: Rémi Bernon --- dlls/mfreadwrite/tests/Makefile.in | 2 +- dlls/mfreadwrite/tests/mfplat.c | 293 ++++++++++++++++++++++++++ dlls/mfreadwrite/tests/resource.rc | 4 + dlls/mfreadwrite/tests/test-48000.wav | Bin 0 -> 2104 bytes 4 files changed, 298 insertions(+), 1 deletion(-) create mode 100644 dlls/mfreadwrite/tests/test-48000.wav diff --git a/dlls/mfreadwrite/tests/Makefile.in b/dlls/mfreadwrite/tests/Makefile.in index c7476c14c6b..f37a371ef2c 100644 --- a/dlls/mfreadwrite/tests/Makefile.in +++ b/dlls/mfreadwrite/tests/Makefile.in @@ -1,5 +1,5 @@ TESTDLL = mfreadwrite.dll -IMPORTS = ole32 user32 d3d9 dxva2 mfplat mfreadwrite mfuuid +IMPORTS = ole32 user32 d3d9 dxva2 mfplat mfreadwrite mfuuid propsys C_SRCS = \ mfplat.c diff --git a/dlls/mfreadwrite/tests/mfplat.c b/dlls/mfreadwrite/tests/mfplat.c index e3ff7f6e7aa..5a7d021ef84 100644 --- a/dlls/mfreadwrite/tests/mfplat.c +++ b/dlls/mfreadwrite/tests/mfplat.c @@ -39,6 +39,7 @@ DEFINE_GUID(GUID_NULL, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0); #include "mfreadwrite.h" #include "d3d9.h" #include "dxva2api.h" +#include "propvarutil.h" #include "wine/heap.h" #include "wine/test.h" @@ -1230,6 +1231,297 @@ done: DestroyWindow(window); } +static const char *debugstr_propvariant(const PROPVARIANT *var) +{ + if (!var) return "(null)"; + switch (var->vt) + { + case VT_NULL: return "type null"; + case VT_EMPTY: return "type empty"; + case VT_BOOL: return wine_dbg_sprintf("type %#x, value %s", var->vt, var->boolVal ? "true" : "false"); + case VT_I1: return wine_dbg_sprintf("type %#x, value %d", var->vt, var->cVal); + case VT_UI1: return wine_dbg_sprintf("type %#x, value %u", var->vt, var->bVal); + case VT_I2: return wine_dbg_sprintf("type %#x, value %d", var->vt, var->iVal); + case VT_UI2: return wine_dbg_sprintf("type %#x, value %u", var->vt, var->uiVal); + case VT_I4: return wine_dbg_sprintf("type %#x, value %d", var->vt, var->lVal); + case VT_UI4: return wine_dbg_sprintf("type %#x, value %u", var->vt, var->ulVal); + case VT_I8: return wine_dbg_sprintf("type %#x, value %I64d", var->vt, (INT64)var->hVal.QuadPart); + case VT_UI8: return wine_dbg_sprintf("type %#x, value %I64u", var->vt, (UINT64)var->uhVal.QuadPart); + case VT_R4: return wine_dbg_sprintf("type %#x, value %f", var->vt, var->fltVal); + case VT_R8: return wine_dbg_sprintf("type %#x, value %f", var->vt, var->dblVal); + case VT_BSTR: + case VT_LPWSTR: return debugstr_w(var->bstrVal); + case VT_LPSTR: return debugstr_a(var->pszVal); + case VT_CLSID: return debugstr_guid(var->puuid); + default: return wine_dbg_sprintf("type %#x", var->vt); + } +} + +struct media_type_item +{ + const GUID *key; + const PROPVARIANT value; + BOOL todo_missing; +}; + +struct media_type_desc +{ + struct media_type_item items[1024]; + UINT todo_spurious; +}; + +static void check_media_type_items(IMFMediaType *media_type, const struct media_type_desc *expect) +{ + UINT32 i, j, count, spurious_count = 0; + BOOL found[1024] = {0}; + PROPVARIANT value; + HRESULT hr; + GUID key; + + hr = IMFMediaType_GetCount(media_type, &count); + ok(hr == S_OK, "GetCount returned hr %#x\n", hr); + + for (i = 0; i < count; i++) + { + PropVariantInit(&value); + hr = IMFMediaType_GetItemByIndex(media_type, i, &key, &value); + ok(hr == S_OK, "GetItemByIndex returned hr %#x\n", hr); + + for (j = 0; expect->items[j].key; j++) if (IsEqualGUID(expect->items[j].key, &key)) break; + if (!expect->items[j].key) + { + todo_wine_if(expect->todo_spurious > spurious_count) + ok(0, "spurious attribute %s\n", debugstr_guid(&key)); + spurious_count++; + continue; + } + + ok(!found[j], "duplicate attribute %s\n", debugstr_guid(&key)); + found[j] = TRUE; + + if (!strcmp(winetest_platform, "wine")) + ok(!expect->items[j].todo_missing, "attribute not missing %s\n", debugstr_guid(&key)); + ok(!PropVariantCompareEx(&value, &expect->items[j].value, 0, 0), "got %s, expected %s.\n", + debugstr_propvariant(&value), debugstr_propvariant(&expect->items[j].value)); + PropVariantClear(&value); + } + + if (!strcmp(winetest_platform, "wine")) + ok(expect->todo_spurious == spurious_count, "%u spurious attribute\n", spurious_count); + + for (j = 0; expect->items[j].key; j++) + { + if (found[j]) continue; + todo_wine_if(expect->items[j].todo_missing) + ok(0, "missing attribute %s\n", debugstr_guid(expect->items[j].key)); + } +} + +static void test_media_types(void) +{ + static const struct media_type_desc audio_44100_s8_desc = + { + .items = + { + {.key = &MF_MT_AUDIO_AVG_BYTES_PER_SECOND, .value = {.vt = VT_UI4, .ulVal = 44100}, .todo_missing = TRUE}, + {.key = &MF_MT_AUDIO_BLOCK_ALIGNMENT, .value = {.vt = VT_UI4, .ulVal = 1}, .todo_missing = TRUE}, + {.key = &MF_MT_AUDIO_NUM_CHANNELS, .value = {.vt = VT_UI4, .ulVal = 1}}, + {.key = &MF_MT_MAJOR_TYPE, .value = {.vt = VT_CLSID, .puuid = (GUID *)&MFMediaType_Audio}}, + {.key = &MF_MT_AUDIO_SAMPLES_PER_SECOND, .value = {.vt = VT_UI4, .ulVal = 44100}}, + {.key = &MF_MT_AUDIO_PREFER_WAVEFORMATEX, .value = {.vt = VT_UI4, .ulVal = 1}, .todo_missing = TRUE}, + {.key = &MF_MT_ALL_SAMPLES_INDEPENDENT, .value = {.vt = VT_UI4, .ulVal = 1}}, + {.key = &MF_MT_AUDIO_BITS_PER_SAMPLE, .value = {.vt = VT_UI4, .ulVal = 8}}, + {.key = &MF_MT_SUBTYPE, .value = {.vt = VT_CLSID, .puuid = (GUID *)&MFAudioFormat_PCM}}, + }, + .todo_spurious = 1, + }; + static const struct media_type_desc audio_48000_s8_desc = + { + .items = + { + {.key = &MF_MT_AUDIO_AVG_BYTES_PER_SECOND, .value = {.vt = VT_UI4, .ulVal = 48000}, .todo_missing = TRUE}, + {.key = &MF_MT_AUDIO_BLOCK_ALIGNMENT, .value = {.vt = VT_UI4, .ulVal = 1}, .todo_missing = TRUE}, + {.key = &MF_MT_AUDIO_NUM_CHANNELS, .value = {.vt = VT_UI4, .ulVal = 1}}, + {.key = &MF_MT_MAJOR_TYPE, .value = {.vt = VT_CLSID, .puuid = (GUID *)&MFMediaType_Audio}}, + {.key = &MF_MT_AUDIO_SAMPLES_PER_SECOND, .value = {.vt = VT_UI4, .ulVal = 48000}}, + {.key = &MF_MT_AUDIO_PREFER_WAVEFORMATEX, .value = {.vt = VT_UI4, .ulVal = 1}, .todo_missing = TRUE}, + {.key = &MF_MT_ALL_SAMPLES_INDEPENDENT, .value = {.vt = VT_UI4, .ulVal = 1}}, + {.key = &MF_MT_AUDIO_BITS_PER_SAMPLE, .value = {.vt = VT_UI4, .ulVal = 8}}, + {.key = &MF_MT_SUBTYPE, .value = {.vt = VT_CLSID, .puuid = (GUID *)&MFAudioFormat_PCM}}, + }, + .todo_spurious = 1, + }; + static const struct media_type_desc audio_48000_s16_desc = + { + .items = + { + {.key = &MF_MT_AUDIO_AVG_BYTES_PER_SECOND, .value = {.vt = VT_UI4, .ulVal = 96000}, .todo_missing = TRUE}, + {.key = &MF_MT_AUDIO_BLOCK_ALIGNMENT, .value = {.vt = VT_UI4, .ulVal = 2}, .todo_missing = TRUE}, + {.key = &MF_MT_AUDIO_NUM_CHANNELS, .value = {.vt = VT_UI4, .ulVal = 1}}, + {.key = &MF_MT_MAJOR_TYPE, .value = {.vt = VT_CLSID, .puuid = (GUID *)&MFMediaType_Audio}}, + {.key = &MF_MT_AUDIO_SAMPLES_PER_SECOND, .value = {.vt = VT_UI4, .ulVal = 48000}}, + {.key = &MF_MT_AUDIO_PREFER_WAVEFORMATEX, .value = {.vt = VT_UI4, .ulVal = 1}, .todo_missing = TRUE}, + {.key = &MF_MT_ALL_SAMPLES_INDEPENDENT, .value = {.vt = VT_UI4, .ulVal = 1}}, + {.key = &MF_MT_AUDIO_BITS_PER_SAMPLE, .value = {.vt = VT_UI4, .ulVal = 16}}, + {.key = &MF_MT_SUBTYPE, .value = {.vt = VT_CLSID, .puuid = (GUID *)&MFAudioFormat_PCM}}, + }, + .todo_spurious = 1, + }; + static const struct media_type_desc audio_44100_f32_desc= + { + .items = + { + {.key = &MF_MT_AUDIO_AVG_BYTES_PER_SECOND, .value = {.vt = VT_UI4, .ulVal = 176400}, .todo_missing = TRUE}, + {.key = &MF_MT_AUDIO_BLOCK_ALIGNMENT, .value = {.vt = VT_UI4, .ulVal = 4}, .todo_missing = TRUE}, + {.key = &MF_MT_AUDIO_NUM_CHANNELS, .value = {.vt = VT_UI4, .ulVal = 1}}, + {.key = &MF_MT_MAJOR_TYPE, .value = {.vt = VT_CLSID, .puuid = (GUID *)&MFMediaType_Audio}}, + {.key = &MF_MT_AUDIO_SAMPLES_PER_SECOND, .value = {.vt = VT_UI4, .ulVal = 44100}}, + {.key = &MF_MT_AUDIO_PREFER_WAVEFORMATEX, .value = {.vt = VT_UI4, .ulVal = 1}, .todo_missing = TRUE}, + {.key = &MF_MT_ALL_SAMPLES_INDEPENDENT, .value = {.vt = VT_UI4, .ulVal = 1}}, + {.key = &MF_MT_AUDIO_BITS_PER_SAMPLE, .value = {.vt = VT_UI4, .ulVal = 32}}, + {.key = &MF_MT_SUBTYPE, .value = {.vt = VT_CLSID, .puuid = (GUID *)&MFAudioFormat_Float}}, + }, + .todo_spurious = 1, + }; + static const struct media_type_desc audio_48000_f32_desc = + { + .items = + { + {.key = &MF_MT_AUDIO_AVG_BYTES_PER_SECOND, .value = {.vt = VT_UI4, .ulVal = 192000}, .todo_missing = TRUE}, + {.key = &MF_MT_AUDIO_BLOCK_ALIGNMENT, .value = {.vt = VT_UI4, .ulVal = 4}, .todo_missing = TRUE}, + {.key = &MF_MT_AUDIO_NUM_CHANNELS, .value = {.vt = VT_UI4, .ulVal = 1}}, + {.key = &MF_MT_MAJOR_TYPE, .value = {.vt = VT_CLSID, .puuid = (GUID *)&MFMediaType_Audio}}, + {.key = &MF_MT_AUDIO_SAMPLES_PER_SECOND, .value = {.vt = VT_UI4, .ulVal = 48000}}, + {.key = &MF_MT_AUDIO_PREFER_WAVEFORMATEX, .value = {.vt = VT_UI4, .ulVal = 1}, .todo_missing = TRUE}, + {.key = &MF_MT_ALL_SAMPLES_INDEPENDENT, .value = {.vt = VT_UI4, .ulVal = 1}}, + {.key = &MF_MT_AUDIO_BITS_PER_SAMPLE, .value = {.vt = VT_UI4, .ulVal = 32}}, + {.key = &MF_MT_SUBTYPE, .value = {.vt = VT_CLSID, .puuid = (GUID *)&MFAudioFormat_Float}}, + }, + .todo_spurious = 1, + }; + + struct test_audio_format + { + GUID subtype; + UINT32 bits; + UINT32 rate; + const struct media_type_desc *current; + }; + + struct test_media_type + { + const char *resource; + const struct media_type_desc *native; + struct test_audio_format *audio_formats; + UINT audio_format_count; + }; + + struct test_audio_format test_audio_formats[] = + { + {.subtype = MFAudioFormat_PCM, .bits = 8, .rate = 44100, .current = &audio_44100_s8_desc}, + {.subtype = MFAudioFormat_Float, .bits = 32, .rate = 44100, .current = &audio_44100_f32_desc}, + {.subtype = MFAudioFormat_PCM, .bits = 8, .rate = 48000, .current = &audio_48000_s8_desc}, + {.subtype = MFAudioFormat_Float, .bits = 32, .rate = 48000, .current = &audio_48000_f32_desc}, + }; + + struct test_media_type tests[] = + { + { + .resource = "test.wav", + .native = &audio_44100_s8_desc, + .audio_formats = test_audio_formats, + .audio_format_count = ARRAY_SIZE(test_audio_formats), + }, + { + .resource = "test-48000.wav", + .native = &audio_48000_s16_desc, + .audio_formats = test_audio_formats, + .audio_format_count = ARRAY_SIZE(test_audio_formats), + }, + }; + + struct test_audio_format audio_format; + IMFMediaType *media_type; + IMFSourceReader *reader; + IMFByteStream *stream; + HRESULT hr; + int i, j; + + if (!pMFCreateMFByteStreamOnStream) + { + win_skip("MFCreateMFByteStreamOnStream() not found\n"); + return; + } + + for (i = 0; i < ARRAY_SIZE(tests); ++i) + { + winetest_push_context(tests[i].resource); + + for (j = 0; j < tests[i].audio_format_count; ++j) + { + audio_format = tests[i].audio_formats[j]; + stream = get_resource_stream(tests[i].resource); + if (FAILED(hr = MFCreateSourceReaderFromByteStream(stream, NULL, &reader))) + { + todo_wine + win_skip("MFCreateSourceReaderFromByteStream() failed\n"); + IMFByteStream_Release(stream); + continue; + } + ok(hr == S_OK, "Failed to create source reader, hr %#x.\n", hr); + + hr = IMFSourceReader_GetNativeMediaType(reader, MF_SOURCE_READER_FIRST_AUDIO_STREAM, 0, &media_type); + ok(hr == S_OK, "Failed to get native mediatype, hr %#x.\n", hr); + winetest_push_context("native audio"); + check_media_type_items(media_type, tests[i].native); + IMFMediaType_Release(media_type); + winetest_pop_context(); + + hr = IMFSourceReader_GetNativeMediaType(reader, MF_SOURCE_READER_FIRST_AUDIO_STREAM, 1, &media_type); + todo_wine + ok(hr == MF_E_NO_MORE_TYPES, "Expected only one native mediatype, hr %#x.\n", hr); + if (hr == S_OK) IMFMediaType_Release(media_type); + + hr = IMFSourceReader_SetStreamSelection(reader, MF_SOURCE_READER_FIRST_AUDIO_STREAM, TRUE); + ok(hr == S_OK, "Unexpected hr %#x.\n", hr); + + hr = MFCreateMediaType(&media_type); + ok(hr == S_OK, "Failed to create media type, hr %#x.\n", hr); + hr = IMFMediaType_SetGUID(media_type, &MF_MT_MAJOR_TYPE, &MFMediaType_Audio); + ok(hr == S_OK, "Failed to set attribute, hr %#x.\n", hr); + hr = IMFMediaType_SetGUID(media_type, &MF_MT_SUBTYPE, &audio_format.subtype); + ok(hr == S_OK, "Failed to set attribute, hr %#x.\n", hr); + hr = IMFMediaType_SetUINT32(media_type, &MF_MT_AUDIO_BITS_PER_SAMPLE, audio_format.bits); + ok(hr == S_OK, "Failed to set attribute, hr %#x.\n", hr); + hr = IMFMediaType_SetUINT32(media_type, &MF_MT_AUDIO_SAMPLES_PER_SECOND, audio_format.rate); + ok(hr == S_OK, "Failed to set attribute, hr %#x.\n", hr); + + hr = IMFMediaType_SetUINT32(media_type, &MF_MT_AUDIO_BLOCK_ALIGNMENT, audio_format.bits / 8); + ok(hr == S_OK, "Failed to set attribute, hr %#x.\n", hr); + hr = IMFMediaType_SetUINT32(media_type, &MF_MT_AUDIO_AVG_BYTES_PER_SECOND, audio_format.rate * audio_format.bits / 8); + ok(hr == S_OK, "Failed to set attribute, hr %#x.\n", hr); + + hr = IMFSourceReader_SetCurrentMediaType(reader, MF_SOURCE_READER_FIRST_AUDIO_STREAM, NULL, media_type); + todo_wine + ok(hr == S_OK || broken(hr == MF_E_TOPO_CODEC_NOT_FOUND) /* <= win7 */, "Failed setting current media type %u, hr %#x.\n", j, hr); + IMFMediaType_Release(media_type); + if (hr != S_OK) continue; + + hr = IMFSourceReader_GetCurrentMediaType(reader, MF_SOURCE_READER_FIRST_AUDIO_STREAM, &media_type); + ok(hr == S_OK, "Failed to get current mediatype, hr %#x.\n", hr); + winetest_push_context("current audio %u", j); + check_media_type_items(media_type, audio_format.current); + winetest_pop_context(); + IMFMediaType_Release(media_type); + + IMFSourceReader_Release(reader); + IMFByteStream_Release(stream); + } + + winetest_pop_context(); + } +} + START_TEST(mfplat) { HRESULT hr; @@ -1242,6 +1534,7 @@ START_TEST(mfplat) test_factory(); test_source_reader(); test_source_reader_from_media_source(); + test_media_types(); test_reader_d3d9(); hr = MFShutdown(); diff --git a/dlls/mfreadwrite/tests/resource.rc b/dlls/mfreadwrite/tests/resource.rc index f54212a8c8f..5b3269fef1d 100644 --- a/dlls/mfreadwrite/tests/resource.rc +++ b/dlls/mfreadwrite/tests/resource.rc @@ -20,3 +20,7 @@ /* @makedep: test.wav */ test.wav RCDATA test.wav + +/* @makedep: test-48000.wav */ +test-48000.wav RCDATA test-48000.wav + diff --git a/dlls/mfreadwrite/tests/test-48000.wav b/dlls/mfreadwrite/tests/test-48000.wav new file mode 100644 index 0000000000000000000000000000000000000000..dedd660bb9a97a9cacedabaddc1b1bafd2f4a176 GIT binary patch literal 2104 zcmV-82*>wQNk&F62mkBYJVimYMdwM}O^;FiR3ljZT8mxDU$$XSW0houWgli@ zW=>|~Wg=w@WS?T-V9s7_T)SDmR(DhBPZ&%FNVh{SKX5vLHDfRwE3qXeAb=Xf6!i`o z2{!{${crb^@x$u{=3L;;+F;cd(Dljz#y-KYyj-|Mv~952tcc+-Tw% z=-%zK^ON~^|62t-3lkCC7Lgn-BCaP4EkrU=H!nQfKu<-8NrO#1QLt3pSH45PWOHQ{W?yDgX7Ob=Whi9CVhmvcU#49ASq4|eQ$J92OlL?QM4CU~I`uW&Fqtbc zCaE9=8%h;@526Xc1Kj=i_Z#v`?1|>z;7;4!)sWC@%W}r6!5F>1xS_Peuqmz8smrDe zq?@67pRAoQoC=#cn!lNwna`P7nmL{wZWlUv6WawfyVKiUhTs~S(R~1y0P|r-rNQ6WM zKv6qsHdHYcEU+dkA&DE%6$B6~3P}WI{(<UN{tstror%9yIp{bwJoll%0n@O6+nVXr$nMs-~~Gy%@se#^K8f(OTBe+hXAk=h5t=@`3ne{z(KY3Iq_)6^R=wA+RPDEL1URHc>kT zK!ildNY6}^P!&{8S3X+cTr^)dVd!E+WK3oKWmslhW(j6sWng3rV`5=uUm9J0T9#L1 zROnDCO(;p~L~uaBJKZ+SF_0`TC#)e2999;L5VQ)?1n&L{`785R?Ud)`;ZNMy)`Zbl z%vQ&R!s)$)xm>k!vCOS&s#B+iqz9tcpZc9|oH?6Wn$MY=nZKDinhKjRoUEOCpPQi! zq|2t&sVS|)u%WcRxEQ^w!E(lH%aG9B)lS>r;ECo+>>Kj<_uT!!1EL9i4@wmU8>t{M zCYdYTF!eRyI+{NoL}y5JOg~V@QwCT3S*Bb8UkqWyVkl%cW$|TGW?yC$W^-kGWG-Wj zVVGZ2UA|h}SFlt(QG-p0Nl!)FKrcK|H$*ZFEv_dnB9R>2784OX3tI(u|C9N%^WNvj&%AL>T)KA*l-+<*k z>kIMb_R0LN0+9%94m}k68KfUFC7>$mFAFvQIl?|rL!?K%OOsD0Q*>5%Suk9hUbA3& zV(w!NWz}U!W@Kh4W|n2HWN>5NVfkOeT|8T8SV>jlQ8i9RN*G42K@B}OI5IN=E~+Rn zBbXiM7a|f(3~dI90HylG^zH5>>2KrG-BQ@}(!9;D$kD?kzp=V_wtce1u28Eas6wT! zqG+IWp3o%Ejnpjx8@ruwKltii90vzfQzyJo;3#S6+L z&u7%n*;n8D$n{KIlS1M_)@lPuEf_ zRyA4lTV-B`U{qqzWAVan)jKcnW&iqnzWj{n;4zRp3I;iqr#=KsOzh2uQ9VY zw|u+%zpuoX$*j)n(@@#f-go3M>iqB3^|$+*0e=Tw4KEY&7@i(6B&I3$E*~@;Ip{rr zLf=LLOXW_6Qs7nbShrg*URPi)VzFc2WVdBHW@TnNX18VEWU*r|Vpm`UZST-cZ@=)2z;y z$*;uwzkItmw=uJ9uj{L_sKTWnqs*Ymo*13Ho3xq(ny8tinfIBXnxLEYoSvSVpyr~2 zrD~|1s~E4>ve>p3yO6&?#3RWx&T!Mw*i_#0 iU}awPTQylLR@YKJPhU$yN9aOKNmEn=0000