strmbase: Implement BaseFilter in strmbase.
[wine/multimedia.git] / dlls / quartz / parser.c
blobe30c61498887f028a9d992579d4f36e6e3dda7c4
1 /*
2 * Parser (Base for parsers and splitters)
4 * Copyright 2003 Robert Shearman
5 * Copyright 2004-2005 Christian Costa
7 * This library is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU Lesser General Public
9 * License as published by the Free Software Foundation; either
10 * version 2.1 of the License, or (at your option) any later version.
12 * This library is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * Lesser General Public License for more details.
17 * You should have received a copy of the GNU Lesser General Public
18 * License along with this library; if not, write to the Free Software
19 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
22 #include "quartz_private.h"
23 #include "control_private.h"
24 #include "pin.h"
26 #include "vfwmsgs.h"
27 #include "amvideo.h"
29 #include "wine/unicode.h"
30 #include "wine/debug.h"
32 #include <math.h>
33 #include <assert.h>
35 #include "parser.h"
37 WINE_DEFAULT_DEBUG_CHANNEL(quartz);
39 static const WCHAR wcsInputPinName[] = {'i','n','p','u','t',' ','p','i','n',0};
40 static const IMediaSeekingVtbl Parser_Seeking_Vtbl;
41 static const IPinVtbl Parser_OutputPin_Vtbl;
42 static const IPinVtbl Parser_InputPin_Vtbl;
44 static HRESULT Parser_ChangeCurrent(IBaseFilter *iface);
45 static HRESULT Parser_ChangeStop(IBaseFilter *iface);
46 static HRESULT Parser_ChangeRate(IBaseFilter *iface);
48 static inline ParserImpl *impl_from_IMediaSeeking( IMediaSeeking *iface )
50 return (ParserImpl *)((char*)iface - FIELD_OFFSET(ParserImpl, mediaSeeking.lpVtbl));
54 HRESULT Parser_Create(ParserImpl* pParser, const IBaseFilterVtbl *Parser_Vtbl, const CLSID* pClsid, PFN_PROCESS_SAMPLE fnProcessSample, PFN_QUERY_ACCEPT fnQueryAccept, PFN_PRE_CONNECT fnPreConnect, PFN_CLEANUP fnCleanup, PFN_DISCONNECT fnDisconnect, REQUESTPROC fnRequest, STOPPROCESSPROC fnDone, CHANGEPROC stop, CHANGEPROC current, CHANGEPROC rate)
56 HRESULT hr;
57 PIN_INFO piInput;
59 /* pTransformFilter is already allocated */
60 BaseFilter_Init(&pParser->filter, Parser_Vtbl, pClsid, (DWORD_PTR)(__FILE__ ": ParserImpl.csFilter"));
62 pParser->fnDisconnect = fnDisconnect;
63 pParser->lastpinchange = GetTickCount();
65 pParser->cStreams = 0;
66 pParser->ppPins = CoTaskMemAlloc(1 * sizeof(IPin *));
68 /* construct input pin */
69 piInput.dir = PINDIR_INPUT;
70 piInput.pFilter = (IBaseFilter *)pParser;
71 lstrcpynW(piInput.achName, wcsInputPinName, sizeof(piInput.achName) / sizeof(piInput.achName[0]));
73 if (!current)
74 current = Parser_ChangeCurrent;
76 if (!stop)
77 stop = Parser_ChangeStop;
79 if (!rate)
80 rate = Parser_ChangeRate;
82 MediaSeekingImpl_Init((IBaseFilter*)pParser, stop, current, rate, &pParser->mediaSeeking, &pParser->filter.csFilter);
83 pParser->mediaSeeking.lpVtbl = &Parser_Seeking_Vtbl;
85 hr = PullPin_Construct(&Parser_InputPin_Vtbl, &piInput, fnProcessSample, (LPVOID)pParser, fnQueryAccept, fnCleanup, fnRequest, fnDone, &pParser->filter.csFilter, (IPin **)&pParser->pInputPin);
87 if (SUCCEEDED(hr))
89 pParser->ppPins[0] = (IPin *)pParser->pInputPin;
90 pParser->pInputPin->fnPreConnect = fnPreConnect;
92 else
94 CoTaskMemFree(pParser->ppPins);
95 BaseFilterImpl_Release((IBaseFilter*)pParser);
96 CoTaskMemFree(pParser);
99 return hr;
102 HRESULT WINAPI Parser_QueryInterface(IBaseFilter * iface, REFIID riid, LPVOID * ppv)
104 ParserImpl *This = (ParserImpl *)iface;
105 TRACE("(%s, %p)\n", qzdebugstr_guid(riid), ppv);
107 *ppv = NULL;
109 if ( IsEqualIID(riid, &IID_IUnknown)
110 || IsEqualIID(riid, &IID_IPersist)
111 || IsEqualIID(riid, &IID_IMediaFilter)
112 || IsEqualIID(riid, &IID_IBaseFilter) )
113 *ppv = This;
115 if (*ppv)
117 IUnknown_AddRef((IUnknown *)(*ppv));
118 return S_OK;
121 if (!IsEqualIID(riid, &IID_IPin) && !IsEqualIID(riid, &IID_IVideoWindow))
122 FIXME("No interface for %s!\n", qzdebugstr_guid(riid));
124 return E_NOINTERFACE;
127 ULONG WINAPI Parser_AddRef(IBaseFilter * iface)
129 return BaseFilterImpl_AddRef(iface);
132 void Parser_Destroy(ParserImpl *This)
134 IPin *connected = NULL;
135 ULONG pinref;
137 assert(!This->filter.refCount);
138 PullPin_WaitForStateChange(This->pInputPin, INFINITE);
140 /* Don't need to clean up output pins, freeing input pin will do that */
141 IPin_ConnectedTo((IPin *)This->pInputPin, &connected);
142 if (connected)
144 assert(IPin_Disconnect(connected) == S_OK);
145 IPin_Release(connected);
146 assert(IPin_Disconnect((IPin *)This->pInputPin) == S_OK);
148 pinref = IPin_Release((IPin *)This->pInputPin);
149 if (pinref)
151 /* Valgrind could find this, if I kill it here */
152 ERR("pinref should be null, is %u, destroying anyway\n", pinref);
153 assert((LONG)pinref > 0);
155 while (pinref)
156 pinref = IPin_Release((IPin *)This->pInputPin);
159 CoTaskMemFree(This->ppPins);
161 TRACE("Destroying parser\n");
162 CoTaskMemFree(This);
165 ULONG WINAPI Parser_Release(IBaseFilter * iface)
167 ParserImpl *This = (ParserImpl *)iface;
168 ULONG refCount = BaseFilterImpl_Release(iface);
170 TRACE("(%p)->() Release from %d\n", This, refCount + 1);
172 if (!refCount)
173 Parser_Destroy(This);
175 return refCount;
178 /** IPersist methods **/
180 HRESULT WINAPI Parser_GetClassID(IBaseFilter * iface, CLSID * pClsid)
182 ParserImpl *This = (ParserImpl *)iface;
184 TRACE("(%p)\n", pClsid);
186 *pClsid = This->filter.clsid;
188 return S_OK;
191 /** IMediaFilter methods **/
193 HRESULT WINAPI Parser_Stop(IBaseFilter * iface)
195 ParserImpl *This = (ParserImpl *)iface;
196 PullPin *pin = (PullPin *)This->ppPins[0];
197 ULONG i;
199 TRACE("()\n");
201 EnterCriticalSection(&pin->thread_lock);
203 IAsyncReader_BeginFlush(This->pInputPin->pReader);
204 EnterCriticalSection(&This->filter.csFilter);
206 if (This->filter.state == State_Stopped)
208 LeaveCriticalSection(&This->filter.csFilter);
209 IAsyncReader_EndFlush(This->pInputPin->pReader);
210 LeaveCriticalSection(&pin->thread_lock);
211 return S_OK;
214 This->filter.state = State_Stopped;
216 for (i = 1; i < (This->cStreams + 1); i++)
218 BaseOutputPinImpl_Inactive((BaseOutputPin *)This->ppPins[i]);
221 LeaveCriticalSection(&This->filter.csFilter);
223 PullPin_PauseProcessing(This->pInputPin);
224 PullPin_WaitForStateChange(This->pInputPin, INFINITE);
225 IAsyncReader_EndFlush(This->pInputPin->pReader);
227 LeaveCriticalSection(&pin->thread_lock);
228 return S_OK;
231 HRESULT WINAPI Parser_Pause(IBaseFilter * iface)
233 HRESULT hr = S_OK;
234 ParserImpl *This = (ParserImpl *)iface;
235 PullPin *pin = (PullPin *)This->ppPins[0];
237 TRACE("()\n");
239 EnterCriticalSection(&pin->thread_lock);
240 EnterCriticalSection(&This->filter.csFilter);
242 if (This->filter.state == State_Paused)
244 LeaveCriticalSection(&This->filter.csFilter);
245 LeaveCriticalSection(&pin->thread_lock);
246 return S_OK;
249 if (This->filter.state == State_Stopped)
251 LeaveCriticalSection(&This->filter.csFilter);
252 hr = IBaseFilter_Run(iface, -1);
253 EnterCriticalSection(&This->filter.csFilter);
256 if (SUCCEEDED(hr))
257 This->filter.state = State_Paused;
259 LeaveCriticalSection(&This->filter.csFilter);
260 LeaveCriticalSection(&pin->thread_lock);
262 return hr;
265 HRESULT WINAPI Parser_Run(IBaseFilter * iface, REFERENCE_TIME tStart)
267 HRESULT hr = S_OK;
268 ParserImpl *This = (ParserImpl *)iface;
269 PullPin *pin = (PullPin *)This->ppPins[0];
271 ULONG i;
273 TRACE("(%s)\n", wine_dbgstr_longlong(tStart));
275 EnterCriticalSection(&pin->thread_lock);
276 EnterCriticalSection(&This->filter.csFilter);
278 HRESULT hr_any = VFW_E_NOT_CONNECTED;
280 if (This->filter.state == State_Running || This->filter.state == State_Paused)
282 This->filter.state = State_Running;
283 LeaveCriticalSection(&This->filter.csFilter);
284 LeaveCriticalSection(&pin->thread_lock);
285 return S_OK;
288 This->filter.rtStreamStart = tStart;
290 for (i = 1; i < (This->cStreams + 1); i++)
292 hr = BaseOutputPinImpl_Active((BaseOutputPin *)This->ppPins[i]);
293 if (SUCCEEDED(hr))
294 hr_any = hr;
297 hr = hr_any;
298 if (SUCCEEDED(hr))
300 LeaveCriticalSection(&This->filter.csFilter);
301 hr = PullPin_StartProcessing(This->pInputPin);
302 EnterCriticalSection(&This->filter.csFilter);
305 if (SUCCEEDED(hr))
306 This->filter.state = State_Running;
308 LeaveCriticalSection(&This->filter.csFilter);
309 LeaveCriticalSection(&pin->thread_lock);
311 return hr;
314 HRESULT WINAPI Parser_GetState(IBaseFilter * iface, DWORD dwMilliSecsTimeout, FILTER_STATE *pState)
316 ParserImpl *This = (ParserImpl *)iface;
317 PullPin *pin = (PullPin *)This->ppPins[0];
318 HRESULT hr = S_OK;
320 TRACE("(%d, %p)\n", dwMilliSecsTimeout, pState);
322 EnterCriticalSection(&pin->thread_lock);
323 EnterCriticalSection(&This->filter.csFilter);
325 *pState = This->filter.state;
327 LeaveCriticalSection(&This->filter.csFilter);
329 if (This->pInputPin && (PullPin_WaitForStateChange(This->pInputPin, dwMilliSecsTimeout) == S_FALSE))
330 hr = VFW_S_STATE_INTERMEDIATE;
331 LeaveCriticalSection(&pin->thread_lock);
333 return hr;
336 HRESULT WINAPI Parser_SetSyncSource(IBaseFilter * iface, IReferenceClock *pClock)
338 ParserImpl *This = (ParserImpl *)iface;
339 PullPin *pin = (PullPin *)This->ppPins[0];
341 TRACE("(%p)\n", pClock);
343 EnterCriticalSection(&pin->thread_lock);
344 BaseFilterImpl_SetSyncSource(iface,pClock);
345 LeaveCriticalSection(&pin->thread_lock);
347 return S_OK;
350 HRESULT WINAPI Parser_GetSyncSource(IBaseFilter * iface, IReferenceClock **ppClock)
352 return BaseFilterImpl_GetSyncSource(iface, ppClock);
355 /** IBaseFilter implementation **/
357 /* FIXME: WRONG */
358 static IPin* WINAPI Parser_GetPin(IBaseFilter *iface, int pos)
360 ParserImpl *This = (ParserImpl *)iface;
362 TRACE("Asking for pos %x\n", pos);
364 /* Input pin also has a pin, hence the > and not >= */
365 if (pos > This->cStreams || pos < 0)
366 return NULL;
368 IPin_AddRef(This->ppPins[pos]);
369 return This->ppPins[pos];
372 static LONG WINAPI Parser_GetPinCount(IBaseFilter *iface)
374 ParserImpl *This = (ParserImpl *)iface;
376 return This->cStreams;
379 static LONG WINAPI Parser_GetPinVersion(IBaseFilter *iface)
381 ParserImpl *This = (ParserImpl *)iface;
383 return This->lastpinchange;
386 HRESULT WINAPI Parser_EnumPins(IBaseFilter * iface, IEnumPins **ppEnum)
388 ParserImpl *This = (ParserImpl *)iface;
390 TRACE("(%p/%p)->(%p)\n", This, iface, ppEnum);
392 return EnumPins_Construct(iface, Parser_GetPin, Parser_GetPinCount, Parser_GetPinVersion, ppEnum);
395 HRESULT WINAPI Parser_FindPin(IBaseFilter * iface, LPCWSTR Id, IPin **ppPin)
397 FIXME("(%p)->(%s,%p)\n", iface, debugstr_w(Id), ppPin);
399 /* FIXME: critical section */
401 return E_NOTIMPL;
404 HRESULT WINAPI Parser_QueryFilterInfo(IBaseFilter * iface, FILTER_INFO *pInfo)
406 return BaseFilterImpl_QueryFilterInfo(iface, pInfo);
409 HRESULT WINAPI Parser_JoinFilterGraph(IBaseFilter * iface, IFilterGraph *pGraph, LPCWSTR pName)
411 return BaseFilterImpl_JoinFilterGraph(iface, pGraph, pName);
414 HRESULT WINAPI Parser_QueryVendorInfo(IBaseFilter * iface, LPWSTR *pVendorInfo)
416 return BaseFilterImpl_QueryVendorInfo(iface, pVendorInfo);
419 HRESULT Parser_AddPin(ParserImpl * This, const PIN_INFO * piOutput, ALLOCATOR_PROPERTIES * props, const AM_MEDIA_TYPE * amt)
421 IPin ** ppOldPins;
422 HRESULT hr;
424 ppOldPins = This->ppPins;
426 This->ppPins = CoTaskMemAlloc((This->cStreams + 2) * sizeof(IPin *));
427 memcpy(This->ppPins, ppOldPins, (This->cStreams + 1) * sizeof(IPin *));
429 hr = BaseOutputPin_Construct(&Parser_OutputPin_Vtbl, sizeof(Parser_OutputPin), piOutput, props, NULL, &This->filter.csFilter, This->ppPins + (This->cStreams + 1));
431 if (SUCCEEDED(hr))
433 IPin *pPin = This->ppPins[This->cStreams + 1];
434 Parser_OutputPin *pin = (Parser_OutputPin *)pPin;
435 pin->pmt = CoTaskMemAlloc(sizeof(AM_MEDIA_TYPE));
436 CopyMediaType(pin->pmt, amt);
437 pin->dwSamplesProcessed = 0;
439 pin->pin.pin.pinInfo.pFilter = (LPVOID)This;
440 pin->pin.custom_allocator = 1;
441 This->cStreams++;
442 This->lastpinchange = GetTickCount();
443 CoTaskMemFree(ppOldPins);
445 else
447 CoTaskMemFree(This->ppPins);
448 This->ppPins = ppOldPins;
449 ERR("Failed with error %x\n", hr);
452 return hr;
455 static HRESULT Parser_RemoveOutputPins(ParserImpl * This)
457 /* NOTE: should be in critical section when calling this function */
458 HRESULT hr;
459 ULONG i;
460 IPin ** ppOldPins = This->ppPins;
462 TRACE("(%p)\n", This);
464 /* reduce the pin array down to 1 (just our input pin) */
465 This->ppPins = CoTaskMemAlloc(sizeof(IPin *) * 1);
466 memcpy(This->ppPins, ppOldPins, sizeof(IPin *) * 1);
468 for (i = 0; i < This->cStreams; i++)
470 hr = BaseOutputPinImpl_BreakConnect((BaseOutputPin *)ppOldPins[i + 1]);
471 TRACE("Disconnect: %08x\n", hr);
472 IPin_Release(ppOldPins[i + 1]);
475 This->lastpinchange = GetTickCount();
476 This->cStreams = 0;
477 CoTaskMemFree(ppOldPins);
479 return S_OK;
482 static HRESULT Parser_ChangeCurrent(IBaseFilter *iface)
484 FIXME("(%p) filter hasn't implemented current position change!\n", iface);
485 return S_OK;
488 static HRESULT Parser_ChangeStop(IBaseFilter *iface)
490 FIXME("(%p) filter hasn't implemented stop position change!\n", iface);
491 return S_OK;
494 static HRESULT Parser_ChangeRate(IBaseFilter *iface)
496 FIXME("(%p) filter hasn't implemented rate change!\n", iface);
497 return S_OK;
501 static HRESULT WINAPI Parser_Seeking_QueryInterface(IMediaSeeking * iface, REFIID riid, LPVOID * ppv)
503 ParserImpl *This = impl_from_IMediaSeeking(iface);
505 return IUnknown_QueryInterface((IUnknown *)This, riid, ppv);
508 static ULONG WINAPI Parser_Seeking_AddRef(IMediaSeeking * iface)
510 ParserImpl *This = impl_from_IMediaSeeking(iface);
512 return IUnknown_AddRef((IUnknown *)This);
515 static ULONG WINAPI Parser_Seeking_Release(IMediaSeeking * iface)
517 ParserImpl *This = impl_from_IMediaSeeking(iface);
519 return IUnknown_Release((IUnknown *)This);
522 static const IMediaSeekingVtbl Parser_Seeking_Vtbl =
524 Parser_Seeking_QueryInterface,
525 Parser_Seeking_AddRef,
526 Parser_Seeking_Release,
527 MediaSeekingImpl_GetCapabilities,
528 MediaSeekingImpl_CheckCapabilities,
529 MediaSeekingImpl_IsFormatSupported,
530 MediaSeekingImpl_QueryPreferredFormat,
531 MediaSeekingImpl_GetTimeFormat,
532 MediaSeekingImpl_IsUsingTimeFormat,
533 MediaSeekingImpl_SetTimeFormat,
534 MediaSeekingImpl_GetDuration,
535 MediaSeekingImpl_GetStopPosition,
536 MediaSeekingImpl_GetCurrentPosition,
537 MediaSeekingImpl_ConvertTimeFormat,
538 MediaSeekingImpl_SetPositions,
539 MediaSeekingImpl_GetPositions,
540 MediaSeekingImpl_GetAvailable,
541 MediaSeekingImpl_SetRate,
542 MediaSeekingImpl_GetRate,
543 MediaSeekingImpl_GetPreroll
546 static HRESULT WINAPI Parser_OutputPin_GetMediaType(IPin *iface, int iPosition, AM_MEDIA_TYPE *pmt)
548 Parser_OutputPin *This = (Parser_OutputPin *)iface;
549 if (iPosition < 0)
550 return E_INVALIDARG;
551 if (iPosition > 0)
552 return VFW_S_NO_MORE_ITEMS;
553 CopyMediaType(pmt, This->pmt);
554 return S_OK;
557 static HRESULT WINAPI Parser_OutputPin_QueryInterface(IPin * iface, REFIID riid, LPVOID * ppv)
559 Parser_OutputPin *This = (Parser_OutputPin *)iface;
561 TRACE("(%s, %p)\n", qzdebugstr_guid(riid), ppv);
563 *ppv = NULL;
565 if (IsEqualIID(riid, &IID_IUnknown))
566 *ppv = iface;
567 else if (IsEqualIID(riid, &IID_IPin))
568 *ppv = iface;
569 else if (IsEqualIID(riid, &IID_IMediaSeeking))
571 return IBaseFilter_QueryInterface(This->pin.pin.pinInfo.pFilter, &IID_IMediaSeeking, ppv);
574 if (*ppv)
576 IUnknown_AddRef((IUnknown *)(*ppv));
577 return S_OK;
580 FIXME("No interface for %s!\n", qzdebugstr_guid(riid));
582 return E_NOINTERFACE;
585 static ULONG WINAPI Parser_OutputPin_Release(IPin * iface)
587 Parser_OutputPin *This = (Parser_OutputPin *)iface;
588 ULONG refCount = InterlockedDecrement(&This->pin.pin.refCount);
590 TRACE("(%p)->() Release from %d\n", iface, refCount + 1);
592 if (!refCount)
594 FreeMediaType(This->pmt);
595 CoTaskMemFree(This->pmt);
596 FreeMediaType(&This->pin.pin.mtCurrent);
597 CoTaskMemFree(This);
598 return 0;
600 return refCount;
603 static HRESULT WINAPI Parser_OutputPin_EnumMediaTypes(IPin * iface, IEnumMediaTypes ** ppEnum)
605 TRACE("(%p)\n", ppEnum);
607 /* override this method to allow enumeration of your types */
609 return EnumMediaTypes_Construct(iface, Parser_OutputPin_GetMediaType, BasePinImpl_GetMediaTypeVersion, ppEnum);
612 static HRESULT WINAPI Parser_OutputPin_Connect(IPin * iface, IPin * pReceivePin, const AM_MEDIA_TYPE * pmt)
614 Parser_OutputPin *This = (Parser_OutputPin *)iface;
615 ParserImpl *parser = (ParserImpl *)This->pin.pin.pinInfo.pFilter;
617 /* Set the allocator to our input pin's */
618 EnterCriticalSection(This->pin.pin.pCritSec);
619 This->pin.alloc = parser->pInputPin->pAlloc;
620 LeaveCriticalSection(This->pin.pin.pCritSec);
622 return BaseOutputPinImpl_Connect(iface, pReceivePin, pmt);
625 static HRESULT WINAPI Parser_OutputPin_QueryAccept(IPin *iface, const AM_MEDIA_TYPE * pmt)
627 Parser_OutputPin *This = (Parser_OutputPin *)iface;
629 TRACE("()\n");
630 dump_AM_MEDIA_TYPE(pmt);
632 return (memcmp(This->pmt, pmt, sizeof(AM_MEDIA_TYPE)) == 0);
635 static const IPinVtbl Parser_OutputPin_Vtbl =
637 Parser_OutputPin_QueryInterface,
638 BasePinImpl_AddRef,
639 Parser_OutputPin_Release,
640 Parser_OutputPin_Connect,
641 BaseOutputPinImpl_ReceiveConnection,
642 BaseOutputPinImpl_Disconnect,
643 BasePinImpl_ConnectedTo,
644 BasePinImpl_ConnectionMediaType,
645 BasePinImpl_QueryPinInfo,
646 BasePinImpl_QueryDirection,
647 BasePinImpl_QueryId,
648 Parser_OutputPin_QueryAccept,
649 Parser_OutputPin_EnumMediaTypes,
650 BasePinImpl_QueryInternalConnections,
651 BaseOutputPinImpl_EndOfStream,
652 BaseOutputPinImpl_BeginFlush,
653 BaseOutputPinImpl_EndFlush,
654 BaseOutputPinImpl_NewSegment
657 static HRESULT WINAPI Parser_PullPin_Disconnect(IPin * iface)
659 HRESULT hr;
660 PullPin *This = (PullPin *)iface;
662 TRACE("()\n");
664 EnterCriticalSection(&This->thread_lock);
665 EnterCriticalSection(This->pin.pCritSec);
667 if (This->pin.pConnectedTo)
669 FILTER_STATE state;
670 ParserImpl *Parser = (ParserImpl *)This->pin.pinInfo.pFilter;
672 LeaveCriticalSection(This->pin.pCritSec);
673 hr = IBaseFilter_GetState(This->pin.pinInfo.pFilter, INFINITE, &state);
674 EnterCriticalSection(This->pin.pCritSec);
676 if (SUCCEEDED(hr) && (state == State_Stopped) && SUCCEEDED(Parser->fnDisconnect(Parser)))
678 LeaveCriticalSection(This->pin.pCritSec);
679 PullPin_Disconnect(iface);
680 EnterCriticalSection(This->pin.pCritSec);
681 hr = Parser_RemoveOutputPins((ParserImpl *)This->pin.pinInfo.pFilter);
683 else
684 hr = VFW_E_NOT_STOPPED;
686 else
687 hr = S_FALSE;
689 LeaveCriticalSection(This->pin.pCritSec);
690 LeaveCriticalSection(&This->thread_lock);
692 return hr;
695 static HRESULT WINAPI Parser_PullPin_ReceiveConnection(IPin * iface, IPin * pReceivePin, const AM_MEDIA_TYPE * pmt)
697 HRESULT hr;
699 TRACE("()\n");
701 hr = PullPin_ReceiveConnection(iface, pReceivePin, pmt);
702 if (FAILED(hr))
704 BasePin *This = (BasePin *)iface;
706 EnterCriticalSection(This->pCritSec);
707 Parser_RemoveOutputPins((ParserImpl *)This->pinInfo.pFilter);
708 LeaveCriticalSection(This->pCritSec);
711 return hr;
714 static const IPinVtbl Parser_InputPin_Vtbl =
716 PullPin_QueryInterface,
717 BasePinImpl_AddRef,
718 PullPin_Release,
719 BaseInputPinImpl_Connect,
720 Parser_PullPin_ReceiveConnection,
721 Parser_PullPin_Disconnect,
722 BasePinImpl_ConnectedTo,
723 BasePinImpl_ConnectionMediaType,
724 BasePinImpl_QueryPinInfo,
725 BasePinImpl_QueryDirection,
726 BasePinImpl_QueryId,
727 PullPin_QueryAccept,
728 BasePinImpl_EnumMediaTypes,
729 BasePinImpl_QueryInternalConnections,
730 PullPin_EndOfStream,
731 PullPin_BeginFlush,
732 PullPin_EndFlush,
733 PullPin_NewSegment