-- v4: mf/tests: Test that IMFMediaSession_SetTopology sets output nodes media types. mf/tests: Test that IMFTopoLoader_Load sets transform nodes media types. mf/tests: Test that IMFTopoLoader_Load doesn't set output nodes media types. mf/tests: Test some IMFMediaSession_SetTopology error cases. mf/tests: Add helpers to wait and check media session events. mf/tests: Allocate test callbacks dynamically and check refcounts. mf/tests: Keep a presentation descriptor in the test source. mf/tests: Move and split some helper code around.
From: R��mi Bernon rbernon@codeweavers.com
--- dlls/mf/tests/mf.c | 477 +++++++++++++++++++++++---------------------- 1 file changed, 245 insertions(+), 232 deletions(-)
diff --git a/dlls/mf/tests/mf.c b/dlls/mf/tests/mf.c index af611fac814..612d5a7db05 100644 --- a/dlls/mf/tests/mf.c +++ b/dlls/mf/tests/mf.c @@ -300,6 +300,230 @@ static BOOL create_transform(GUID category, MFT_REGISTER_TYPE_INFO *input_type, return TRUE; }
+static void init_media_type(IMFMediaType *mediatype, const struct attribute_desc *desc, ULONG limit) +{ + HRESULT hr; + ULONG i; + + hr = IMFMediaType_DeleteAllItems(mediatype); + ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); + + for (i = 0; i < limit && desc[i].key; ++i) + { + hr = IMFMediaType_SetItem(mediatype, desc[i].key, &desc[i].value); + ok(hr == S_OK, "SetItem %s returned %#lx\n", debugstr_a(desc[i].name), hr); + } +} + +static void create_descriptors(UINT enum_types_count, IMFMediaType **enum_types, const media_type_desc *current_desc, + IMFPresentationDescriptor **pd, IMFStreamDescriptor **sd) +{ + HRESULT hr; + + hr = MFCreateStreamDescriptor(0, enum_types_count, enum_types, sd); + ok(hr == S_OK, "Failed to create stream descriptor, hr %#lx.\n", hr); + + hr = MFCreatePresentationDescriptor(1, sd, pd); + ok(hr == S_OK, "Failed to create presentation descriptor, hr %#lx.\n", hr); + + if (current_desc) + { + IMFMediaTypeHandler *handler; + IMFMediaType *type; + + hr = MFCreateMediaType(&type); + ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); + init_media_type(type, *current_desc, -1); + + hr = IMFStreamDescriptor_GetMediaTypeHandler(*sd, &handler); + ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); + hr = IMFMediaTypeHandler_SetCurrentMediaType(handler, type); + ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); + + IMFMediaTypeHandler_Release(handler); + IMFMediaType_Release(type); + } +} + +static void init_source_node(IMFMediaSource *source, MF_CONNECT_METHOD method, IMFTopologyNode *node, + IMFPresentationDescriptor *pd, IMFStreamDescriptor *sd) +{ + HRESULT hr; + + hr = IMFTopologyNode_DeleteAllItems(node); + ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); + + hr = IMFTopologyNode_SetUnknown(node, &MF_TOPONODE_PRESENTATION_DESCRIPTOR, (IUnknown *)pd); + ok(hr == S_OK, "Failed to set node pd, hr %#lx.\n", hr); + hr = IMFTopologyNode_SetUnknown(node, &MF_TOPONODE_STREAM_DESCRIPTOR, (IUnknown *)sd); + ok(hr == S_OK, "Failed to set node sd, hr %#lx.\n", hr); + + if (method != -1) + { + hr = IMFTopologyNode_SetUINT32(node, &MF_TOPONODE_CONNECT_METHOD, method); + ok(hr == S_OK, "Failed to set connect method, hr %#lx.\n", hr); + } + + if (source) + { + hr = IMFTopologyNode_SetUnknown(node, &MF_TOPONODE_SOURCE, (IUnknown *)source); + ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); + } +} + +static void init_sink_node(IMFStreamSink *stream_sink, MF_CONNECT_METHOD method, IMFTopologyNode *node) +{ + HRESULT hr; + + hr = IMFTopologyNode_DeleteAllItems(node); + ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); + + hr = IMFTopologyNode_SetObject(node, (IUnknown *)stream_sink); + ok(hr == S_OK, "Failed to set object, hr %#lx.\n", hr); + + if (method != -1) + { + hr = IMFTopologyNode_SetUINT32(node, &MF_TOPONODE_CONNECT_METHOD, method); + ok(hr == S_OK, "Failed to set connect method, hr %#lx.\n", hr); + } +} + +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) + free(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 = calloc(1, sizeof(*source)); + source->IMFMediaSource_iface.lpVtbl = &test_source_vtbl; + source->refcount = 1; + + return &source->IMFMediaSource_iface; +} + static HRESULT WINAPI test_unk_QueryInterface(IUnknown *iface, REFIID riid, void **obj) { if (IsEqualIID(riid, &IID_IUnknown)) @@ -1970,231 +2194,6 @@ 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) - free(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 = calloc(1, sizeof(*source)); - source->IMFMediaSource_iface.lpVtbl = &test_source_vtbl; - source->refcount = 1; - - return &source->IMFMediaSource_iface; -} - -static void init_media_type(IMFMediaType *mediatype, const struct attribute_desc *desc, ULONG limit) -{ - HRESULT hr; - ULONG i; - - hr = IMFMediaType_DeleteAllItems(mediatype); - ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); - - for (i = 0; i < limit && desc[i].key; ++i) - { - hr = IMFMediaType_SetItem(mediatype, desc[i].key, &desc[i].value); - ok(hr == S_OK, "SetItem %s returned %#lx\n", debugstr_a(desc[i].name), hr); - } -} - -static void init_source_node(IMFMediaSource *source, MF_CONNECT_METHOD method, IMFTopologyNode *node, - UINT enum_types_count, IMFMediaType **enum_types, const media_type_desc *current_desc) -{ - IMFPresentationDescriptor *pd; - IMFStreamDescriptor *sd; - HRESULT hr; - - hr = IMFTopologyNode_DeleteAllItems(node); - ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); - - hr = MFCreateStreamDescriptor(0, enum_types_count, enum_types, &sd); - ok(hr == S_OK, "Failed to create stream descriptor, hr %#lx.\n", hr); - - hr = MFCreatePresentationDescriptor(1, &sd, &pd); - ok(hr == S_OK, "Failed to create presentation descriptor, hr %#lx.\n", hr); - - hr = IMFTopologyNode_SetUnknown(node, &MF_TOPONODE_PRESENTATION_DESCRIPTOR, (IUnknown *)pd); - ok(hr == S_OK, "Failed to set node pd, hr %#lx.\n", hr); - - IMFPresentationDescriptor_Release(pd); - - hr = IMFTopologyNode_SetUnknown(node, &MF_TOPONODE_STREAM_DESCRIPTOR, (IUnknown *)sd); - ok(hr == S_OK, "Failed to set node sd, hr %#lx.\n", hr); - - if (method != -1) - { - hr = IMFTopologyNode_SetUINT32(node, &MF_TOPONODE_CONNECT_METHOD, method); - ok(hr == S_OK, "Failed to set connect method, hr %#lx.\n", hr); - } - - if (source) - { - hr = IMFTopologyNode_SetUnknown(node, &MF_TOPONODE_SOURCE, (IUnknown *)source); - ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); - } - - if (current_desc) - { - IMFMediaTypeHandler *handler; - IMFMediaType *type; - - hr = MFCreateMediaType(&type); - ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); - init_media_type(type, *current_desc, -1); - - hr = IMFStreamDescriptor_GetMediaTypeHandler(sd, &handler); - ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); - hr = IMFMediaTypeHandler_SetCurrentMediaType(handler, type); - ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); - - IMFMediaTypeHandler_Release(handler); - IMFMediaType_Release(type); - } - - IMFStreamDescriptor_Release(sd); -} - -static void init_sink_node(IMFStreamSink *stream_sink, MF_CONNECT_METHOD method, IMFTopologyNode *node) -{ - HRESULT hr; - - hr = IMFTopologyNode_DeleteAllItems(node); - ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); - - hr = IMFTopologyNode_SetObject(node, (IUnknown *)stream_sink); - ok(hr == S_OK, "Failed to set object, hr %#lx.\n", hr); - - if (method != -1) - { - hr = IMFTopologyNode_SetUINT32(node, &MF_TOPONODE_CONNECT_METHOD, method); - ok(hr == S_OK, "Failed to set connect method, hr %#lx.\n", hr); - } -} - enum loader_test_flags { LOADER_EXPECTED_DECODER = 0x1, @@ -2581,6 +2580,15 @@ static void test_topology_loader(void) ref = IMFActivate_Release(sink_activate); ok(ref == 0, "Release returned %ld\n", ref);
+ hr = IMFTopologyNode_SetUnknown(src_node, &MF_TOPONODE_STREAM_DESCRIPTOR, NULL); + ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); + hr = IMFTopologyNode_SetUnknown(src_node, &MF_TOPONODE_PRESENTATION_DESCRIPTOR, NULL); + ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); + ref = IMFPresentationDescriptor_Release(pd); + ok(ref == 0, "Release returned %ld\n", ref); + ref = IMFStreamDescriptor_Release(sd); + ok(ref == 0, "Release returned %ld\n", ref); +
hr = MFCreateMediaType(&input_type); ok(hr == S_OK, "Failed to create media type, hr %#lx.\n", hr); @@ -2619,7 +2627,11 @@ static void test_topology_loader(void) handler.media_types = NULL; }
- init_source_node(source, test->source_method, src_node, 1, &input_type, test->current_input); + create_descriptors(1, &input_type, test->current_input, &pd, &sd); + init_source_node(source, test->source_method, src_node, pd, sd); + IMFPresentationDescriptor_Release(pd); + IMFStreamDescriptor_Release(sd); + init_sink_node(&stream_sink.IMFStreamSink_iface, test->sink_method, sink_node);
hr = IMFTopology_GetCount(topology, &count); @@ -2794,11 +2806,6 @@ todo_wine { ref = IMFMediaSource_Release(source); ok(ref == 0, "Release returned %ld\n", ref);
- ref = IMFPresentationDescriptor_Release(pd); - ok(ref == 0, "Release returned %ld\n", ref); - ref = IMFStreamDescriptor_Release(sd); - ok(ref == 0, "Release returned %ld\n", ref); - ref = IMFMediaType_Release(input_type); ok(ref == 0, "Release returned %ld\n", ref); ref = IMFMediaType_Release(output_type); @@ -2820,10 +2827,12 @@ static void test_topology_loader_evr(void) }; IMFTopologyNode *node, *source_node, *evr_node; IMFTopology *topology, *full_topology; + IMFPresentationDescriptor *pd; IMFMediaTypeHandler *handler; unsigned int i, count, value; IMFStreamSink *stream_sink; IMFMediaType *media_type; + IMFStreamDescriptor *sd; IMFActivate *activate; IMFTopoLoader *loader; IMFMediaSink *sink; @@ -2846,7 +2855,11 @@ static void test_topology_loader_evr(void) hr = MFCreateMediaType(&media_type); ok(hr == S_OK, "Failed to create media type, hr %#lx.\n", hr); init_media_type(media_type, media_type_desc, -1); - init_source_node(NULL, -1, source_node, 1, &media_type, &media_type_desc); + + create_descriptors(1, &media_type, &media_type_desc, &pd, &sd); + init_source_node(NULL, -1, source_node, pd, sd); + IMFPresentationDescriptor_Release(pd); + IMFStreamDescriptor_Release(sd);
/* EVR sink node. */ window = create_window();
From: R��mi Bernon rbernon@codeweavers.com
--- dlls/mf/tests/mf.c | 63 ++++++++++++++++++++++++++++------------------ 1 file changed, 38 insertions(+), 25 deletions(-)
diff --git a/dlls/mf/tests/mf.c b/dlls/mf/tests/mf.c index 612d5a7db05..5dba4ecdb88 100644 --- a/dlls/mf/tests/mf.c +++ b/dlls/mf/tests/mf.c @@ -392,6 +392,7 @@ struct test_source { IMFMediaSource IMFMediaSource_iface; LONG refcount; + IMFPresentationDescriptor *pd; };
static struct test_source *impl_from_IMFMediaSource(IMFMediaSource *iface) @@ -429,7 +430,10 @@ static ULONG WINAPI test_source_Release(IMFMediaSource *iface) ULONG refcount = InterlockedDecrement(&source->refcount);
if (!refcount) + { + IMFPresentationDescriptor_Release(source->pd); free(source); + }
return refcount; } @@ -461,14 +465,14 @@ static HRESULT WINAPI test_source_QueueEvent(IMFMediaSource *iface, MediaEventTy
static HRESULT WINAPI test_source_GetCharacteristics(IMFMediaSource *iface, DWORD *flags) { - ok(0, "Unexpected call.\n"); - return E_NOTIMPL; + *flags = 0; + return S_OK; }
static HRESULT WINAPI test_source_CreatePresentationDescriptor(IMFMediaSource *iface, IMFPresentationDescriptor **pd) { - ok(0, "Unexpected call.\n"); - return E_NOTIMPL; + struct test_source *source = impl_from_IMFMediaSource(iface); + return IMFPresentationDescriptor_Clone(source->pd, pd); }
static HRESULT WINAPI test_source_Start(IMFMediaSource *iface, IMFPresentationDescriptor *pd, const GUID *time_format, @@ -513,13 +517,14 @@ static const IMFMediaSourceVtbl test_source_vtbl = test_source_Shutdown, };
-static IMFMediaSource *create_test_source(void) +static IMFMediaSource *create_test_source(IMFPresentationDescriptor *pd) { struct test_source *source;
source = calloc(1, sizeof(*source)); source->IMFMediaSource_iface.lpVtbl = &test_source_vtbl; source->refcount = 1; + IMFPresentationDescriptor_AddRef((source->pd = pd));
return &source->IMFMediaSource_iface; } @@ -2504,34 +2509,28 @@ static void test_topology_loader(void) hr = MFCreateTopologyNode(MF_TOPOLOGY_SOURCESTREAM_NODE, &src_node); ok(hr == S_OK, "Failed to create topology node, hr %#lx.\n", hr);
- /* When a decoder is involved, windows requires this attribute to be present */ - source = create_test_source(); - - hr = IMFTopologyNode_SetUnknown(src_node, &MF_TOPONODE_SOURCE, (IUnknown *)source); - ok(hr == S_OK, "Failed to set node source, hr %#lx.\n", hr); - hr = MFCreateMediaType(&media_type); ok(hr == S_OK, "Failed to create media type, hr %#lx.\n", hr); - hr = IMFMediaType_SetGUID(media_type, &MF_MT_MAJOR_TYPE, &MFMediaType_Audio); ok(hr == S_OK, "Failed to set attribute, hr %#lx.\n", hr); hr = IMFMediaType_SetGUID(media_type, &MF_MT_SUBTYPE, &MFAudioFormat_PCM); ok(hr == S_OK, "Failed to set attribute, hr %#lx.\n", hr);
- hr = MFCreateStreamDescriptor(0, 1, &media_type, &sd); - ok(hr == S_OK, "Failed to create stream descriptor, hr %#lx.\n", hr); + /* When a decoder is involved, windows requires this attribute to be present */ + create_descriptors(1, &media_type, NULL, &pd, &sd); + IMFMediaType_Release(media_type); + + source = create_test_source(pd); + + hr = IMFTopologyNode_SetUnknown(src_node, &MF_TOPONODE_SOURCE, (IUnknown *)source); + ok(hr == S_OK, "Failed to set node source, hr %#lx.\n", hr);
hr = IMFTopologyNode_SetUnknown(src_node, &MF_TOPONODE_STREAM_DESCRIPTOR, (IUnknown *)sd); ok(hr == S_OK, "Failed to set node sd, hr %#lx.\n", hr);
- hr = MFCreatePresentationDescriptor(1, &sd, &pd); - ok(hr == S_OK, "Failed to create presentation descriptor, hr %#lx.\n", hr); - hr = IMFTopologyNode_SetUnknown(src_node, &MF_TOPONODE_PRESENTATION_DESCRIPTOR, (IUnknown *)pd); ok(hr == S_OK, "Failed to set node pd, hr %#lx.\n", hr);
- IMFMediaType_Release(media_type); - hr = IMFTopology_AddNode(topology, src_node); ok(hr == S_OK, "Failed to add a node, hr %#lx.\n", hr);
@@ -2580,10 +2579,14 @@ static void test_topology_loader(void) ref = IMFActivate_Release(sink_activate); ok(ref == 0, "Release returned %ld\n", ref);
+ hr = IMFTopologyNode_SetUnknown(src_node, &MF_TOPONODE_SOURCE, NULL); + ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); hr = IMFTopologyNode_SetUnknown(src_node, &MF_TOPONODE_STREAM_DESCRIPTOR, NULL); ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); hr = IMFTopologyNode_SetUnknown(src_node, &MF_TOPONODE_PRESENTATION_DESCRIPTOR, NULL); ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); + ref = IMFMediaSource_Release(source); + ok(ref == 0, "Release returned %ld\n", ref); ref = IMFPresentationDescriptor_Release(pd); ok(ref == 0, "Release returned %ld\n", ref); ref = IMFStreamDescriptor_Release(sd); @@ -2628,10 +2631,10 @@ static void test_topology_loader(void) }
create_descriptors(1, &input_type, test->current_input, &pd, &sd); - init_source_node(source, test->source_method, src_node, pd, sd); - IMFPresentationDescriptor_Release(pd); - IMFStreamDescriptor_Release(sd);
+ source = create_test_source(pd); + + init_source_node(source, test->source_method, src_node, pd, sd); init_sink_node(&stream_sink.IMFStreamSink_iface, test->sink_method, sink_node);
hr = IMFTopology_GetCount(topology, &count); @@ -2791,6 +2794,19 @@ todo_wine { else ok(!handler.enum_count, "got %lu GetMediaTypeByIndex\n", handler.enum_count);
+ hr = IMFTopologyNode_SetUnknown(src_node, &MF_TOPONODE_SOURCE, NULL); + ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); + hr = IMFTopologyNode_SetUnknown(src_node, &MF_TOPONODE_STREAM_DESCRIPTOR, NULL); + ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); + hr = IMFTopologyNode_SetUnknown(src_node, &MF_TOPONODE_PRESENTATION_DESCRIPTOR, NULL); + ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); + ref = IMFMediaSource_Release(source); + ok(ref == 0, "Release returned %ld\n", ref); + ref = IMFPresentationDescriptor_Release(pd); + ok(ref == 0, "Release returned %ld\n", ref); + ref = IMFStreamDescriptor_Release(sd); + ok(ref == 0, "Release returned %ld\n", ref); + winetest_pop_context(); }
@@ -2803,9 +2819,6 @@ todo_wine { ref = IMFTopologyNode_Release(sink_node); ok(ref == 0, "Release returned %ld\n", ref);
- ref = IMFMediaSource_Release(source); - ok(ref == 0, "Release returned %ld\n", ref); - ref = IMFMediaType_Release(input_type); ok(ref == 0, "Release returned %ld\n", ref); ref = IMFMediaType_Release(output_type);
From: R��mi Bernon rbernon@codeweavers.com
--- dlls/mf/tests/mf.c | 86 ++++++++++++++++++++++++++++++++-------------- 1 file changed, 61 insertions(+), 25 deletions(-)
diff --git a/dlls/mf/tests/mf.c b/dlls/mf/tests/mf.c index 5dba4ecdb88..454694cac8b 100644 --- a/dlls/mf/tests/mf.c +++ b/dlls/mf/tests/mf.c @@ -1792,8 +1792,14 @@ static const struct test_stream_sink test_stream_sink = {.IMFStreamSink_iface.lp struct test_callback { IMFAsyncCallback IMFAsyncCallback_iface; + LONG refcount; };
+static struct test_callback *impl_from_IMFAsyncCallback(IMFAsyncCallback *iface) +{ + return CONTAINING_RECORD(iface, struct test_callback, IMFAsyncCallback_iface); +} + static HRESULT WINAPI testcallback_QueryInterface(IMFAsyncCallback *iface, REFIID riid, void **obj) { if (IsEqualIID(riid, &IID_IMFAsyncCallback) || @@ -1810,12 +1816,21 @@ static HRESULT WINAPI testcallback_QueryInterface(IMFAsyncCallback *iface, REFII
static ULONG WINAPI testcallback_AddRef(IMFAsyncCallback *iface) { - return 2; + struct test_callback *callback = impl_from_IMFAsyncCallback(iface); + return InterlockedIncrement(&callback->refcount); }
static ULONG WINAPI testcallback_Release(IMFAsyncCallback *iface) { - return 1; + struct test_callback *callback = impl_from_IMFAsyncCallback(iface); + ULONG refcount = InterlockedDecrement(&callback->refcount); + + if (!refcount) + { + free(callback); + } + + return refcount; }
static HRESULT WINAPI testcallback_GetParameters(IMFAsyncCallback *iface, DWORD *flags, DWORD *queue) @@ -1840,20 +1855,35 @@ static const IMFAsyncCallbackVtbl testcallbackvtbl = testcallback_Invoke, };
-static void init_test_callback(struct test_callback *callback) +static IMFAsyncCallback *create_test_callback(void) { + struct test_callback *callback; + + if (!(callback = calloc(1, sizeof(*callback)))) + return NULL; + + callback->refcount = 1; callback->IMFAsyncCallback_iface.lpVtbl = &testcallbackvtbl; + + return &callback->IMFAsyncCallback_iface; }
-static void test_session_events(IMFMediaSession *session) +static void test_media_session_events(void) { - struct test_callback callback, callback2; + IMFAsyncCallback *callback, *callback2; + IMFMediaSession *session; IMFAsyncResult *result; IMFMediaEvent *event; HRESULT hr;
- init_test_callback(&callback); - init_test_callback(&callback2); + hr = MFStartup(MF_VERSION, MFSTARTUP_FULL); + ok(hr == S_OK, "Startup failure, hr %#lx.\n", hr); + + callback = create_test_callback(); + callback2 = create_test_callback(); + + hr = MFCreateMediaSession(NULL, &session); + ok(hr == S_OK, "Failed to create media session, hr %#lx.\n", hr);
hr = IMFMediaSession_GetEvent(session, MF_EVENT_FLAG_NO_WAIT, &event); ok(hr == MF_E_NO_EVENTS_AVAILABLE, "Unexpected hr %#lx.\n", hr); @@ -1862,26 +1892,31 @@ static void test_session_events(IMFMediaSession *session) hr = IMFMediaSession_BeginGetEvent(session, NULL, NULL); ok(hr == E_INVALIDARG, "Unexpected hr %#lx.\n", hr);
- hr = IMFMediaSession_BeginGetEvent(session, &callback.IMFAsyncCallback_iface, (IUnknown *)session); + hr = IMFMediaSession_BeginGetEvent(session, callback, (IUnknown *)session); ok(hr == S_OK, "Failed to Begin*, hr %#lx.\n", hr); + EXPECT_REF(callback, 2);
/* Same callback, same state. */ - hr = IMFMediaSession_BeginGetEvent(session, &callback.IMFAsyncCallback_iface, (IUnknown *)session); + hr = IMFMediaSession_BeginGetEvent(session, callback, (IUnknown *)session); ok(hr == MF_S_MULTIPLE_BEGIN, "Unexpected hr %#lx.\n", hr); + EXPECT_REF(callback, 2);
/* Same callback, different state. */ - hr = IMFMediaSession_BeginGetEvent(session, &callback.IMFAsyncCallback_iface, (IUnknown *)&callback.IMFAsyncCallback_iface); + hr = IMFMediaSession_BeginGetEvent(session, callback, (IUnknown *)callback); ok(hr == MF_E_MULTIPLE_BEGIN, "Unexpected hr %#lx.\n", hr); + EXPECT_REF(callback, 2);
/* Different callback, same state. */ - hr = IMFMediaSession_BeginGetEvent(session, &callback2.IMFAsyncCallback_iface, (IUnknown *)session); + hr = IMFMediaSession_BeginGetEvent(session, callback2, (IUnknown *)session); ok(hr == MF_E_MULTIPLE_SUBSCRIBERS, "Unexpected hr %#lx.\n", hr); + EXPECT_REF(callback2, 1);
/* Different callback, different state. */ - hr = IMFMediaSession_BeginGetEvent(session, &callback2.IMFAsyncCallback_iface, (IUnknown *)&callback.IMFAsyncCallback_iface); + hr = IMFMediaSession_BeginGetEvent(session, callback2, (IUnknown *)callback); ok(hr == MF_E_MULTIPLE_SUBSCRIBERS, "Unexpected hr %#lx.\n", hr); + EXPECT_REF(callback, 2);
- hr = MFCreateAsyncResult(NULL, &callback.IMFAsyncCallback_iface, NULL, &result); + hr = MFCreateAsyncResult(NULL, callback, NULL, &result); ok(hr == S_OK, "Failed to create result, hr %#lx.\n", hr);
hr = IMFMediaSession_EndGetEvent(session, result, &event); @@ -1890,6 +1925,17 @@ static void test_session_events(IMFMediaSession *session) /* Shutdown behavior. */ hr = IMFMediaSession_Shutdown(session); ok(hr == S_OK, "Failed to shut down, hr %#lx.\n", hr); + IMFMediaSession_Release(session); + + /* Shutdown leaks callback */ + EXPECT_REF(callback, 2); + EXPECT_REF(callback2, 1); + + IMFAsyncCallback_Release(callback); + IMFAsyncCallback_Release(callback2); + + hr = MFShutdown(); + ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); }
static void test_media_session(void) @@ -1903,8 +1949,8 @@ static void test_media_session(void) PROPVARIANT propvar; IMFGetService *gs; IMFClock *clock; - DWORD caps; HRESULT hr; + DWORD caps;
hr = MFStartup(MF_VERSION, MFSTARTUP_FULL); ok(hr == S_OK, "Startup failure, hr %#lx.\n", hr); @@ -2007,17 +2053,6 @@ static void test_media_session(void) IMFMediaSession_Release(session);
IMFAttributes_Release(attributes); - - /* Basic events behavior. */ - hr = MFCreateMediaSession(NULL, &session); - ok(hr == S_OK, "Failed to create media session, hr %#lx.\n", hr); - - test_session_events(session); - - IMFMediaSession_Release(session); - - hr = MFShutdown(); - ok(hr == S_OK, "Shutdown failure, hr %#lx.\n", hr); }
static void test_media_session_rate_control(void) @@ -9795,6 +9830,7 @@ START_TEST(mf) test_MFGetService(); test_sequencer_source(); test_media_session(); + test_media_session_events(); test_media_session_rate_control(); test_MFShutdownObject(); test_presentation_clock();
From: R��mi Bernon rbernon@codeweavers.com
--- dlls/mf/tests/mf.c | 124 ++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 123 insertions(+), 1 deletion(-)
diff --git a/dlls/mf/tests/mf.c b/dlls/mf/tests/mf.c index 454694cac8b..36ef586267e 100644 --- a/dlls/mf/tests/mf.c +++ b/dlls/mf/tests/mf.c @@ -1793,6 +1793,9 @@ struct test_callback { IMFAsyncCallback IMFAsyncCallback_iface; LONG refcount; + + HANDLE event; + IMFMediaEvent *media_event; };
static struct test_callback *impl_from_IMFAsyncCallback(IMFAsyncCallback *iface) @@ -1827,6 +1830,9 @@ static ULONG WINAPI testcallback_Release(IMFAsyncCallback *iface)
if (!refcount) { + if (callback->media_event) + IMFMediaEvent_Release(callback->media_event); + CloseHandle(callback->event); free(callback); }
@@ -1841,9 +1847,28 @@ static HRESULT WINAPI testcallback_GetParameters(IMFAsyncCallback *iface, DWORD
static HRESULT WINAPI testcallback_Invoke(IMFAsyncCallback *iface, IMFAsyncResult *result) { + struct test_callback *callback = CONTAINING_RECORD(iface, struct test_callback, IMFAsyncCallback_iface); + IUnknown *object; + HRESULT hr; + ok(result != NULL, "Unexpected result object.\n");
- return E_NOTIMPL; + if (callback->media_event) + IMFMediaEvent_Release(callback->media_event); + + hr = IMFAsyncResult_GetObject(result, &object); + ok(hr == E_POINTER, "Unexpected hr %#lx.\n", hr); + + hr = IMFAsyncResult_GetState(result, &object); + ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); + hr = IMFMediaEventGenerator_EndGetEvent((IMFMediaEventGenerator *)object, + result, &callback->media_event); + ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); + IUnknown_Release(object); + + SetEvent(callback->event); + + return S_OK; }
static const IMFAsyncCallbackVtbl testcallbackvtbl = @@ -1864,16 +1889,54 @@ static IMFAsyncCallback *create_test_callback(void)
callback->refcount = 1; callback->IMFAsyncCallback_iface.lpVtbl = &testcallbackvtbl; + callback->event = CreateEventW(NULL, FALSE, FALSE, NULL); + ok(!!callback->event, "CreateEventW failed, error %lu\n", GetLastError());
return &callback->IMFAsyncCallback_iface; }
+#define wait_media_event(a, b, c, d, e) wait_media_event_(__LINE__, a, b, c, d, e) +static HRESULT wait_media_event_(int line, IMFMediaSession *session, IMFAsyncCallback *callback, + MediaEventType expect_type, DWORD timeout, PROPVARIANT *value) +{ + struct test_callback *impl = impl_from_IMFAsyncCallback(callback); + MediaEventType type; + HRESULT hr, status; + DWORD ret; + GUID guid; + + do + { + hr = IMFMediaSession_BeginGetEvent(session, &impl->IMFAsyncCallback_iface, (IUnknown *)session); + ok_(__FILE__, line)(hr == S_OK, "Unexpected hr %#lx.\n", hr); + ret = WaitForSingleObject(impl->event, timeout); + ok_(__FILE__, line)(ret == WAIT_OBJECT_0, "WaitForSingleObject returned %lu\n", ret); + hr = IMFMediaEvent_GetType(impl->media_event, &type); + ok_(__FILE__, line)(hr == S_OK, "Unexpected hr %#lx.\n", hr); + } while (type != expect_type); + + ok_(__FILE__, line)(type == expect_type, "got type %lu\n", type); + + hr = IMFMediaEvent_GetExtendedType(impl->media_event, &guid); + ok_(__FILE__, line)(hr == S_OK, "Unexpected hr %#lx.\n", hr); + ok_(__FILE__, line)(IsEqualGUID(&guid, &GUID_NULL), "got extended type %s\n", debugstr_guid(&guid)); + + hr = IMFMediaEvent_GetValue(impl->media_event, value); + ok_(__FILE__, line)(hr == S_OK, "Unexpected hr %#lx.\n", hr); + + hr = IMFMediaEvent_GetStatus(impl->media_event, &status); + ok_(__FILE__, line)(hr == S_OK, "Unexpected hr %#lx.\n", hr); + + return status; +} + static void test_media_session_events(void) { IMFAsyncCallback *callback, *callback2; IMFMediaSession *session; IMFAsyncResult *result; IMFMediaEvent *event; + PROPVARIANT propvar; HRESULT hr;
hr = MFStartup(MF_VERSION, MFSTARTUP_FULL); @@ -1934,6 +1997,65 @@ static void test_media_session_events(void) IMFAsyncCallback_Release(callback); IMFAsyncCallback_Release(callback2);
+ + callback = create_test_callback(); + + hr = MFCreateMediaSession(NULL, &session); + ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); + + propvar.vt = VT_EMPTY; + hr = IMFMediaSession_Start(session, &GUID_NULL, &propvar); + ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); + hr = wait_media_event(session, callback, MESessionStarted, 1000, &propvar); + ok(hr == MF_E_INVALIDREQUEST, "Unexpected hr %#lx.\n", hr); + ok(propvar.vt == VT_EMPTY, "got vt %u\n", propvar.vt); + + hr = IMFMediaSession_Stop(session); + ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); + hr = wait_media_event(session, callback, MESessionStopped, 1000, &propvar); + todo_wine + ok(hr == MF_E_INVALIDREQUEST, "Unexpected hr %#lx.\n", hr); + ok(propvar.vt == VT_EMPTY, "got vt %u\n", propvar.vt); + + hr = IMFMediaSession_Pause(session); + ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); + hr = wait_media_event(session, callback, MESessionPaused, 1000, &propvar); + todo_wine + ok(hr == MF_E_INVALIDREQUEST, "Unexpected hr %#lx.\n", hr); + ok(propvar.vt == VT_EMPTY, "got vt %u\n", propvar.vt); + + hr = IMFMediaSession_ClearTopologies(session); + ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); + hr = wait_media_event(session, callback, MESessionTopologiesCleared, 1000, &propvar); + ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); + ok(propvar.vt == VT_EMPTY, "got vt %u\n", propvar.vt); + + hr = IMFMediaSession_ClearTopologies(session); + ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); + hr = wait_media_event(session, callback, MESessionTopologiesCleared, 1000, &propvar); + ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); + ok(propvar.vt == VT_EMPTY, "got vt %u\n", propvar.vt); + + hr = IMFMediaSession_Close(session); + ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); + hr = wait_media_event(session, callback, MESessionClosed, 1000, &propvar); + ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); + ok(propvar.vt == VT_EMPTY, "got vt %u\n", propvar.vt); + + hr = IMFMediaSession_ClearTopologies(session); + ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); + hr = wait_media_event(session, callback, MESessionTopologiesCleared, 1000, &propvar); + ok(hr == MF_E_INVALIDREQUEST, "Unexpected hr %#lx.\n", hr); + ok(propvar.vt == VT_EMPTY, "got vt %u\n", propvar.vt); + + hr = IMFMediaSession_Shutdown(session); + ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); + + /* sometimes briefly leaking */ + IMFMediaSession_Release(session); + IMFAsyncCallback_Release(callback); + + hr = MFShutdown(); ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); }
From: R��mi Bernon rbernon@codeweavers.com
--- dlls/mf/tests/mf.c | 106 +++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 106 insertions(+)
diff --git a/dlls/mf/tests/mf.c b/dlls/mf/tests/mf.c index 36ef586267e..349cb0f2825 100644 --- a/dlls/mf/tests/mf.c +++ b/dlls/mf/tests/mf.c @@ -1727,6 +1727,7 @@ static HRESULT WINAPI test_stream_sink_QueueEvent(IMFStreamSink *iface, MediaEve
static HRESULT WINAPI test_stream_sink_GetMediaSink(IMFStreamSink *iface, IMFMediaSink **sink) { + todo_wine ok(0, "Unexpected call.\n"); return E_NOTIMPL; } @@ -1932,12 +1933,34 @@ static HRESULT wait_media_event_(int line, IMFMediaSession *session, IMFAsyncCal
static void test_media_session_events(void) { + static const media_type_desc audio_pcm_44100 = + { + ATTR_GUID(MF_MT_MAJOR_TYPE, MFMediaType_Audio), + ATTR_GUID(MF_MT_SUBTYPE, MFAudioFormat_PCM), + ATTR_UINT32(MF_MT_AUDIO_NUM_CHANNELS, 1), + ATTR_UINT32(MF_MT_AUDIO_SAMPLES_PER_SECOND, 44100), + ATTR_UINT32(MF_MT_AUDIO_AVG_BYTES_PER_SECOND, 44100), + ATTR_UINT32(MF_MT_AUDIO_BLOCK_ALIGNMENT, 1), + ATTR_UINT32(MF_MT_AUDIO_BITS_PER_SAMPLE, 8), + }; + + struct test_stream_sink stream_sink = test_stream_sink; + struct test_handler handler = test_handler; IMFAsyncCallback *callback, *callback2; + IMFTopologyNode *src_node, *sink_node; + IMFPresentationDescriptor *pd; IMFMediaSession *session; + IMFMediaType *input_type; + IMFStreamDescriptor *sd; IMFAsyncResult *result; + IMFMediaSource *source; + IMFTopology *topology; IMFMediaEvent *event; PROPVARIANT propvar; HRESULT hr; + ULONG ref; + + stream_sink.handler = &handler.IMFMediaTypeHandler_iface;
hr = MFStartup(MF_VERSION, MFSTARTUP_FULL); ok(hr == S_OK, "Startup failure, hr %#lx.\n", hr); @@ -2051,10 +2074,93 @@ static void test_media_session_events(void) hr = IMFMediaSession_Shutdown(session); ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
+ /* sometimes briefly leaking */ + IMFMediaSession_Release(session); + + + hr = MFCreateMediaSession(NULL, &session); + ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); + + hr = MFCreateMediaType(&input_type); + ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); + init_media_type(input_type, audio_pcm_44100, -1); + create_descriptors(1, &input_type, NULL, &pd, &sd); + + hr = MFCreateTopologyNode(MF_TOPOLOGY_OUTPUT_NODE, &sink_node); + ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); + init_sink_node(&stream_sink.IMFStreamSink_iface, -1, sink_node); + + hr = MFCreateTopologyNode(MF_TOPOLOGY_SOURCESTREAM_NODE, &src_node); + ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); + init_source_node(NULL, -1, src_node, pd, sd); + + hr = MFCreateTopology(&topology); + ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); + hr = IMFTopology_AddNode(topology, sink_node); + ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); + hr = IMFTopology_AddNode(topology, src_node); + ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); + hr = IMFTopologyNode_ConnectOutput(src_node, 0, sink_node, 0); + ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); + + hr = IMFMediaSession_SetTopology(session, 0, topology); + todo_wine + ok(hr == MF_E_TOPO_MISSING_SOURCE, "Unexpected hr %#lx.\n", hr); + if (hr == S_OK) + { + hr = wait_media_event(session, callback, MESessionTopologySet, 1000, &propvar); + ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); + PropVariantClear(&propvar); + } + + source = create_test_source(pd); + init_source_node(source, -1, src_node, pd, sd); + + hr = IMFMediaSession_SetTopology(session, 0, topology); + todo_wine + ok(hr == MF_E_TOPO_STREAM_DESCRIPTOR_NOT_SELECTED, "Unexpected hr %#lx.\n", hr); + if (hr == S_OK) + { + hr = wait_media_event(session, callback, MESessionTopologySet, 1000, &propvar); + ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); + PropVariantClear(&propvar); + } + + hr = IMFMediaSession_ClearTopologies(session); + ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); + hr = wait_media_event(session, callback, MESessionTopologiesCleared, 1000, &propvar); + ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); + ok(propvar.vt == VT_EMPTY, "got vt %u\n", propvar.vt); + + hr = IMFMediaSession_Shutdown(session); + ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); + /* sometimes briefly leaking */ IMFMediaSession_Release(session); IMFAsyncCallback_Release(callback);
+ if (handler.current_type) + IMFMediaType_Release(handler.current_type); + handler.current_type = NULL; + + hr = IMFTopology_Clear(topology); + ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); + ref = IMFTopologyNode_Release(src_node); + ok(ref == 0, "Release returned %ld\n", ref); + ref = IMFTopologyNode_Release(sink_node); + ok(ref == 0, "Release returned %ld\n", ref); + ref = IMFTopology_Release(topology); + ok(ref == 0, "Release returned %ld\n", ref); + + ref = IMFMediaSource_Release(source); + ok(ref == 0, "Release returned %ld\n", ref); + ref = IMFPresentationDescriptor_Release(pd); + ok(ref == 0, "Release returned %ld\n", ref); + ref = IMFStreamDescriptor_Release(sd); + ok(ref == 0, "Release returned %ld\n", ref); + ref = IMFMediaType_Release(input_type); + ok(ref == 0, "Release returned %ld\n", ref); +
hr = MFShutdown(); ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
From: R��mi Bernon rbernon@codeweavers.com
--- dlls/mf/tests/mf.c | 22 ++++++++++++++++++---- 1 file changed, 18 insertions(+), 4 deletions(-)
diff --git a/dlls/mf/tests/mf.c b/dlls/mf/tests/mf.c index 349cb0f2825..34cab54a607 100644 --- a/dlls/mf/tests/mf.c +++ b/dlls/mf/tests/mf.c @@ -1532,6 +1532,8 @@ static void test_sequencer_source(void) struct test_handler { IMFMediaTypeHandler IMFMediaTypeHandler_iface; + + ULONG set_current_count; IMFMediaType *current_type; IMFMediaType *invalid_type;
@@ -1619,9 +1621,13 @@ static HRESULT WINAPI test_handler_GetMediaTypeByIndex(IMFMediaTypeHandler *ifac
static HRESULT WINAPI test_handler_SetCurrentMediaType(IMFMediaTypeHandler *iface, IMFMediaType *media_type) { - /* FIXME: Wine sets downstream media type when resolving topology, native doesn't */ - todo_wine - ok(0, "Unexpected call.\n"); + struct test_handler *impl = impl_from_IMFMediaTypeHandler(iface); + + if (impl->current_type) + IMFMediaType_Release(impl->current_type); + IMFMediaType_AddRef((impl->current_type = media_type)); + impl->set_current_count++; + return S_OK; }
@@ -2871,10 +2877,11 @@ static void test_topology_loader(void) init_media_type(input_type, *test->input_type, -1); init_media_type(output_type, *test->output_type, -1);
+ handler.set_current_count = 0; if (test->flags & LOADER_NO_CURRENT_OUTPUT) handler.current_type = NULL; else - handler.current_type = output_type; + IMFMediaType_AddRef((handler.current_type = output_type));
if (test->flags & LOADER_SET_INVALID_INPUT) handler.invalid_type = input_type; @@ -3057,6 +3064,13 @@ todo_wine { else ok(!handler.enum_count, "got %lu GetMediaTypeByIndex\n", handler.enum_count);
+ todo_wine_if((test->flags & LOADER_NO_CURRENT_OUTPUT) && !(test->flags & LOADER_SET_MEDIA_TYPES)) + ok(!handler.set_current_count, "got %lu SetCurrentMediaType\n", handler.set_current_count); + + if (handler.current_type) + IMFMediaType_Release(handler.current_type); + handler.current_type = NULL; + hr = IMFTopologyNode_SetUnknown(src_node, &MF_TOPONODE_SOURCE, NULL); ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); hr = IMFTopologyNode_SetUnknown(src_node, &MF_TOPONODE_STREAM_DESCRIPTOR, NULL);
From: R��mi Bernon rbernon@codeweavers.com
--- dlls/mf/tests/mf.c | 89 ++++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 87 insertions(+), 2 deletions(-)
diff --git a/dlls/mf/tests/mf.c b/dlls/mf/tests/mf.c index 34cab54a607..7937351eb4a 100644 --- a/dlls/mf/tests/mf.c +++ b/dlls/mf/tests/mf.c @@ -2478,10 +2478,21 @@ enum loader_test_flags LOADER_NO_CURRENT_OUTPUT = 0x20, LOADER_SET_INVALID_INPUT = 0x40, LOADER_SET_MEDIA_TYPES = 0x80, + LOADER_ADD_RESAMPLER_MFT = 0x100, };
static void test_topology_loader(void) { + static const media_type_desc audio_float_44100 = + { + ATTR_GUID(MF_MT_MAJOR_TYPE, MFMediaType_Audio), + ATTR_GUID(MF_MT_SUBTYPE, MFAudioFormat_Float), + ATTR_UINT32(MF_MT_AUDIO_NUM_CHANNELS, 1), + ATTR_UINT32(MF_MT_AUDIO_BLOCK_ALIGNMENT, 4), + ATTR_UINT32(MF_MT_AUDIO_SAMPLES_PER_SECOND, 44100), + ATTR_UINT32(MF_MT_AUDIO_AVG_BYTES_PER_SECOND, 4 * 44100), + ATTR_UINT32(MF_MT_AUDIO_BITS_PER_SAMPLE, 4 * 8), + }; static const media_type_desc audio_pcm_44100 = { ATTR_GUID(MF_MT_MAJOR_TYPE, MFMediaType_Audio), @@ -2502,6 +2513,18 @@ static void test_topology_loader(void) ATTR_UINT32(MF_MT_AUDIO_BLOCK_ALIGNMENT, 1), ATTR_UINT32(MF_MT_AUDIO_BITS_PER_SAMPLE, 8), }; + static const media_type_desc audio_pcm_48000_resampler = + { + ATTR_GUID(MF_MT_MAJOR_TYPE, MFMediaType_Audio), + ATTR_GUID(MF_MT_SUBTYPE, MFAudioFormat_PCM), + ATTR_UINT32(MF_MT_AUDIO_BITS_PER_SAMPLE, 16), + ATTR_UINT32(MF_MT_AUDIO_NUM_CHANNELS, 2), + ATTR_UINT32(MF_MT_AUDIO_SAMPLES_PER_SECOND, 48000), + ATTR_UINT32(MF_MT_AUDIO_AVG_BYTES_PER_SECOND, 192000), + ATTR_UINT32(MF_MT_AUDIO_BLOCK_ALIGNMENT, 4), + ATTR_UINT32(MF_MT_ALL_SAMPLES_INDEPENDENT, 1), + ATTR_UINT32(MF_MT_AUDIO_PREFER_WAVEFORMATEX, 1), + }; static const media_type_desc audio_float_48000 = { ATTR_GUID(MF_MT_MAJOR_TYPE, MFMediaType_Audio), @@ -2659,6 +2682,19 @@ static void test_topology_loader(void) .expected_result = MF_E_INVALIDMEDIATYPE, },
+ { + /* Float -> PCM, refuse input type, add converter */ + .input_type = &audio_float_44100, .output_type = &audio_pcm_48000, .sink_method = MF_CONNECT_DIRECT, .source_method = -1, + .expected_result = MF_E_NO_MORE_TYPES, + .flags = LOADER_SET_INVALID_INPUT | LOADER_ADD_RESAMPLER_MFT | LOADER_EXPECTED_CONVERTER | LOADER_TODO, + }, + { + /* Float -> PCM, refuse input type, add converter, allow resampler output type */ + .input_type = &audio_float_44100, .output_type = &audio_pcm_48000_resampler, .sink_method = MF_CONNECT_DIRECT, .source_method = -1, + .expected_result = S_OK, + .flags = LOADER_SET_INVALID_INPUT | LOADER_ADD_RESAMPLER_MFT | LOADER_EXPECTED_CONVERTER | LOADER_TODO, + }, + { /* MP3 -> PCM */ .input_type = &audio_mp3_44100, .output_type = &audio_pcm_44100, .sink_method = MF_CONNECT_DIRECT, .source_method = -1, @@ -2900,6 +2936,46 @@ static void test_topology_loader(void) handler.media_types = NULL; }
+ if (test->flags & LOADER_ADD_RESAMPLER_MFT) + { + hr = IMFTopology_Clear(topology); + ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); + hr = IMFTopology_AddNode(topology, src_node); + ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); + hr = IMFTopology_AddNode(topology, sink_node); + ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); + + hr = MFCreateTopologyNode(MF_TOPOLOGY_TRANSFORM_NODE, &mft_node); + ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); + + hr = CoCreateInstance(&CLSID_CResamplerMediaObject, NULL, CLSCTX_INPROC_SERVER, &IID_IMFTransform, (void **)&transform); + ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); + hr = IMFTopologyNode_SetGUID(mft_node, &MF_TOPONODE_TRANSFORM_OBJECTID, &CLSID_CResamplerMediaObject); + ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); + hr = IMFTopologyNode_SetObject(mft_node, (IUnknown *)transform); + ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); + IMFTransform_Release(transform); + + hr = IMFTopology_AddNode(topology, mft_node); + ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); + hr = IMFTopologyNode_ConnectOutput(src_node, 0, mft_node, 0); + ok(hr == S_OK, "Failed to connect nodes, hr %#lx.\n", hr); + hr = IMFTopologyNode_ConnectOutput(mft_node, 0, sink_node, 0); + ok(hr == S_OK, "Failed to connect nodes, hr %#lx.\n", hr); + IMFTopologyNode_Release(mft_node); + } + else + { + hr = IMFTopology_Clear(topology); + ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); + hr = IMFTopology_AddNode(topology, src_node); + ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); + hr = IMFTopology_AddNode(topology, sink_node); + ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); + hr = IMFTopologyNode_ConnectOutput(src_node, 0, sink_node, 0); + ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); + } + create_descriptors(1, &input_type, test->current_input, &pd, &sd);
source = create_test_source(pd); @@ -3028,13 +3104,22 @@ todo_wine {
hr = IMFTransform_GetOutputCurrentType(transform, 0, &media_type); ok(hr == S_OK, "Failed to get transform output type, hr %#lx.\n", hr); - hr = IMFMediaType_Compare(output_type, (IMFAttributes *)media_type, MF_ATTRIBUTES_MATCH_OUR_ITEMS, &ret); ok(hr == S_OK, "Failed to compare media types, hr %#lx.\n", hr); ok(ret, "Output type of last transform doesn't match sink node type.\n"); + IMFMediaType_Release(media_type);
- IMFTopologyNode_Release(mft_node); + hr = IMFTransform_GetInputCurrentType(transform, 0, &media_type); + ok(hr == S_OK, "Failed to get transform input type, hr %#lx.\n", hr); + if ((test->flags & (LOADER_EXPECTED_CONVERTER | LOADER_EXPECTED_DECODER)) != (LOADER_EXPECTED_CONVERTER | LOADER_EXPECTED_DECODER)) + { + hr = IMFMediaType_Compare(input_type, (IMFAttributes *)media_type, MF_ATTRIBUTES_MATCH_OUR_ITEMS, &ret); + ok(hr == S_OK, "Failed to compare media types, hr %#lx.\n", hr); + ok(ret, "Input type of transform doesn't match source node type.\n"); + } IMFMediaType_Release(media_type); + + IMFTopologyNode_Release(mft_node); IMFTransform_Release(transform); }
From: R��mi Bernon rbernon@codeweavers.com
--- dlls/mf/tests/mf.c | 357 ++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 349 insertions(+), 8 deletions(-)
diff --git a/dlls/mf/tests/mf.c b/dlls/mf/tests/mf.c index 7937351eb4a..35ccde2f9cb 100644 --- a/dlls/mf/tests/mf.c +++ b/dlls/mf/tests/mf.c @@ -1637,7 +1637,13 @@ static HRESULT WINAPI test_handler_GetCurrentMediaType(IMFMediaTypeHandler *ifac HRESULT hr;
if (!impl->current_type) - return impl->media_types ? MF_E_NOT_INITIALIZED : E_FAIL; + { + if (!impl->media_types) + return E_FAIL; + if (!impl->media_types_count) + return MF_E_TRANSFORM_TYPE_NOT_SET; + return MF_E_NOT_INITIALIZED; + }
if (FAILED(hr = MFCreateMediaType(media_type))) return hr; @@ -1670,10 +1676,120 @@ static const IMFMediaTypeHandlerVtbl test_handler_vtbl =
static const struct test_handler test_handler = {.IMFMediaTypeHandler_iface.lpVtbl = &test_handler_vtbl};
+struct test_media_sink +{ + IMFMediaSink IMFMediaSink_iface; + BOOL shutdown; +}; + +static struct test_media_sink *impl_from_IMFMediaSink(IMFMediaSink *iface) +{ + return CONTAINING_RECORD(iface, struct test_media_sink, IMFMediaSink_iface); +} + +static HRESULT WINAPI test_media_sink_QueryInterface(IMFMediaSink *iface, REFIID riid, void **obj) +{ + if (IsEqualIID(riid, &IID_IMFMediaSink) + || IsEqualIID(riid, &IID_IUnknown)) + { + IMFMediaSink_AddRef((*obj = iface)); + return S_OK; + } + + *obj = NULL; + return E_NOINTERFACE; +} + +static ULONG WINAPI test_media_sink_AddRef(IMFMediaSink *iface) +{ + return 2; +} + +static ULONG WINAPI test_media_sink_Release(IMFMediaSink *iface) +{ + return 1; +} + +static HRESULT WINAPI test_media_sink_GetCharacteristics(IMFMediaSink *iface, DWORD *characteristics) +{ + *characteristics = 0; + return S_OK; +} + +static HRESULT WINAPI test_media_sink_AddStreamSink(IMFMediaSink *iface, + DWORD stream_sink_id, IMFMediaType *media_type, IMFStreamSink **stream_sink) +{ + ok(0, "Unexpected call.\n"); + return E_NOTIMPL; +} + +static HRESULT WINAPI test_media_sink_RemoveStreamSink(IMFMediaSink *iface, DWORD stream_sink_id) +{ + ok(0, "Unexpected call.\n"); + return E_NOTIMPL; +} + +static HRESULT WINAPI test_media_sink_GetStreamSinkCount(IMFMediaSink *iface, DWORD *count) +{ + ok(0, "Unexpected call.\n"); + return E_NOTIMPL; +} + +static HRESULT WINAPI test_media_sink_GetStreamSinkByIndex(IMFMediaSink *iface, DWORD index, IMFStreamSink **sink) +{ + ok(0, "Unexpected call.\n"); + return E_NOTIMPL; +} + +static HRESULT WINAPI test_media_sink_GetStreamSinkById(IMFMediaSink *iface, DWORD stream_sink_id, IMFStreamSink **sink) +{ + ok(0, "Unexpected call.\n"); + return E_NOTIMPL; +} + +static HRESULT WINAPI test_media_sink_SetPresentationClock(IMFMediaSink *iface, IMFPresentationClock *clock) +{ + ok(0, "Unexpected call.\n"); + return E_NOTIMPL; +} + +static HRESULT WINAPI test_media_sink_GetPresentationClock(IMFMediaSink *iface, IMFPresentationClock **clock) +{ + ok(0, "Unexpected call.\n"); + return E_NOTIMPL; +} + +static HRESULT WINAPI test_media_sink_Shutdown(IMFMediaSink *iface) +{ + struct test_media_sink *sink = impl_from_IMFMediaSink(iface); + ok(!sink->shutdown, "Unexpected call.\n"); + sink->shutdown = TRUE; + return S_OK; +} + +static const IMFMediaSinkVtbl test_media_sink_vtbl = +{ + test_media_sink_QueryInterface, + test_media_sink_AddRef, + test_media_sink_Release, + test_media_sink_GetCharacteristics, + test_media_sink_AddStreamSink, + test_media_sink_RemoveStreamSink, + test_media_sink_GetStreamSinkCount, + test_media_sink_GetStreamSinkByIndex, + test_media_sink_GetStreamSinkById, + test_media_sink_SetPresentationClock, + test_media_sink_GetPresentationClock, + test_media_sink_Shutdown, +}; + +static const struct test_media_sink test_media_sink = {.IMFMediaSink_iface.lpVtbl = &test_media_sink_vtbl}; + struct test_stream_sink { IMFStreamSink IMFStreamSink_iface; IMFMediaTypeHandler *handler; + IMFMediaSink *media_sink; };
static struct test_stream_sink *impl_from_IMFStreamSink(IMFStreamSink *iface) @@ -1733,6 +1849,14 @@ static HRESULT WINAPI test_stream_sink_QueueEvent(IMFStreamSink *iface, MediaEve
static HRESULT WINAPI test_stream_sink_GetMediaSink(IMFStreamSink *iface, IMFMediaSink **sink) { + struct test_stream_sink *impl = impl_from_IMFStreamSink(iface); + + if (impl->media_sink) + { + IMFMediaSink_AddRef((*sink = impl->media_sink)); + return S_OK; + } + todo_wine ok(0, "Unexpected call.\n"); return E_NOTIMPL; @@ -1939,24 +2063,35 @@ static HRESULT wait_media_event_(int line, IMFMediaSession *session, IMFAsyncCal
static void test_media_session_events(void) { - static const media_type_desc audio_pcm_44100 = + static const media_type_desc audio_float_44100 = { ATTR_GUID(MF_MT_MAJOR_TYPE, MFMediaType_Audio), - ATTR_GUID(MF_MT_SUBTYPE, MFAudioFormat_PCM), + ATTR_GUID(MF_MT_SUBTYPE, MFAudioFormat_Float), ATTR_UINT32(MF_MT_AUDIO_NUM_CHANNELS, 1), + ATTR_UINT32(MF_MT_AUDIO_BLOCK_ALIGNMENT, 4), ATTR_UINT32(MF_MT_AUDIO_SAMPLES_PER_SECOND, 44100), - ATTR_UINT32(MF_MT_AUDIO_AVG_BYTES_PER_SECOND, 44100), - ATTR_UINT32(MF_MT_AUDIO_BLOCK_ALIGNMENT, 1), - ATTR_UINT32(MF_MT_AUDIO_BITS_PER_SAMPLE, 8), + ATTR_UINT32(MF_MT_AUDIO_AVG_BYTES_PER_SECOND, 4 * 44100), + ATTR_UINT32(MF_MT_AUDIO_BITS_PER_SAMPLE, 4 * 8), + }; + static const media_type_desc audio_pcm_48000 = + { + ATTR_GUID(MF_MT_MAJOR_TYPE, MFMediaType_Audio), + ATTR_GUID(MF_MT_SUBTYPE, MFAudioFormat_PCM), + ATTR_UINT32(MF_MT_AUDIO_NUM_CHANNELS, 1), + ATTR_UINT32(MF_MT_AUDIO_BLOCK_ALIGNMENT, 2), + ATTR_UINT32(MF_MT_AUDIO_SAMPLES_PER_SECOND, 48000), + ATTR_UINT32(MF_MT_AUDIO_AVG_BYTES_PER_SECOND, 2 * 48000), + ATTR_UINT32(MF_MT_AUDIO_BITS_PER_SAMPLE, 2 * 8), };
struct test_stream_sink stream_sink = test_stream_sink; + struct test_media_sink media_sink = test_media_sink; struct test_handler handler = test_handler; IMFAsyncCallback *callback, *callback2; + IMFMediaType *input_type, *output_type; IMFTopologyNode *src_node, *sink_node; IMFPresentationDescriptor *pd; IMFMediaSession *session; - IMFMediaType *input_type; IMFStreamDescriptor *sd; IMFAsyncResult *result; IMFMediaSource *source; @@ -1967,6 +2102,7 @@ static void test_media_session_events(void) ULONG ref;
stream_sink.handler = &handler.IMFMediaTypeHandler_iface; + stream_sink.media_sink = &media_sink.IMFMediaSink_iface;
hr = MFStartup(MF_VERSION, MFSTARTUP_FULL); ok(hr == S_OK, "Startup failure, hr %#lx.\n", hr); @@ -2089,13 +2225,19 @@ static void test_media_session_events(void)
hr = MFCreateMediaType(&input_type); ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); - init_media_type(input_type, audio_pcm_44100, -1); + init_media_type(input_type, audio_float_44100, -1); create_descriptors(1, &input_type, NULL, &pd, &sd);
hr = MFCreateTopologyNode(MF_TOPOLOGY_OUTPUT_NODE, &sink_node); ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); init_sink_node(&stream_sink.IMFStreamSink_iface, -1, sink_node);
+ hr = MFCreateMediaType(&output_type); + ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); + init_media_type(output_type, audio_pcm_48000, -1); + handler.media_types_count = 1; + handler.media_types = &output_type; + hr = MFCreateTopologyNode(MF_TOPOLOGY_SOURCESTREAM_NODE, &src_node); ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); init_source_node(NULL, -1, src_node, pd, sd); @@ -2117,6 +2259,7 @@ static void test_media_session_events(void) hr = wait_media_event(session, callback, MESessionTopologySet, 1000, &propvar); ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); PropVariantClear(&propvar); + handler.enum_count = handler.set_current_count = 0; }
source = create_test_source(pd); @@ -2130,6 +2273,7 @@ static void test_media_session_events(void) hr = wait_media_event(session, callback, MESessionTopologySet, 1000, &propvar); ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); PropVariantClear(&propvar); + handler.enum_count = handler.set_current_count = 0; }
hr = IMFMediaSession_ClearTopologies(session); @@ -2140,9 +2284,206 @@ static void test_media_session_events(void)
hr = IMFMediaSession_Shutdown(session); ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); + todo_wine + ok(!media_sink.shutdown, "media sink is shutdown.\n"); + media_sink.shutdown = FALSE; + + /* sometimes briefly leaking */ + IMFMediaSession_Release(session); + + if (handler.current_type) + IMFMediaType_Release(handler.current_type); + handler.current_type = NULL; + + + /* SetTopology without a current output type */ + + hr = MFCreateMediaSession(NULL, &session); + ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); + + IMFPresentationDescriptor_SelectStream(pd, 0); + + hr = IMFMediaSession_SetTopology(session, MFSESSION_SETTOPOLOGY_NORESOLUTION, topology); + ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); + hr = wait_media_event(session, callback, MESessionTopologySet, 1000, &propvar); + ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); + ok(propvar.vt == VT_UNKNOWN, "got vt %u\n", propvar.vt); + ok(propvar.punkVal == (IUnknown *)topology, "got punkVal %p\n", propvar.punkVal); + PropVariantClear(&propvar); + + ok(!handler.enum_count, "got %lu GetMediaTypeByIndex\n", handler.enum_count); + ok(!handler.set_current_count, "got %lu SetCurrentMediaType\n", handler.set_current_count); + handler.enum_count = handler.set_current_count = 0; + + hr = IMFMediaSession_ClearTopologies(session); + ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); + hr = wait_media_event(session, callback, MESessionTopologiesCleared, 1000, &propvar); + ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); + ok(propvar.vt == VT_EMPTY, "got vt %u\n", propvar.vt); + + hr = IMFMediaSession_Shutdown(session); + ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); + ok(media_sink.shutdown, "media sink didn't shutdown.\n"); + media_sink.shutdown = FALSE; + + /* sometimes briefly leaking */ + IMFMediaSession_Release(session); + + if (handler.current_type) + IMFMediaType_Release(handler.current_type); + handler.current_type = NULL; + + + /* SetTopology without a current output type */ + + hr = MFCreateMediaSession(NULL, &session); + ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); + + hr = IMFMediaSession_SetTopology(session, 0, topology); + ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); + hr = wait_media_event(session, callback, MESessionTopologySet, 1000, &propvar); + ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); + ok(propvar.vt == VT_UNKNOWN, "got vt %u\n", propvar.vt); + ok(propvar.punkVal != (IUnknown *)topology, "got punkVal %p\n", propvar.punkVal); + PropVariantClear(&propvar); + + todo_wine + ok(!handler.enum_count, "got %lu GetMediaTypeByIndex\n", handler.enum_count); + ok(handler.set_current_count, "got %lu SetCurrentMediaType\n", handler.set_current_count); + handler.enum_count = handler.set_current_count = 0; + + hr = IMFMediaSession_ClearTopologies(session); + ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); + hr = wait_media_event(session, callback, MESessionTopologiesCleared, 1000, &propvar); + ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); + ok(propvar.vt == VT_EMPTY, "got vt %u\n", propvar.vt); + + hr = IMFMediaSession_Shutdown(session); + ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); + ok(media_sink.shutdown, "media sink didn't shutdown.\n"); + media_sink.shutdown = FALSE; + + /* sometimes briefly leaking */ + IMFMediaSession_Release(session); + + if (handler.current_type) + IMFMediaType_Release(handler.current_type); + handler.current_type = NULL; + + + /* SetTopology without a current output type, refusing input type */ + + handler.invalid_type = input_type; + + hr = MFCreateMediaSession(NULL, &session); + ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); + + hr = IMFMediaSession_SetTopology(session, 0, topology); + ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); + hr = wait_media_event(session, callback, MESessionTopologySet, 1000, &propvar); + ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); + ok(propvar.vt == VT_UNKNOWN, "got vt %u\n", propvar.vt); + ok(propvar.punkVal != (IUnknown *)topology, "got punkVal %p\n", propvar.punkVal); + PropVariantClear(&propvar); + + ok(handler.enum_count, "got %lu GetMediaTypeByIndex\n", handler.enum_count); + todo_wine + ok(handler.set_current_count, "got %lu SetCurrentMediaType\n", handler.set_current_count); + handler.enum_count = handler.set_current_count = 0; + + hr = IMFMediaSession_ClearTopologies(session); + ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); + hr = wait_media_event(session, callback, MESessionTopologiesCleared, 1000, &propvar); + ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); + ok(propvar.vt == VT_EMPTY, "got vt %u\n", propvar.vt); + + hr = IMFMediaSession_Shutdown(session); + ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); + ok(media_sink.shutdown, "media sink didn't shutdown.\n"); + media_sink.shutdown = FALSE; + + /* sometimes briefly leaking */ + IMFMediaSession_Release(session); + + if (handler.current_type) + IMFMediaType_Release(handler.current_type); + handler.current_type = NULL; + + + /* SetTopology without a current output type, refusing input type, requiring a converter */ + + handler.media_types_count = 0; + handler.invalid_type = input_type; + + hr = MFCreateMediaSession(NULL, &session); + ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); + + hr = IMFMediaSession_SetTopology(session, 0, topology); + ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); + hr = wait_media_event(session, callback, MESessionTopologySet, 1000, &propvar); + ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); + ok(propvar.vt == VT_UNKNOWN, "got vt %u\n", propvar.vt); + ok(propvar.punkVal != (IUnknown *)topology, "got punkVal %p\n", propvar.punkVal); + PropVariantClear(&propvar); + + ok(!handler.enum_count, "got %lu GetMediaTypeByIndex\n", handler.enum_count); + ok(handler.set_current_count, "got %lu SetCurrentMediaType\n", handler.set_current_count); + handler.enum_count = handler.set_current_count = 0; + + hr = IMFMediaSession_ClearTopologies(session); + ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); + hr = wait_media_event(session, callback, MESessionTopologiesCleared, 1000, &propvar); + ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); + ok(propvar.vt == VT_EMPTY, "got vt %u\n", propvar.vt); + + hr = IMFMediaSession_Shutdown(session); + ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); + ok(media_sink.shutdown, "media sink didn't shutdown.\n"); + media_sink.shutdown = FALSE;
/* sometimes briefly leaking */ IMFMediaSession_Release(session); + + if (handler.current_type) + IMFMediaType_Release(handler.current_type); + handler.current_type = NULL; + + + /* SetTopology with a current output type */ + + handler.media_types_count = 1; + IMFMediaType_AddRef((handler.current_type = output_type)); + + hr = MFCreateMediaSession(NULL, &session); + ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); + + hr = IMFMediaSession_SetTopology(session, 0, topology); + ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); + hr = wait_media_event(session, callback, MESessionTopologySet, 1000, &propvar); + ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); + ok(propvar.vt == VT_UNKNOWN, "got vt %u\n", propvar.vt); + ok(propvar.punkVal != (IUnknown *)topology, "got punkVal %p\n", propvar.punkVal); + PropVariantClear(&propvar); + + ok(!handler.enum_count, "got %lu GetMediaTypeByIndex\n", handler.enum_count); + todo_wine + ok(handler.set_current_count, "got %lu SetCurrentMediaType\n", handler.set_current_count); + handler.enum_count = handler.set_current_count = 0; + + hr = IMFMediaSession_ClearTopologies(session); + ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); + hr = wait_media_event(session, callback, MESessionTopologiesCleared, 1000, &propvar); + ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); + ok(propvar.vt == VT_EMPTY, "got vt %u\n", propvar.vt); + + hr = IMFMediaSession_Shutdown(session); + ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); + ok(media_sink.shutdown, "media sink didn't shutdown.\n"); + media_sink.shutdown = FALSE; + + /* sometimes briefly leaking */ + IMFMediaSession_Release(session); + IMFAsyncCallback_Release(callback);
if (handler.current_type)
I only included the tests for now, it's getting long and I have a few additional patches for fixes.
This merge request was approved by Nikolay Sivov.