winegstreamer: Implement IQualityControl in MPEG audio decoder.

Signed-off-by: Anton Baskanov <baskanov@gmail.com>
This commit is contained in:
Anton Baskanov 2022-04-13 11:37:23 +07:00 committed by Alexandre Julliard
parent 16d93a32e3
commit ea81a48259
2 changed files with 129 additions and 2 deletions

View file

@ -242,7 +242,7 @@ static void test_interfaces(void)
check_interface(pin, &IID_IMemInputPin, TRUE);
check_interface(pin, &IID_IPin, TRUE);
todo_wine check_interface(pin, &IID_IQualityControl, TRUE);
check_interface(pin, &IID_IQualityControl, TRUE);
check_interface(pin, &IID_IUnknown, TRUE);
check_interface(pin, &IID_IMediaPosition, FALSE);
@ -255,7 +255,7 @@ static void test_interfaces(void)
check_interface(pin, &IID_IPin, TRUE);
check_interface(pin, &IID_IMediaPosition, TRUE);
check_interface(pin, &IID_IMediaSeeking, TRUE);
todo_wine check_interface(pin, &IID_IQualityControl, TRUE);
check_interface(pin, &IID_IQualityControl, TRUE);
check_interface(pin, &IID_IUnknown, TRUE);
check_interface(pin, &IID_IAsyncReader, FALSE);

View file

@ -35,6 +35,10 @@ struct transform
struct strmbase_source source;
struct strmbase_passthrough passthrough;
IQualityControl sink_IQualityControl_iface;
IQualityControl source_IQualityControl_iface;
IQualityControl *qc_sink;
struct wg_transform *transform;
const struct transform_ops *ops;
@ -272,6 +276,8 @@ static HRESULT transform_sink_query_interface(struct strmbase_pin *pin, REFIID i
if (IsEqualGUID(iid, &IID_IMemInputPin))
*out = &filter->sink.IMemInputPin_iface;
else if (IsEqualGUID(iid, &IID_IQualityControl))
*out = &filter->sink_IQualityControl_iface;
else
return E_NOINTERFACE;
@ -419,6 +425,8 @@ static HRESULT transform_source_query_interface(struct strmbase_pin *pin, REFIID
*out = &filter->passthrough.IMediaPosition_iface;
else if (IsEqualGUID(iid, &IID_IMediaSeeking))
*out = &filter->passthrough.IMediaSeeking_iface;
else if (IsEqualGUID(iid, &IID_IQualityControl))
*out = &filter->source_IQualityControl_iface;
else
return E_NOINTERFACE;
@ -443,6 +451,122 @@ static const struct strmbase_source_ops source_ops =
.pfnDecideBufferSize = transform_source_DecideBufferSize,
};
static struct transform *impl_from_sink_IQualityControl(IQualityControl *iface)
{
return CONTAINING_RECORD(iface, struct transform, sink_IQualityControl_iface);
}
static HRESULT WINAPI sink_quality_control_QueryInterface(IQualityControl *iface, REFIID iid, void **out)
{
struct transform *filter = impl_from_sink_IQualityControl(iface);
return IPin_QueryInterface(&filter->source.pin.IPin_iface, iid, out);
}
static ULONG WINAPI sink_quality_control_AddRef(IQualityControl *iface)
{
struct transform *filter = impl_from_sink_IQualityControl(iface);
return IPin_AddRef(&filter->source.pin.IPin_iface);
}
static ULONG WINAPI sink_quality_control_Release(IQualityControl *iface)
{
struct transform *filter = impl_from_sink_IQualityControl(iface);
return IPin_Release(&filter->source.pin.IPin_iface);
}
static HRESULT WINAPI sink_quality_control_Notify(IQualityControl *iface, IBaseFilter *sender, Quality q)
{
struct transform *filter = impl_from_sink_IQualityControl(iface);
TRACE("filter %p, sender %p, type %#x, proportion %ld, late %s, timestamp %s.\n",
filter, sender, q.Type, q.Proportion, debugstr_time(q.Late), debugstr_time(q.TimeStamp));
return S_OK;
}
static HRESULT WINAPI sink_quality_control_SetSink(IQualityControl *iface, IQualityControl *sink)
{
struct transform *filter = impl_from_sink_IQualityControl(iface);
TRACE("filter %p, sink %p.\n", filter, sink);
filter->qc_sink = sink;
return S_OK;
}
static const IQualityControlVtbl sink_quality_control_vtbl =
{
sink_quality_control_QueryInterface,
sink_quality_control_AddRef,
sink_quality_control_Release,
sink_quality_control_Notify,
sink_quality_control_SetSink,
};
static struct transform *impl_from_source_IQualityControl(IQualityControl *iface)
{
return CONTAINING_RECORD(iface, struct transform, source_IQualityControl_iface);
}
static HRESULT WINAPI source_quality_control_QueryInterface(IQualityControl *iface, REFIID iid, void **out)
{
struct transform *filter = impl_from_source_IQualityControl(iface);
return IPin_QueryInterface(&filter->source.pin.IPin_iface, iid, out);
}
static ULONG WINAPI source_quality_control_AddRef(IQualityControl *iface)
{
struct transform *filter = impl_from_source_IQualityControl(iface);
return IPin_AddRef(&filter->source.pin.IPin_iface);
}
static ULONG WINAPI source_quality_control_Release(IQualityControl *iface)
{
struct transform *filter = impl_from_source_IQualityControl(iface);
return IPin_Release(&filter->source.pin.IPin_iface);
}
static HRESULT WINAPI source_quality_control_Notify(IQualityControl *iface, IBaseFilter *sender, Quality q)
{
struct transform *filter = impl_from_source_IQualityControl(iface);
IQualityControl *peer;
HRESULT hr = VFW_E_NOT_FOUND;
TRACE("filter %p, sender %p, type %#x, proportion %ld, late %s, timestamp %s.\n",
filter, sender, q.Type, q.Proportion, debugstr_time(q.Late), debugstr_time(q.TimeStamp));
if (filter->qc_sink)
return IQualityControl_Notify(filter->qc_sink, &filter->filter.IBaseFilter_iface, q);
if (filter->sink.pin.peer
&& SUCCEEDED(IPin_QueryInterface(filter->sink.pin.peer, &IID_IQualityControl, (void **)&peer)))
{
hr = IQualityControl_Notify(peer, &filter->filter.IBaseFilter_iface, q);
IQualityControl_Release(peer);
}
return hr;
}
static HRESULT WINAPI source_quality_control_SetSink(IQualityControl *iface, IQualityControl *sink)
{
struct transform *filter = impl_from_source_IQualityControl(iface);
TRACE("filter %p, sink %p.\n", filter, sink);
return S_OK;
}
static const IQualityControlVtbl source_quality_control_vtbl =
{
source_quality_control_QueryInterface,
source_quality_control_AddRef,
source_quality_control_Release,
source_quality_control_Notify,
source_quality_control_SetSink,
};
static HRESULT transform_create(IUnknown *outer, const CLSID *clsid, const struct transform_ops *ops, struct transform **out)
{
struct transform *object;
@ -459,6 +583,9 @@ static HRESULT transform_create(IUnknown *outer, const CLSID *clsid, const struc
ISeekingPassThru_Init(&object->passthrough.ISeekingPassThru_iface, FALSE,
&object->sink.pin.IPin_iface);
object->sink_IQualityControl_iface.lpVtbl = &sink_quality_control_vtbl;
object->source_IQualityControl_iface.lpVtbl = &source_quality_control_vtbl;
object->ops = ops;
*out = object;