[PATCH 5/5] quartz/tests: Add tests for MPEG audio decoder quality control.
Anton Baskanov
wine at gitlab.winehq.org
Tue May 17 03:24:14 CDT 2022
From: Anton Baskanov <baskanov at gmail.com>
Signed-off-by: Anton Baskanov <baskanov at gmail.com>
---
dlls/quartz/tests/mpegaudio.c | 223 ++++++++++++++++++++++++++++++++++
1 file changed, 223 insertions(+)
diff --git a/dlls/quartz/tests/mpegaudio.c b/dlls/quartz/tests/mpegaudio.c
index d3d5c3d76f0..804cbbcc3d1 100644
--- a/dlls/quartz/tests/mpegaudio.c
+++ b/dlls/quartz/tests/mpegaudio.c
@@ -789,11 +789,118 @@ static void test_media_types(void)
ok(!ref, "Got outstanding refcount %ld.\n", ref);
}
+struct testqc
+{
+ IQualityControl IQualityControl_iface;
+ IUnknown IUnknown_inner;
+ IUnknown *outer_unk;
+ LONG refcount;
+ IBaseFilter *notify_sender;
+ Quality notify_quality;
+ HRESULT notify_hr;
+};
+
+static struct testqc *impl_from_IQualityControl(IQualityControl *iface)
+{
+ return CONTAINING_RECORD(iface, struct testqc, IQualityControl_iface);
+}
+
+static HRESULT WINAPI testqc_QueryInterface(IQualityControl *iface, REFIID iid, void **out)
+{
+ struct testqc *qc = impl_from_IQualityControl(iface);
+ return IUnknown_QueryInterface(qc->outer_unk, iid, out);
+}
+
+static ULONG WINAPI testqc_AddRef(IQualityControl *iface)
+{
+ struct testqc *qc = impl_from_IQualityControl(iface);
+ return IUnknown_AddRef(qc->outer_unk);
+}
+
+static ULONG WINAPI testqc_Release(IQualityControl *iface)
+{
+ struct testqc *qc = impl_from_IQualityControl(iface);
+ return IUnknown_Release(qc->outer_unk);
+}
+
+static HRESULT WINAPI testqc_Notify(IQualityControl *iface, IBaseFilter *sender, Quality q)
+{
+ struct testqc *qc = impl_from_IQualityControl(iface);
+
+ qc->notify_sender = sender;
+ qc->notify_quality = q;
+
+ return qc->notify_hr;
+}
+
+static HRESULT WINAPI testqc_SetSink(IQualityControl *iface, IQualityControl *sink)
+{
+ ok(0, "Unexpected call.\n");
+ return E_NOTIMPL;
+}
+
+static const IQualityControlVtbl testqc_vtbl =
+{
+ testqc_QueryInterface,
+ testqc_AddRef,
+ testqc_Release,
+ testqc_Notify,
+ testqc_SetSink,
+};
+
+static struct testqc *impl_from_qc_IUnknown(IUnknown *iface)
+{
+ return CONTAINING_RECORD(iface, struct testqc, IUnknown_inner);
+}
+
+static HRESULT WINAPI testqc_inner_QueryInterface(IUnknown *iface, REFIID iid, void **out)
+{
+ struct testqc *qc = impl_from_qc_IUnknown(iface);
+
+ if (IsEqualIID(iid, &IID_IUnknown))
+ *out = iface;
+ else if (IsEqualIID(iid, &IID_IQualityControl))
+ *out = &qc->IQualityControl_iface;
+ else
+ return E_NOINTERFACE;
+
+ IUnknown_AddRef((IUnknown *)*out);
+ return S_OK;
+}
+
+static ULONG WINAPI testqc_inner_AddRef(IUnknown *iface)
+{
+ struct testqc *qc = impl_from_qc_IUnknown(iface);
+ return InterlockedIncrement(&qc->refcount);
+}
+
+static ULONG WINAPI testqc_inner_Release(IUnknown *iface)
+{
+ struct testqc *qc = impl_from_qc_IUnknown(iface);
+ return InterlockedDecrement(&qc->refcount);
+}
+
+static const IUnknownVtbl testqc_inner_vtbl =
+{
+ testqc_inner_QueryInterface,
+ testqc_inner_AddRef,
+ testqc_inner_Release,
+};
+
+static void testqc_init(struct testqc *qc, IUnknown *outer)
+{
+ memset(qc, 0, sizeof(*qc));
+ qc->IQualityControl_iface.lpVtbl = &testqc_vtbl;
+ qc->IUnknown_inner.lpVtbl = &testqc_inner_vtbl;
+ qc->outer_unk = outer ? outer : &qc->IUnknown_inner;
+}
+
struct testfilter
{
struct strmbase_filter filter;
struct strmbase_source source;
struct strmbase_sink sink;
+ struct testqc *qc;
const AM_MEDIA_TYPE *mt;
unsigned int got_sample, got_new_segment, got_eos, got_begin_flush, got_end_flush;
REFERENCE_TIME expected_start_time;
@@ -827,6 +934,19 @@ static const struct strmbase_filter_ops testfilter_ops =
.filter_destroy = testfilter_destroy,
};
+static HRESULT testsource_query_interface(struct strmbase_pin *iface, REFIID iid, void **out)
+{
+ struct testfilter *filter = impl_from_strmbase_filter(iface->filter);
+
+ if (IsEqualGUID(iid, &IID_IQualityControl) && filter->qc)
+ *out = &filter->qc->IQualityControl_iface;
+ else
+ return E_NOINTERFACE;
+
+ IUnknown_AddRef((IUnknown *)*out);
+ return S_OK;
+}
+
static HRESULT WINAPI testsource_DecideAllocator(struct strmbase_source *iface,
IMemInputPin *peer, IMemAllocator **allocator)
{
@@ -835,6 +955,7 @@ static HRESULT WINAPI testsource_DecideAllocator(struct strmbase_source *iface,
static const struct strmbase_source_ops testsource_ops =
{
+ .base.pin_query_interface = testsource_query_interface,
.pfnAttemptConnection = BaseOutputPinImpl_AttemptConnection,
.pfnDecideAllocator = testsource_DecideAllocator,
};
@@ -1108,6 +1229,107 @@ static void test_source_allocator(IFilterGraph2 *graph, IMediaControl *control,
IFilterGraph2_Disconnect(graph, &testsource->source.pin.IPin_iface);
}
+static void test_quality_control(IFilterGraph2 *graph, IBaseFilter *filter,
+ IPin *sink, IPin *source, struct testfilter *testsource, struct testfilter *testsink)
+{
+ struct testqc testsource_qc;
+ IQualityControl *source_qc;
+ IQualityControl *sink_qc;
+ Quality quality = {0};
+ struct testqc qc;
+ HRESULT hr;
+
+ testqc_init(&testsource_qc, testsource->filter.outer_unk);
+ testqc_init(&qc, NULL);
+
+ hr = IPin_QueryInterface(sink, &IID_IQualityControl, (void **)&sink_qc);
+ ok(hr == S_OK, "Got hr %#lx.\n", hr);
+ hr = IPin_QueryInterface(source, &IID_IQualityControl, (void **)&source_qc);
+ ok(hr == S_OK, "Got hr %#lx.\n", hr);
+
+ hr = IQualityControl_Notify(sink_qc, &testsink->filter.IBaseFilter_iface, quality);
+ ok(hr == S_OK, "Got hr %#lx.\n", hr);
+
+ hr = IQualityControl_Notify(source_qc, &testsink->filter.IBaseFilter_iface, quality);
+ ok(hr == VFW_E_NOT_FOUND, "Got hr %#lx.\n", hr);
+
+ hr = IQualityControl_SetSink(sink_qc, &qc.IQualityControl_iface);
+ ok(hr == S_OK, "Got hr %#lx.\n", hr);
+ qc.notify_sender = (IBaseFilter *)0xdeadbeef;
+ memset(&qc.notify_quality, 0xaa, sizeof(qc.notify_quality));
+ hr = IQualityControl_Notify(source_qc, &testsink->filter.IBaseFilter_iface, quality);
+ ok(hr == S_OK, "Got hr %#lx.\n", hr);
+ ok(qc.notify_sender == filter, "Got sender %p.\n", qc.notify_sender);
+ ok(!memcmp(&qc.notify_quality, &quality, sizeof(quality)), "Quality didn't match.\n");
+ hr = IQualityControl_SetSink(sink_qc, NULL);
+ ok(hr == S_OK, "Got hr %#lx.\n", hr);
+
+ hr = IQualityControl_SetSink(source_qc, &qc.IQualityControl_iface);
+ ok(hr == S_OK, "Got hr %#lx.\n", hr);
+ qc.notify_sender = (IBaseFilter *)0xdeadbeef;
+ hr = IQualityControl_Notify(source_qc, &testsink->filter.IBaseFilter_iface, quality);
+ ok(hr == VFW_E_NOT_FOUND, "Got hr %#lx.\n", hr);
+ ok(qc.notify_sender == (IBaseFilter *)0xdeadbeef, "Got sender %p.\n", qc.notify_sender);
+ hr = IQualityControl_SetSink(source_qc, NULL);
+ ok(hr == S_OK, "Got hr %#lx.\n", hr);
+
+ hr = IFilterGraph2_ConnectDirect(graph, &testsource->source.pin.IPin_iface, sink, &mp2_mt);
+ ok(hr == S_OK, "Got hr %#lx.\n", hr);
+
+ hr = IQualityControl_Notify(source_qc, &testsink->filter.IBaseFilter_iface, quality);
+ ok(hr == VFW_E_NOT_FOUND, "Got hr %#lx.\n", hr);
+
+ testsource->qc = &testsource_qc;
+
+ qc.notify_sender = (IBaseFilter *)0xdeadbeef;
+ hr = IQualityControl_Notify(sink_qc, &testsink->filter.IBaseFilter_iface, quality);
+ ok(hr == S_OK, "Got hr %#lx.\n", hr);
+ ok(qc.notify_sender == (IBaseFilter *)0xdeadbeef, "Got sender %p.\n", qc.notify_sender);
+
+ testsource_qc.notify_sender = (IBaseFilter *)0xdeadbeef;
+ memset(&testsource_qc.notify_quality, 0xaa, sizeof(testsource_qc.notify_quality));
+ hr = IQualityControl_Notify(source_qc, &testsink->filter.IBaseFilter_iface, quality);
+ ok(hr == S_OK, "Got hr %#lx.\n", hr);
+ ok(testsource_qc.notify_sender == filter, "Got sender %p.\n", testsource_qc.notify_sender);
+ ok(!memcmp(&testsource_qc.notify_quality, &quality, sizeof(quality)), "Quality didn't match.\n");
+
+ testsource_qc.notify_hr = E_FAIL;
+ hr = IQualityControl_Notify(source_qc, &testsink->filter.IBaseFilter_iface, quality);
+ ok(hr == E_FAIL, "Got hr %#lx.\n", hr);
+ testsource_qc.notify_hr = S_OK;
+
+ hr = IQualityControl_SetSink(sink_qc, &qc.IQualityControl_iface);
+ ok(hr == S_OK, "Got hr %#lx.\n", hr);
+ qc.notify_sender = (IBaseFilter *)0xdeadbeef;
+ memset(&qc.notify_quality, 0xaa, sizeof(qc.notify_quality));
+ hr = IQualityControl_Notify(source_qc, &testsink->filter.IBaseFilter_iface, quality);
+ ok(hr == S_OK, "Got hr %#lx.\n", hr);
+ ok(qc.notify_sender == filter, "Got sender %p.\n", qc.notify_sender);
+ ok(!memcmp(&qc.notify_quality, &quality, sizeof(quality)), "Quality didn't match.\n");
+ hr = IQualityControl_SetSink(sink_qc, NULL);
+ ok(hr == S_OK, "Got hr %#lx.\n", hr);
+
+ hr = IQualityControl_SetSink(source_qc, &qc.IQualityControl_iface);
+ ok(hr == S_OK, "Got hr %#lx.\n", hr);
+ qc.notify_sender = (IBaseFilter *)0xdeadbeef;
+ hr = IQualityControl_Notify(source_qc, &testsink->filter.IBaseFilter_iface, quality);
+ ok(hr == S_OK, "Got hr %#lx.\n", hr);
+ ok(qc.notify_sender == (IBaseFilter *)0xdeadbeef, "Got sender %p.\n", qc.notify_sender);
+ hr = IQualityControl_SetSink(source_qc, NULL);
+ ok(hr == S_OK, "Got hr %#lx.\n", hr);
+
+ IFilterGraph2_Disconnect(graph, sink);
+ IFilterGraph2_Disconnect(graph, &testsource->source.pin.IPin_iface);
+
+ hr = IQualityControl_Notify(source_qc, &testsink->filter.IBaseFilter_iface, quality);
+ ok(hr == VFW_E_NOT_FOUND, "Got hr %#lx.\n", hr);
+
+ IQualityControl_Release(source_qc);
+ IQualityControl_Release(sink_qc);
+
+ testsource->qc = NULL;
+}
+
static void test_sample_processing(IMediaControl *control, IMemInputPin *input, struct testfilter *sink)
{
REFERENCE_TIME start, stop;
@@ -1333,6 +1555,7 @@ static void test_connect_pin(void)
IFilterGraph2_QueryInterface(graph, &IID_IMediaControl, (void **)&control);
test_source_allocator(graph, control, sink, source, &testsource, &testsink);
+ test_quality_control(graph, filter, sink, source, &testsource, &testsink);
/* Test sink connection. */
--
GitLab
https://gitlab.winehq.org/wine/wine/-/merge_requests/83
More information about the wine-devel
mailing list