[PATCH v2 3/5] qasf/dmowrapper: Implement source connection.
Zebediah Figura
z.figura12 at gmail.com
Tue Feb 18 23:19:09 CST 2020
Signed-off-by: Zebediah Figura <zfigura at codeweavers.com>
---
dlls/qasf/dmowrapper.c | 46 +++++++
dlls/qasf/tests/dmowrapper.c | 240 ++++++++++++++++++++++++++++++++++-
dlls/strmbase/pin.c | 3 +
include/wine/strmbase.h | 2 +
4 files changed, 285 insertions(+), 6 deletions(-)
diff --git a/dlls/qasf/dmowrapper.c b/dlls/qasf/dmowrapper.c
index 28d8e82175c..7a18d0ba079 100644
--- a/dlls/qasf/dmowrapper.c
+++ b/dlls/qasf/dmowrapper.c
@@ -166,10 +166,56 @@ static HRESULT dmo_wrapper_source_get_media_type(struct strmbase_pin *iface, uns
return hr == S_OK ? S_OK : VFW_S_NO_MORE_ITEMS;
}
+static HRESULT WINAPI dmo_wrapper_source_DecideBufferSize(struct strmbase_source *iface,
+ IMemAllocator *allocator, ALLOCATOR_PROPERTIES *props)
+{
+ struct dmo_wrapper *filter = impl_from_strmbase_filter(iface->pin.filter);
+ DWORD index = impl_source_from_strmbase_pin(&iface->pin) - filter->sources;
+ ALLOCATOR_PROPERTIES ret_props;
+ DWORD size = 0, alignment = 0;
+ IMediaObject *dmo;
+ HRESULT hr;
+
+ IUnknown_QueryInterface(filter->dmo, &IID_IMediaObject, (void **)&dmo);
+
+ if (SUCCEEDED(hr = IMediaObject_SetOutputType(dmo, index,
+ (const DMO_MEDIA_TYPE *)&iface->pin.mt, 0)))
+ hr = IMediaObject_GetOutputSizeInfo(dmo, index, &size, &alignment);
+
+ if (SUCCEEDED(hr))
+ {
+ props->cBuffers = max(props->cBuffers, 1);
+ props->cbBuffer = max(max(props->cbBuffer, size), 16384);
+ props->cbAlign = max(props->cbAlign, alignment);
+ hr = IMemAllocator_SetProperties(allocator, props, &ret_props);
+ }
+
+ IMediaObject_Release(dmo);
+
+ return hr;
+}
+
+static void dmo_wrapper_source_disconnect(struct strmbase_source *iface)
+{
+ struct dmo_wrapper *filter = impl_from_strmbase_filter(iface->pin.filter);
+ IMediaObject *dmo;
+
+ IUnknown_QueryInterface(filter->dmo, &IID_IMediaObject, (void **)&dmo);
+
+ IMediaObject_SetOutputType(dmo, impl_source_from_strmbase_pin(&iface->pin) - filter->sources,
+ NULL, DMO_SET_TYPEF_CLEAR);
+
+ IMediaObject_Release(dmo);
+}
+
static const struct strmbase_source_ops source_ops =
{
.base.pin_query_accept = dmo_wrapper_source_query_accept,
.base.pin_get_media_type = dmo_wrapper_source_get_media_type,
+ .pfnAttemptConnection = BaseOutputPinImpl_AttemptConnection,
+ .pfnDecideAllocator = BaseOutputPinImpl_DecideAllocator,
+ .pfnDecideBufferSize = dmo_wrapper_source_DecideBufferSize,
+ .source_disconnect = dmo_wrapper_source_disconnect,
};
static inline struct dmo_wrapper *impl_from_IDMOWrapperFilter(IDMOWrapperFilter *iface)
diff --git a/dlls/qasf/tests/dmowrapper.c b/dlls/qasf/tests/dmowrapper.c
index 641fa689042..dbb9d9d17f3 100644
--- a/dlls/qasf/tests/dmowrapper.c
+++ b/dlls/qasf/tests/dmowrapper.c
@@ -61,10 +61,13 @@ static const IMediaObjectVtbl dmo_vtbl;
static IMediaObject testdmo = {&dmo_vtbl};
static IUnknown *testdmo_outer_unk;
static LONG testdmo_refcount = 1;
-static AM_MEDIA_TYPE testdmo_input_mt;
-static BOOL testdmo_input_mt_set;
+static AM_MEDIA_TYPE testdmo_input_mt, testdmo_output_mt;
+static BOOL testdmo_input_mt_set, testdmo_output_mt_set;
static HRESULT testdmo_GetInputSizeInfo_hr = E_NOTIMPL;
+static HRESULT testdmo_GetOutputSizeInfo_hr = S_OK;
+static DWORD testdmo_output_size = 123;
+static DWORD testdmo_output_alignment = 1;
static HRESULT WINAPI dmo_inner_QueryInterface(IUnknown *iface, REFIID iid, void **out)
{
@@ -183,6 +186,13 @@ static HRESULT WINAPI dmo_SetOutputType(IMediaObject *iface, DWORD index, const
strmbase_dump_media_type((AM_MEDIA_TYPE *)type);
if (flags & DMO_SET_TYPEF_TEST_ONLY)
return type->lSampleSize == 321 ? S_OK : S_FALSE;
+ if (flags & DMO_SET_TYPEF_CLEAR)
+ {
+ testdmo_output_mt_set = FALSE;
+ return S_OK;
+ }
+ MoCopyMediaType((DMO_MEDIA_TYPE *)&testdmo_output_mt, type);
+ testdmo_output_mt_set = TRUE;
return S_OK;
}
@@ -210,8 +220,10 @@ static HRESULT WINAPI dmo_GetInputSizeInfo(IMediaObject *iface, DWORD index,
static HRESULT WINAPI dmo_GetOutputSizeInfo(IMediaObject *iface, DWORD index, DWORD *size, DWORD *alignment)
{
- ok(0, "Unexpected call.\n");
- return E_NOTIMPL;
+ if (winetest_debug > 1) trace("GetOutputSizeInfo(%u)\n", index);
+ *size = testdmo_output_size;
+ *alignment = testdmo_output_alignment;
+ return testdmo_GetOutputSizeInfo_hr;
}
static HRESULT WINAPI dmo_GetInputMaxLatency(IMediaObject *iface, DWORD index, REFERENCE_TIME *latency)
@@ -1137,6 +1149,71 @@ static void test_sink_allocator(IMemInputPin *input)
IMemAllocator_Release(ret_allocator);
}
+static void test_source_allocator(IFilterGraph2 *graph, IPin *source, struct testfilter *testsink)
+{
+ ALLOCATOR_PROPERTIES props, req_props = {2, 30000, 32, 0};
+ IMemAllocator *allocator;
+ HRESULT hr;
+
+ hr = IFilterGraph2_ConnectDirect(graph, source, &testsink->sink.pin.IPin_iface, &mt2);
+ ok(hr == S_OK, "Got hr %#x.\n", hr);
+
+ ok(!!testsink->sink.pAllocator, "Expected an allocator.\n");
+ hr = IMemAllocator_GetProperties(testsink->sink.pAllocator, &props);
+ ok(hr == S_OK, "Got hr %#x.\n", hr);
+ ok(props.cBuffers == 1, "Got %d buffers.\n", props.cBuffers);
+ ok(props.cbBuffer == 16384, "Got size %d.\n", props.cbBuffer);
+ ok(props.cbAlign == 1, "Got alignment %d.\n", props.cbAlign);
+ ok(!props.cbPrefix, "Got prefix %d.\n", props.cbPrefix);
+
+ IFilterGraph2_Disconnect(graph, source);
+ IFilterGraph2_Disconnect(graph, &testsink->sink.pin.IPin_iface);
+
+ testdmo_output_alignment = 16;
+ testdmo_output_size = 20000;
+
+ hr = IFilterGraph2_ConnectDirect(graph, source, &testsink->sink.pin.IPin_iface, &mt2);
+ ok(hr == S_OK, "Got hr %#x.\n", hr);
+
+ ok(!!testsink->sink.pAllocator, "Expected an allocator.\n");
+ hr = IMemAllocator_GetProperties(testsink->sink.pAllocator, &props);
+ ok(hr == S_OK, "Got hr %#x.\n", hr);
+ ok(props.cBuffers == 1, "Got %d buffers.\n", props.cBuffers);
+ ok(props.cbBuffer == 20000, "Got size %d.\n", props.cbBuffer);
+ ok(props.cbAlign == 16, "Got alignment %d.\n", props.cbAlign);
+ ok(!props.cbPrefix, "Got prefix %d.\n", props.cbPrefix);
+
+ IFilterGraph2_Disconnect(graph, source);
+ IFilterGraph2_Disconnect(graph, &testsink->sink.pin.IPin_iface);
+
+ testdmo_GetOutputSizeInfo_hr = E_NOTIMPL;
+ hr = IFilterGraph2_ConnectDirect(graph, source, &testsink->sink.pin.IPin_iface, &mt2);
+ ok(hr == E_NOTIMPL, "Got hr %#x.\n", hr);
+ testdmo_GetOutputSizeInfo_hr = S_OK;
+
+ CoCreateInstance(&CLSID_MemoryAllocator, NULL, CLSCTX_INPROC_SERVER,
+ &IID_IMemAllocator, (void **)&allocator);
+ testsink->sink.pAllocator = allocator;
+
+ hr = IMemAllocator_SetProperties(allocator, &req_props, &props);
+ ok(hr == S_OK, "Got hr %#x.\n", hr);
+
+ hr = IFilterGraph2_ConnectDirect(graph, source, &testsink->sink.pin.IPin_iface, &mt2);
+ ok(hr == S_OK, "Got hr %#x.\n", hr);
+
+ ok(testsink->sink.pAllocator == allocator, "Expected an allocator.\n");
+ hr = IMemAllocator_GetProperties(testsink->sink.pAllocator, &props);
+ ok(hr == S_OK, "Got hr %#x.\n", hr);
+ ok(props.cBuffers == 1, "Got %d buffers.\n", props.cBuffers);
+ ok(props.cbBuffer == 20000, "Got size %d.\n", props.cbBuffer);
+ ok(props.cbAlign == 16, "Got alignment %d.\n", props.cbAlign);
+ ok(!props.cbPrefix, "Got prefix %d.\n", props.cbPrefix);
+
+ IFilterGraph2_Disconnect(graph, source);
+ IFilterGraph2_Disconnect(graph, &testsink->sink.pin.IPin_iface);
+
+}
+
static void test_connect_pin(void)
{
AM_MEDIA_TYPE req_mt =
@@ -1146,20 +1223,23 @@ static void test_connect_pin(void)
.formattype = FORMAT_None,
};
IBaseFilter *filter = create_dmo_wrapper();
- struct testfilter testsource;
+ struct testfilter testsource, testsink;
+ IPin *sink, *source, *peer;
IMemInputPin *meminput;
IFilterGraph2 *graph;
- IPin *sink, *peer;
AM_MEDIA_TYPE mt;
HRESULT hr;
ULONG ref;
testfilter_init(&testsource);
+ testfilter_init(&testsink);
CoCreateInstance(&CLSID_FilterGraph, NULL, CLSCTX_INPROC_SERVER,
&IID_IFilterGraph2, (void **)&graph);
IFilterGraph2_AddFilter(graph, &testsource.filter.IBaseFilter_iface, L"source");
+ IFilterGraph2_AddFilter(graph, &testsink.filter.IBaseFilter_iface, L"sink");
IFilterGraph2_AddFilter(graph, filter, L"DMO wrapper");
IBaseFilter_FindPin(filter, L"in0", &sink);
+ IBaseFilter_FindPin(filter, L"out0", &source);
IPin_QueryInterface(sink, &IID_IMemInputPin, (void **)&meminput);
/* Test sink connection. */
@@ -1194,6 +1274,149 @@ static void test_connect_pin(void)
test_sink_allocator(meminput);
+ /* Test source connection. */
+ peer = (IPin *)0xdeadbeef;
+ hr = IPin_ConnectedTo(source, &peer);
+ ok(hr == VFW_E_NOT_CONNECTED, "Got hr %#x.\n", hr);
+ ok(!peer, "Got peer %p.\n", peer);
+
+ hr = IPin_ConnectionMediaType(source, &mt);
+ ok(hr == VFW_E_NOT_CONNECTED, "Got hr %#x.\n", hr);
+
+ ok(!testdmo_output_mt_set, "Output type should not be set.\n");
+
+ /* Exact connection. */
+
+ req_mt = mt2;
+ hr = IFilterGraph2_ConnectDirect(graph, source, &testsink.sink.pin.IPin_iface, &req_mt);
+ ok(hr == S_OK, "Got hr %#x.\n", hr);
+
+ hr = IPin_ConnectedTo(source, &peer);
+ ok(hr == S_OK, "Got hr %#x.\n", hr);
+ ok(peer == &testsink.sink.pin.IPin_iface, "Got peer %p.\n", peer);
+ IPin_Release(peer);
+
+ hr = IPin_ConnectionMediaType(source, &mt);
+ ok(hr == S_OK, "Got hr %#x.\n", hr);
+ ok(compare_media_types(&mt, &req_mt), "Media types didn't match.\n");
+
+ ok(testdmo_output_mt_set, "Ouput type should be set.\n");
+ ok(compare_media_types(&testdmo_output_mt, &req_mt), "Media types didn't match.\n");
+
+ hr = IFilterGraph2_Disconnect(graph, source);
+ ok(hr == S_OK, "Got hr %#x.\n", hr);
+ hr = IFilterGraph2_Disconnect(graph, source);
+ ok(hr == S_FALSE, "Got hr %#x.\n", hr);
+ ok(testsink.sink.pin.peer == source, "Got peer %p.\n", testsink.sink.pin.peer);
+ IFilterGraph2_Disconnect(graph, &testsink.sink.pin.IPin_iface);
+
+ peer = (IPin *)0xdeadbeef;
+ hr = IPin_ConnectedTo(source, &peer);
+ ok(hr == VFW_E_NOT_CONNECTED, "Got hr %#x.\n", hr);
+ ok(!peer, "Got peer %p.\n", peer);
+
+ hr = IPin_ConnectionMediaType(source, &mt);
+ ok(hr == VFW_E_NOT_CONNECTED, "Got hr %#x.\n", hr);
+
+ ok(!testdmo_output_mt_set, "Output type should not be set.\n");
+
+ req_mt.lSampleSize = 0;
+ hr = IFilterGraph2_ConnectDirect(graph, source, &testsink.sink.pin.IPin_iface, &req_mt);
+ ok(hr == VFW_E_TYPE_NOT_ACCEPTED, "Got hr %#x.\n", hr);
+
+ /* Connection with wildcards. */
+
+ hr = IFilterGraph2_ConnectDirect(graph, source, &testsink.sink.pin.IPin_iface, NULL);
+ ok(hr == S_OK, "Got hr %#x.\n", hr);
+ ok(compare_media_types(&testsink.sink.pin.mt, &mt2), "Media types didn't match.\n");
+ ok(testdmo_output_mt_set, "Ouput type should be set.\n");
+ ok(compare_media_types(&testdmo_output_mt, &mt2), "Media types didn't match.\n");
+ IFilterGraph2_Disconnect(graph, source);
+ IFilterGraph2_Disconnect(graph, &testsink.sink.pin.IPin_iface);
+
+ req_mt.majortype = GUID_NULL;
+ hr = IFilterGraph2_ConnectDirect(graph, source, &testsink.sink.pin.IPin_iface, &req_mt);
+ ok(hr == S_OK, "Got hr %#x.\n", hr);
+ ok(compare_media_types(&testsink.sink.pin.mt, &mt2), "Media types didn't match.\n");
+ IFilterGraph2_Disconnect(graph, source);
+ IFilterGraph2_Disconnect(graph, &testsink.sink.pin.IPin_iface);
+
+ req_mt.subtype = MEDIASUBTYPE_RGB32;
+ hr = IFilterGraph2_ConnectDirect(graph, source, &testsink.sink.pin.IPin_iface, &req_mt);
+ ok(hr == VFW_E_NO_ACCEPTABLE_TYPES, "Got hr %#x.\n", hr);
+
+ req_mt.subtype = GUID_NULL;
+ hr = IFilterGraph2_ConnectDirect(graph, source, &testsink.sink.pin.IPin_iface, &req_mt);
+ ok(hr == S_OK, "Got hr %#x.\n", hr);
+ ok(compare_media_types(&testsink.sink.pin.mt, &mt2), "Media types didn't match.\n");
+ IFilterGraph2_Disconnect(graph, source);
+ IFilterGraph2_Disconnect(graph, &testsink.sink.pin.IPin_iface);
+
+ req_mt.formattype = FORMAT_WaveFormatEx;
+ hr = IFilterGraph2_ConnectDirect(graph, source, &testsink.sink.pin.IPin_iface, &req_mt);
+ ok(hr == VFW_E_NO_ACCEPTABLE_TYPES, "Got hr %#x.\n", hr);
+
+ req_mt = mt2;
+ req_mt.formattype = GUID_NULL;
+ hr = IFilterGraph2_ConnectDirect(graph, source, &testsink.sink.pin.IPin_iface, &req_mt);
+ ok(hr == S_OK, "Got hr %#x.\n", hr);
+ ok(compare_media_types(&testsink.sink.pin.mt, &mt2), "Media types didn't match.\n");
+ IFilterGraph2_Disconnect(graph, source);
+ IFilterGraph2_Disconnect(graph, &testsink.sink.pin.IPin_iface);
+
+ req_mt.subtype = MEDIASUBTYPE_RGB32;
+ hr = IFilterGraph2_ConnectDirect(graph, source, &testsink.sink.pin.IPin_iface, &req_mt);
+ ok(hr == VFW_E_NO_ACCEPTABLE_TYPES, "Got hr %#x.\n", hr);
+
+ req_mt.subtype = GUID_NULL;
+ hr = IFilterGraph2_ConnectDirect(graph, source, &testsink.sink.pin.IPin_iface, &req_mt);
+ ok(hr == S_OK, "Got hr %#x.\n", hr);
+ ok(compare_media_types(&testsink.sink.pin.mt, &mt2), "Media types didn't match.\n");
+ IFilterGraph2_Disconnect(graph, source);
+ IFilterGraph2_Disconnect(graph, &testsink.sink.pin.IPin_iface);
+
+ req_mt.majortype = MEDIATYPE_Audio;
+ hr = IFilterGraph2_ConnectDirect(graph, source, &testsink.sink.pin.IPin_iface, &req_mt);
+ ok(hr == VFW_E_NO_ACCEPTABLE_TYPES, "Got hr %#x.\n", hr);
+
+ mt = req_mt;
+ testsink.sink_mt = &mt;
+ hr = IFilterGraph2_ConnectDirect(graph, source, &testsink.sink.pin.IPin_iface, NULL);
+ ok(hr == S_OK, "Got hr %#x.\n", hr);
+ ok(compare_media_types(&testsink.sink.pin.mt, &mt), "Media types didn't match.\n");
+ IFilterGraph2_Disconnect(graph, source);
+ IFilterGraph2_Disconnect(graph, &testsink.sink.pin.IPin_iface);
+
+ mt.lSampleSize = 1;
+ hr = IFilterGraph2_ConnectDirect(graph, source, &testsink.sink.pin.IPin_iface, &req_mt);
+ ok(hr == VFW_E_NO_ACCEPTABLE_TYPES, "Got hr %#x.\n", hr);
+ mt.lSampleSize = 321;
+
+ mt.majortype = mt.subtype = mt.formattype = GUID_NULL;
+ req_mt = mt;
+ hr = IFilterGraph2_ConnectDirect(graph, source, &testsink.sink.pin.IPin_iface, &req_mt);
+ ok(hr == S_OK, "Got hr %#x.\n", hr);
+ ok(compare_media_types(&testsink.sink.pin.mt, &mt), "Media types didn't match.\n");
+ IFilterGraph2_Disconnect(graph, source);
+ IFilterGraph2_Disconnect(graph, &testsink.sink.pin.IPin_iface);
+
+ req_mt.majortype = mt2.majortype;
+ hr = IFilterGraph2_ConnectDirect(graph, source, &testsink.sink.pin.IPin_iface, &req_mt);
+ ok(hr == VFW_E_NO_ACCEPTABLE_TYPES, "Got hr %#x.\n", hr);
+ req_mt.majortype = GUID_NULL;
+
+ req_mt.subtype = mt2.subtype;
+ hr = IFilterGraph2_ConnectDirect(graph, source, &testsink.sink.pin.IPin_iface, &req_mt);
+ ok(hr == VFW_E_NO_ACCEPTABLE_TYPES, "Got hr %#x.\n", hr);
+ req_mt.subtype = GUID_NULL;
+
+ req_mt.formattype = mt2.formattype;
+ hr = IFilterGraph2_ConnectDirect(graph, source, &testsink.sink.pin.IPin_iface, &req_mt);
+ ok(hr == VFW_E_NO_ACCEPTABLE_TYPES, "Got hr %#x.\n", hr);
+ req_mt.formattype = GUID_NULL;
+
+ testsink.sink_mt = NULL;
+
hr = IFilterGraph2_Disconnect(graph, sink);
ok(hr == S_OK, "Got hr %#x.\n", hr);
hr = IFilterGraph2_Disconnect(graph, sink);
@@ -1211,7 +1434,10 @@ static void test_connect_pin(void)
ok(!testdmo_input_mt_set, "Input type should not be set.\n");
+ test_source_allocator(graph, source, &testsink);
+
IPin_Release(sink);
+ IPin_Release(source);
IMemInputPin_Release(meminput);
ref = IFilterGraph2_Release(graph);
ok(!ref, "Got outstanding refcount %d.\n", ref);
@@ -1219,6 +1445,8 @@ static void test_connect_pin(void)
ok(!ref, "Got outstanding refcount %d.\n", ref);
ref = IBaseFilter_Release(&testsource.filter.IBaseFilter_iface);
ok(!ref, "Got outstanding refcount %d.\n", ref);
+ ref = IBaseFilter_Release(&testsink.filter.IBaseFilter_iface);
+ ok(!ref, "Got outstanding refcount %d.\n", ref);
}
START_TEST(dmowrapper)
diff --git a/dlls/strmbase/pin.c b/dlls/strmbase/pin.c
index 8a565b536e2..4676c9d82b0 100644
--- a/dlls/strmbase/pin.c
+++ b/dlls/strmbase/pin.c
@@ -555,6 +555,9 @@ static HRESULT WINAPI source_Disconnect(IPin *iface)
return VFW_E_NOT_STOPPED;
}
+ if (This->pFuncsTable->source_disconnect)
+ This->pFuncsTable->source_disconnect(This);
+
if (This->pMemInputPin)
{
IMemInputPin_Release(This->pMemInputPin);
diff --git a/include/wine/strmbase.h b/include/wine/strmbase.h
index 5151e68644b..0e0f73afa3c 100644
--- a/include/wine/strmbase.h
+++ b/include/wine/strmbase.h
@@ -74,6 +74,8 @@ struct strmbase_source_ops
BaseOutputPin_DecideBufferSize pfnDecideBufferSize;
/* Required for BaseOutputPinImpl_AttemptConnection */
BaseOutputPin_DecideAllocator pfnDecideAllocator;
+
+ void (*source_disconnect)(struct strmbase_source *pin);
};
struct strmbase_sink
--
2.25.0
More information about the wine-devel
mailing list