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