Signed-off-by: Derek Lesho <dlesho(a)codeweavers.com>
---
v2: Restructure topology loader tests to reduce boilerplate.
---
dlls/mf/tests/Makefile.in | 2 -
dlls/mf/tests/mf.c | 603 +++++++++++++++++++++++++++++++-------
dlls/mf/tests/resource.rc | 22 --
dlls/mf/tests/test.mp3 | Bin 0 -> 2551 bytes
4 files changed, 501 insertions(+), 126 deletions(-)
delete mode 100644 dlls/mf/tests/resource.rc
create mode 100644 dlls/mf/tests/test.mp3
diff --git a/dlls/mf/tests/Makefile.in b/dlls/mf/tests/Makefile.in
index 5eb9ee4d4e3..614eb4fbc9e 100644
--- a/dlls/mf/tests/Makefile.in
+++ b/dlls/mf/tests/Makefile.in
@@ -3,5 +3,3 @@ IMPORTS = mf mfplat mfuuid ole32 user32
C_SRCS = \
mf.c
-
-RC_SRCS = resource.rc
diff --git a/dlls/mf/tests/mf.c b/dlls/mf/tests/mf.c
index 41ca385cc2b..a5d971bf121 100644
--- a/dlls/mf/tests/mf.c
+++ b/dlls/mf/tests/mf.c
@@ -44,6 +44,7 @@ DEFINE_GUID(MFVideoFormat_ABGR32, 0x00000020, 0x0000, 0x0010, 0x80, 0x00, 0x00,
#include "mmdeviceapi.h"
#include "audioclient.h"
#include "evr.h"
+#include "propvarutil.h"
#include "wine/test.h"
@@ -97,34 +98,6 @@ static HWND create_window(void)
0, 0, r.right - r.left, r.bottom - r.top, NULL, NULL, NULL, NULL);
}
-static WCHAR *load_resource(const WCHAR *name)
-{
- static WCHAR pathW[MAX_PATH];
- DWORD written;
- HANDLE file;
- HRSRC res;
- void *ptr;
-
- GetTempPathW(ARRAY_SIZE(pathW), pathW);
- lstrcatW(pathW, name);
-
- file = CreateFileW(pathW, GENERIC_READ|GENERIC_WRITE, 0,
- NULL, CREATE_ALWAYS, 0, 0);
- ok(file != INVALID_HANDLE_VALUE, "file creation failed, at %s, error %d\n",
- wine_dbgstr_w(pathW), GetLastError());
-
- res = FindResourceW(NULL, name, (LPCWSTR)RT_RCDATA);
- ok(res != 0, "couldn't find resource\n");
- ptr = LockResource(LoadResource(GetModuleHandleA(NULL), res));
- WriteFile(file, ptr, SizeofResource(GetModuleHandleA(NULL), res),
- &written, NULL);
- ok(written == SizeofResource(GetModuleHandleA(NULL), res),
- "couldn't write resource\n" );
- CloseHandle(file);
-
- return pathW;
-}
-
static HRESULT WINAPI test_unk_QueryInterface(IUnknown *iface, REFIID riid, void **obj)
{
if (IsEqualIID(riid, &IID_IUnknown))
@@ -1447,26 +1420,316 @@ static const IMFSampleGrabberSinkCallbackVtbl test_grabber_callback_vtbl =
test_grabber_callback_OnShutdown,
};
+struct test_source
+{
+ IMFMediaSource IMFMediaSource_iface;
+ LONG refcount;
+};
+
+static struct test_source *impl_from_IMFMediaSource(IMFMediaSource *iface)
+{
+ return CONTAINING_RECORD(iface, struct test_source, IMFMediaSource_iface);
+}
+
+static HRESULT WINAPI test_source_QueryInterface(IMFMediaSource *iface, REFIID riid, void **out)
+{
+ if (IsEqualIID(riid, &IID_IMFMediaSource)
+ || IsEqualIID(riid, &IID_IMFMediaEventGenerator)
+ || IsEqualIID(riid, &IID_IUnknown))
+ {
+ *out = iface;
+ }
+ else
+ {
+ *out = NULL;
+ return E_NOINTERFACE;
+ }
+
+ IMFMediaSource_AddRef(iface);
+ return S_OK;
+}
+
+static ULONG WINAPI test_source_AddRef(IMFMediaSource *iface)
+{
+ struct test_source *source = impl_from_IMFMediaSource(iface);
+ return InterlockedIncrement(&source->refcount);
+}
+
+static ULONG WINAPI test_source_Release(IMFMediaSource *iface)
+{
+ struct test_source *source = impl_from_IMFMediaSource(iface);
+ ULONG refcount = InterlockedDecrement(&source->refcount);
+
+ if (!refcount)
+ HeapFree(GetProcessHeap(), 0, source);
+
+ return refcount;
+}
+
+static HRESULT WINAPI test_source_GetEvent(IMFMediaSource *iface, DWORD flags, IMFMediaEvent **event)
+{
+ ok(0, "Unexpected call.\n");
+ return E_NOTIMPL;
+}
+
+static HRESULT WINAPI test_source_BeginGetEvent(IMFMediaSource *iface, IMFAsyncCallback *callback, IUnknown *state)
+{
+ ok(0, "Unexpected call.\n");
+ return E_NOTIMPL;
+}
+
+static HRESULT WINAPI test_source_EndGetEvent(IMFMediaSource *iface, IMFAsyncResult *result, IMFMediaEvent **event)
+{
+ ok(0, "Unexpected call.\n");
+ return E_NOTIMPL;
+}
+
+static HRESULT WINAPI test_source_QueueEvent(IMFMediaSource *iface, MediaEventType event_type, REFGUID ext_type,
+ HRESULT hr, const PROPVARIANT *value)
+{
+ ok(0, "Unexpected call.\n");
+ return E_NOTIMPL;
+}
+
+static HRESULT WINAPI test_source_GetCharacteristics(IMFMediaSource *iface, DWORD *flags)
+{
+ ok(0, "Unexpected call.\n");
+ return E_NOTIMPL;
+}
+
+static HRESULT WINAPI test_source_CreatePresentationDescriptor(IMFMediaSource *iface, IMFPresentationDescriptor **pd)
+{
+ ok(0, "Unexpected call.\n");
+ return E_NOTIMPL;
+}
+
+static HRESULT WINAPI test_source_Start(IMFMediaSource *iface, IMFPresentationDescriptor *pd, const GUID *time_format,
+ const PROPVARIANT *start_position)
+{
+ ok(0, "Unexpected call.\n");
+ return E_NOTIMPL;
+}
+
+static HRESULT WINAPI test_source_Stop(IMFMediaSource *iface)
+{
+ ok(0, "Unexpected call.\n");
+ return E_NOTIMPL;
+}
+
+static HRESULT WINAPI test_source_Pause(IMFMediaSource *iface)
+{
+ ok(0, "Unexpected call.\n");
+ return E_NOTIMPL;
+}
+
+static HRESULT WINAPI test_source_Shutdown(IMFMediaSource *iface)
+{
+ ok(0, "Unexpected call.\n");
+ return E_NOTIMPL;
+}
+
+static const IMFMediaSourceVtbl test_source_vtbl =
+{
+ test_source_QueryInterface,
+ test_source_AddRef,
+ test_source_Release,
+ test_source_GetEvent,
+ test_source_BeginGetEvent,
+ test_source_EndGetEvent,
+ test_source_QueueEvent,
+ test_source_GetCharacteristics,
+ test_source_CreatePresentationDescriptor,
+ test_source_Start,
+ test_source_Stop,
+ test_source_Pause,
+ test_source_Shutdown,
+};
+
+static IMFMediaSource *create_test_source(void)
+{
+ struct test_source *source;
+
+ source = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*source));
+ source->IMFMediaSource_iface.lpVtbl = &test_source_vtbl;
+ source->refcount = 1;
+
+ return &source->IMFMediaSource_iface;
+}
+
static void test_topology_loader(void)
{
+ static const struct resolution_test
+ {
+ union
+ {
+ WAVEFORMATEX input_type;
+ MPEGLAYER3WAVEFORMAT mp3_input_type;
+ };
+ WAVEFORMATEX output_type;
+ MF_CONNECT_METHOD method;
+ HRESULT expected_result;
+ BOOL expect_decoder, expect_converter, wine_todo;
+ }
+ resolution_tests[] =
+ {
+ {
+ .input_type = {
+ .wFormatTag = WAVE_FORMAT_PCM, .nChannels = 1, .nSamplesPerSec = 44100,
+ .nAvgBytesPerSec = 44100, .nBlockAlign = 1, .wBitsPerSample = 8, .cbSize = 0,
+ },
+ .output_type = {
+ .wFormatTag = WAVE_FORMAT_PCM, .nChannels = 1, .nSamplesPerSec = 44100,
+ .nAvgBytesPerSec = 44100, .nBlockAlign = 1, .wBitsPerSample = 8, .cbSize = 0,
+ },
+ .method = MF_CONNECT_DIRECT,
+ .expected_result = S_OK,
+ .expect_decoder = FALSE,
+ .expect_converter = FALSE,
+ .wine_todo = FALSE,
+ },
+ {
+ .input_type = {
+ .wFormatTag = WAVE_FORMAT_PCM, .nChannels = 1, .nSamplesPerSec = 44100,
+ .nAvgBytesPerSec = 44100, .nBlockAlign = 1, .wBitsPerSample = 8, .cbSize = 0,
+ },
+ .output_type = {
+ .wFormatTag = WAVE_FORMAT_PCM, .nChannels = 1, .nSamplesPerSec = 48000,
+ .nAvgBytesPerSec = 48000, .nBlockAlign = 1, .wBitsPerSample = 8, .cbSize = 0,
+ },
+ .method = MF_CONNECT_DIRECT,
+ .expected_result = MF_E_INVALIDMEDIATYPE,
+ .expect_decoder = FALSE,
+ .expect_converter = FALSE,
+ .wine_todo = TRUE,
+ },
+ {
+ .input_type = {
+ .wFormatTag = WAVE_FORMAT_PCM, .nChannels = 1, .nSamplesPerSec = 44100,
+ .nAvgBytesPerSec = 44100, .nBlockAlign = 1, .wBitsPerSample = 8, .cbSize = 0,
+ },
+ .output_type = {
+ .wFormatTag = WAVE_FORMAT_PCM, .nChannels = 1, .nSamplesPerSec = 48000,
+ .nAvgBytesPerSec = 48000, .nBlockAlign = 1, .wBitsPerSample = 8, .cbSize = 0,
+ },
+ .method = MF_CONNECT_ALLOW_CONVERTER,
+ .expected_result = S_OK,
+ .expect_decoder = FALSE,
+ .expect_converter = TRUE,
+ .wine_todo = TRUE,
+ },
+ /* Test MF_TOPONODE_CONNECT_METHOD:
+ - 0x1 (MF_CONNECT_ALLOW_CONVERTER) allows converters
+ - 0x3 (MF_CONNECT_ALLOW_DECODER) allows converters and decoders
+ - 0x2 allows neither */
+ {
+ .mp3_input_type = {
+ {
+ .wFormatTag = WAVE_FORMAT_MPEGLAYER3, .nChannels = 2, .nSamplesPerSec = 44100,
+ .nAvgBytesPerSec = 16000, .nBlockAlign = 1, .wBitsPerSample = 0, .cbSize = MPEGLAYER3_WFX_EXTRA_BYTES,
+ },
+ .wID = MPEGLAYER3_ID_MPEG,
+ .fdwFlags = 0,
+ .nBlockSize = 417,
+ .nFramesPerBlock = 0,
+ .nCodecDelay = 0,
+ },
+ .output_type = {
+ .wFormatTag = WAVE_FORMAT_PCM, .nChannels = 1, .nSamplesPerSec = 44100,
+ .nAvgBytesPerSec = 44100, .nBlockAlign = 1, .wBitsPerSample = 8, .cbSize = 0,
+ },
+ .method = MF_CONNECT_DIRECT,
+ .expected_result = MF_E_INVALIDMEDIATYPE,
+ .expect_decoder = FALSE,
+ .expect_converter = FALSE,
+ .wine_todo = TRUE,
+ },
+ {
+ .mp3_input_type = {
+ {
+ .wFormatTag = WAVE_FORMAT_MPEGLAYER3, .nChannels = 2, .nSamplesPerSec = 44100,
+ .nAvgBytesPerSec = 16000, .nBlockAlign = 1, .wBitsPerSample = 0, .cbSize = MPEGLAYER3_WFX_EXTRA_BYTES,
+ },
+ .wID = MPEGLAYER3_ID_MPEG,
+ .fdwFlags = 0,
+ .nBlockSize = 417,
+ .nFramesPerBlock = 0,
+ .nCodecDelay = 0,
+ },
+ .output_type = {
+ .wFormatTag = WAVE_FORMAT_PCM, .nChannels = 2, .nSamplesPerSec = 44100,
+ .nAvgBytesPerSec = 44100, .nBlockAlign = 1, .wBitsPerSample = 8, .cbSize = 0,
+ },
+ .method = MF_CONNECT_ALLOW_CONVERTER,
+ .expected_result = MF_E_TRANSFORM_NOT_POSSIBLE_FOR_CURRENT_MEDIATYPE_COMBINATION,
+ .expect_decoder = FALSE,
+ .expect_converter = FALSE,
+ .wine_todo = TRUE,
+ },
+ {
+ .mp3_input_type = {
+ {
+ .wFormatTag = WAVE_FORMAT_MPEGLAYER3, .nChannels = 2, .nSamplesPerSec = 44100,
+ .nAvgBytesPerSec = 16000, .nBlockAlign = 1, .wBitsPerSample = 0, .cbSize = MPEGLAYER3_WFX_EXTRA_BYTES,
+ },
+ .wID = MPEGLAYER3_ID_MPEG,
+ .fdwFlags = 0,
+ .nBlockSize = 417,
+ .nFramesPerBlock = 0,
+ .nCodecDelay = 0,
+ },
+ .output_type = {
+ .wFormatTag = WAVE_FORMAT_PCM, .nChannels = 2, .nSamplesPerSec = 44100,
+ .nAvgBytesPerSec = 44100, .nBlockAlign = 1, .wBitsPerSample = 8, .cbSize = 0,
+ },
+ .method = 2,
+ .expected_result = MF_E_INVALIDMEDIATYPE,
+ .expect_decoder = FALSE,
+ .expect_converter = FALSE,
+ .wine_todo = TRUE,
+ },
+ {
+ .mp3_input_type = {
+ {
+ .wFormatTag = WAVE_FORMAT_MPEGLAYER3, .nChannels = 2, .nSamplesPerSec = 44100,
+ .nAvgBytesPerSec = 16000, .nBlockAlign = 1, .wBitsPerSample = 0, .cbSize = MPEGLAYER3_WFX_EXTRA_BYTES,
+ },
+ .wID = MPEGLAYER3_ID_MPEG,
+ .fdwFlags = 0,
+ .nBlockSize = 417,
+ .nFramesPerBlock = 0,
+ .nCodecDelay = 0,
+ },
+ .output_type = {
+ .wFormatTag = WAVE_FORMAT_PCM, .nChannels = 1, .nSamplesPerSec = 44100,
+ .nAvgBytesPerSec = 44100, .nBlockAlign = 1, .wBitsPerSample = 8, .cbSize = 0,
+ },
+ .method = MF_CONNECT_ALLOW_DECODER,
+ .expected_result = S_OK,
+ .expect_decoder = TRUE,
+ .expect_converter = FALSE,
+ .wine_todo = TRUE,
+ },
+ };
+
IMFSampleGrabberSinkCallback test_grabber_callback = { &test_grabber_callback_vtbl };
+ IMFTopologyNode *src_node, *sink_node, *src_node2, *sink_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;
- IMFAttributes *attr;
+ IUnknown *node_object;
+ BOOL compare_result;
IMFMediaSink *sink;
- WCHAR *filename;
- BOOL selected;
+ WORD node_count;
+ unsigned int i;
+ TOPOID node_id;
HRESULT hr;
GUID guid;
@@ -1487,44 +1750,41 @@ static void test_topology_loader(void)
todo_wine
ok(hr == MF_E_TOPO_UNSUPPORTED, "Unexpected hr %#x.\n", hr);
- hr = MFCreateSourceResolver(&resolver);
- ok(hr == S_OK, "Failed to create source resolver, hr %#x.\n", hr);
+ /* Add source node. */
+ hr = MFCreateTopologyNode(MF_TOPOLOGY_SOURCESTREAM_NODE, &src_node);
+ ok(hr == S_OK, "Failed to create topology node, hr %#x.\n", hr);
- filename = load_resource(L"test.wav");
+ /* when a decoder is involved, windows requires this attribute to be present */
+ source = create_test_source();
- 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);
+ hr = IMFTopologyNode_SetUnknown(src_node, &MF_TOPONODE_SOURCE, (IUnknown *)source);
+ ok(hr == S_OK, "Failed to set node source, hr %#x.\n", hr);
- IMFByteStream_QueryInterface(stream, &IID_IMFAttributes, (void **)&attr);
- IMFAttributes_SetString(attr, &MF_BYTESTREAM_CONTENT_TYPE, L"audio/wav");
- IMFAttributes_Release(attr);
+ IMFMediaSource_Release(source);
- 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 = MFCreateMediaType(&media_type);
+ ok(hr == S_OK, "Failed to create media type, hr %#x.\n", hr);
- hr = IMFMediaSource_CreatePresentationDescriptor(source, &pd);
- ok(hr == S_OK, "Failed to create descriptor, hr %#x.\n", hr);
- if (FAILED(hr))
- return;
+ 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 = IMFPresentationDescriptor_GetStreamDescriptorByIndex(pd, 0, &selected, &sd);
- ok(hr == S_OK, "Failed to get stream descriptor, hr %#x.\n", hr);
+ hr = MFCreateStreamDescriptor(0, 1, &media_type, &sd);
+ ok(hr == S_OK, "Failed to create stream descriptor, hr %#x.\n");
- /* Add source node. */
- hr = MFCreateTopologyNode(MF_TOPOLOGY_SOURCESTREAM_NODE, &src_node);
- ok(hr == S_OK, "Failed to create topology node, 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 = IMFTopologyNode_SetUnknown(src_node, &MF_TOPONODE_SOURCE, (IUnknown *)source);
- ok(hr == S_OK, "Failed to set node source, hr %#x.\n", hr);
+ hr = MFCreatePresentationDescriptor(1, &sd, &pd);
+ ok(hr == S_OK, "Failed to create presentation descriptor, hr %#x.\n");
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);
+ IMFPresentationDescriptor_Release(pd);
+ IMFStreamDescriptor_Release(sd);
+ IMFMediaType_Release(media_type);
hr = IMFTopology_AddNode(topology, src_node);
ok(hr == S_OK, "Failed to add a node, hr %#x.\n", hr);
@@ -1534,7 +1794,9 @@ todo_wine
todo_wine
ok(hr == MF_E_TOPO_UNSUPPORTED, "Unexpected hr %#x.\n", hr);
- /* Add grabber sink. */
+ hr = MFCreateTopologyNode(MF_TOPOLOGY_OUTPUT_NODE, &sink_node);
+ ok(hr == S_OK, "Failed to create output node, hr %#x.\n", hr);
+
hr = MFCreateMediaType(&media_type);
ok(hr == S_OK, "Failed to create media type, hr %#x.\n", hr);
@@ -1546,13 +1808,11 @@ todo_wine
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 = MFCreateTopologyNode(MF_TOPOLOGY_OUTPUT_NODE, &sink_node);
- ok(hr == S_OK, "Failed to create output node, hr %#x.\n", hr);
-
hr = IMFTopologyNode_SetObject(sink_node, (IUnknown *)sink_activate);
ok(hr == S_OK, "Failed to set object, hr %#x.\n", hr);
+
+ IMFMediaType_Release(media_type);
+
hr = IMFTopology_AddNode(topology, sink_node);
ok(hr == S_OK, "Failed to add sink node, hr %#x.\n", hr);
@@ -1567,55 +1827,194 @@ todo_wine
hr = IMFTopoLoader_Load(loader, topology, &full_topology, NULL);
ok(hr == MF_E_TOPO_SINK_ACTIVATES_UNSUPPORTED, "Unexpected hr %#x.\n", hr);
- hr = IMFActivate_ActivateObject(sink_activate, &IID_IMFMediaSink, (void **)&sink);
- ok(hr == S_OK, "Failed to activate, hr %#x.\n", hr);
+ for (i = 0; i < ARRAY_SIZE(resolution_tests); i++)
+ {
+ IMFMediaType *input_type, *output_type;
+ IMFMediaTypeHandler *mth;
- hr = IMFMediaSink_GetStreamSinkByIndex(sink, 0, &stream_sink);
- ok(hr == S_OK, "Unexpected hr %#x.\n", hr);
+ /* TODO: remove once
+ 1) sample grabber IsMediaTypeSupported is fixed and
+ 2) MFInitMediaTypeFromWaveFormatEx gains support for non-zero cbSize */
+ if(resolution_tests[i].wine_todo && !strcmp(winetest_platform, "wine"))
+ {
+ todo_wine ok(0, "Skipping test %u on wine.\n", i);
+ continue;
+ }
- hr = IMFTopologyNode_SetObject(sink_node, (IUnknown *)stream_sink);
- ok(hr == S_OK, "Failed to set object, hr %#x.\n", hr);
+ hr = MFCreateMediaType(&input_type);
+ ok(hr == S_OK, "Failed to create media type, hr %#x.\n", hr);
- IMFStreamSink_Release(stream_sink);
+ hr = MFInitMediaTypeFromWaveFormatEx(input_type, &resolution_tests[i].input_type, sizeof(WAVEFORMATEX) + resolution_tests[i].input_type.cbSize);
+ ok(hr == S_OK, "MFInitMediaTypeFromWaveFormatEx failed, hr %#x.\n", hr);
- hr = IMFTopology_GetCount(topology, &count);
- ok(hr == S_OK, "Failed to get attribute count, hr %#x.\n", hr);
- ok(count == 0, "Unexpected count %u.\n", count);
+ hr = MFCreateMediaType(&output_type);
+ ok(hr == S_OK, "Failed to create media type, hr %#x.\n", hr);
- hr = IMFTopoLoader_Load(loader, topology, &full_topology, NULL);
- ok(hr == S_OK, "Failed to resolve topology, hr %#x.\n", hr);
- ok(full_topology != topology, "Unexpected instance.\n");
+ hr = MFInitMediaTypeFromWaveFormatEx(output_type, &resolution_tests[i].output_type, sizeof(WAVEFORMATEX) + resolution_tests[i].output_type.cbSize);
+ ok(hr == S_OK, "MFInitMediaTypeFromWaveFormatEx failed, hr %#x.\n", hr);
- hr = IMFTopology_GetCount(topology, &count);
- ok(hr == S_OK, "Failed to get attribute count, hr %#x.\n", hr);
- ok(count == 0, "Unexpected count %u.\n", count);
+ hr = MFCreateStreamDescriptor(0, 1, &input_type, &sd);
+ ok(hr == S_OK, "Failed to create stream descriptor, hr %#x.\n", hr);
- hr = IMFTopology_GetCount(full_topology, &count);
- ok(hr == S_OK, "Failed to get attribute count, hr %#x.\n", hr);
+ hr = IMFStreamDescriptor_GetMediaTypeHandler(sd, &mth);
+ ok(hr == S_OK, "Failed to get media type handler, hr %#x.\n", hr);
+
+ hr = IMFMediaTypeHandler_SetCurrentMediaType(mth, input_type);
+ ok(hr == S_OK, "Failed to set current media type, hr %#x.\n", hr);
+
+ IMFMediaTypeHandler_Release(mth);
+
+ hr = MFCreatePresentationDescriptor(1, &sd, &pd);
+ ok(hr == S_OK, "Failed to create presentation descriptor, 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);
+
+ IMFPresentationDescriptor_Release(pd);
+
+ hr = IMFTopologyNode_SetUnknown(src_node, &MF_TOPONODE_STREAM_DESCRIPTOR, (IUnknown *)sd);
+ ok(hr == S_OK, "Failed to set node sd, hr %#x.\n", hr);
+
+ IMFStreamDescriptor_Release(sd);
+
+ hr = MFCreateSampleGrabberSinkActivate(output_type, &test_grabber_callback, &sink_activate);
+ ok(hr == S_OK, "Failed to create grabber sink, hr %#x.\n", hr);
+
+ 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);
+
+ IMFMediaSink_Release(sink);
+
+ 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, resolution_tests[i].method);
+ ok(hr == S_OK, "Failed to set connect method, hr %#x.\n", hr);
+
+ hr = IMFTopology_GetCount(topology, &count);
+ ok(hr == S_OK, "Failed to get attribute count, hr %#x.\n", hr);
+ ok(count == 0, "Unexpected count %u.\n", count);
+
+ hr = IMFTopoLoader_Load(loader, topology, &full_topology, NULL);
+todo_wine_if(resolution_tests[i].wine_todo)
+ ok(hr == resolution_tests[i].expected_result, "Unexpected hr %#x on test %u.\n", hr, i);
+ ok(full_topology != topology, "Unexpected instance.\n");
+
+ if (resolution_tests[i].expected_result == S_OK && hr == S_OK)
+ {
+ hr = IMFTopology_GetCount(full_topology, &count);
+ ok(hr == S_OK, "Failed to get attribute count, hr %#x.\n", hr);
todo_wine
- ok(count == 1, "Unexpected count %u.\n", count);
+ ok(count == 1, "Unexpected count %u.\n", count);
- hr = IMFTopology_GetItemByIndex(full_topology, 0, &guid, NULL);
+ hr = IMFTopology_GetItemByIndex(full_topology, 0, &guid, NULL);
todo_wine {
- ok(hr == S_OK, "Failed to get attribute key, hr %#x.\n", hr);
- ok(IsEqualGUID(&guid, &MF_TOPOLOGY_RESOLUTION_STATUS), "Unexpected key %s.\n", wine_dbgstr_guid(&guid));
+ ok(hr == S_OK, "Failed to get attribute key, hr %#x.\n", hr);
+ ok(IsEqualGUID(&guid, &MF_TOPOLOGY_RESOLUTION_STATUS), "Unexpected key %s.\n", wine_dbgstr_guid(&guid));
}
- value = 0xdeadbeef;
- hr = IMFTopology_GetUINT32(full_topology, &MF_TOPOLOGY_RESOLUTION_STATUS, &value);
+ value = 0xdeadbeef;
+ hr = IMFTopology_GetUINT32(full_topology, &MF_TOPOLOGY_RESOLUTION_STATUS, &value);
todo_wine {
- ok(hr == S_OK, "Failed to get attribute, hr %#x.\n", hr);
- ok(value == MF_TOPOLOGY_RESOLUTION_SUCCEEDED, "Unexpected value %#x.\n", value);
+ ok(hr == S_OK, "Failed to get attribute, hr %#x.\n", hr);
+ ok(value == MF_TOPOLOGY_RESOLUTION_SUCCEEDED, "Unexpected value %#x.\n", value);
}
- hr = IMFTopoLoader_Load(loader, full_topology, &topology2, NULL);
- ok(hr == S_OK, "Failed to resolve topology, hr %#x.\n", hr);
- ok(full_topology != topology2, "Unexpected instance.\n");
- IMFTopology_Release(topology2);
- IMFTopology_Release(full_topology);
+ hr = IMFTopology_GetNodeCount(full_topology, &node_count);
+ ok(hr == S_OK, "Failed to get node count, hr %#x.\n", hr);
+ ok(node_count == 2 + resolution_tests[i].expect_decoder + resolution_tests[i].expect_converter, "Unexpected node count %u.\n", node_count);
+
+ 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_GetTopoNodeID(sink_node, &node_id);
+ ok(hr == S_OK, "Failed to get sink node id, hr %#x.\n", hr);
+
+ hr = IMFTopology_GetNodeByID(full_topology, node_id, &sink_node2);
+ ok(hr == S_OK, "Failed to get sink in resolved topology, hr %#x.\n", hr);
+
+ if (resolution_tests[i].expect_decoder || resolution_tests[i].expect_converter)
+ {
+ 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_Compare(media_type, (IMFAttributes *)input_type, MF_ATTRIBUTES_MATCH_ALL_ITEMS, &compare_result);
+ ok(hr == S_OK, "Failed to compare media types, hr %#x.\n", hr);
+ ok(compare_result, "Input type of first transform doesn't match source node type.\n");
+
+ IMFTopologyNode_Release(mft_node);
+ IMFMediaType_Release(media_type);
+ IMFTransform_Release(transform);
+
+ hr = IMFTopologyNode_GetInput(sink_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_GetOutputCurrentType(transform, 0, &media_type);
+ ok(hr == S_OK, "Failed to get transform output type, hr %#x.\n", hr);
+
+ hr = IMFMediaType_Compare(media_type, (IMFAttributes *)output_type, MF_ATTRIBUTES_MATCH_ALL_ITEMS, &compare_result);
+ ok(hr == S_OK, "Failed to compare media types, hr %#x.\n", hr);
+ ok(compare_result, "Output type of last transform doesn't match sink node type.\n");
+
+ IMFTopologyNode_Release(mft_node);
+ IMFMediaType_Release(media_type);
+ IMFTransform_Release(transform);
+ }
+
+ IMFTopologyNode_Release(sink_node2);
+
+ hr = IMFTopoLoader_Load(loader, full_topology, &topology2, NULL);
+ ok(hr == S_OK, "Failed to resolve topology, hr %#x.\n", hr);
+ ok(full_topology != topology2, "Unexpected instance.\n");
+
+ IMFTopology_Release(topology2);
+ IMFTopology_Release(full_topology);
+ }
+
+ hr = IMFTopology_GetCount(topology, &count);
+ ok(hr == S_OK, "Failed to get attribute count, hr %#x.\n", hr);
+ ok(count == 0, "Unexpected count %u.\n", count);
+
+ IMFActivate_ShutdownObject(sink_activate);
+ IMFActivate_Release(sink_activate);
+ IMFMediaType_Release(input_type);
+ IMFMediaType_Release(output_type);
+ }
- 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
deleted file mode 100644
index f54212a8c8f..00000000000
--- a/dlls/mf/tests/resource.rc
+++ /dev/null
@@ -1,22 +0,0 @@
-/*
- * Copyright 2019 Nikolay Sivov for CodeWeavers
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2.1 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
- */
-
-#include "windef.h"
-
-/* @makedep: test.wav */
-test.wav RCDATA test.wav
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
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
literal 0
HcmV?d00001
--
2.29.2