[PATCH 1/4] mf/topoloader: Add partial topology resolution tests.

Derek Lesho dlesho at codeweavers.com
Tue Nov 24 15:29:34 CST 2020


Signed-off-by: Derek Lesho <dlesho at codeweavers.com>
---
I'm not sure if this is too many of too few tests, and if the kinds of tests I have here are wanted.  I was going to add tests for MF_ENUMERATE_SOURCE_TYPES and MF_CONNECT_RESOLVE_INDEPENDENT_OUTPUTTYPES, but they got really large, and didn't really prove much beyond what is already documented in the MSDN.  Another test I chose to leave out is for what happens on topologies with sources without a currently selected media type, since Microsoft is pretty clear that will never happen.

Also note that these tests aren't un-todo'd in this patchset.  The first test requires 1) the more correct sample grabber IsMediaTypeSupportedImplementation and 2) the audio resampler MFT.  The second tests requires the media source to output compressed MPEG streams and for a MPEG decoder to be present.
---
 dlls/mf/tests/mf.c        | 200 +++++++++++++++++++++++++++++++++++++-
 dlls/mf/tests/resource.rc |   3 +
 dlls/mf/tests/test.mp3    | Bin 0 -> 2551 bytes
 3 files changed, 201 insertions(+), 2 deletions(-)
 create mode 100644 dlls/mf/tests/test.mp3

diff --git a/dlls/mf/tests/mf.c b/dlls/mf/tests/mf.c
index 43dc9a49ee7..4c70f7ee857 100644
--- a/dlls/mf/tests/mf.c
+++ b/dlls/mf/tests/mf.c
@@ -1418,22 +1418,27 @@ static const IMFSampleGrabberSinkCallbackVtbl test_grabber_callback_vtbl =
 static void test_topology_loader(void)
 {
     IMFSampleGrabberSinkCallback test_grabber_callback = { &test_grabber_callback_vtbl };
+    IMFTopologyNode *src_node, *sink_node, *src_node2, *mft_node;
     IMFTopology *topology, *topology2, *full_topology;
-    IMFTopologyNode *src_node, *sink_node;
+    unsigned int count, value, index;
     IMFPresentationDescriptor *pd;
     IMFSourceResolver *resolver;
     IMFActivate *sink_activate;
     IMFStreamSink *stream_sink;
-    unsigned int count, value;
+    MF_TOPOLOGY_TYPE node_type;
     IMFMediaType *media_type;
     IMFStreamDescriptor *sd;
     MF_OBJECT_TYPE obj_type;
+    IMFTransform *transform;
     IMFMediaSource *source;
     IMFTopoLoader *loader;
     IMFByteStream *stream;
+    IUnknown *node_object;
     IMFAttributes *attr;
     IMFMediaSink *sink;
+    WORD node_count;
     WCHAR *filename;
+    TOPOID node_id;
     BOOL selected;
     HRESULT hr;
     GUID guid;
@@ -1581,9 +1586,200 @@ todo_wine {
     IMFTopology_Release(topology2);
     IMFTopology_Release(full_topology);
 
+    /* Partial topology (requires converter) */
+
+    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, &MFAudioFormat_PCM);
+    ok(hr == S_OK, "Failed to set attribute, hr %#x.\n", hr);
+    /* resample from 44100hz to 48000hz */
+    hr = IMFMediaType_SetUINT32(media_type, &MF_MT_AUDIO_SAMPLES_PER_SECOND, 48000);
+    ok(hr == S_OK, "Failed to set attribute, hr %#x.\n", hr);
+
+    hr = MFCreateSampleGrabberSinkActivate(media_type, &test_grabber_callback, &sink_activate);
+    ok(hr == S_OK, "Failed to create grabber sink, hr %#x.\n", hr);
+
+    IMFMediaType_Release(media_type);
+
+    hr = IMFActivate_ActivateObject(sink_activate, &IID_IMFMediaSink, (void **)&sink);
+    ok(hr == S_OK, "Failed to activate, hr %#x.\n", hr);
+
+    hr = IMFMediaSink_GetStreamSinkByIndex(sink, 0, &stream_sink);
+    ok(hr == S_OK, "Unexpected hr %#x.\n", hr);
+
+    hr = IMFTopologyNode_SetObject(sink_node, (IUnknown *)stream_sink);
+    ok(hr == S_OK, "Failed to set object, hr %#x.\n", hr);
+
+    hr = IMFTopologyNode_SetUINT32(sink_node, &MF_TOPONODE_CONNECT_METHOD, MF_CONNECT_ALLOW_CONVERTER);
+    ok(hr == S_OK, "Failed to set connect method, hr %#x.\n", hr);
+
+    IMFStreamSink_Release(stream_sink);
+
+    hr = IMFTopoLoader_Load(loader, topology, &full_topology, NULL);
+    ok(hr == S_OK, "Failed to resolve topology, hr %#x.\n", hr);
+
+    hr = IMFTopology_GetNodeCount(full_topology, &node_count);
+    ok(hr == S_OK, "Failed to get node count, hr %#x.\n", hr);
+todo_wine
+    ok(node_count == 3, "Unexpected node count %u\n", node_count);
+    if (node_count != 3)
+    {
+        IMFMediaSource_Release(source);
+        IMFSourceResolver_Release(resolver);
+        IMFByteStream_Release(stream);
+
+        IMFTopoLoader_Release(loader);
+
+        hr = MFShutdown();
+        ok(hr == S_OK, "Shutdown failure, hr %#x.\n", hr);
+        return;
+    }
+
+    hr = IMFTopologyNode_GetTopoNodeID(src_node, &node_id);
+    ok(hr == S_OK, "Failed to get source node id, hr %#x.\n", hr);
+
+    hr = IMFTopology_GetNodeByID(full_topology, node_id, &src_node2);
+    ok(hr == S_OK, "Failed to get source in resolved topology, hr %#x.\n", hr);
+
+    hr = IMFTopologyNode_GetOutput(src_node2, 0, &mft_node, &index);
+    ok(hr == S_OK, "Failed to get transform node in resolved topology, hr %#x.\n", hr);
+    ok(index == 0, "Unexpected stream index %u.\n", index);
+
+    hr = IMFTopologyNode_GetNodeType(mft_node, &node_type);
+    ok(hr == S_OK, "Failed to get transform node type in resolved topology, hr %#x.\n", hr);
+    ok(node_type == MF_TOPOLOGY_TRANSFORM_NODE, "Unexpected node type %u, expected MF_TOPOLOGY_TRANSFORM_NODE.\n", node_type);
+
+    hr = IMFTopologyNode_GetObject(mft_node, &node_object);
+    ok(hr == S_OK, "Failed to get object of transform node, hr %#x.\n", hr);
+
+    hr = IUnknown_QueryInterface(node_object, &IID_IMFTransform, (void**) &transform);
+    ok(hr == S_OK, "Failed to get IMFTransform from transform node's object, hr %#x.\n", hr);
+    IUnknown_Release(node_object);
+
+    hr = IMFTransform_GetInputCurrentType(transform, 0, &media_type);
+    ok(hr == S_OK, "Failed to get transform input type, hr %#x.\n", hr);
+
+    hr = IMFMediaType_GetUINT32(media_type, &MF_MT_AUDIO_SAMPLES_PER_SECOND, &value);
+    ok(hr == S_OK, "Failed to get MF_MT_AUDIO_SAMPLES_PER_SECOND on transform input type, hr %#x.\n", hr);
+    ok(value == 44100, "Unexpected sample rate of transform input type %u, expected 44100\n", value);
+
+    IMFMediaType_Release(media_type);
+
+    hr = IMFTransform_GetOutputCurrentType(transform, 0, &media_type);
+    ok(hr == S_OK, "Failed to get transform output type, hr %#x.\n", hr);
+
+    hr = IMFMediaType_GetUINT32(media_type, &MF_MT_AUDIO_SAMPLES_PER_SECOND, &value);
+    ok(hr == S_OK, "Failed to get MF_MT_AUDIO_SAMPLES_PER_SECOND on transform output type, hr %#x.\n", hr);
+    ok(value == 48000, "Unexpected sample rate of transform input type %u, expected 48000\n", value);
+
+    IMFMediaType_Release(media_type);
+    IMFTransform_Release(transform);
+    IMFTopology_Release(full_topology);
+
     IMFMediaSource_Release(source);
     IMFSourceResolver_Release(resolver);
     IMFByteStream_Release(stream);
+
+    /* Test MF_TOPONODE_CONNECT_METHOD:
+        - 0x1 (MF_CONNECT_ALLOW_CONVERTER) allows converters
+        - 0x3 (MF_CONNECT_ALLOW_DECODER) allows converters and decoders
+        - 0x2 allows neither */
+
+    hr = MFCreateSourceResolver(&resolver);
+    ok(hr == S_OK, "Failed to create source resolver, hr %#x.\n", hr);
+
+    filename = load_resource(L"test.mp3");
+
+    hr = MFCreateFile(MF_ACCESSMODE_READ, MF_OPENMODE_FAIL_IF_NOT_EXIST, MF_FILEFLAGS_NONE, filename, &stream);
+    ok(hr == S_OK, "Failed to create file stream, hr %#x.\n", hr);
+
+    IMFByteStream_QueryInterface(stream, &IID_IMFAttributes, (void **)&attr);
+    IMFAttributes_SetString(attr, &MF_BYTESTREAM_CONTENT_TYPE, L"audio/mpeg");
+    IMFAttributes_Release(attr);
+
+    hr = IMFSourceResolver_CreateObjectFromByteStream(resolver, stream, NULL, MF_RESOLUTION_MEDIASOURCE, NULL,
+            &obj_type, (IUnknown **)&source);
+    ok(hr == S_OK || broken(FAILED(hr)) /* Vista */, "Failed to create source, hr %#x.\n", hr);
+    if (FAILED(hr))
+        return;
+
+    hr = IMFMediaSource_CreatePresentationDescriptor(source, &pd);
+    ok(hr == S_OK, "Failed to create descriptor, hr %#x.\n", hr);
+    if (FAILED(hr))
+        return;
+
+    hr = IMFPresentationDescriptor_GetStreamDescriptorByIndex(pd, 0, &selected, &sd);
+    ok(hr == S_OK, "Failed to get stream descriptor, hr %#x.\n", hr);
+
+    hr = IMFTopologyNode_SetUnknown(src_node, &MF_TOPONODE_SOURCE, (IUnknown *)source);
+    ok(hr == S_OK, "Failed to set node source, hr %#x.\n", hr);
+
+    hr = IMFTopologyNode_SetUnknown(src_node, &MF_TOPONODE_PRESENTATION_DESCRIPTOR, (IUnknown *)pd);
+    ok(hr == S_OK, "Failed to set node pd, hr %#x.\n", hr);
+
+    hr = IMFTopologyNode_SetUnknown(src_node, &MF_TOPONODE_STREAM_DESCRIPTOR, (IUnknown *)sd);
+    ok(hr == S_OK, "Failed to set node sd, 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, &MFAudioFormat_PCM);
+    ok(hr == S_OK, "Failed to set attribute, hr %#x.\n", hr);
+
+    hr = MFCreateSampleGrabberSinkActivate(media_type, &test_grabber_callback, &sink_activate);
+    ok(hr == S_OK, "Failed to create grabber sink, hr %#x.\n", hr);
+
+    IMFMediaType_Release(media_type);
+
+    hr = IMFActivate_ActivateObject(sink_activate, &IID_IMFMediaSink, (void **)&sink);
+    ok(hr == S_OK, "Failed to activate, hr %#x.\n", hr);
+
+    hr = IMFMediaSink_GetStreamSinkByIndex(sink, 0, &stream_sink);
+    ok(hr == S_OK, "Unexpected hr %#x.\n", hr);
+
+    hr = IMFTopologyNode_SetObject(sink_node, (IUnknown *)stream_sink);
+    ok(hr == S_OK, "Failed to set object, hr %#x.\n", hr);
+
+    IMFStreamSink_Release(stream_sink);
+
+    hr = IMFTopologyNode_SetUINT32(sink_node, &MF_TOPONODE_CONNECT_METHOD, MF_CONNECT_DIRECT);
+    ok(hr == S_OK, "Failed to set connect method, hr %#x.\n", hr);
+
+    hr = IMFTopoLoader_Load(loader, topology, &full_topology, NULL);
+    ok(hr == MF_E_INVALIDMEDIATYPE, "Unexpected hr %#x.\n", hr);
+
+    hr = IMFTopologyNode_SetUINT32(sink_node, &MF_TOPONODE_CONNECT_METHOD, MF_CONNECT_ALLOW_CONVERTER);
+    ok(hr == S_OK, "Failed to set connect method, hr %#x.\n", hr);
+
+    hr = IMFTopoLoader_Load(loader, topology, &full_topology, NULL);
+    ok(hr == MF_E_TRANSFORM_NOT_POSSIBLE_FOR_CURRENT_MEDIATYPE_COMBINATION, "Unexpected hr %#x.\n", hr);
+
+    hr = IMFTopologyNode_SetUINT32(sink_node, &MF_TOPONODE_CONNECT_METHOD, 2);
+    ok(hr == S_OK, "Failed to set connect method, hr %#x.\n", hr);
+
+    hr = IMFTopoLoader_Load(loader, topology, &full_topology, NULL);
+    ok(hr == MF_E_INVALIDMEDIATYPE, "Failed to resolve topology, hr %#x.\n", hr);
+
+    hr = IMFTopologyNode_SetUINT32(sink_node, &MF_TOPONODE_CONNECT_METHOD, MF_CONNECT_ALLOW_DECODER);
+    ok(hr == S_OK, "Failed to set connect method, hr %#x.\n", hr);
+
+    hr = IMFTopoLoader_Load(loader, topology, &full_topology, NULL);
+    ok(hr == S_OK, "Failed to resolve topology, hr %#x.\n", hr);
+
+    hr = IMFTopology_GetNodeCount(full_topology, &node_count);
+    ok(hr == S_OK, "Failed to get node count, hr %#x.\n", hr);
+    ok(node_count == 3, "Unexpected node count %u\n", node_count);
+
+    IMFTopology_Release(full_topology);
+    IMFMediaSource_Release(source);
+    IMFSourceResolver_Release(resolver);
+    IMFByteStream_Release(stream);
+
     IMFTopoLoader_Release(loader);
 
     hr = MFShutdown();
diff --git a/dlls/mf/tests/resource.rc b/dlls/mf/tests/resource.rc
index f54212a8c8f..5e847cd0b3b 100644
--- a/dlls/mf/tests/resource.rc
+++ b/dlls/mf/tests/resource.rc
@@ -20,3 +20,6 @@
 
 /* @makedep: test.wav */
 test.wav RCDATA test.wav
+
+/* @makedep: test.mp3 */
+test.mp3 RCDATA test.mp3
diff --git a/dlls/mf/tests/test.mp3 b/dlls/mf/tests/test.mp3
new file mode 100644
index 0000000000000000000000000000000000000000..8b66f19da24624d58beda20187e1f6f85bdc4f44
GIT binary patch
literal 2551
zcmeH}iBr=_7RP@%xN!*g6(n*=fo4evhp=cE2!{lTLQq&?fRG>o0|Lr$SQ82N5s(nM
zWC(IB1mzSL&;bEqHrx)EAi4yQ(~%KHM3n50v8HOOhQDBIztz?6b-${v_xjUS{haMh
z;lRFhJ>1<1pp^pv7}5V4&CC*wGecucOn#4kokY7ie_9>vIx}ctU<5n{5CZ_Iet`T}
z{cwQz2Wa8|i4M?yCScAKFy|AP{ly>BgNc82rTT*$W-b5N{-3oVpg at oxQl6MZMS)cw
zLh%5I=H)`iok#mM<5=KiVux|Wx?l$|J@~kj0Fr@^e-k?s(G-;K)50E}ZH*@xN<#sr
zA1OgI(jluYWjvxG+yn&|Pk^L%J;o#8`Y@!n#D63{<{;n at py$cl$5WuSo13GEx?rW?
zn3Q7)H?aU*@2W+x>FGs=g<@zf0V<2cJCTggIH-rTMh`~8?pu~A{-zi{vMo75&C)I=
zbrk1;A59gMJ>2jTtljlpa?#DIn+WlhYhG7R7wCWQ)9Gf7PWjPr{b~w*)WP?4mF~#m
z2~T&-ZAOvn=kf~XM##0wx6eNq=qjw6Q at +%S`47MBD>@%nR8+vL9lSh~ye=}_t^3?N
z%b$HU6me=qlr}v)tkEYrv040KWBY<|WQV=|kEzWLQL$+1l<dZfPu#7+&OOn(wX)fF
z$cNb?;imzO>xlEBa?#?XBvY9$CFi}?ivYa3ZrCO(8fxA(kEPUP4dLbSe$E_A6C*9X
zoVPl#D7Li=4=WX9DP!Br$@C5n>@e3g5bfp$YQx^|gbp3O!UJI(Ld^jXrQ^-V*urW&
z2#5&)@H}h<T|2ekzt6nf_Fa+Syti(benFa!+jYA;h6QPT4}NVEGYYCz2^o&04Ze3s
zETO*XNU}R?R(t$((~#Tk*sSd1@^hi-0x{~ZRCL|+Swi#lS$eMeef#l$IXA9cE*q$k
z1|NZQs#k@&>#HR!6o5Ayh~Aw~#*kWt%=CLfOBW4R&H&D8e)#uKO0TrNvK?vti1iLI
zrdVK=O9070e#O$jst3w7Me~f9oS`)*S<6Km(mz)J+*p;X(-IJCaet^*tv=sOOirb~
znC{RRD7Rs(%lEXRx)o~Q^(rTMWGQv~J`?)>EpldP6ZLM~E3^BH?Z>7?-pybeuEN4}
z=i%NN6f6-iI6{?`{V7!f4sno7Tk?*t>djtK%m`Y}I8yxYqhsXGTPB)QH{^K+(@zCw
z|9-46MVQYKL(<}ZG*&NyNF(Wm51d*8zIm1tGwR-=zT_XcuJSF7KM?ae-O7j%o6wNN
z at hvOQ-%6e=yER=^z7vmd(<yCK%Ho>u6S84#DTfZ&wbD`hga81dOlUU#X0;lm^E)9o
z7sJvLNwZl$ZKQXy+&_ozCq>`3$?V=cmg4B71RF5;$@U9!immV)6Q>VfT&T-Qoz#QF
zlET;F8;HE_U-BSu4~56==W-EB?IeVKgWR at EUHG-d(OGAX?1&0<N>y$i>1mY)*O)ok
zagr|2+DhUOfv6VhQotn!ZdN8}^JSc>BLRbZz`KGtOpK3wKpK}qH+I!%(IzB*YdT}f
z at 3CCvWK&kx5+iEFcrBMQXno4HibM4A;OzORcUc(;jz=X^NSet6yLlITqO?~WTgMXt
z$S at TV3V9zc5Go9z1>(Bu<hPnoG(y5)FVPF>9c7gs#{E>*bLX}6Ls^wZE(bdQ#xy(h
zqMLd~_ at 4Pa6P$$Ng}v)<^I~~Rs|k5Klr~a9Q_|Dqi^4Ci85LB_4Ti}=`C#$k`qH@;
zy4It;=F_Z|JTw8<FzhhfOqnKbC5&IHlr>%`T+ at zu6LQm;xUgW-$?2`kuxAMdt0S_h
z@!`2$0CXIS+P0}8?Gy5ZZ7GHh=(f_q at 98U{tIb&MBnSw=B`^Uv3VN)J1vKV0H*&kW
zqBAuiGPg=XJD5mluds0i;2Q+^G8Fnae(&&4%DA!*xS5FvZOP#N^x&#vLu#|A99wpz
z7Nol<m`%fvTDp(@qWRJjDW0l!q^2f&xmwKzbC?~?;TDZEBi*9}j1(Jgx;UpQ73GE-
z90~0Ed19X4PH7XzbH@(9*y?C}%8yOy)(FlDgexK<%xITMlk7-hu9+eLxLcCjBi(OR
zKWAW{5fl{dM`bb_rlo4a!*EqZkEqAVISP~@GPB3nQjiFPXkVQvu at fH@AS5kgwlD$H
zhI;D4b5~T=E1dYVIb7thD>_h`t)AHVRCVi1whgA${4=5bk<rD^_GN296E7xLRs-`Z
z<*hfyOI}w_ZQd(6jk4Bm_i^^qI6+e&M!d1=FP6Dqz!>pgYYe*@Z9!Y8J$Da%f||dM
z{(<_vFitBd--5I2M(gl-y}Y;i@>KR7*>pKZv^)7Qc6fD7bU9?#b^B=T&+IdkykJ7U
zXrB-RkbwG<_QLQWl0&G+U at I_p3htB0M1X`?AfZK7(K1uHh0N4}NyTB6$YJhIO#|e4
zpW&@msvz2bqMHZD4(ZUzdgtP|#XO~-IJO!!j3v6UNMyfy-PAVsJEU<9lG)C8R{GI<
c(xM&8<FQwKqOB{zbiZdgpqKdn)}L?Szh6E_`Tzg`

literal 0
HcmV?d00001

-- 
2.29.2




More information about the wine-devel mailing list