xref: /reactos/sdk/lib/3rdparty/strmbase/pin.c (revision a7ef5747)
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