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