-- v2: mf: Initialize output media types when binding session output nodes. mf/tests: Test that IMFMediaSession_SetTopology should set 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 | 127 +++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 127 insertions(+)
diff --git a/dlls/mf/tests/mf.c b/dlls/mf/tests/mf.c index 36ef586267e..5717d7b04bb 100644 --- a/dlls/mf/tests/mf.c +++ b/dlls/mf/tests/mf.c @@ -1932,12 +1932,32 @@ 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), + }; + IMFAsyncCallback *callback, *callback2; + IMFTopologyNode *src_node, *sink_node; + IMFTopology *topology, *full_topology; + IMFPresentationDescriptor *pd; + IMFStreamSink *stream_sink; IMFMediaSession *session; + IMFMediaType *input_type; + IMFMediaSink *media_sink; + IMFStreamDescriptor *sd; IMFAsyncResult *result; + IMFMediaSource *source; IMFMediaEvent *event; PROPVARIANT propvar; HRESULT hr; + ULONG ref;
hr = MFStartup(MF_VERSION, MFSTARTUP_FULL); ok(hr == S_OK, "Startup failure, hr %#lx.\n", hr); @@ -2051,10 +2071,117 @@ 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 = MFCreateTopologyNode(MF_TOPOLOGY_OUTPUT_NODE, &sink_node); + ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); + hr = MFCreateAudioRenderer(NULL, &media_sink); + ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); + hr = IMFMediaSink_GetStreamSinkByIndex(media_sink, 0, &stream_sink); + ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); + init_sink_node(stream_sink, -1, sink_node); + + 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_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); + } + + IMFPresentationDescriptor_SelectStream(pd, 0); + + 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); + hr = IUnknown_QueryInterface(propvar.punkVal, &IID_IMFTopology, (void **)&full_topology); + 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);
+ /* Windows requires this to avoid leaking source */ + hr = IMFTopology_Clear(full_topology); + ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); + ref = IMFTopology_Release(full_topology); + ok(ref == 0, "Release returned %ld\n", ref); + + 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 = IMFMediaSink_Release(media_sink); + todo_wine + ok(ref == 0, "Release returned %ld\n", ref); + ref = IMFStreamSink_Release(stream_sink); + 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 | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-)
diff --git a/dlls/mf/tests/mf.c b/dlls/mf/tests/mf.c index 5717d7b04bb..c8232bd543a 100644 --- a/dlls/mf/tests/mf.c +++ b/dlls/mf/tests/mf.c @@ -1944,12 +1944,13 @@ static void test_media_session_events(void) };
IMFAsyncCallback *callback, *callback2; + IMFMediaType *input_type, *media_type; IMFTopologyNode *src_node, *sink_node; IMFTopology *topology, *full_topology; IMFPresentationDescriptor *pd; + IMFMediaTypeHandler *handler; IMFStreamSink *stream_sink; IMFMediaSession *session; - IMFMediaType *input_type; IMFMediaSink *media_sink; IMFStreamDescriptor *sd; IMFAsyncResult *result; @@ -2129,6 +2130,11 @@ static void test_media_session_events(void)
IMFPresentationDescriptor_SelectStream(pd, 0);
+ hr = IMFStreamSink_GetMediaTypeHandler(stream_sink, &handler); + ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); + hr = IMFMediaTypeHandler_GetCurrentMediaType(handler, &media_type); + ok(hr == MF_E_NOT_INITIALIZED, "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); @@ -2139,6 +2145,12 @@ static void test_media_session_events(void) ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); PropVariantClear(&propvar);
+ hr = IMFMediaTypeHandler_GetCurrentMediaType(handler, &media_type); + todo_wine + ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); + IMFMediaTypeHandler_Release(handler); + if (hr == S_OK) IMFMediaType_Release(media_type); + hr = IMFMediaSession_ClearTopologies(session); ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); hr = wait_media_event(session, callback, MESessionTopologiesCleared, 1000, &propvar);
From: R��mi Bernon rbernon@codeweavers.com
--- dlls/mf/session.c | 21 +++++++++++++++++++++ dlls/mf/tests/mf.c | 5 +++-- 2 files changed, 24 insertions(+), 2 deletions(-)
diff --git a/dlls/mf/session.c b/dlls/mf/session.c index 87fe77a730f..18952fb1f6e 100644 --- a/dlls/mf/session.c +++ b/dlls/mf/session.c @@ -592,7 +592,28 @@ static HRESULT session_bind_output_nodes(IMFTopology *topology) }
if (stream_sink) + { + IMFMediaTypeHandler *handler; + + if (SUCCEEDED(hr = IMFStreamSink_GetMediaTypeHandler(stream_sink, &handler))) + { + IMFMediaType *type; + + if (SUCCEEDED(hr = IMFMediaTypeHandler_GetCurrentMediaType(handler, &type))) + IMFMediaType_Release(type); + else if (hr == MF_E_NOT_INITIALIZED) + { + for (i = 0; FAILED(hr) && SUCCEEDED(hr = IMFMediaTypeHandler_GetMediaTypeByIndex(handler, i, &type)); ++i) + { + hr = IMFMediaTypeHandler_SetCurrentMediaType(handler, type); + IMFMediaType_Release(type); + } + } + + IMFMediaTypeHandler_Release(handler); + } IMFStreamSink_Release(stream_sink); + } IUnknown_Release(object); }
diff --git a/dlls/mf/tests/mf.c b/dlls/mf/tests/mf.c index c8232bd543a..e603aa8ce60 100644 --- a/dlls/mf/tests/mf.c +++ b/dlls/mf/tests/mf.c @@ -2133,6 +2133,7 @@ static void test_media_session_events(void) hr = IMFStreamSink_GetMediaTypeHandler(stream_sink, &handler); ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); hr = IMFMediaTypeHandler_GetCurrentMediaType(handler, &media_type); + todo_wine ok(hr == MF_E_NOT_INITIALIZED, "Unexpected hr %#lx.\n", hr);
hr = IMFMediaSession_SetTopology(session, 0, topology); @@ -2146,10 +2147,9 @@ static void test_media_session_events(void) PropVariantClear(&propvar);
hr = IMFMediaTypeHandler_GetCurrentMediaType(handler, &media_type); - todo_wine ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); IMFMediaTypeHandler_Release(handler); - if (hr == S_OK) IMFMediaType_Release(media_type); + IMFMediaType_Release(media_type);
hr = IMFMediaSession_ClearTopologies(session); ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); @@ -2183,6 +2183,7 @@ static void test_media_session_events(void) todo_wine ok(ref == 0, "Release returned %ld\n", ref); ref = IMFStreamSink_Release(stream_sink); + todo_wine ok(ref == 0, "Release returned %ld\n", ref);
ref = IMFMediaSource_Release(source);
v2: Fix the test failure, initializing propvar before first use. Fix typo in commit title.
Do we have tests that show that loader does not set the types? Calling SetTopology(0) invokes the loader, it's not immediately clear which part does initialization. Does MFSESSION_SETTOPOLOGY_NORESOLUTION also set the types? Another variant is setting with zero flags, but with MF_TOPOLOGY_RESOLUTION_STATUS set to "resolved".
Setting first accepted type is weird, because it could easily cause mismatched types with upstream node, but if that's what it does..