[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