Commit 5d8ef3ff authored by Anton Baskanov's avatar Anton Baskanov Committed by Alexandre Julliard

quartz/tests: Add tests for MPEG layer-3 decoder quality control.

parent ac83c31e
......@@ -775,11 +775,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;
LONG sample_size;
......@@ -815,6 +922,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)
{
......@@ -823,6 +943,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,
};
......@@ -1066,6 +1187,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, &mp3_mt1);
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 *meminput, struct testfilter *testsink)
{
......@@ -1311,6 +1533,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. */
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment