1c2c66affSColin Finck /* 2c2c66affSColin Finck * Generic Implementation of IPin Interface 3c2c66affSColin Finck * 4c2c66affSColin Finck * Copyright 2003 Robert Shearman 5c2c66affSColin Finck * Copyright 2010 Aric Stewart, CodeWeavers 6c2c66affSColin Finck * 7c2c66affSColin Finck * This library is free software; you can redistribute it and/or 8c2c66affSColin Finck * modify it under the terms of the GNU Lesser General Public 9c2c66affSColin Finck * License as published by the Free Software Foundation; either 10c2c66affSColin Finck * version 2.1 of the License, or (at your option) any later version. 11c2c66affSColin Finck * 12c2c66affSColin Finck * This library is distributed in the hope that it will be useful, 13c2c66affSColin Finck * but WITHOUT ANY WARRANTY; without even the implied warranty of 14c2c66affSColin Finck * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 15c2c66affSColin Finck * Lesser General Public License for more details. 16c2c66affSColin Finck * 17c2c66affSColin Finck * You should have received a copy of the GNU Lesser General Public 18c2c66affSColin Finck * License along with this library; if not, write to the Free Software 19c2c66affSColin Finck * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA 20c2c66affSColin Finck */ 21c2c66affSColin Finck 22c2c66affSColin Finck #include "strmbase_private.h" 23c2c66affSColin Finck 24c2c66affSColin Finck static const IMemInputPinVtbl MemInputPin_Vtbl; 25c2c66affSColin Finck 26c2c66affSColin Finck typedef HRESULT (*SendPinFunc)( IPin *to, LPVOID arg ); 27c2c66affSColin Finck 28c2c66affSColin Finck static inline BasePin *impl_from_IPin( IPin *iface ) 29c2c66affSColin Finck { 30c2c66affSColin Finck return CONTAINING_RECORD(iface, BasePin, IPin_iface); 31c2c66affSColin Finck } 32c2c66affSColin Finck 33c2c66affSColin Finck /** Helper function, there are a lot of places where the error code is inherited 34c2c66affSColin Finck * The following rules apply: 35c2c66affSColin Finck * 36c2c66affSColin Finck * Return the first received error code (E_NOTIMPL is ignored) 37c2c66affSColin Finck * If no errors occur: return the first received non-error-code that isn't S_OK 38c2c66affSColin Finck */ 39c2c66affSColin Finck static HRESULT updatehres( HRESULT original, HRESULT new ) 40c2c66affSColin Finck { 41c2c66affSColin Finck if (FAILED( original ) || new == E_NOTIMPL) 42c2c66affSColin Finck return original; 43c2c66affSColin Finck 44c2c66affSColin Finck if (FAILED( new ) || original == S_OK) 45c2c66affSColin Finck return new; 46c2c66affSColin Finck 47c2c66affSColin Finck return original; 48c2c66affSColin Finck } 49c2c66affSColin Finck 50c2c66affSColin Finck /** Sends a message from a pin further to other, similar pins 51c2c66affSColin Finck * fnMiddle is called on each pin found further on the stream. 52c2c66affSColin Finck * fnEnd (can be NULL) is called when the message can't be sent any further (this is a renderer or source) 53c2c66affSColin Finck * 54c2c66affSColin Finck * If the pin given is an input pin, the message will be sent downstream to other input pins 55c2c66affSColin Finck * If the pin given is an output pin, the message will be sent upstream to other output pins 56c2c66affSColin Finck */ 57c2c66affSColin Finck static HRESULT SendFurther( IPin *from, SendPinFunc fnMiddle, LPVOID arg, SendPinFunc fnEnd ) 58c2c66affSColin Finck { 59c2c66affSColin Finck PIN_INFO pin_info; 60c2c66affSColin Finck ULONG amount = 0; 61c2c66affSColin Finck HRESULT hr = S_OK; 62c2c66affSColin Finck HRESULT hr_return = S_OK; 63c2c66affSColin Finck IEnumPins *enumpins = NULL; 64c2c66affSColin Finck BOOL foundend = TRUE; 65c2c66affSColin Finck PIN_DIRECTION from_dir; 66c2c66affSColin Finck 67c2c66affSColin Finck IPin_QueryDirection( from, &from_dir ); 68c2c66affSColin Finck 69c2c66affSColin Finck hr = IPin_QueryInternalConnections( from, NULL, &amount ); 70c2c66affSColin Finck if (hr != E_NOTIMPL && amount) 71c2c66affSColin Finck FIXME("Use QueryInternalConnections!\n"); 72c2c66affSColin Finck 73c2c66affSColin Finck pin_info.pFilter = NULL; 74c2c66affSColin Finck hr = IPin_QueryPinInfo( from, &pin_info ); 75c2c66affSColin Finck if (FAILED(hr)) 76c2c66affSColin Finck goto out; 77c2c66affSColin Finck 78c2c66affSColin Finck hr = IBaseFilter_EnumPins( pin_info.pFilter, &enumpins ); 79c2c66affSColin Finck if (FAILED(hr)) 80c2c66affSColin Finck goto out; 81c2c66affSColin Finck 82c2c66affSColin Finck hr = IEnumPins_Reset( enumpins ); 83c2c66affSColin Finck while (hr == S_OK) { 84c2c66affSColin Finck IPin *pin = NULL; 85c2c66affSColin Finck hr = IEnumPins_Next( enumpins, 1, &pin, NULL ); 86c2c66affSColin Finck if (hr == VFW_E_ENUM_OUT_OF_SYNC) 87c2c66affSColin Finck { 88c2c66affSColin Finck hr = IEnumPins_Reset( enumpins ); 89c2c66affSColin Finck continue; 90c2c66affSColin Finck } 91c2c66affSColin Finck if (pin) 92c2c66affSColin Finck { 93c2c66affSColin Finck PIN_DIRECTION dir; 94c2c66affSColin Finck 95c2c66affSColin Finck IPin_QueryDirection( pin, &dir ); 96c2c66affSColin Finck if (dir != from_dir) 97c2c66affSColin Finck { 98c2c66affSColin Finck IPin *connected = NULL; 99c2c66affSColin Finck 100c2c66affSColin Finck foundend = FALSE; 101c2c66affSColin Finck IPin_ConnectedTo( pin, &connected ); 102c2c66affSColin Finck if (connected) 103c2c66affSColin Finck { 104c2c66affSColin Finck HRESULT hr_local; 105c2c66affSColin Finck 106c2c66affSColin Finck hr_local = fnMiddle( connected, arg ); 107c2c66affSColin Finck hr_return = updatehres( hr_return, hr_local ); 108c2c66affSColin Finck IPin_Release(connected); 109c2c66affSColin Finck } 110c2c66affSColin Finck } 111c2c66affSColin Finck IPin_Release( pin ); 112c2c66affSColin Finck } 113c2c66affSColin Finck else 114c2c66affSColin Finck { 115c2c66affSColin Finck hr = S_OK; 116c2c66affSColin Finck break; 117c2c66affSColin Finck } 118c2c66affSColin Finck } 119c2c66affSColin Finck 120c2c66affSColin Finck if (!foundend) 121c2c66affSColin Finck hr = hr_return; 122c2c66affSColin Finck else if (fnEnd) { 123c2c66affSColin Finck HRESULT hr_local; 124c2c66affSColin Finck 125c2c66affSColin Finck hr_local = fnEnd( from, arg ); 126c2c66affSColin Finck hr_return = updatehres( hr_return, hr_local ); 127c2c66affSColin Finck } 128c2c66affSColin Finck IEnumPins_Release(enumpins); 129c2c66affSColin Finck 130c2c66affSColin Finck out: 131c2c66affSColin Finck if (pin_info.pFilter) 132c2c66affSColin Finck IBaseFilter_Release( pin_info.pFilter ); 133c2c66affSColin Finck return hr; 134c2c66affSColin Finck } 135c2c66affSColin Finck 136c2c66affSColin Finck static void Copy_PinInfo(PIN_INFO * pDest, const PIN_INFO * pSrc) 137c2c66affSColin Finck { 138c2c66affSColin Finck /* Tempting to just do a memcpy, but the name field is 139c2c66affSColin Finck 128 characters long! We will probably never exceed 10 140c2c66affSColin Finck most of the time, so we are better off copying 141c2c66affSColin Finck each field manually */ 142c2c66affSColin Finck strcpyW(pDest->achName, pSrc->achName); 143c2c66affSColin Finck pDest->dir = pSrc->dir; 144c2c66affSColin Finck pDest->pFilter = pSrc->pFilter; 145c2c66affSColin Finck } 146c2c66affSColin Finck 147c2c66affSColin Finck static void dump_AM_MEDIA_TYPE(const AM_MEDIA_TYPE * pmt) 148c2c66affSColin Finck { 149c2c66affSColin Finck if (!pmt) 150c2c66affSColin Finck return; 151c2c66affSColin Finck TRACE("\t%s\n\t%s\n\t...\n\t%s\n", debugstr_guid(&pmt->majortype), debugstr_guid(&pmt->subtype), debugstr_guid(&pmt->formattype)); 152c2c66affSColin Finck } 153c2c66affSColin Finck 154c2c66affSColin Finck static BOOL CompareMediaTypes(const AM_MEDIA_TYPE * pmt1, const AM_MEDIA_TYPE * pmt2, BOOL bWildcards) 155c2c66affSColin Finck { 156c2c66affSColin Finck TRACE("pmt1: "); 157c2c66affSColin Finck dump_AM_MEDIA_TYPE(pmt1); 158c2c66affSColin Finck TRACE("pmt2: "); 159c2c66affSColin Finck dump_AM_MEDIA_TYPE(pmt2); 160c2c66affSColin Finck return (((bWildcards && (IsEqualGUID(&pmt1->majortype, &GUID_NULL) || IsEqualGUID(&pmt2->majortype, &GUID_NULL))) || IsEqualGUID(&pmt1->majortype, &pmt2->majortype)) && 161c2c66affSColin Finck ((bWildcards && (IsEqualGUID(&pmt1->subtype, &GUID_NULL) || IsEqualGUID(&pmt2->subtype, &GUID_NULL))) || IsEqualGUID(&pmt1->subtype, &pmt2->subtype))); 162c2c66affSColin Finck } 163c2c66affSColin Finck 164c2c66affSColin Finck /*** Common Base Pin function */ 165c2c66affSColin Finck HRESULT WINAPI BasePinImpl_GetMediaType(BasePin *iface, int iPosition, AM_MEDIA_TYPE *pmt) 166c2c66affSColin Finck { 167c2c66affSColin Finck if (iPosition < 0) 168c2c66affSColin Finck return E_INVALIDARG; 169c2c66affSColin Finck return VFW_S_NO_MORE_ITEMS; 170c2c66affSColin Finck } 171c2c66affSColin Finck 172c2c66affSColin Finck LONG WINAPI BasePinImpl_GetMediaTypeVersion(BasePin *iface) 173c2c66affSColin Finck { 174c2c66affSColin Finck return 1; 175c2c66affSColin Finck } 176c2c66affSColin Finck 177c2c66affSColin Finck ULONG WINAPI BasePinImpl_AddRef(IPin * iface) 178c2c66affSColin Finck { 179c2c66affSColin Finck BasePin *This = impl_from_IPin(iface); 180c2c66affSColin Finck ULONG refCount = InterlockedIncrement(&This->refCount); 181c2c66affSColin Finck 182c2c66affSColin Finck TRACE("(%p)->() AddRef from %d\n", iface, refCount - 1); 183c2c66affSColin Finck 184c2c66affSColin Finck return refCount; 185c2c66affSColin Finck } 186c2c66affSColin Finck 187c2c66affSColin Finck HRESULT WINAPI BasePinImpl_Disconnect(IPin * iface) 188c2c66affSColin Finck { 189c2c66affSColin Finck HRESULT hr; 190c2c66affSColin Finck BasePin *This = impl_from_IPin(iface); 191c2c66affSColin Finck 192c2c66affSColin Finck TRACE("()\n"); 193c2c66affSColin Finck 194c2c66affSColin Finck EnterCriticalSection(This->pCritSec); 195c2c66affSColin Finck { 196c2c66affSColin Finck if (This->pConnectedTo) 197c2c66affSColin Finck { 198c2c66affSColin Finck IPin_Release(This->pConnectedTo); 199c2c66affSColin Finck This->pConnectedTo = NULL; 200c2c66affSColin Finck FreeMediaType(&This->mtCurrent); 201c2c66affSColin Finck ZeroMemory(&This->mtCurrent, sizeof(This->mtCurrent)); 202c2c66affSColin Finck hr = S_OK; 203c2c66affSColin Finck } 204c2c66affSColin Finck else 205c2c66affSColin Finck hr = S_FALSE; 206c2c66affSColin Finck } 207c2c66affSColin Finck LeaveCriticalSection(This->pCritSec); 208c2c66affSColin Finck 209c2c66affSColin Finck return hr; 210c2c66affSColin Finck } 211c2c66affSColin Finck 212c2c66affSColin Finck HRESULT WINAPI BasePinImpl_ConnectedTo(IPin * iface, IPin ** ppPin) 213c2c66affSColin Finck { 214c2c66affSColin Finck HRESULT hr; 215c2c66affSColin Finck BasePin *This = impl_from_IPin(iface); 216c2c66affSColin Finck 217c2c66affSColin Finck TRACE("(%p)\n", ppPin); 218c2c66affSColin Finck 219c2c66affSColin Finck EnterCriticalSection(This->pCritSec); 220c2c66affSColin Finck { 221c2c66affSColin Finck if (This->pConnectedTo) 222c2c66affSColin Finck { 223c2c66affSColin Finck *ppPin = This->pConnectedTo; 224c2c66affSColin Finck IPin_AddRef(*ppPin); 225c2c66affSColin Finck hr = S_OK; 226c2c66affSColin Finck } 227c2c66affSColin Finck else 228c2c66affSColin Finck { 229c2c66affSColin Finck hr = VFW_E_NOT_CONNECTED; 230c2c66affSColin Finck *ppPin = NULL; 231c2c66affSColin Finck } 232c2c66affSColin Finck } 233c2c66affSColin Finck LeaveCriticalSection(This->pCritSec); 234c2c66affSColin Finck 235c2c66affSColin Finck return hr; 236c2c66affSColin Finck } 237c2c66affSColin Finck 238c2c66affSColin Finck HRESULT WINAPI BasePinImpl_ConnectionMediaType(IPin * iface, AM_MEDIA_TYPE * pmt) 239c2c66affSColin Finck { 240c2c66affSColin Finck HRESULT hr; 241c2c66affSColin Finck BasePin *This = impl_from_IPin(iface); 242c2c66affSColin Finck 243c2c66affSColin Finck TRACE("(%p/%p)->(%p)\n", This, iface, pmt); 244c2c66affSColin Finck 245c2c66affSColin Finck EnterCriticalSection(This->pCritSec); 246c2c66affSColin Finck { 247c2c66affSColin Finck if (This->pConnectedTo) 248c2c66affSColin Finck { 249c2c66affSColin Finck CopyMediaType(pmt, &This->mtCurrent); 250c2c66affSColin Finck hr = S_OK; 251c2c66affSColin Finck } 252c2c66affSColin Finck else 253c2c66affSColin Finck { 254c2c66affSColin Finck ZeroMemory(pmt, sizeof(*pmt)); 255c2c66affSColin Finck hr = VFW_E_NOT_CONNECTED; 256c2c66affSColin Finck } 257c2c66affSColin Finck } 258c2c66affSColin Finck LeaveCriticalSection(This->pCritSec); 259c2c66affSColin Finck 260c2c66affSColin Finck return hr; 261c2c66affSColin Finck } 262c2c66affSColin Finck 263c2c66affSColin Finck HRESULT WINAPI BasePinImpl_QueryPinInfo(IPin * iface, PIN_INFO * pInfo) 264c2c66affSColin Finck { 265c2c66affSColin Finck BasePin *This = impl_from_IPin(iface); 266c2c66affSColin Finck 267c2c66affSColin Finck TRACE("(%p/%p)->(%p)\n", This, iface, pInfo); 268c2c66affSColin Finck 269c2c66affSColin Finck Copy_PinInfo(pInfo, &This->pinInfo); 270c2c66affSColin Finck IBaseFilter_AddRef(pInfo->pFilter); 271c2c66affSColin Finck 272c2c66affSColin Finck return S_OK; 273c2c66affSColin Finck } 274c2c66affSColin Finck 275c2c66affSColin Finck HRESULT WINAPI BasePinImpl_QueryDirection(IPin * iface, PIN_DIRECTION * pPinDir) 276c2c66affSColin Finck { 277c2c66affSColin Finck BasePin *This = impl_from_IPin(iface); 278c2c66affSColin Finck 279c2c66affSColin Finck TRACE("(%p/%p)->(%p)\n", This, iface, pPinDir); 280c2c66affSColin Finck 281c2c66affSColin Finck *pPinDir = This->pinInfo.dir; 282c2c66affSColin Finck 283c2c66affSColin Finck return S_OK; 284c2c66affSColin Finck } 285c2c66affSColin Finck 286c2c66affSColin Finck HRESULT WINAPI BasePinImpl_QueryId(IPin * iface, LPWSTR * Id) 287c2c66affSColin Finck { 288c2c66affSColin Finck BasePin *This = impl_from_IPin(iface); 289c2c66affSColin Finck 290c2c66affSColin Finck TRACE("(%p/%p)->(%p)\n", This, iface, Id); 291c2c66affSColin Finck 292c2c66affSColin Finck *Id = CoTaskMemAlloc((strlenW(This->pinInfo.achName) + 1) * sizeof(WCHAR)); 293c2c66affSColin Finck if (!*Id) 294c2c66affSColin Finck return E_OUTOFMEMORY; 295c2c66affSColin Finck 296c2c66affSColin Finck strcpyW(*Id, This->pinInfo.achName); 297c2c66affSColin Finck 298c2c66affSColin Finck return S_OK; 299c2c66affSColin Finck } 300c2c66affSColin Finck 301c2c66affSColin Finck HRESULT WINAPI BasePinImpl_QueryAccept(IPin * iface, const AM_MEDIA_TYPE * pmt) 302c2c66affSColin Finck { 303c2c66affSColin Finck TRACE("(%p)->(%p)\n", iface, pmt); 304c2c66affSColin Finck 305c2c66affSColin Finck return S_OK; 306c2c66affSColin Finck } 307c2c66affSColin Finck 308c2c66affSColin Finck HRESULT WINAPI BasePinImpl_EnumMediaTypes(IPin * iface, IEnumMediaTypes ** ppEnum) 309c2c66affSColin Finck { 310c2c66affSColin Finck BasePin *This = impl_from_IPin(iface); 311c2c66affSColin Finck 312c2c66affSColin Finck TRACE("(%p/%p)->(%p)\n", This, iface, ppEnum); 313c2c66affSColin Finck 314c2c66affSColin Finck /* override this method to allow enumeration of your types */ 315c2c66affSColin Finck 316c2c66affSColin Finck return EnumMediaTypes_Construct(This, This->pFuncsTable->pfnGetMediaType, This->pFuncsTable->pfnGetMediaTypeVersion , ppEnum); 317c2c66affSColin Finck } 318c2c66affSColin Finck 319c2c66affSColin Finck HRESULT WINAPI BasePinImpl_QueryInternalConnections(IPin * iface, IPin ** apPin, ULONG * cPin) 320c2c66affSColin Finck { 321c2c66affSColin Finck BasePin *This = impl_from_IPin(iface); 322c2c66affSColin Finck 323c2c66affSColin Finck TRACE("(%p/%p)->(%p, %p)\n", This, iface, apPin, cPin); 324c2c66affSColin Finck 325c2c66affSColin Finck return E_NOTIMPL; /* to tell caller that all input pins connected to all output pins */ 326c2c66affSColin Finck } 327c2c66affSColin Finck 328c2c66affSColin Finck HRESULT WINAPI BasePinImpl_NewSegment(IPin * iface, REFERENCE_TIME tStart, REFERENCE_TIME tStop, double dRate) 329c2c66affSColin Finck { 330c2c66affSColin Finck BasePin *This = impl_from_IPin(iface); 331c2c66affSColin Finck 332*a7ef5747SThomas Faber TRACE("(%s, %s, %e)\n", wine_dbgstr_longlong(tStart), wine_dbgstr_longlong(tStop), dRate); 333c2c66affSColin Finck 334c2c66affSColin Finck This->tStart = tStart; 335c2c66affSColin Finck This->tStop = tStop; 336c2c66affSColin Finck This->dRate = dRate; 337c2c66affSColin Finck 338c2c66affSColin Finck return S_OK; 339c2c66affSColin Finck } 340c2c66affSColin Finck 341c2c66affSColin Finck /*** OutputPin implementation ***/ 342c2c66affSColin Finck 343c2c66affSColin Finck static inline BaseOutputPin *impl_BaseOutputPin_from_IPin( IPin *iface ) 344c2c66affSColin Finck { 345c2c66affSColin Finck return CONTAINING_RECORD(iface, BaseOutputPin, pin.IPin_iface); 346c2c66affSColin Finck } 347c2c66affSColin Finck 348c2c66affSColin Finck static inline BaseOutputPin *impl_BaseOutputPin_from_BasePin( BasePin *iface ) 349c2c66affSColin Finck { 350c2c66affSColin Finck return CONTAINING_RECORD(iface, BaseOutputPin, pin); 351c2c66affSColin Finck } 352c2c66affSColin Finck 353c2c66affSColin Finck HRESULT WINAPI BaseOutputPinImpl_QueryInterface(IPin * iface, REFIID riid, LPVOID * ppv) 354c2c66affSColin Finck { 355c2c66affSColin Finck BaseOutputPin *This = impl_BaseOutputPin_from_IPin(iface); 356c2c66affSColin Finck 357c2c66affSColin Finck TRACE("(%p/%p)->(%s, %p)\n", This, iface, debugstr_guid(riid), ppv); 358c2c66affSColin Finck 359c2c66affSColin Finck *ppv = NULL; 360c2c66affSColin Finck 361c2c66affSColin Finck if (IsEqualIID(riid, &IID_IUnknown)) 362c2c66affSColin Finck *ppv = iface; 363c2c66affSColin Finck else if (IsEqualIID(riid, &IID_IPin)) 364c2c66affSColin Finck *ppv = iface; 365c2c66affSColin Finck else if (IsEqualIID(riid, &IID_IMediaSeeking) || 366c2c66affSColin Finck IsEqualIID(riid, &IID_IQualityControl)) 367c2c66affSColin Finck { 368c2c66affSColin Finck return IBaseFilter_QueryInterface(This->pin.pinInfo.pFilter, riid, ppv); 369c2c66affSColin Finck } 370c2c66affSColin Finck 371c2c66affSColin Finck if (*ppv) 372c2c66affSColin Finck { 373c2c66affSColin Finck IUnknown_AddRef((IUnknown *)(*ppv)); 374c2c66affSColin Finck return S_OK; 375c2c66affSColin Finck } 376c2c66affSColin Finck 377c2c66affSColin Finck FIXME("No interface for %s!\n", debugstr_guid(riid)); 378c2c66affSColin Finck 379c2c66affSColin Finck return E_NOINTERFACE; 380c2c66affSColin Finck } 381c2c66affSColin Finck 382c2c66affSColin Finck ULONG WINAPI BaseOutputPinImpl_Release(IPin * iface) 383c2c66affSColin Finck { 384c2c66affSColin Finck BaseOutputPin *This = impl_BaseOutputPin_from_IPin(iface); 385c2c66affSColin Finck ULONG refCount = InterlockedDecrement(&This->pin.refCount); 386c2c66affSColin Finck 387c2c66affSColin Finck TRACE("(%p)->() Release from %d\n", iface, refCount + 1); 388c2c66affSColin Finck 389c2c66affSColin Finck if (!refCount) 390c2c66affSColin Finck BaseOutputPin_Destroy(This); 391*a7ef5747SThomas Faber 392c2c66affSColin Finck return refCount; 393c2c66affSColin Finck } 394c2c66affSColin Finck 395c2c66affSColin Finck HRESULT WINAPI BaseOutputPinImpl_Connect(IPin * iface, IPin * pReceivePin, const AM_MEDIA_TYPE * pmt) 396c2c66affSColin Finck { 397c2c66affSColin Finck HRESULT hr; 398c2c66affSColin Finck BaseOutputPin *This = impl_BaseOutputPin_from_IPin(iface); 399c2c66affSColin Finck 400c2c66affSColin Finck TRACE("(%p/%p)->(%p, %p)\n", This, iface, pReceivePin, pmt); 401c2c66affSColin Finck dump_AM_MEDIA_TYPE(pmt); 402c2c66affSColin Finck 403c2c66affSColin Finck if (!pReceivePin) 404c2c66affSColin Finck return E_POINTER; 405c2c66affSColin Finck 406c2c66affSColin Finck /* If we try to connect to ourselves, we will definitely deadlock. 407c2c66affSColin Finck * There are other cases where we could deadlock too, but this 408c2c66affSColin Finck * catches the obvious case */ 409c2c66affSColin Finck assert(pReceivePin != iface); 410c2c66affSColin Finck 411c2c66affSColin Finck EnterCriticalSection(This->pin.pCritSec); 412c2c66affSColin Finck { 413c2c66affSColin Finck /* if we have been a specific type to connect with, then we can either connect 414c2c66affSColin Finck * with that or fail. We cannot choose different AM_MEDIA_TYPE */ 415c2c66affSColin Finck if (pmt && !IsEqualGUID(&pmt->majortype, &GUID_NULL) && !IsEqualGUID(&pmt->subtype, &GUID_NULL)) 416c2c66affSColin Finck hr = This->pin.pFuncsTable->pfnAttemptConnection(&This->pin, pReceivePin, pmt); 417c2c66affSColin Finck else 418c2c66affSColin Finck { 419c2c66affSColin Finck /* negotiate media type */ 420c2c66affSColin Finck 421c2c66affSColin Finck IEnumMediaTypes * pEnumCandidates; 422c2c66affSColin Finck AM_MEDIA_TYPE * pmtCandidate = NULL; /* Candidate media type */ 423c2c66affSColin Finck 424c2c66affSColin Finck if (SUCCEEDED(hr = IPin_EnumMediaTypes(iface, &pEnumCandidates))) 425c2c66affSColin Finck { 426c2c66affSColin Finck hr = VFW_E_NO_ACCEPTABLE_TYPES; /* Assume the worst, but set to S_OK if connected successfully */ 427c2c66affSColin Finck 428c2c66affSColin Finck /* try this filter's media types first */ 429c2c66affSColin Finck while (S_OK == IEnumMediaTypes_Next(pEnumCandidates, 1, &pmtCandidate, NULL)) 430c2c66affSColin Finck { 431c2c66affSColin Finck assert(pmtCandidate); 432c2c66affSColin Finck dump_AM_MEDIA_TYPE(pmtCandidate); 433c2c66affSColin Finck if (!IsEqualGUID(&FORMAT_None, &pmtCandidate->formattype) 434c2c66affSColin Finck && !IsEqualGUID(&GUID_NULL, &pmtCandidate->formattype)) 435c2c66affSColin Finck assert(pmtCandidate->pbFormat); 436c2c66affSColin Finck if (( !pmt || CompareMediaTypes(pmt, pmtCandidate, TRUE) ) && 437c2c66affSColin Finck (This->pin.pFuncsTable->pfnAttemptConnection(&This->pin, pReceivePin, pmtCandidate) == S_OK)) 438c2c66affSColin Finck { 439c2c66affSColin Finck hr = S_OK; 440c2c66affSColin Finck DeleteMediaType(pmtCandidate); 441c2c66affSColin Finck break; 442c2c66affSColin Finck } 443c2c66affSColin Finck DeleteMediaType(pmtCandidate); 444c2c66affSColin Finck pmtCandidate = NULL; 445c2c66affSColin Finck } 446c2c66affSColin Finck IEnumMediaTypes_Release(pEnumCandidates); 447c2c66affSColin Finck } 448c2c66affSColin Finck 449c2c66affSColin Finck /* then try receiver filter's media types */ 450c2c66affSColin Finck if (hr != S_OK && SUCCEEDED(hr = IPin_EnumMediaTypes(pReceivePin, &pEnumCandidates))) /* if we haven't already connected successfully */ 451c2c66affSColin Finck { 452c2c66affSColin Finck ULONG fetched; 453c2c66affSColin Finck 454c2c66affSColin Finck hr = VFW_E_NO_ACCEPTABLE_TYPES; /* Assume the worst, but set to S_OK if connected successfully */ 455c2c66affSColin Finck 456c2c66affSColin Finck while (S_OK == IEnumMediaTypes_Next(pEnumCandidates, 1, &pmtCandidate, &fetched)) 457c2c66affSColin Finck { 458c2c66affSColin Finck assert(pmtCandidate); 459c2c66affSColin Finck dump_AM_MEDIA_TYPE(pmtCandidate); 460c2c66affSColin Finck if (( !pmt || CompareMediaTypes(pmt, pmtCandidate, TRUE) ) && 461c2c66affSColin Finck (This->pin.pFuncsTable->pfnAttemptConnection(&This->pin, pReceivePin, pmtCandidate) == S_OK)) 462c2c66affSColin Finck { 463c2c66affSColin Finck hr = S_OK; 464c2c66affSColin Finck DeleteMediaType(pmtCandidate); 465c2c66affSColin Finck break; 466c2c66affSColin Finck } 467c2c66affSColin Finck DeleteMediaType(pmtCandidate); 468c2c66affSColin Finck pmtCandidate = NULL; 469c2c66affSColin Finck } /* while */ 470c2c66affSColin Finck IEnumMediaTypes_Release(pEnumCandidates); 471c2c66affSColin Finck } /* if not found */ 472c2c66affSColin Finck } /* if negotiate media type */ 473c2c66affSColin Finck } /* if succeeded */ 474c2c66affSColin Finck LeaveCriticalSection(This->pin.pCritSec); 475c2c66affSColin Finck 476c2c66affSColin Finck TRACE(" -- %x\n", hr); 477c2c66affSColin Finck return hr; 478c2c66affSColin Finck } 479c2c66affSColin Finck 480c2c66affSColin Finck HRESULT WINAPI BaseOutputPinImpl_ReceiveConnection(IPin * iface, IPin * pReceivePin, const AM_MEDIA_TYPE * pmt) 481c2c66affSColin Finck { 482c2c66affSColin Finck ERR("Incoming connection on an output pin! (%p, %p)\n", pReceivePin, pmt); 483c2c66affSColin Finck 484c2c66affSColin Finck return E_UNEXPECTED; 485c2c66affSColin Finck } 486c2c66affSColin Finck 487c2c66affSColin Finck HRESULT WINAPI BaseOutputPinImpl_Disconnect(IPin * iface) 488c2c66affSColin Finck { 489c2c66affSColin Finck HRESULT hr; 490c2c66affSColin Finck BaseOutputPin *This = impl_BaseOutputPin_from_IPin(iface); 491c2c66affSColin Finck 492c2c66affSColin Finck TRACE("()\n"); 493c2c66affSColin Finck 494c2c66affSColin Finck EnterCriticalSection(This->pin.pCritSec); 495c2c66affSColin Finck { 496c2c66affSColin Finck if (This->pMemInputPin) 497c2c66affSColin Finck { 498c2c66affSColin Finck IMemInputPin_Release(This->pMemInputPin); 499c2c66affSColin Finck This->pMemInputPin = NULL; 500c2c66affSColin Finck } 501c2c66affSColin Finck if (This->pin.pConnectedTo) 502c2c66affSColin Finck { 503c2c66affSColin Finck IPin_Release(This->pin.pConnectedTo); 504c2c66affSColin Finck This->pin.pConnectedTo = NULL; 505c2c66affSColin Finck FreeMediaType(&This->pin.mtCurrent); 506c2c66affSColin Finck ZeroMemory(&This->pin.mtCurrent, sizeof(This->pin.mtCurrent)); 507c2c66affSColin Finck hr = S_OK; 508c2c66affSColin Finck } 509c2c66affSColin Finck else 510c2c66affSColin Finck hr = S_FALSE; 511c2c66affSColin Finck } 512c2c66affSColin Finck LeaveCriticalSection(This->pin.pCritSec); 513c2c66affSColin Finck 514c2c66affSColin Finck return hr; 515c2c66affSColin Finck } 516c2c66affSColin Finck 517c2c66affSColin Finck HRESULT WINAPI BaseOutputPinImpl_EndOfStream(IPin * iface) 518c2c66affSColin Finck { 519c2c66affSColin Finck TRACE("()\n"); 520c2c66affSColin Finck 521c2c66affSColin Finck /* not supposed to do anything in an output pin */ 522c2c66affSColin Finck 523c2c66affSColin Finck return E_UNEXPECTED; 524c2c66affSColin Finck } 525c2c66affSColin Finck 526c2c66affSColin Finck HRESULT WINAPI BaseOutputPinImpl_BeginFlush(IPin * iface) 527c2c66affSColin Finck { 528c2c66affSColin Finck TRACE("(%p)->()\n", iface); 529c2c66affSColin Finck 530c2c66affSColin Finck /* not supposed to do anything in an output pin */ 531c2c66affSColin Finck 532c2c66affSColin Finck return E_UNEXPECTED; 533c2c66affSColin Finck } 534c2c66affSColin Finck 535c2c66affSColin Finck HRESULT WINAPI BaseOutputPinImpl_EndFlush(IPin * iface) 536c2c66affSColin Finck { 537c2c66affSColin Finck TRACE("(%p)->()\n", iface); 538c2c66affSColin Finck 539c2c66affSColin Finck /* not supposed to do anything in an output pin */ 540c2c66affSColin Finck 541c2c66affSColin Finck return E_UNEXPECTED; 542c2c66affSColin Finck } 543c2c66affSColin Finck 544c2c66affSColin Finck HRESULT WINAPI BaseOutputPinImpl_GetDeliveryBuffer(BaseOutputPin *This, IMediaSample ** ppSample, REFERENCE_TIME * tStart, REFERENCE_TIME * tStop, DWORD dwFlags) 545c2c66affSColin Finck { 546c2c66affSColin Finck HRESULT hr; 547c2c66affSColin Finck 548c2c66affSColin Finck TRACE("(%p, %p, %p, %x)\n", ppSample, tStart, tStop, dwFlags); 549c2c66affSColin Finck 550c2c66affSColin Finck if (!This->pin.pConnectedTo) 551c2c66affSColin Finck hr = VFW_E_NOT_CONNECTED; 552c2c66affSColin Finck else 553c2c66affSColin Finck { 554c2c66affSColin Finck hr = IMemAllocator_GetBuffer(This->pAllocator, ppSample, tStart, tStop, dwFlags); 555c2c66affSColin Finck 556c2c66affSColin Finck if (SUCCEEDED(hr)) 557c2c66affSColin Finck hr = IMediaSample_SetTime(*ppSample, tStart, tStop); 558c2c66affSColin Finck } 559c2c66affSColin Finck 560c2c66affSColin Finck return hr; 561c2c66affSColin Finck } 562c2c66affSColin Finck 563c2c66affSColin Finck /* replaces OutputPin_SendSample */ 564c2c66affSColin Finck HRESULT WINAPI BaseOutputPinImpl_Deliver(BaseOutputPin *This, IMediaSample * pSample) 565c2c66affSColin Finck { 566c2c66affSColin Finck IMemInputPin * pMemConnected = NULL; 567c2c66affSColin Finck PIN_INFO pinInfo; 568c2c66affSColin Finck HRESULT hr; 569c2c66affSColin Finck 570c2c66affSColin Finck EnterCriticalSection(This->pin.pCritSec); 571c2c66affSColin Finck { 572c2c66affSColin Finck if (!This->pin.pConnectedTo || !This->pMemInputPin) 573c2c66affSColin Finck hr = VFW_E_NOT_CONNECTED; 574c2c66affSColin Finck else 575c2c66affSColin Finck { 576c2c66affSColin Finck /* we don't have the lock held when using This->pMemInputPin, 577c2c66affSColin Finck * so we need to AddRef it to stop it being deleted while we are 578c2c66affSColin Finck * using it. Same with its filter. */ 579c2c66affSColin Finck pMemConnected = This->pMemInputPin; 580c2c66affSColin Finck IMemInputPin_AddRef(pMemConnected); 581c2c66affSColin Finck hr = IPin_QueryPinInfo(This->pin.pConnectedTo, &pinInfo); 582c2c66affSColin Finck } 583c2c66affSColin Finck } 584c2c66affSColin Finck LeaveCriticalSection(This->pin.pCritSec); 585c2c66affSColin Finck 586c2c66affSColin Finck if (SUCCEEDED(hr)) 587c2c66affSColin Finck { 588c2c66affSColin Finck /* NOTE: if we are in a critical section when Receive is called 589c2c66affSColin Finck * then it causes some problems (most notably with the native Video 590c2c66affSColin Finck * Renderer) if we are re-entered for whatever reason */ 591c2c66affSColin Finck hr = IMemInputPin_Receive(pMemConnected, pSample); 592c2c66affSColin Finck 593c2c66affSColin Finck /* If the filter's destroyed, tell upstream to stop sending data */ 594c2c66affSColin Finck if(IBaseFilter_Release(pinInfo.pFilter) == 0 && SUCCEEDED(hr)) 595c2c66affSColin Finck hr = S_FALSE; 596c2c66affSColin Finck } 597c2c66affSColin Finck if (pMemConnected) 598c2c66affSColin Finck IMemInputPin_Release(pMemConnected); 599c2c66affSColin Finck 600c2c66affSColin Finck return hr; 601c2c66affSColin Finck } 602c2c66affSColin Finck 603c2c66affSColin Finck /* replaces OutputPin_CommitAllocator */ 604c2c66affSColin Finck HRESULT WINAPI BaseOutputPinImpl_Active(BaseOutputPin *This) 605c2c66affSColin Finck { 606c2c66affSColin Finck HRESULT hr; 607c2c66affSColin Finck 608c2c66affSColin Finck TRACE("(%p)->()\n", This); 609c2c66affSColin Finck 610c2c66affSColin Finck EnterCriticalSection(This->pin.pCritSec); 611c2c66affSColin Finck { 612c2c66affSColin Finck if (!This->pin.pConnectedTo || !This->pMemInputPin) 613c2c66affSColin Finck hr = VFW_E_NOT_CONNECTED; 614c2c66affSColin Finck else 615c2c66affSColin Finck hr = IMemAllocator_Commit(This->pAllocator); 616c2c66affSColin Finck } 617c2c66affSColin Finck LeaveCriticalSection(This->pin.pCritSec); 618c2c66affSColin Finck 619c2c66affSColin Finck TRACE("--> %08x\n", hr); 620c2c66affSColin Finck return hr; 621c2c66affSColin Finck } 622c2c66affSColin Finck 623c2c66affSColin Finck /* replaces OutputPin_DecommitAllocator */ 624c2c66affSColin Finck HRESULT WINAPI BaseOutputPinImpl_Inactive(BaseOutputPin *This) 625c2c66affSColin Finck { 626c2c66affSColin Finck HRESULT hr; 627c2c66affSColin Finck 628c2c66affSColin Finck TRACE("(%p)->()\n", This); 629c2c66affSColin Finck 630c2c66affSColin Finck EnterCriticalSection(This->pin.pCritSec); 631c2c66affSColin Finck { 632c2c66affSColin Finck if (!This->pin.pConnectedTo || !This->pMemInputPin) 633c2c66affSColin Finck hr = VFW_E_NOT_CONNECTED; 634c2c66affSColin Finck else 635c2c66affSColin Finck hr = IMemAllocator_Decommit(This->pAllocator); 636c2c66affSColin Finck } 637c2c66affSColin Finck LeaveCriticalSection(This->pin.pCritSec); 638c2c66affSColin Finck 639c2c66affSColin Finck TRACE("--> %08x\n", hr); 640c2c66affSColin Finck return hr; 641c2c66affSColin Finck } 642c2c66affSColin Finck 643c2c66affSColin Finck /* replaces OutputPin_DeliverDisconnect */ 644c2c66affSColin Finck HRESULT WINAPI BaseOutputPinImpl_BreakConnect(BaseOutputPin *This) 645c2c66affSColin Finck { 646c2c66affSColin Finck HRESULT hr; 647c2c66affSColin Finck 648c2c66affSColin Finck TRACE("(%p)->()\n", This); 649c2c66affSColin Finck 650c2c66affSColin Finck EnterCriticalSection(This->pin.pCritSec); 651c2c66affSColin Finck { 652c2c66affSColin Finck if (!This->pin.pConnectedTo || !This->pMemInputPin) 653c2c66affSColin Finck hr = VFW_E_NOT_CONNECTED; 654c2c66affSColin Finck else 655c2c66affSColin Finck { 656c2c66affSColin Finck hr = IMemAllocator_Decommit(This->pAllocator); 657c2c66affSColin Finck 658c2c66affSColin Finck if (SUCCEEDED(hr)) 659c2c66affSColin Finck hr = IPin_Disconnect(This->pin.pConnectedTo); 660c2c66affSColin Finck } 661c2c66affSColin Finck IPin_Disconnect(&This->pin.IPin_iface); 662c2c66affSColin Finck } 663c2c66affSColin Finck LeaveCriticalSection(This->pin.pCritSec); 664c2c66affSColin Finck 665c2c66affSColin Finck return hr; 666c2c66affSColin Finck } 667c2c66affSColin Finck 668c2c66affSColin Finck HRESULT WINAPI BaseOutputPinImpl_InitAllocator(BaseOutputPin *This, IMemAllocator **pMemAlloc) 669c2c66affSColin Finck { 670c2c66affSColin Finck return CoCreateInstance(&CLSID_MemoryAllocator, NULL, CLSCTX_INPROC_SERVER, &IID_IMemAllocator, (LPVOID*)pMemAlloc); 671c2c66affSColin Finck } 672c2c66affSColin Finck 673c2c66affSColin Finck HRESULT WINAPI BaseOutputPinImpl_DecideAllocator(BaseOutputPin *This, IMemInputPin *pPin, IMemAllocator **pAlloc) 674c2c66affSColin Finck { 675c2c66affSColin Finck HRESULT hr; 676c2c66affSColin Finck 677c2c66affSColin Finck hr = IMemInputPin_GetAllocator(pPin, pAlloc); 678c2c66affSColin Finck 679c2c66affSColin Finck if (hr == VFW_E_NO_ALLOCATOR) 680c2c66affSColin Finck /* Input pin provides no allocator, use standard memory allocator */ 681c2c66affSColin Finck hr = BaseOutputPinImpl_InitAllocator(This, pAlloc); 682c2c66affSColin Finck 683c2c66affSColin Finck if (SUCCEEDED(hr)) 684c2c66affSColin Finck { 685c2c66affSColin Finck ALLOCATOR_PROPERTIES rProps; 686c2c66affSColin Finck ZeroMemory(&rProps, sizeof(ALLOCATOR_PROPERTIES)); 687c2c66affSColin Finck 688c2c66affSColin Finck IMemInputPin_GetAllocatorRequirements(pPin, &rProps); 689c2c66affSColin Finck hr = This->pFuncsTable->pfnDecideBufferSize(This, *pAlloc, &rProps); 690c2c66affSColin Finck } 691c2c66affSColin Finck 692c2c66affSColin Finck if (SUCCEEDED(hr)) 693c2c66affSColin Finck hr = IMemInputPin_NotifyAllocator(pPin, *pAlloc, FALSE); 694c2c66affSColin Finck 695c2c66affSColin Finck return hr; 696c2c66affSColin Finck } 697c2c66affSColin Finck 698c2c66affSColin Finck /*** The Construct functions ***/ 699c2c66affSColin Finck 700c2c66affSColin Finck /* Function called as a helper to IPin_Connect */ 701c2c66affSColin Finck /* specific AM_MEDIA_TYPE - it cannot be NULL */ 702c2c66affSColin Finck HRESULT WINAPI BaseOutputPinImpl_AttemptConnection(BasePin* iface, IPin * pReceivePin, const AM_MEDIA_TYPE * pmt) 703c2c66affSColin Finck { 704c2c66affSColin Finck BaseOutputPin *This = impl_BaseOutputPin_from_BasePin(iface); 705c2c66affSColin Finck HRESULT hr; 706c2c66affSColin Finck IMemAllocator * pMemAlloc = NULL; 707c2c66affSColin Finck 708c2c66affSColin Finck TRACE("(%p, %p)\n", pReceivePin, pmt); 709c2c66affSColin Finck dump_AM_MEDIA_TYPE(pmt); 710c2c66affSColin Finck 711c2c66affSColin Finck /* FIXME: call queryacceptproc */ 712c2c66affSColin Finck 713c2c66affSColin Finck This->pin.pConnectedTo = pReceivePin; 714c2c66affSColin Finck IPin_AddRef(pReceivePin); 715c2c66affSColin Finck CopyMediaType(&This->pin.mtCurrent, pmt); 716c2c66affSColin Finck 717c2c66affSColin Finck hr = IPin_ReceiveConnection(pReceivePin, &iface->IPin_iface, pmt); 718c2c66affSColin Finck 719c2c66affSColin Finck /* get the IMemInputPin interface we will use to deliver samples to the 720c2c66affSColin Finck * connected pin */ 721c2c66affSColin Finck if (SUCCEEDED(hr)) 722c2c66affSColin Finck { 723c2c66affSColin Finck This->pMemInputPin = NULL; 724c2c66affSColin Finck hr = IPin_QueryInterface(pReceivePin, &IID_IMemInputPin, (LPVOID)&This->pMemInputPin); 725c2c66affSColin Finck 726c2c66affSColin Finck if (SUCCEEDED(hr)) 727c2c66affSColin Finck { 728c2c66affSColin Finck hr = This->pFuncsTable->pfnDecideAllocator(This, This->pMemInputPin, &pMemAlloc); 729c2c66affSColin Finck if (SUCCEEDED(hr)) 730c2c66affSColin Finck This->pAllocator = pMemAlloc; 731c2c66affSColin Finck else if (pMemAlloc) 732c2c66affSColin Finck IMemAllocator_Release(pMemAlloc); 733c2c66affSColin Finck } 734c2c66affSColin Finck 735c2c66affSColin Finck /* break connection if we couldn't get the allocator */ 736c2c66affSColin Finck if (FAILED(hr)) 737c2c66affSColin Finck { 738c2c66affSColin Finck if (This->pMemInputPin) 739c2c66affSColin Finck IMemInputPin_Release(This->pMemInputPin); 740c2c66affSColin Finck This->pMemInputPin = NULL; 741c2c66affSColin Finck 742c2c66affSColin Finck IPin_Disconnect(pReceivePin); 743c2c66affSColin Finck } 744c2c66affSColin Finck } 745c2c66affSColin Finck 746c2c66affSColin Finck if (FAILED(hr)) 747c2c66affSColin Finck { 748c2c66affSColin Finck IPin_Release(This->pin.pConnectedTo); 749c2c66affSColin Finck This->pin.pConnectedTo = NULL; 750c2c66affSColin Finck FreeMediaType(&This->pin.mtCurrent); 751c2c66affSColin Finck } 752c2c66affSColin Finck 753c2c66affSColin Finck TRACE(" -- %x\n", hr); 754c2c66affSColin Finck return hr; 755c2c66affSColin Finck } 756c2c66affSColin Finck 757c2c66affSColin Finck static HRESULT OutputPin_Init(const IPinVtbl *OutputPin_Vtbl, const PIN_INFO * pPinInfo, const BaseOutputPinFuncTable* vtbl, LPCRITICAL_SECTION pCritSec, BaseOutputPin * pPinImpl) 758c2c66affSColin Finck { 759c2c66affSColin Finck TRACE("\n"); 760c2c66affSColin Finck 761c2c66affSColin Finck /* Common attributes */ 762c2c66affSColin Finck pPinImpl->pin.IPin_iface.lpVtbl = OutputPin_Vtbl; 763c2c66affSColin Finck pPinImpl->pin.refCount = 1; 764c2c66affSColin Finck pPinImpl->pin.pConnectedTo = NULL; 765c2c66affSColin Finck pPinImpl->pin.pCritSec = pCritSec; 766c2c66affSColin Finck pPinImpl->pin.tStart = 0; 767c2c66affSColin Finck pPinImpl->pin.tStop = 0; 768c2c66affSColin Finck pPinImpl->pin.dRate = 1.0; 769c2c66affSColin Finck Copy_PinInfo(&pPinImpl->pin.pinInfo, pPinInfo); 770c2c66affSColin Finck pPinImpl->pin.pFuncsTable = &vtbl->base; 771c2c66affSColin Finck ZeroMemory(&pPinImpl->pin.mtCurrent, sizeof(AM_MEDIA_TYPE)); 772c2c66affSColin Finck 773c2c66affSColin Finck /* Output pin attributes */ 774c2c66affSColin Finck pPinImpl->pMemInputPin = NULL; 775c2c66affSColin Finck pPinImpl->pAllocator = NULL; 776c2c66affSColin Finck pPinImpl->pFuncsTable = vtbl; 777c2c66affSColin Finck 778c2c66affSColin Finck return S_OK; 779c2c66affSColin Finck } 780c2c66affSColin Finck 781c2c66affSColin Finck HRESULT WINAPI BaseOutputPin_Construct(const IPinVtbl *OutputPin_Vtbl, LONG outputpin_size, const PIN_INFO * pPinInfo, const BaseOutputPinFuncTable* vtbl, LPCRITICAL_SECTION pCritSec, IPin ** ppPin) 782c2c66affSColin Finck { 783c2c66affSColin Finck BaseOutputPin * pPinImpl; 784c2c66affSColin Finck 785c2c66affSColin Finck *ppPin = NULL; 786c2c66affSColin Finck 787c2c66affSColin Finck if (pPinInfo->dir != PINDIR_OUTPUT) 788c2c66affSColin Finck { 789c2c66affSColin Finck ERR("Pin direction(%x) != PINDIR_OUTPUT\n", pPinInfo->dir); 790c2c66affSColin Finck return E_INVALIDARG; 791c2c66affSColin Finck } 792c2c66affSColin Finck 793c2c66affSColin Finck assert(outputpin_size >= sizeof(BaseOutputPin)); 794c2c66affSColin Finck assert(vtbl->base.pfnAttemptConnection); 795c2c66affSColin Finck 796c2c66affSColin Finck pPinImpl = CoTaskMemAlloc(outputpin_size); 797c2c66affSColin Finck 798c2c66affSColin Finck if (!pPinImpl) 799c2c66affSColin Finck return E_OUTOFMEMORY; 800c2c66affSColin Finck 801c2c66affSColin Finck if (SUCCEEDED(OutputPin_Init(OutputPin_Vtbl, pPinInfo, vtbl, pCritSec, pPinImpl))) 802c2c66affSColin Finck { 803c2c66affSColin Finck *ppPin = &pPinImpl->pin.IPin_iface; 804c2c66affSColin Finck return S_OK; 805c2c66affSColin Finck } 806c2c66affSColin Finck 807c2c66affSColin Finck CoTaskMemFree(pPinImpl); 808c2c66affSColin Finck return E_FAIL; 809c2c66affSColin Finck } 810c2c66affSColin Finck 811c2c66affSColin Finck HRESULT WINAPI BaseOutputPin_Destroy(BaseOutputPin *This) 812c2c66affSColin Finck { 813c2c66affSColin Finck FreeMediaType(&This->pin.mtCurrent); 814c2c66affSColin Finck if (This->pAllocator) 815c2c66affSColin Finck IMemAllocator_Release(This->pAllocator); 816c2c66affSColin Finck This->pAllocator = NULL; 817c2c66affSColin Finck CoTaskMemFree(This); 818c2c66affSColin Finck return S_OK; 819c2c66affSColin Finck } 820c2c66affSColin Finck 821c2c66affSColin Finck /*** Input Pin implementation ***/ 822c2c66affSColin Finck 823c2c66affSColin Finck static inline BaseInputPin *impl_BaseInputPin_from_IPin( IPin *iface ) 824c2c66affSColin Finck { 825c2c66affSColin Finck return CONTAINING_RECORD(iface, BaseInputPin, pin.IPin_iface); 826c2c66affSColin Finck } 827c2c66affSColin Finck 828c2c66affSColin Finck HRESULT WINAPI BaseInputPinImpl_QueryInterface(IPin * iface, REFIID riid, LPVOID * ppv) 829c2c66affSColin Finck { 830c2c66affSColin Finck BaseInputPin *This = impl_BaseInputPin_from_IPin(iface); 831c2c66affSColin Finck 832c2c66affSColin Finck TRACE("(%p)->(%s, %p)\n", iface, debugstr_guid(riid), ppv); 833c2c66affSColin Finck 834c2c66affSColin Finck *ppv = NULL; 835c2c66affSColin Finck 836c2c66affSColin Finck if (IsEqualIID(riid, &IID_IUnknown)) 837c2c66affSColin Finck *ppv = iface; 838c2c66affSColin Finck else if (IsEqualIID(riid, &IID_IPin)) 839c2c66affSColin Finck *ppv = iface; 840c2c66affSColin Finck else if (IsEqualIID(riid, &IID_IMemInputPin)) 841c2c66affSColin Finck *ppv = &This->IMemInputPin_iface; 842c2c66affSColin Finck else if (IsEqualIID(riid, &IID_IMediaSeeking)) 843c2c66affSColin Finck { 844c2c66affSColin Finck return IBaseFilter_QueryInterface(This->pin.pinInfo.pFilter, &IID_IMediaSeeking, ppv); 845c2c66affSColin Finck } 846c2c66affSColin Finck 847c2c66affSColin Finck if (*ppv) 848c2c66affSColin Finck { 849c2c66affSColin Finck IUnknown_AddRef((IUnknown *)(*ppv)); 850c2c66affSColin Finck return S_OK; 851c2c66affSColin Finck } 852c2c66affSColin Finck 853c2c66affSColin Finck FIXME("No interface for %s!\n", debugstr_guid(riid)); 854c2c66affSColin Finck 855c2c66affSColin Finck return E_NOINTERFACE; 856c2c66affSColin Finck } 857c2c66affSColin Finck 858c2c66affSColin Finck ULONG WINAPI BaseInputPinImpl_Release(IPin * iface) 859c2c66affSColin Finck { 860c2c66affSColin Finck BaseInputPin *This = impl_BaseInputPin_from_IPin(iface); 861c2c66affSColin Finck ULONG refCount = InterlockedDecrement(&This->pin.refCount); 862c2c66affSColin Finck 863c2c66affSColin Finck TRACE("(%p)->() Release from %d\n", iface, refCount + 1); 864c2c66affSColin Finck 865c2c66affSColin Finck if (!refCount) 866c2c66affSColin Finck BaseInputPin_Destroy(This); 867c2c66affSColin Finck 868c2c66affSColin Finck return refCount; 869c2c66affSColin Finck } 870c2c66affSColin Finck 871c2c66affSColin Finck HRESULT WINAPI BaseInputPinImpl_Connect(IPin * iface, IPin * pConnector, const AM_MEDIA_TYPE * pmt) 872c2c66affSColin Finck { 873c2c66affSColin Finck ERR("Outgoing connection on an input pin! (%p, %p)\n", pConnector, pmt); 874c2c66affSColin Finck 875c2c66affSColin Finck return E_UNEXPECTED; 876c2c66affSColin Finck } 877c2c66affSColin Finck 878c2c66affSColin Finck 879c2c66affSColin Finck HRESULT WINAPI BaseInputPinImpl_ReceiveConnection(IPin * iface, IPin * pReceivePin, const AM_MEDIA_TYPE * pmt) 880c2c66affSColin Finck { 881c2c66affSColin Finck BaseInputPin *This = impl_BaseInputPin_from_IPin(iface); 882c2c66affSColin Finck PIN_DIRECTION pindirReceive; 883c2c66affSColin Finck HRESULT hr = S_OK; 884c2c66affSColin Finck 885c2c66affSColin Finck TRACE("(%p, %p)\n", pReceivePin, pmt); 886c2c66affSColin Finck dump_AM_MEDIA_TYPE(pmt); 887c2c66affSColin Finck 888c2c66affSColin Finck EnterCriticalSection(This->pin.pCritSec); 889c2c66affSColin Finck { 890c2c66affSColin Finck if (This->pin.pConnectedTo) 891c2c66affSColin Finck hr = VFW_E_ALREADY_CONNECTED; 892c2c66affSColin Finck 893c2c66affSColin Finck if (SUCCEEDED(hr) && This->pin.pFuncsTable->pfnCheckMediaType(&This->pin, pmt) != S_OK) 894c2c66affSColin Finck hr = VFW_E_TYPE_NOT_ACCEPTED; /* FIXME: shouldn't we just map common errors onto 895c2c66affSColin Finck * VFW_E_TYPE_NOT_ACCEPTED and pass the value on otherwise? */ 896c2c66affSColin Finck 897c2c66affSColin Finck if (SUCCEEDED(hr)) 898c2c66affSColin Finck { 899c2c66affSColin Finck IPin_QueryDirection(pReceivePin, &pindirReceive); 900c2c66affSColin Finck 901c2c66affSColin Finck if (pindirReceive != PINDIR_OUTPUT) 902c2c66affSColin Finck { 903c2c66affSColin Finck ERR("Can't connect from non-output pin\n"); 904c2c66affSColin Finck hr = VFW_E_INVALID_DIRECTION; 905c2c66affSColin Finck } 906c2c66affSColin Finck } 907c2c66affSColin Finck 908c2c66affSColin Finck if (SUCCEEDED(hr)) 909c2c66affSColin Finck { 910c2c66affSColin Finck CopyMediaType(&This->pin.mtCurrent, pmt); 911c2c66affSColin Finck This->pin.pConnectedTo = pReceivePin; 912c2c66affSColin Finck IPin_AddRef(pReceivePin); 913c2c66affSColin Finck } 914c2c66affSColin Finck } 915c2c66affSColin Finck LeaveCriticalSection(This->pin.pCritSec); 916c2c66affSColin Finck 917c2c66affSColin Finck return hr; 918c2c66affSColin Finck } 919c2c66affSColin Finck 920c2c66affSColin Finck static HRESULT deliver_endofstream(IPin* pin, LPVOID unused) 921c2c66affSColin Finck { 922c2c66affSColin Finck return IPin_EndOfStream( pin ); 923c2c66affSColin Finck } 924c2c66affSColin Finck 925c2c66affSColin Finck HRESULT WINAPI BaseInputPinImpl_QueryAccept(IPin * iface, const AM_MEDIA_TYPE * pmt) 926c2c66affSColin Finck { 927c2c66affSColin Finck BaseInputPin *This = impl_BaseInputPin_from_IPin(iface); 928c2c66affSColin Finck 929c2c66affSColin Finck TRACE("(%p/%p)->(%p)\n", This, iface, pmt); 930c2c66affSColin Finck 931c2c66affSColin Finck return (This->pin.pFuncsTable->pfnCheckMediaType(&This->pin, pmt) == S_OK ? S_OK : S_FALSE); 932c2c66affSColin Finck } 933c2c66affSColin Finck 934c2c66affSColin Finck HRESULT WINAPI BaseInputPinImpl_EndOfStream(IPin * iface) 935c2c66affSColin Finck { 936c2c66affSColin Finck HRESULT hr = S_OK; 937c2c66affSColin Finck BaseInputPin *This = impl_BaseInputPin_from_IPin(iface); 938c2c66affSColin Finck 939c2c66affSColin Finck TRACE("(%p)\n", This); 940c2c66affSColin Finck 941c2c66affSColin Finck EnterCriticalSection(This->pin.pCritSec); 942c2c66affSColin Finck if (This->flushing) 943c2c66affSColin Finck hr = S_FALSE; 944c2c66affSColin Finck else 945c2c66affSColin Finck This->end_of_stream = TRUE; 946c2c66affSColin Finck LeaveCriticalSection(This->pin.pCritSec); 947c2c66affSColin Finck 948c2c66affSColin Finck if (hr == S_OK) 949c2c66affSColin Finck hr = SendFurther( iface, deliver_endofstream, NULL, NULL ); 950c2c66affSColin Finck return hr; 951c2c66affSColin Finck } 952c2c66affSColin Finck 953c2c66affSColin Finck static HRESULT deliver_beginflush(IPin* pin, LPVOID unused) 954c2c66affSColin Finck { 955c2c66affSColin Finck return IPin_BeginFlush( pin ); 956c2c66affSColin Finck } 957c2c66affSColin Finck 958c2c66affSColin Finck HRESULT WINAPI BaseInputPinImpl_BeginFlush(IPin * iface) 959c2c66affSColin Finck { 960c2c66affSColin Finck BaseInputPin *This = impl_BaseInputPin_from_IPin(iface); 961c2c66affSColin Finck HRESULT hr; 962c2c66affSColin Finck TRACE("() semi-stub\n"); 963c2c66affSColin Finck 964c2c66affSColin Finck EnterCriticalSection(This->pin.pCritSec); 965c2c66affSColin Finck This->flushing = TRUE; 966c2c66affSColin Finck 967c2c66affSColin Finck hr = SendFurther( iface, deliver_beginflush, NULL, NULL ); 968c2c66affSColin Finck LeaveCriticalSection(This->pin.pCritSec); 969c2c66affSColin Finck 970c2c66affSColin Finck return hr; 971c2c66affSColin Finck } 972c2c66affSColin Finck 973c2c66affSColin Finck static HRESULT deliver_endflush(IPin* pin, LPVOID unused) 974c2c66affSColin Finck { 975c2c66affSColin Finck return IPin_EndFlush( pin ); 976c2c66affSColin Finck } 977c2c66affSColin Finck 978c2c66affSColin Finck HRESULT WINAPI BaseInputPinImpl_EndFlush(IPin * iface) 979c2c66affSColin Finck { 980c2c66affSColin Finck BaseInputPin *This = impl_BaseInputPin_from_IPin(iface); 981c2c66affSColin Finck HRESULT hr; 982c2c66affSColin Finck TRACE("(%p)\n", This); 983c2c66affSColin Finck 984c2c66affSColin Finck EnterCriticalSection(This->pin.pCritSec); 985c2c66affSColin Finck This->flushing = This->end_of_stream = FALSE; 986c2c66affSColin Finck 987c2c66affSColin Finck hr = SendFurther( iface, deliver_endflush, NULL, NULL ); 988c2c66affSColin Finck LeaveCriticalSection(This->pin.pCritSec); 989c2c66affSColin Finck 990c2c66affSColin Finck return hr; 991c2c66affSColin Finck } 992c2c66affSColin Finck 993c2c66affSColin Finck typedef struct newsegmentargs 994c2c66affSColin Finck { 995c2c66affSColin Finck REFERENCE_TIME tStart, tStop; 996c2c66affSColin Finck double rate; 997c2c66affSColin Finck } newsegmentargs; 998c2c66affSColin Finck 999c2c66affSColin Finck static HRESULT deliver_newsegment(IPin *pin, LPVOID data) 1000c2c66affSColin Finck { 1001c2c66affSColin Finck newsegmentargs *args = data; 1002c2c66affSColin Finck return IPin_NewSegment(pin, args->tStart, args->tStop, args->rate); 1003c2c66affSColin Finck } 1004c2c66affSColin Finck 1005c2c66affSColin Finck HRESULT WINAPI BaseInputPinImpl_NewSegment(IPin * iface, REFERENCE_TIME tStart, REFERENCE_TIME tStop, double dRate) 1006c2c66affSColin Finck { 1007c2c66affSColin Finck BaseInputPin *This = impl_BaseInputPin_from_IPin(iface); 1008c2c66affSColin Finck newsegmentargs args; 1009c2c66affSColin Finck 1010*a7ef5747SThomas Faber TRACE("(%s, %s, %e)\n", wine_dbgstr_longlong(tStart), wine_dbgstr_longlong(tStop), dRate); 1011c2c66affSColin Finck 1012c2c66affSColin Finck args.tStart = This->pin.tStart = tStart; 1013c2c66affSColin Finck args.tStop = This->pin.tStop = tStop; 1014c2c66affSColin Finck args.rate = This->pin.dRate = dRate; 1015c2c66affSColin Finck 1016c2c66affSColin Finck return SendFurther( iface, deliver_newsegment, &args, NULL ); 1017c2c66affSColin Finck } 1018c2c66affSColin Finck 1019c2c66affSColin Finck /*** IMemInputPin implementation ***/ 1020c2c66affSColin Finck 1021c2c66affSColin Finck static inline BaseInputPin *impl_from_IMemInputPin( IMemInputPin *iface ) 1022c2c66affSColin Finck { 1023c2c66affSColin Finck return CONTAINING_RECORD(iface, BaseInputPin, IMemInputPin_iface); 1024c2c66affSColin Finck } 1025c2c66affSColin Finck 1026c2c66affSColin Finck static HRESULT WINAPI MemInputPin_QueryInterface(IMemInputPin * iface, REFIID riid, LPVOID * ppv) 1027c2c66affSColin Finck { 1028c2c66affSColin Finck BaseInputPin *This = impl_from_IMemInputPin(iface); 1029c2c66affSColin Finck 1030c2c66affSColin Finck return IPin_QueryInterface(&This->pin.IPin_iface, riid, ppv); 1031c2c66affSColin Finck } 1032c2c66affSColin Finck 1033c2c66affSColin Finck static ULONG WINAPI MemInputPin_AddRef(IMemInputPin * iface) 1034c2c66affSColin Finck { 1035c2c66affSColin Finck BaseInputPin *This = impl_from_IMemInputPin(iface); 1036c2c66affSColin Finck 1037c2c66affSColin Finck return IPin_AddRef(&This->pin.IPin_iface); 1038c2c66affSColin Finck } 1039c2c66affSColin Finck 1040c2c66affSColin Finck static ULONG WINAPI MemInputPin_Release(IMemInputPin * iface) 1041c2c66affSColin Finck { 1042c2c66affSColin Finck BaseInputPin *This = impl_from_IMemInputPin(iface); 1043c2c66affSColin Finck 1044c2c66affSColin Finck return IPin_Release(&This->pin.IPin_iface); 1045c2c66affSColin Finck } 1046c2c66affSColin Finck 1047c2c66affSColin Finck static HRESULT WINAPI MemInputPin_GetAllocator(IMemInputPin * iface, IMemAllocator ** ppAllocator) 1048c2c66affSColin Finck { 1049c2c66affSColin Finck BaseInputPin *This = impl_from_IMemInputPin(iface); 1050c2c66affSColin Finck 1051c2c66affSColin Finck TRACE("(%p/%p)->(%p)\n", This, iface, ppAllocator); 1052c2c66affSColin Finck 1053c2c66affSColin Finck *ppAllocator = This->pAllocator; 1054c2c66affSColin Finck if (*ppAllocator) 1055c2c66affSColin Finck IMemAllocator_AddRef(*ppAllocator); 1056c2c66affSColin Finck 1057c2c66affSColin Finck return *ppAllocator ? S_OK : VFW_E_NO_ALLOCATOR; 1058c2c66affSColin Finck } 1059c2c66affSColin Finck 1060c2c66affSColin Finck static HRESULT WINAPI MemInputPin_NotifyAllocator(IMemInputPin * iface, IMemAllocator * pAllocator, BOOL bReadOnly) 1061c2c66affSColin Finck { 1062c2c66affSColin Finck BaseInputPin *This = impl_from_IMemInputPin(iface); 1063c2c66affSColin Finck 1064c2c66affSColin Finck TRACE("(%p/%p)->(%p, %d)\n", This, iface, pAllocator, bReadOnly); 1065c2c66affSColin Finck 1066c2c66affSColin Finck if (bReadOnly) 1067c2c66affSColin Finck FIXME("Read only flag not handled yet!\n"); 1068c2c66affSColin Finck 1069c2c66affSColin Finck /* FIXME: Should we release the allocator on disconnection? */ 1070c2c66affSColin Finck if (!pAllocator) 1071c2c66affSColin Finck { 1072c2c66affSColin Finck WARN("Null allocator\n"); 1073c2c66affSColin Finck return E_POINTER; 1074c2c66affSColin Finck } 1075c2c66affSColin Finck 1076c2c66affSColin Finck if (This->preferred_allocator && pAllocator != This->preferred_allocator) 1077c2c66affSColin Finck return E_FAIL; 1078c2c66affSColin Finck 1079c2c66affSColin Finck if (This->pAllocator) 1080c2c66affSColin Finck IMemAllocator_Release(This->pAllocator); 1081c2c66affSColin Finck This->pAllocator = pAllocator; 1082c2c66affSColin Finck if (This->pAllocator) 1083c2c66affSColin Finck IMemAllocator_AddRef(This->pAllocator); 1084c2c66affSColin Finck 1085c2c66affSColin Finck return S_OK; 1086c2c66affSColin Finck } 1087c2c66affSColin Finck 1088c2c66affSColin Finck static HRESULT WINAPI MemInputPin_GetAllocatorRequirements(IMemInputPin * iface, ALLOCATOR_PROPERTIES * pProps) 1089c2c66affSColin Finck { 1090c2c66affSColin Finck BaseInputPin *This = impl_from_IMemInputPin(iface); 1091c2c66affSColin Finck 1092c2c66affSColin Finck TRACE("(%p/%p)->(%p)\n", This, iface, pProps); 1093c2c66affSColin Finck 1094c2c66affSColin Finck /* override this method if you have any specific requirements */ 1095c2c66affSColin Finck 1096c2c66affSColin Finck return E_NOTIMPL; 1097c2c66affSColin Finck } 1098c2c66affSColin Finck 1099c2c66affSColin Finck static HRESULT WINAPI MemInputPin_Receive(IMemInputPin * iface, IMediaSample * pSample) 1100c2c66affSColin Finck { 1101c2c66affSColin Finck BaseInputPin *This = impl_from_IMemInputPin(iface); 1102c2c66affSColin Finck HRESULT hr = S_FALSE; 1103c2c66affSColin Finck 1104c2c66affSColin Finck /* this trace commented out for performance reasons */ 1105c2c66affSColin Finck /*TRACE("(%p/%p)->(%p)\n", This, iface, pSample);*/ 1106c2c66affSColin Finck if (This->pFuncsTable->pfnReceive) 1107c2c66affSColin Finck hr = This->pFuncsTable->pfnReceive(This, pSample); 1108c2c66affSColin Finck return hr; 1109c2c66affSColin Finck } 1110c2c66affSColin Finck 1111c2c66affSColin Finck static HRESULT WINAPI MemInputPin_ReceiveMultiple(IMemInputPin * iface, IMediaSample ** pSamples, LONG nSamples, LONG *nSamplesProcessed) 1112c2c66affSColin Finck { 1113c2c66affSColin Finck HRESULT hr = S_OK; 1114c2c66affSColin Finck BaseInputPin *This = impl_from_IMemInputPin(iface); 1115c2c66affSColin Finck 1116c2c66affSColin Finck TRACE("(%p/%p)->(%p, %d, %p)\n", This, iface, pSamples, nSamples, nSamplesProcessed); 1117c2c66affSColin Finck 1118c2c66affSColin Finck for (*nSamplesProcessed = 0; *nSamplesProcessed < nSamples; (*nSamplesProcessed)++) 1119c2c66affSColin Finck { 1120c2c66affSColin Finck hr = IMemInputPin_Receive(iface, pSamples[*nSamplesProcessed]); 1121c2c66affSColin Finck if (hr != S_OK) 1122c2c66affSColin Finck break; 1123c2c66affSColin Finck } 1124c2c66affSColin Finck 1125c2c66affSColin Finck return hr; 1126c2c66affSColin Finck } 1127c2c66affSColin Finck 1128c2c66affSColin Finck static HRESULT WINAPI MemInputPin_ReceiveCanBlock(IMemInputPin * iface) 1129c2c66affSColin Finck { 1130c2c66affSColin Finck BaseInputPin *This = impl_from_IMemInputPin(iface); 1131c2c66affSColin Finck 1132c2c66affSColin Finck TRACE("(%p/%p)->()\n", This, iface); 1133c2c66affSColin Finck 1134c2c66affSColin Finck return S_OK; 1135c2c66affSColin Finck } 1136c2c66affSColin Finck 1137c2c66affSColin Finck static const IMemInputPinVtbl MemInputPin_Vtbl = 1138c2c66affSColin Finck { 1139c2c66affSColin Finck MemInputPin_QueryInterface, 1140c2c66affSColin Finck MemInputPin_AddRef, 1141c2c66affSColin Finck MemInputPin_Release, 1142c2c66affSColin Finck MemInputPin_GetAllocator, 1143c2c66affSColin Finck MemInputPin_NotifyAllocator, 1144c2c66affSColin Finck MemInputPin_GetAllocatorRequirements, 1145c2c66affSColin Finck MemInputPin_Receive, 1146c2c66affSColin Finck MemInputPin_ReceiveMultiple, 1147c2c66affSColin Finck MemInputPin_ReceiveCanBlock 1148c2c66affSColin Finck }; 1149c2c66affSColin Finck 1150c2c66affSColin Finck static HRESULT InputPin_Init(const IPinVtbl *InputPin_Vtbl, const PIN_INFO * pPinInfo, 1151c2c66affSColin Finck const BaseInputPinFuncTable* vtbl, 1152c2c66affSColin Finck LPCRITICAL_SECTION pCritSec, IMemAllocator *allocator, BaseInputPin * pPinImpl) 1153c2c66affSColin Finck { 1154c2c66affSColin Finck TRACE("\n"); 1155c2c66affSColin Finck 1156c2c66affSColin Finck /* Common attributes */ 1157c2c66affSColin Finck pPinImpl->pin.refCount = 1; 1158c2c66affSColin Finck pPinImpl->pin.pConnectedTo = NULL; 1159c2c66affSColin Finck pPinImpl->pin.pCritSec = pCritSec; 1160c2c66affSColin Finck pPinImpl->pin.tStart = 0; 1161c2c66affSColin Finck pPinImpl->pin.tStop = 0; 1162c2c66affSColin Finck pPinImpl->pin.dRate = 1.0; 1163c2c66affSColin Finck Copy_PinInfo(&pPinImpl->pin.pinInfo, pPinInfo); 1164c2c66affSColin Finck ZeroMemory(&pPinImpl->pin.mtCurrent, sizeof(AM_MEDIA_TYPE)); 1165c2c66affSColin Finck pPinImpl->pin.pFuncsTable = &vtbl->base; 1166c2c66affSColin Finck 1167c2c66affSColin Finck /* Input pin attributes */ 1168c2c66affSColin Finck pPinImpl->pFuncsTable = vtbl; 1169c2c66affSColin Finck pPinImpl->pAllocator = pPinImpl->preferred_allocator = allocator; 1170c2c66affSColin Finck if (pPinImpl->preferred_allocator) 1171c2c66affSColin Finck IMemAllocator_AddRef(pPinImpl->preferred_allocator); 1172c2c66affSColin Finck pPinImpl->pin.IPin_iface.lpVtbl = InputPin_Vtbl; 1173c2c66affSColin Finck pPinImpl->IMemInputPin_iface.lpVtbl = &MemInputPin_Vtbl; 1174c2c66affSColin Finck pPinImpl->flushing = pPinImpl->end_of_stream = FALSE; 1175c2c66affSColin Finck 1176c2c66affSColin Finck return S_OK; 1177c2c66affSColin Finck } 1178c2c66affSColin Finck 1179c2c66affSColin Finck HRESULT BaseInputPin_Construct(const IPinVtbl *InputPin_Vtbl, LONG inputpin_size, const PIN_INFO * pPinInfo, 1180c2c66affSColin Finck const BaseInputPinFuncTable* vtbl, 1181c2c66affSColin Finck LPCRITICAL_SECTION pCritSec, IMemAllocator *allocator, IPin ** ppPin) 1182c2c66affSColin Finck { 1183c2c66affSColin Finck BaseInputPin * pPinImpl; 1184c2c66affSColin Finck 1185c2c66affSColin Finck *ppPin = NULL; 1186c2c66affSColin Finck 1187c2c66affSColin Finck assert(inputpin_size >= sizeof(BaseInputPin)); 1188c2c66affSColin Finck assert(vtbl->base.pfnCheckMediaType); 1189c2c66affSColin Finck 1190c2c66affSColin Finck if (pPinInfo->dir != PINDIR_INPUT) 1191c2c66affSColin Finck { 1192c2c66affSColin Finck ERR("Pin direction(%x) != PINDIR_INPUT\n", pPinInfo->dir); 1193c2c66affSColin Finck return E_INVALIDARG; 1194c2c66affSColin Finck } 1195c2c66affSColin Finck 1196c2c66affSColin Finck pPinImpl = CoTaskMemAlloc(inputpin_size); 1197c2c66affSColin Finck 1198c2c66affSColin Finck if (!pPinImpl) 1199c2c66affSColin Finck return E_OUTOFMEMORY; 1200c2c66affSColin Finck 1201c2c66affSColin Finck if (SUCCEEDED(InputPin_Init(InputPin_Vtbl, pPinInfo, vtbl, pCritSec, allocator, pPinImpl))) 1202c2c66affSColin Finck { 1203*a7ef5747SThomas Faber *ppPin = &pPinImpl->pin.IPin_iface; 1204c2c66affSColin Finck return S_OK; 1205c2c66affSColin Finck } 1206c2c66affSColin Finck 1207c2c66affSColin Finck CoTaskMemFree(pPinImpl); 1208c2c66affSColin Finck return E_FAIL; 1209c2c66affSColin Finck } 1210c2c66affSColin Finck 1211c2c66affSColin Finck HRESULT WINAPI BaseInputPin_Destroy(BaseInputPin *This) 1212c2c66affSColin Finck { 1213c2c66affSColin Finck FreeMediaType(&This->pin.mtCurrent); 1214c2c66affSColin Finck if (This->pAllocator) 1215c2c66affSColin Finck IMemAllocator_Release(This->pAllocator); 1216c2c66affSColin Finck This->pAllocator = NULL; 1217c2c66affSColin Finck This->pin.IPin_iface.lpVtbl = NULL; 1218c2c66affSColin Finck CoTaskMemFree(This); 1219c2c66affSColin Finck return S_OK; 1220c2c66affSColin Finck } 1221