diff --git a/dlls/quartz/dsoundrender.c b/dlls/quartz/dsoundrender.c index 4714b2b3764..1369cd47088 100644 --- a/dlls/quartz/dsoundrender.c +++ b/dlls/quartz/dsoundrender.c @@ -407,7 +407,7 @@ static HRESULT WINAPI DSoundRender_DoRenderSample(BaseRenderer *iface, IMediaSam q.Proportion = 1.; q.Late = jitter; q.TimeStamp = tStart; - IQualityControl_Notify((IQualityControl *)&This->renderer.qcimpl, (IBaseFilter*)This, q); + IQualityControl_Notify((IQualityControl *)This->renderer.qcimpl, (IBaseFilter*)This, q); } return hr; } diff --git a/dlls/strmbase/qualitycontrol.c b/dlls/strmbase/qualitycontrol.c index 8bcaaa998f5..b73f912d1e3 100644 --- a/dlls/strmbase/qualitycontrol.c +++ b/dlls/strmbase/qualitycontrol.c @@ -27,6 +27,7 @@ #include "dshow.h" #include "wine/strmbase.h" +#include "strmbase_private.h" #include "uuids.h" #include "wine/debug.h" @@ -35,11 +36,22 @@ WINE_DEFAULT_DEBUG_CHANNEL(strmbase_qc); -void QualityControlImpl_init(QualityControlImpl *This, IPin *input, IBaseFilter *self) { +HRESULT QualityControlImpl_Create(IPin *input, IBaseFilter *self, QualityControlImpl **ppv) { + QualityControlImpl *This; + *ppv = HeapAlloc(GetProcessHeap(),0,sizeof(QualityControlImpl)); + if (!ppv) + return E_OUTOFMEMORY; + This = *ppv; This->input = input; This->self = self; This->tonotify = NULL; This->clock = NULL; + return S_OK; +} + +HRESULT QualityControlImpl_Destroy(QualityControlImpl *This) +{ + return HeapFree(GetProcessHeap(),0,This); } HRESULT WINAPI QualityControlImpl_QueryInterface(IQualityControl *iface, REFIID riid, void **ppv) { diff --git a/dlls/strmbase/renderer.c b/dlls/strmbase/renderer.c index a4261ee5757..7c6a1f17976 100644 --- a/dlls/strmbase/renderer.c +++ b/dlls/strmbase/renderer.c @@ -26,6 +26,7 @@ #include "wine/strmbase.h" #include "uuids.h" #include "vfwmsgs.h" +#include "strmbase_private.h" WINE_DEFAULT_DEBUG_CHANNEL(strmbase); @@ -267,8 +268,8 @@ HRESULT WINAPI BaseRenderer_Init(BaseRenderer * This, const IBaseFilterVtbl *Vtb This->RenderEvent = CreateEventW(NULL, FALSE, FALSE, NULL); This->pMediaSample = NULL; - QualityControlImpl_init(&This->qcimpl, &This->pInputPin->pin.IPin_iface, &This->filter.IBaseFilter_iface); - This->qcimpl.lpVtbl = &Renderer_QualityControl_Vtbl; + QualityControlImpl_Create(&This->pInputPin->pin.IPin_iface, &This->filter.IBaseFilter_iface, &This->qcimpl); + This->qcimpl->IQualityControl_iface.lpVtbl = &Renderer_QualityControl_Vtbl; } return hr; @@ -282,7 +283,7 @@ HRESULT WINAPI BaseRendererImpl_QueryInterface(IBaseFilter* iface, REFIID riid, return IUnknown_QueryInterface(This->pPosition, riid, ppv); else if (IsEqualIID(riid, &IID_IQualityControl)) { - *ppv = &This->qcimpl.lpVtbl; + *ppv = &This->qcimpl->IQualityControl_iface; IUnknown_AddRef((IUnknown *)(*ppv)); return S_OK; } @@ -317,6 +318,7 @@ ULONG WINAPI BaseRendererImpl_Release(IBaseFilter* iface) CloseHandle(This->evComplete); CloseHandle(This->ThreadSignal); CloseHandle(This->RenderEvent); + QualityControlImpl_Destroy(This->qcimpl); } return refCount; } @@ -383,7 +385,7 @@ HRESULT WINAPI BaseRendererImpl_Receive(BaseRenderer *This, IMediaSample * pSamp if (This->pFuncsTable->pfnOnWaitStart) This->pFuncsTable->pfnOnWaitStart(This); - hr = QualityControlRender_WaitFor(&This->qcimpl, pSample, This->RenderEvent); + hr = QualityControlRender_WaitFor(This->qcimpl, pSample, This->RenderEvent); if (This->pFuncsTable->pfnOnWaitEnd) This->pFuncsTable->pfnOnWaitEnd(This); @@ -398,12 +400,12 @@ HRESULT WINAPI BaseRendererImpl_Receive(BaseRenderer *This, IMediaSample * pSamp if (SUCCEEDED(hr)) { - QualityControlRender_BeginRender(&This->qcimpl); + QualityControlRender_BeginRender(This->qcimpl); hr = This->pFuncsTable->pfnDoRenderSample(This, pSample); - QualityControlRender_EndRender(&This->qcimpl); + QualityControlRender_EndRender(This->qcimpl); } - QualityControlRender_DoQOS(&This->qcimpl); + QualityControlRender_DoQOS(This->qcimpl); BaseRendererImpl_ClearPendingSample(This); LeaveCriticalSection(&This->csRenderLock); @@ -482,7 +484,7 @@ HRESULT WINAPI BaseRendererImpl_Run(IBaseFilter * iface, REFERENCE_TIME tStart) } if (SUCCEEDED(hr)) { - QualityControlRender_Start(&This->qcimpl, This->filter.rtStreamStart); + QualityControlRender_Start(This->qcimpl, This->filter.rtStreamStart); if (This->pFuncsTable->pfnOnStartStreaming) This->pFuncsTable->pfnOnStartStreaming(This); if (This->filter.state == State_Stopped) @@ -533,7 +535,7 @@ HRESULT WINAPI BaseRendererImpl_SetSyncSource(IBaseFilter *iface, IReferenceCloc HRESULT hr; EnterCriticalSection(&This->filter.csFilter); - QualityControlRender_SetClock(&This->qcimpl, clock); + QualityControlRender_SetClock(This->qcimpl, clock); hr = BaseFilterImpl_SetSyncSource(iface, clock); LeaveCriticalSection(&This->filter.csFilter); return hr; @@ -592,7 +594,7 @@ HRESULT WINAPI BaseRendererImpl_BeginFlush(BaseRenderer* iface) HRESULT WINAPI BaseRendererImpl_EndFlush(BaseRenderer* iface) { TRACE("(%p)\n", iface); - QualityControlRender_Start(&iface->qcimpl, iface->filter.rtStreamStart); + QualityControlRender_Start(iface->qcimpl, iface->filter.rtStreamStart); RendererPosPassThru_ResetMediaTime(iface->pPosition); ResetEvent(iface->ThreadSignal); ResetEvent(iface->RenderEvent); diff --git a/dlls/strmbase/strmbase_private.h b/dlls/strmbase/strmbase_private.h new file mode 100644 index 00000000000..6363bf5307d --- /dev/null +++ b/dlls/strmbase/strmbase_private.h @@ -0,0 +1,50 @@ +/* + * Header file for private strmbase implementations + * + * Copyright 2012 Aric Stewart, CodeWeavers + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA + */ + +/* Quality Control */ +typedef struct QualityControlImpl { + IQualityControl IQualityControl_iface; + IPin *input; + IBaseFilter *self; + IQualityControl *tonotify; + + /* Render stuff */ + IReferenceClock *clock; + REFERENCE_TIME last_in_time, last_left, avg_duration, avg_pt, avg_render, start, stop; + REFERENCE_TIME current_jitter, current_rstart, current_rstop, clockstart; + double avg_rate; + LONG64 rendered, dropped; + BOOL qos_handled, is_dropped; +} QualityControlImpl; + +HRESULT QualityControlImpl_Create(IPin *input, IBaseFilter *self, QualityControlImpl **ppv); +HRESULT QualityControlImpl_Destroy(QualityControlImpl *This); +HRESULT WINAPI QualityControlImpl_QueryInterface(IQualityControl *iface, REFIID riid, void **ppv); +ULONG WINAPI QualityControlImpl_AddRef(IQualityControl *iface); +ULONG WINAPI QualityControlImpl_Release(IQualityControl *iface); +HRESULT WINAPI QualityControlImpl_Notify(IQualityControl *iface, IBaseFilter *sender, Quality qm); +HRESULT WINAPI QualityControlImpl_SetSink(IQualityControl *iface, IQualityControl *tonotify); + +void QualityControlRender_Start(QualityControlImpl *This, REFERENCE_TIME tStart); +void QualityControlRender_SetClock(QualityControlImpl *This, IReferenceClock *clock); +HRESULT QualityControlRender_WaitFor(QualityControlImpl *This, IMediaSample *sample, HANDLE ev); +void QualityControlRender_DoQOS(QualityControlImpl *priv); +void QualityControlRender_BeginRender(QualityControlImpl *This); +void QualityControlRender_EndRender(QualityControlImpl *This); diff --git a/dlls/strmbase/transform.c b/dlls/strmbase/transform.c index 493324d2446..2a515765bce 100644 --- a/dlls/strmbase/transform.c +++ b/dlls/strmbase/transform.c @@ -35,6 +35,7 @@ #include "wine/unicode.h" #include "wine/debug.h" #include "wine/strmbase.h" +#include "strmbase_private.h" WINE_DEFAULT_DEBUG_CHANNEL(strmbase); @@ -233,8 +234,7 @@ static HRESULT TransformFilter_Init(const IBaseFilterVtbl *pVtbl, const CLSID* p if (FAILED(hr)) ERR("Cannot create output pin (%x)\n", hr); else { - QualityControlImpl_init(&pTransformFilter->qcimpl, pTransformFilter->ppPins[0], &pTransformFilter->filter.IBaseFilter_iface); - pTransformFilter->qcimpl.lpVtbl = &TransformFilter_QualityControl_Vtbl; + QualityControlImpl_Create( pTransformFilter->ppPins[0], &pTransformFilter->filter.IBaseFilter_iface, &pTransformFilter->qcimpl); } } if (FAILED(hr)) @@ -278,7 +278,7 @@ HRESULT WINAPI TransformFilterImpl_QueryInterface(IBaseFilter * iface, REFIID ri TRACE("(%p/%p)->(%s, %p)\n", This, iface, debugstr_guid(riid), ppv); if (IsEqualIID(riid, &IID_IQualityControl)) { - *ppv = (IQualityControl*)&This->qcimpl; + *ppv = (IQualityControl*)This->qcimpl; IUnknown_AddRef((IUnknown*)*ppv); return S_OK; } @@ -322,6 +322,7 @@ ULONG WINAPI TransformFilterImpl_Release(IBaseFilter * iface) This->csReceive.DebugInfo->Spare[0] = 0; DeleteCriticalSection(&This->csReceive); FreeMediaType(&This->pmt); + QualityControlImpl_Destroy(This->qcimpl); CoTaskMemFree(This); return 0; @@ -401,6 +402,11 @@ HRESULT WINAPI TransformFilterImpl_Run(IBaseFilter * iface, REFERENCE_TIME tStar return hr; } +HRESULT WINAPI TransformFilterImpl_Notify(TransformFilter *iface, IBaseFilter *sender, Quality qm) +{ + return QualityControlImpl_Notify((IQualityControl*)&iface->qcimpl, sender, qm); +} + /** IBaseFilter implementation **/ HRESULT WINAPI TransformFilterImpl_FindPin(IBaseFilter * iface, LPCWSTR Id, IPin **ppPin) @@ -602,7 +608,7 @@ static HRESULT WINAPI TransformFilter_QualityControlImpl_Notify(IQualityControl if (This->pFuncsTable->pfnNotify) return This->pFuncsTable->pfnNotify(This, sender, qm); else - return QualityControlImpl_Notify(iface, sender, qm); + return TransformFilterImpl_Notify(This, sender, qm); } static const IQualityControlVtbl TransformFilter_QualityControl_Vtbl = { diff --git a/dlls/winegstreamer/gstdemux.c b/dlls/winegstreamer/gstdemux.c index 730634dc7e1..fea844de349 100644 --- a/dlls/winegstreamer/gstdemux.c +++ b/dlls/winegstreamer/gstdemux.c @@ -73,6 +73,7 @@ typedef struct GSTImpl { struct GSTOutPin { BaseOutputPin pin; + IQualityControl IQualityControl_iface; GstPad *their_src; GstPad *my_sink; @@ -80,7 +81,6 @@ struct GSTOutPin { AM_MEDIA_TYPE * pmt; HANDLE caps_event; GstSegment *segment; - QualityControlImpl qcimpl; SourceSeeking seek; }; @@ -1395,9 +1395,31 @@ static const IMediaSeekingVtbl GST_Seeking_Vtbl = SourceSeekingImpl_GetPreroll }; +static inline GSTOutPin *impl_from_IQualityControl( IQualityControl *iface ) +{ + return (GSTOutPin*)CONTAINING_RECORD(iface, GSTOutPin, IQualityControl_iface); +} + +HRESULT WINAPI GST_QualityControl_QueryInterface(IQualityControl *iface, REFIID riid, void **ppv) +{ + GSTOutPin *pin = impl_from_IQualityControl(iface); + return IPin_QueryInterface((IPin*)pin, riid, ppv); +} + +ULONG WINAPI GST_QualityControl_AddRef(IQualityControl *iface) +{ + GSTOutPin *pin = impl_from_IQualityControl(iface); + return IPin_AddRef((IPin*)pin); +} + +ULONG WINAPI GST_QualityControl_Release(IQualityControl *iface) +{ + GSTOutPin *pin = impl_from_IQualityControl(iface); + return IPin_Release((IPin*)pin); +} + static HRESULT WINAPI GST_QualityControl_Notify(IQualityControl *iface, IBaseFilter *sender, Quality qm) { - QualityControlImpl *This = (QualityControlImpl*)iface; - GSTOutPin *pin = (GSTOutPin*)This->self; + GSTOutPin *pin = impl_from_IQualityControl(iface); REFERENCE_TIME late = qm.Late; if (qm.Late < 0 && -qm.Late > qm.TimeStamp) late = -qm.TimeStamp; @@ -1405,12 +1427,18 @@ static HRESULT WINAPI GST_QualityControl_Notify(IQualityControl *iface, IBaseFil return S_OK; } +HRESULT WINAPI GST_QualityControl_SetSink(IQualityControl *iface, IQualityControl *tonotify) +{ + /* Do nothing */ + return S_OK; +} + static const IQualityControlVtbl GSTOutPin_QualityControl_Vtbl = { - QualityControlImpl_QueryInterface, - QualityControlImpl_AddRef, - QualityControlImpl_Release, + GST_QualityControl_QueryInterface, + GST_QualityControl_AddRef, + GST_QualityControl_Release, GST_QualityControl_Notify, - QualityControlImpl_SetSink + GST_QualityControl_SetSink }; static HRESULT WINAPI GSTOutPin_QueryInterface(IPin *iface, REFIID riid, void **ppv) { @@ -1427,7 +1455,7 @@ static HRESULT WINAPI GSTOutPin_QueryInterface(IPin *iface, REFIID riid, void ** else if (IsEqualIID(riid, &IID_IMediaSeeking)) *ppv = &This->seek; else if (IsEqualIID(riid, &IID_IQualityControl)) - *ppv = &This->qcimpl; + *ppv = &This->IQualityControl_iface; if (*ppv) { IUnknown_AddRef((IUnknown *)(*ppv)); @@ -1555,8 +1583,7 @@ static HRESULT GST_AddPin(GSTImpl *This, const PIN_INFO *piOutput, const AM_MEDI pin->caps_event = CreateEventW(NULL, 0, 0, NULL); pin->segment = gst_segment_new(); This->cStreams++; - QualityControlImpl_init(&pin->qcimpl, NULL, (IBaseFilter*)pin); - pin->qcimpl.lpVtbl = &GSTOutPin_QualityControl_Vtbl; + pin->IQualityControl_iface.lpVtbl = &GSTOutPin_QualityControl_Vtbl; SourceSeeking_Init(&pin->seek, &GST_Seeking_Vtbl, GST_ChangeStop, GST_ChangeCurrent, GST_ChangeRate, &This->filter.csFilter); BaseFilterImpl_IncrementPinVersion((BaseFilter*)This); } else diff --git a/dlls/winegstreamer/gsttffilter.c b/dlls/winegstreamer/gsttffilter.c index 8230943a593..a4ec7f3ec59 100644 --- a/dlls/winegstreamer/gsttffilter.c +++ b/dlls/winegstreamer/gsttffilter.c @@ -442,7 +442,7 @@ static HRESULT WINAPI Gstreamer_transform_QOS(TransformFilter *iface, IBaseFilte if (qm.Late < 0 && -qm.Late > qm.TimeStamp) late = -qm.TimeStamp; gst_pad_push_event(This->my_sink, gst_event_new_qos(1000. / qm.Proportion, late * 100, qm.TimeStamp * 100)); - return QualityControlImpl_Notify((IQualityControl*)&iface->qcimpl, sender, qm); + return TransformFilterImpl_Notify(iface, sender, qm); } static HRESULT Gstreamer_transform_create(IUnknown *punkout, const CLSID *clsid, const char *name, const TransformFilterFuncTable *vtbl, void **obj) diff --git a/include/wine/strmbase.h b/include/wine/strmbase.h index 6be9b0df83c..770055a87b7 100644 --- a/include/wine/strmbase.h +++ b/include/wine/strmbase.h @@ -194,36 +194,6 @@ HRESULT WINAPI EnumMediaTypes_Construct(BasePin *iface, BasePin_GetMediaType enu HRESULT WINAPI EnumPins_Construct(BaseFilter *base, BaseFilter_GetPin receive_pin, BaseFilter_GetPinCount receive_pincount, BaseFilter_GetPinVersion receive_version, IEnumPins ** ppEnum); -/* Quality Control */ -typedef struct QualityControlImpl { - const IQualityControlVtbl *lpVtbl; - IPin *input; - IBaseFilter *self; - IQualityControl *tonotify; - - /* Render stuff */ - IReferenceClock *clock; - REFERENCE_TIME last_in_time, last_left, avg_duration, avg_pt, avg_render, start, stop; - REFERENCE_TIME current_jitter, current_rstart, current_rstop, clockstart; - double avg_rate; - LONG64 rendered, dropped; - BOOL qos_handled, is_dropped; -} QualityControlImpl; - -void QualityControlImpl_init(QualityControlImpl *This, IPin *input, IBaseFilter *self); -HRESULT WINAPI QualityControlImpl_QueryInterface(IQualityControl *iface, REFIID riid, void **ppv); -ULONG WINAPI QualityControlImpl_AddRef(IQualityControl *iface); -ULONG WINAPI QualityControlImpl_Release(IQualityControl *iface); -HRESULT WINAPI QualityControlImpl_Notify(IQualityControl *iface, IBaseFilter *sender, Quality qm); -HRESULT WINAPI QualityControlImpl_SetSink(IQualityControl *iface, IQualityControl *tonotify); - -void QualityControlRender_Start(QualityControlImpl *This, REFERENCE_TIME tStart); -void QualityControlRender_SetClock(QualityControlImpl *This, IReferenceClock *clock); -HRESULT QualityControlRender_WaitFor(QualityControlImpl *This, IMediaSample *sample, HANDLE ev); -void QualityControlRender_DoQOS(QualityControlImpl *priv); -void QualityControlRender_BeginRender(QualityControlImpl *This); -void QualityControlRender_EndRender(QualityControlImpl *This); - /* Transform Filter */ typedef struct TransformFilter { @@ -235,7 +205,7 @@ typedef struct TransformFilter CRITICAL_SECTION csReceive; const struct TransformFilterFuncTable * pFuncsTable; - QualityControlImpl qcimpl; + struct QualityControlImpl *qcimpl; } TransformFilter; typedef HRESULT (WINAPI *TransformFilter_DecideBufferSize) (TransformFilter *iface, IMemAllocator *pAlloc, ALLOCATOR_PROPERTIES *ppropInputRequest); @@ -277,6 +247,7 @@ HRESULT WINAPI TransformFilterImpl_Stop(IBaseFilter * iface); HRESULT WINAPI TransformFilterImpl_Pause(IBaseFilter * iface); HRESULT WINAPI TransformFilterImpl_Run(IBaseFilter * iface, REFERENCE_TIME tStart); HRESULT WINAPI TransformFilterImpl_FindPin(IBaseFilter * iface, LPCWSTR Id, IPin **ppPin); +HRESULT WINAPI TransformFilterImpl_Notify(TransformFilter *iface, IBaseFilter *sender, Quality qm); HRESULT TransformFilter_Construct( const IBaseFilterVtbl *filterVtbl, LONG filter_size, const CLSID* pClsid, const TransformFilterFuncTable* pFuncsTable, IBaseFilter ** ppTransformFilter); @@ -588,7 +559,7 @@ typedef struct BaseRendererTag IMediaSample *pMediaSample; IQualityControl *pQSink; - QualityControlImpl qcimpl; + struct QualityControlImpl *qcimpl; const struct BaseRendererFuncTable * pFuncsTable; } BaseRenderer;