From 2c945b01e04e3d8b507b938341f53fd5f0a032f7 Mon Sep 17 00:00:00 2001 From: Piotr Caban Date: Mon, 25 Nov 2013 16:25:06 +0100 Subject: [PATCH] qcap: Add AVI Mux output pin stub. --- dlls/qcap/avimux.c | 339 ++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 337 insertions(+), 2 deletions(-) diff --git a/dlls/qcap/avimux.c b/dlls/qcap/avimux.c index 99fcb4e9e3b..d369bf34de2 100644 --- a/dlls/qcap/avimux.c +++ b/dlls/qcap/avimux.c @@ -32,6 +32,13 @@ WINE_DEFAULT_DEBUG_CHANNEL(qcap); +static const WCHAR output_name[] = {'A','V','I',' ','O','u','t',0}; + +typedef struct { + BaseOutputPin pin; + IQualityControl IQualityControl_iface; +} AviMuxOut; + typedef struct { BaseFilter filter; IConfigAviMux IConfigAviMux_iface; @@ -39,6 +46,8 @@ typedef struct { IMediaSeeking IMediaSeeking_iface; IPersistMediaPropertyBag IPersistMediaPropertyBag_iface; ISpecifyPropertyPages ISpecifyPropertyPages_iface; + + AviMuxOut *out; } AviMux; static inline AviMux* impl_from_BaseFilter(BaseFilter *filter) @@ -50,6 +59,12 @@ static IPin* WINAPI AviMux_GetPin(BaseFilter *iface, int pos) { AviMux *This = impl_from_BaseFilter(iface); FIXME("(%p)->(%d)\n", This, pos); + + if(pos == 0) { + IPin_AddRef(&This->out->pin.pin.IPin_iface); + return &This->out->pin.pin.IPin_iface; + } + return NULL; } @@ -108,6 +123,12 @@ static ULONG WINAPI AviMux_Release(IBaseFilter *iface) TRACE("(%p) new refcount: %u\n", This, ref); if(!ref) { + if(This->out->pin.pin.pConnectedTo) { + IPin_Disconnect(This->out->pin.pin.pConnectedTo); + IPin_Disconnect(&This->out->pin.pin.IPin_iface); + } + BaseOutputPinImpl_Release(&This->out->pin.pin.IPin_iface); + HeapFree(GetProcessHeap(), 0, This); ObjectRefCount(FALSE); } @@ -138,14 +159,21 @@ static HRESULT WINAPI AviMux_Run(IBaseFilter *iface, REFERENCE_TIME tStart) static HRESULT WINAPI AviMux_EnumPins(IBaseFilter *iface, IEnumPins **ppEnum) { AviMux *This = impl_from_IBaseFilter(iface); - FIXME("(%p)->(%p)\n", This, ppEnum); - return E_NOTIMPL; + TRACE("(%p)->(%p)\n", This, ppEnum); + return BaseFilterImpl_EnumPins(iface, ppEnum); } static HRESULT WINAPI AviMux_FindPin(IBaseFilter *iface, LPCWSTR Id, IPin **ppPin) { AviMux *This = impl_from_IBaseFilter(iface); FIXME("(%p)->(%s %p)\n", This, debugstr_w(Id), ppPin); + + if(!lstrcmpiW(Id, output_name)) { + IPin_AddRef(&This->out->pin.pin.IPin_iface); + *ppPin = &This->out->pin.pin.IPin_iface; + return S_OK; + } + return E_NOTIMPL; } @@ -595,9 +623,302 @@ static const ISpecifyPropertyPagesVtbl SpecifyPropertyPagesVtbl = { SpecifyPropertyPages_GetPages }; +static HRESULT WINAPI AviMuxOut_AttemptConnection(BasePin *base, + IPin *pReceivePin, const AM_MEDIA_TYPE *pmt) +{ + TRACE("(%p)->(%p AM_MEDIA_TYPE(%p))\n", base, pReceivePin, pmt); + dump_AM_MEDIA_TYPE(pmt); + return BaseOutputPinImpl_AttemptConnection(base, pReceivePin, pmt); +} + +static LONG WINAPI AviMuxOut_GetMediaTypeVersion(BasePin *base) +{ + FIXME("(%p)\n", base); + return 0; +} + +static HRESULT WINAPI AviMuxOut_GetMediaType(BasePin *base, int iPosition, AM_MEDIA_TYPE *amt) +{ + TRACE("(%p)->(%d %p)\n", base, iPosition, amt); + + if(iPosition < 0) + return E_INVALIDARG; + if(iPosition > 0) + return VFW_S_NO_MORE_ITEMS; + + amt->majortype = MEDIATYPE_Stream; + amt->subtype = MEDIASUBTYPE_Avi; + amt->bFixedSizeSamples = TRUE; + amt->bTemporalCompression = FALSE; + amt->lSampleSize = 1; + amt->formattype = GUID_NULL; + amt->pUnk = NULL; + amt->cbFormat = 0; + amt->pbFormat = NULL; + return S_OK; +} + +static const BasePinFuncTable AviMuxOut_BaseFuncTable = { + NULL, + AviMuxOut_AttemptConnection, + AviMuxOut_GetMediaTypeVersion, + AviMuxOut_GetMediaType +}; + +static HRESULT WINAPI AviMuxOut_DecideBufferSize(BaseOutputPin *base, + IMemAllocator *pAlloc, ALLOCATOR_PROPERTIES *ppropInputRequest) +{ + FIXME("(%p)->(%p %p)\n", base, pAlloc, ppropInputRequest); + return E_NOTIMPL; +} + +static HRESULT WINAPI AviMuxOut_DecideAllocator(BaseOutputPin *base, + IMemInputPin *pPin, IMemAllocator **pAlloc) +{ + FIXME("(%p)->(%p %p)\n", base, pPin, pAlloc); + return E_NOTIMPL; +} + +static HRESULT WINAPI AviMuxOut_BreakConnect(BaseOutputPin *base) +{ + FIXME("(%p)\n", base); + return E_NOTIMPL; +} + +static const BaseOutputPinFuncTable AviMuxOut_BaseOutputFuncTable = { + AviMuxOut_DecideBufferSize, + AviMuxOut_DecideAllocator, + AviMuxOut_BreakConnect +}; + +static inline AviMux* impl_from_out_IPin(IPin *iface) +{ + BasePin *bp = CONTAINING_RECORD(iface, BasePin, IPin_iface); + IBaseFilter *bf = bp->pinInfo.pFilter; + + return impl_from_IBaseFilter(bf); +} + +static HRESULT WINAPI AviMuxOut_QueryInterface(IPin *iface, REFIID riid, void **ppv) +{ + AviMux *This = impl_from_out_IPin(iface); + + TRACE("(%p)->(%s %p)\n", This, debugstr_guid(riid), ppv); + + if(IsEqualIID(riid, &IID_IUnknown) || IsEqualIID(riid, &IID_IPin)) + *ppv = iface; + else if(IsEqualIID(riid, &IID_IQualityControl)) + *ppv = &This->out->IQualityControl_iface; + else { + FIXME("no interface for %s\n", debugstr_guid(riid)); + *ppv = NULL; + return E_NOINTERFACE; + } + + IUnknown_AddRef((IUnknown*)*ppv); + return S_OK; +} + +static ULONG WINAPI AviMuxOut_AddRef(IPin *iface) +{ + AviMux *This = impl_from_out_IPin(iface); + return IBaseFilter_AddRef(&This->filter.IBaseFilter_iface); +} + +static ULONG WINAPI AviMuxOut_Release(IPin *iface) +{ + AviMux *This = impl_from_out_IPin(iface); + return IBaseFilter_Release(&This->filter.IBaseFilter_iface); +} + +static HRESULT WINAPI AviMuxOut_Connect(IPin *iface, + IPin *pReceivePin, const AM_MEDIA_TYPE *pmt) +{ + AviMux *This = impl_from_out_IPin(iface); + TRACE("(%p)->(%p AM_MEDIA_TYPE(%p))\n", This, pReceivePin, pmt); + dump_AM_MEDIA_TYPE(pmt); + return BaseOutputPinImpl_Connect(iface, pReceivePin, pmt); +} + +static HRESULT WINAPI AviMuxOut_ReceiveConnection(IPin *iface, + IPin *pConnector, const AM_MEDIA_TYPE *pmt) +{ + AviMux *This = impl_from_out_IPin(iface); + TRACE("(%p)->(%p AM_MEDIA_TYPE(%p)\n", This, pConnector, pmt); + dump_AM_MEDIA_TYPE(pmt); + return BaseOutputPinImpl_ReceiveConnection(iface, pConnector, pmt); +} + +static HRESULT WINAPI AviMuxOut_Disconnect(IPin *iface) +{ + AviMux *This = impl_from_out_IPin(iface); + TRACE("(%p)\n", This); + return BaseOutputPinImpl_Disconnect(iface); +} + +static HRESULT WINAPI AviMuxOut_ConnectedTo(IPin *iface, IPin **pPin) +{ + AviMux *This = impl_from_out_IPin(iface); + TRACE("(%p)->(%p)\n", This, pPin); + return BasePinImpl_ConnectedTo(iface, pPin); +} + +static HRESULT WINAPI AviMuxOut_ConnectionMediaType(IPin *iface, AM_MEDIA_TYPE *pmt) +{ + AviMux *This = impl_from_out_IPin(iface); + TRACE("(%p)->(%p)\n", This, pmt); + return BasePinImpl_ConnectionMediaType(iface, pmt); +} + +static HRESULT WINAPI AviMuxOut_QueryPinInfo(IPin *iface, PIN_INFO *pInfo) +{ + AviMux *This = impl_from_out_IPin(iface); + TRACE("(%p)->(%p)\n", This, pInfo); + return BasePinImpl_QueryPinInfo(iface, pInfo); +} + +static HRESULT WINAPI AviMuxOut_QueryDirection(IPin *iface, PIN_DIRECTION *pPinDir) +{ + AviMux *This = impl_from_out_IPin(iface); + TRACE("(%p)->(%p)\n", This, pPinDir); + return BasePinImpl_QueryDirection(iface, pPinDir); +} + +static HRESULT WINAPI AviMuxOut_QueryId(IPin *iface, LPWSTR *Id) +{ + AviMux *This = impl_from_out_IPin(iface); + TRACE("(%p)->(%p)\n", This, Id); + return BasePinImpl_QueryId(iface, Id); +} + +static HRESULT WINAPI AviMuxOut_QueryAccept(IPin *iface, const AM_MEDIA_TYPE *pmt) +{ + AviMux *This = impl_from_out_IPin(iface); + TRACE("(%p)->(AM_MEDIA_TYPE(%p))\n", This, pmt); + dump_AM_MEDIA_TYPE(pmt); + return BasePinImpl_QueryAccept(iface, pmt); +} + +static HRESULT WINAPI AviMuxOut_EnumMediaTypes(IPin *iface, IEnumMediaTypes **ppEnum) +{ + AviMux *This = impl_from_out_IPin(iface); + TRACE("(%p)->(%p)\n", This, ppEnum); + return BasePinImpl_EnumMediaTypes(iface, ppEnum); +} + +static HRESULT WINAPI AviMuxOut_QueryInternalConnections( + IPin *iface, IPin **apPin, ULONG *nPin) +{ + AviMux *This = impl_from_out_IPin(iface); + FIXME("(%p)->(%p %p)\n", This, apPin, nPin); + return E_NOTIMPL; +} + +static HRESULT WINAPI AviMuxOut_EndOfStream(IPin *iface) +{ + AviMux *This = impl_from_out_IPin(iface); + TRACE("(%p)\n", This); + return BaseOutputPinImpl_EndOfStream(iface); +} + +static HRESULT WINAPI AviMuxOut_BeginFlush(IPin *iface) +{ + AviMux *This = impl_from_out_IPin(iface); + TRACE("(%p)\n", This); + return BaseOutputPinImpl_BeginFlush(iface); +} + +static HRESULT WINAPI AviMuxOut_EndFlush(IPin *iface) +{ + AviMux *This = impl_from_out_IPin(iface); + TRACE("(%p)\n", This); + return BaseOutputPinImpl_EndFlush(iface); +} + +static HRESULT WINAPI AviMuxOut_NewSegment(IPin *iface, REFERENCE_TIME tStart, + REFERENCE_TIME tStop, double dRate) +{ + AviMux *This = impl_from_out_IPin(iface); + TRACE("(%p)->(0x%x%08x 0x%x%08x %lf)\n", This, (ULONG)(tStart >> 32), + (ULONG)tStart, (ULONG)(tStop >> 32), (ULONG)tStop, dRate); + return BasePinImpl_NewSegment(iface, tStart, tStop, dRate); +} + +static const IPinVtbl AviMuxOut_PinVtbl = { + AviMuxOut_QueryInterface, + AviMuxOut_AddRef, + AviMuxOut_Release, + AviMuxOut_Connect, + AviMuxOut_ReceiveConnection, + AviMuxOut_Disconnect, + AviMuxOut_ConnectedTo, + AviMuxOut_ConnectionMediaType, + AviMuxOut_QueryPinInfo, + AviMuxOut_QueryDirection, + AviMuxOut_QueryId, + AviMuxOut_QueryAccept, + AviMuxOut_EnumMediaTypes, + AviMuxOut_QueryInternalConnections, + AviMuxOut_EndOfStream, + AviMuxOut_BeginFlush, + AviMuxOut_EndFlush, + AviMuxOut_NewSegment +}; + +static inline AviMux* impl_from_out_IQualityControl(IQualityControl *iface) +{ + AviMuxOut *amo = CONTAINING_RECORD(iface, AviMuxOut, IQualityControl_iface); + return impl_from_IBaseFilter(amo->pin.pin.pinInfo.pFilter); +} + +static HRESULT WINAPI AviMuxOut_QualityControl_QueryInterface( + IQualityControl *iface, REFIID riid, void **ppv) +{ + AviMux *This = impl_from_out_IQualityControl(iface); + return IPin_QueryInterface(&This->out->pin.pin.IPin_iface, riid, ppv); +} + +static ULONG WINAPI AviMuxOut_QualityControl_AddRef(IQualityControl *iface) +{ + AviMux *This = impl_from_out_IQualityControl(iface); + return IBaseFilter_AddRef(&This->filter.IBaseFilter_iface); +} + +static ULONG WINAPI AviMuxOut_QualityControl_Release(IQualityControl *iface) +{ + AviMux *This = impl_from_out_IQualityControl(iface); + return IBaseFilter_Release(&This->filter.IBaseFilter_iface); +} + +static HRESULT WINAPI AviMuxOut_QualityControl_Notify(IQualityControl *iface, + IBaseFilter *pSelf, Quality q) +{ + AviMux *This = impl_from_out_IQualityControl(iface); + FIXME("(%p)->(%p Quality)\n", This, pSelf); + return E_NOTIMPL; +} + +static HRESULT WINAPI AviMuxOut_QualityControl_SetSink( + IQualityControl *iface, IQualityControl *piqc) +{ + AviMux *This = impl_from_out_IQualityControl(iface); + FIXME("(%p)->(%p)\n", This, piqc); + return E_NOTIMPL; +} + +static const IQualityControlVtbl AviMuxOut_QualityControlVtbl = { + AviMuxOut_QualityControl_QueryInterface, + AviMuxOut_QualityControl_AddRef, + AviMuxOut_QualityControl_Release, + AviMuxOut_QualityControl_Notify, + AviMuxOut_QualityControl_SetSink +}; + IUnknown* WINAPI QCAP_createAVIMux(IUnknown *pUnkOuter, HRESULT *phr) { AviMux *avimux; + PIN_INFO info; + HRESULT hr; TRACE("(%p)\n", pUnkOuter); @@ -620,6 +941,20 @@ IUnknown* WINAPI QCAP_createAVIMux(IUnknown *pUnkOuter, HRESULT *phr) avimux->IPersistMediaPropertyBag_iface.lpVtbl = &PersistMediaPropertyBagVtbl; avimux->ISpecifyPropertyPages_iface.lpVtbl = &SpecifyPropertyPagesVtbl; + info.dir = PINDIR_OUTPUT; + info.pFilter = &avimux->filter.IBaseFilter_iface; + lstrcpyW(info.achName, output_name); + hr = BaseOutputPin_Construct(&AviMuxOut_PinVtbl, sizeof(AviMuxOut), &info, + &AviMuxOut_BaseFuncTable, &AviMuxOut_BaseOutputFuncTable, + &avimux->filter.csFilter, (IPin**)&avimux->out); + if(FAILED(hr)) { + BaseFilterImpl_Release(&avimux->filter.IBaseFilter_iface); + HeapFree(GetProcessHeap(), 0, avimux); + *phr = hr; + return NULL; + } + avimux->out->IQualityControl_iface.lpVtbl = &AviMuxOut_QualityControlVtbl; + ObjectRefCount(TRUE); *phr = S_OK; return (IUnknown*)&avimux->filter.IBaseFilter_iface;