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"
29 #include "wine/unicode.h"
30 #include "wine/debug.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)
59 /* pTransformFilter is already allocated */
60 pParser->clsid = *pClsid;
61 pParser->lpVtbl = Parser_Vtbl;
62 pParser->refCount = 1;
63 InitializeCriticalSection(&pParser->csFilter);
64 pParser->csFilter.DebugInfo->Spare[0] = (DWORD_PTR)(__FILE__ ": ParserImpl.csFilter");
65 pParser->state = State_Stopped;
66 pParser->pClock = NULL;
67 pParser->fnDisconnect = fnDisconnect;
68 ZeroMemory(&pParser->filterInfo, sizeof(FILTER_INFO));
69 pParser->lastpinchange = GetTickCount();
71 pParser->cStreams = 0;
72 pParser->ppPins = CoTaskMemAlloc(1 * sizeof(IPin *));
74 /* construct input pin */
75 piInput.dir = PINDIR_INPUT;
76 piInput.pFilter = (IBaseFilter *)pParser;
77 lstrcpynW(piInput.achName, wcsInputPinName, sizeof(piInput.achName) / sizeof(piInput.achName[0]));
80 current = Parser_ChangeCurrent;
83 stop = Parser_ChangeStop;
86 rate = Parser_ChangeRate;
88 MediaSeekingImpl_Init((IBaseFilter*)pParser, stop, current, rate, &pParser->mediaSeeking, &pParser->csFilter);
89 pParser->mediaSeeking.lpVtbl = &Parser_Seeking_Vtbl;
91 hr = PullPin_Construct(&Parser_InputPin_Vtbl, &piInput, fnProcessSample, (LPVOID)pParser, fnQueryAccept, fnCleanup, fnRequest, fnDone, &pParser->csFilter, (IPin **)&pParser->pInputPin);
95 pParser->ppPins[0] = (IPin *)pParser->pInputPin;
96 pParser->pInputPin->fnPreConnect = fnPreConnect;
100 CoTaskMemFree(pParser->ppPins);
101 pParser->csFilter.DebugInfo->Spare[0] = 0;
102 DeleteCriticalSection(&pParser->csFilter);
103 CoTaskMemFree(pParser);
109 HRESULT WINAPI Parser_QueryInterface(IBaseFilter * iface, REFIID riid, LPVOID * ppv)
111 ParserImpl *This = (ParserImpl *)iface;
112 TRACE("(%s, %p)\n", qzdebugstr_guid(riid), ppv);
116 if ( IsEqualIID(riid, &IID_IUnknown)
117 || IsEqualIID(riid, &IID_IPersist)
118 || IsEqualIID(riid, &IID_IMediaFilter)
119 || IsEqualIID(riid, &IID_IBaseFilter) )
124 IUnknown_AddRef((IUnknown *)(*ppv));
128 if (!IsEqualIID(riid, &IID_IPin) && !IsEqualIID(riid, &IID_IVideoWindow))
129 FIXME("No interface for %s!\n", qzdebugstr_guid(riid));
131 return E_NOINTERFACE;
134 ULONG WINAPI Parser_AddRef(IBaseFilter * iface)
136 ParserImpl *This = (ParserImpl *)iface;
137 ULONG refCount = InterlockedIncrement(&This->refCount);
139 TRACE("(%p/%p)->() AddRef from %d\n", This, iface, refCount - 1);
144 void Parser_Destroy(ParserImpl *This)
146 IPin *connected = NULL;
149 assert(!This->refCount);
150 PullPin_WaitForStateChange(This->pInputPin, INFINITE);
153 IReferenceClock_Release(This->pClock);
155 /* Don't need to clean up output pins, freeing input pin will do that */
156 IPin_ConnectedTo((IPin *)This->pInputPin, &connected);
159 assert(IPin_Disconnect(connected) == S_OK);
160 IPin_Release(connected);
161 assert(IPin_Disconnect((IPin *)This->pInputPin) == S_OK);
163 pinref = IPin_Release((IPin *)This->pInputPin);
166 /* Valgrind could find this, if I kill it here */
167 ERR("pinref should be null, is %u, destroying anyway\n", pinref);
168 assert((LONG)pinref > 0);
171 pinref = IPin_Release((IPin *)This->pInputPin);
174 CoTaskMemFree(This->ppPins);
177 This->csFilter.DebugInfo->Spare[0] = 0;
178 DeleteCriticalSection(&This->csFilter);
180 TRACE("Destroying parser\n");
184 ULONG WINAPI Parser_Release(IBaseFilter * iface)
186 ParserImpl *This = (ParserImpl *)iface;
187 ULONG refCount = InterlockedDecrement(&This->refCount);
189 TRACE("(%p)->() Release from %d\n", This, refCount + 1);
192 Parser_Destroy(This);
197 /** IPersist methods **/
199 HRESULT WINAPI Parser_GetClassID(IBaseFilter * iface, CLSID * pClsid)
201 ParserImpl *This = (ParserImpl *)iface;
203 TRACE("(%p)\n", pClsid);
205 *pClsid = This->clsid;
210 /** IMediaFilter methods **/
212 HRESULT WINAPI Parser_Stop(IBaseFilter * iface)
214 ParserImpl *This = (ParserImpl *)iface;
215 PullPin *pin = (PullPin *)This->ppPins[0];
220 EnterCriticalSection(&pin->thread_lock);
222 IAsyncReader_BeginFlush(This->pInputPin->pReader);
223 EnterCriticalSection(&This->csFilter);
225 if (This->state == State_Stopped)
227 LeaveCriticalSection(&This->csFilter);
228 IAsyncReader_EndFlush(This->pInputPin->pReader);
229 LeaveCriticalSection(&pin->thread_lock);
233 This->state = State_Stopped;
235 for (i = 1; i < (This->cStreams + 1); i++)
237 OutputPin_DecommitAllocator((OutputPin *)This->ppPins[i]);
240 LeaveCriticalSection(&This->csFilter);
242 PullPin_PauseProcessing(This->pInputPin);
243 PullPin_WaitForStateChange(This->pInputPin, INFINITE);
244 IAsyncReader_EndFlush(This->pInputPin->pReader);
246 LeaveCriticalSection(&pin->thread_lock);
250 HRESULT WINAPI Parser_Pause(IBaseFilter * iface)
253 ParserImpl *This = (ParserImpl *)iface;
254 PullPin *pin = (PullPin *)This->ppPins[0];
258 EnterCriticalSection(&pin->thread_lock);
259 EnterCriticalSection(&This->csFilter);
261 if (This->state == State_Paused)
263 LeaveCriticalSection(&This->csFilter);
264 LeaveCriticalSection(&pin->thread_lock);
268 if (This->state == State_Stopped)
270 LeaveCriticalSection(&This->csFilter);
271 hr = IBaseFilter_Run(iface, -1);
272 EnterCriticalSection(&This->csFilter);
276 This->state = State_Paused;
278 LeaveCriticalSection(&This->csFilter);
279 LeaveCriticalSection(&pin->thread_lock);
284 HRESULT WINAPI Parser_Run(IBaseFilter * iface, REFERENCE_TIME tStart)
287 ParserImpl *This = (ParserImpl *)iface;
288 PullPin *pin = (PullPin *)This->ppPins[0];
292 TRACE("(%s)\n", wine_dbgstr_longlong(tStart));
294 EnterCriticalSection(&pin->thread_lock);
295 EnterCriticalSection(&This->csFilter);
297 HRESULT hr_any = VFW_E_NOT_CONNECTED;
299 if (This->state == State_Running || This->state == State_Paused)
301 This->state = State_Running;
302 LeaveCriticalSection(&This->csFilter);
303 LeaveCriticalSection(&pin->thread_lock);
307 This->rtStreamStart = tStart;
309 for (i = 1; i < (This->cStreams + 1); i++)
311 hr = OutputPin_CommitAllocator((OutputPin *)This->ppPins[i]);
319 LeaveCriticalSection(&This->csFilter);
320 hr = PullPin_StartProcessing(This->pInputPin);
321 EnterCriticalSection(&This->csFilter);
325 This->state = State_Running;
327 LeaveCriticalSection(&This->csFilter);
328 LeaveCriticalSection(&pin->thread_lock);
333 HRESULT WINAPI Parser_GetState(IBaseFilter * iface, DWORD dwMilliSecsTimeout, FILTER_STATE *pState)
335 ParserImpl *This = (ParserImpl *)iface;
336 PullPin *pin = (PullPin *)This->ppPins[0];
339 TRACE("(%d, %p)\n", dwMilliSecsTimeout, pState);
341 EnterCriticalSection(&pin->thread_lock);
342 EnterCriticalSection(&This->csFilter);
344 *pState = This->state;
346 LeaveCriticalSection(&This->csFilter);
348 if (This->pInputPin && (PullPin_WaitForStateChange(This->pInputPin, dwMilliSecsTimeout) == S_FALSE))
349 hr = VFW_S_STATE_INTERMEDIATE;
350 LeaveCriticalSection(&pin->thread_lock);
355 HRESULT WINAPI Parser_SetSyncSource(IBaseFilter * iface, IReferenceClock *pClock)
357 ParserImpl *This = (ParserImpl *)iface;
358 PullPin *pin = (PullPin *)This->ppPins[0];
360 TRACE("(%p)\n", pClock);
362 EnterCriticalSection(&pin->thread_lock);
363 EnterCriticalSection(&This->csFilter);
366 IReferenceClock_Release(This->pClock);
367 This->pClock = pClock;
369 IReferenceClock_AddRef(This->pClock);
371 LeaveCriticalSection(&This->csFilter);
372 LeaveCriticalSection(&pin->thread_lock);
377 HRESULT WINAPI Parser_GetSyncSource(IBaseFilter * iface, IReferenceClock **ppClock)
379 ParserImpl *This = (ParserImpl *)iface;
381 TRACE("(%p)\n", ppClock);
383 EnterCriticalSection(&This->csFilter);
385 *ppClock = This->pClock;
387 IReferenceClock_AddRef(This->pClock);
389 LeaveCriticalSection(&This->csFilter);
394 /** IBaseFilter implementation **/
397 static IPin* WINAPI Parser_GetPin(IBaseFilter *iface, int pos)
399 ParserImpl *This = (ParserImpl *)iface;
401 TRACE("Asking for pos %x\n", pos);
403 /* Input pin also has a pin, hence the > and not >= */
404 if (pos > This->cStreams || pos < 0)
407 IPin_AddRef(This->ppPins[pos]);
408 return This->ppPins[pos];
411 static LONG WINAPI Parser_GetPinCount(IBaseFilter *iface)
413 ParserImpl *This = (ParserImpl *)iface;
415 return This->cStreams;
418 static LONG WINAPI Parser_GetPinVersion(IBaseFilter *iface)
420 ParserImpl *This = (ParserImpl *)iface;
422 return This->lastpinchange;
425 HRESULT WINAPI Parser_EnumPins(IBaseFilter * iface, IEnumPins **ppEnum)
427 ParserImpl *This = (ParserImpl *)iface;
429 TRACE("(%p/%p)->(%p)\n", This, iface, ppEnum);
431 return EnumPins_Construct(iface, Parser_GetPin, Parser_GetPinCount, Parser_GetPinVersion, ppEnum);
434 HRESULT WINAPI Parser_FindPin(IBaseFilter * iface, LPCWSTR Id, IPin **ppPin)
436 FIXME("(%p)->(%s,%p)\n", iface, debugstr_w(Id), ppPin);
438 /* FIXME: critical section */
443 HRESULT WINAPI Parser_QueryFilterInfo(IBaseFilter * iface, FILTER_INFO *pInfo)
445 ParserImpl *This = (ParserImpl *)iface;
447 TRACE("(%p)\n", pInfo);
449 strcpyW(pInfo->achName, This->filterInfo.achName);
450 pInfo->pGraph = This->filterInfo.pGraph;
453 IFilterGraph_AddRef(pInfo->pGraph);
458 HRESULT WINAPI Parser_JoinFilterGraph(IBaseFilter * iface, IFilterGraph *pGraph, LPCWSTR pName)
461 ParserImpl *This = (ParserImpl *)iface;
463 TRACE("(%p, %s)\n", pGraph, debugstr_w(pName));
465 EnterCriticalSection(&This->csFilter);
468 strcpyW(This->filterInfo.achName, pName);
470 *This->filterInfo.achName = '\0';
471 This->filterInfo.pGraph = pGraph; /* NOTE: do NOT increase ref. count */
473 LeaveCriticalSection(&This->csFilter);
478 HRESULT WINAPI Parser_QueryVendorInfo(IBaseFilter * iface, LPWSTR *pVendorInfo)
480 TRACE("(%p)\n", pVendorInfo);
484 HRESULT Parser_AddPin(ParserImpl * This, const PIN_INFO * piOutput, ALLOCATOR_PROPERTIES * props, const AM_MEDIA_TYPE * amt)
489 ppOldPins = This->ppPins;
491 This->ppPins = CoTaskMemAlloc((This->cStreams + 2) * sizeof(IPin *));
492 memcpy(This->ppPins, ppOldPins, (This->cStreams + 1) * sizeof(IPin *));
494 hr = OutputPin_Construct(&Parser_OutputPin_Vtbl, sizeof(Parser_OutputPin), piOutput, props, &This->csFilter, This->ppPins + (This->cStreams + 1));
498 IPin *pPin = This->ppPins[This->cStreams + 1];
499 Parser_OutputPin *pin = (Parser_OutputPin *)pPin;
500 pin->pmt = CoTaskMemAlloc(sizeof(AM_MEDIA_TYPE));
501 CopyMediaType(pin->pmt, amt);
502 pin->dwSamplesProcessed = 0;
504 pin->pin.pin.pinInfo.pFilter = (LPVOID)This;
505 pin->pin.custom_allocator = 1;
507 This->lastpinchange = GetTickCount();
508 CoTaskMemFree(ppOldPins);
512 CoTaskMemFree(This->ppPins);
513 This->ppPins = ppOldPins;
514 ERR("Failed with error %x\n", hr);
520 static HRESULT Parser_RemoveOutputPins(ParserImpl * This)
522 /* NOTE: should be in critical section when calling this function */
525 IPin ** ppOldPins = This->ppPins;
527 TRACE("(%p)\n", This);
529 /* reduce the pin array down to 1 (just our input pin) */
530 This->ppPins = CoTaskMemAlloc(sizeof(IPin *) * 1);
531 memcpy(This->ppPins, ppOldPins, sizeof(IPin *) * 1);
533 for (i = 0; i < This->cStreams; i++)
535 hr = OutputPin_DeliverDisconnect((OutputPin *)ppOldPins[i + 1]);
536 TRACE("Disconnect: %08x\n", hr);
537 IPin_Release(ppOldPins[i + 1]);
540 This->lastpinchange = GetTickCount();
542 CoTaskMemFree(ppOldPins);
547 static HRESULT Parser_ChangeCurrent(IBaseFilter *iface)
549 FIXME("(%p) filter hasn't implemented current position change!\n", iface);
553 static HRESULT Parser_ChangeStop(IBaseFilter *iface)
555 FIXME("(%p) filter hasn't implemented stop position change!\n", iface);
559 static HRESULT Parser_ChangeRate(IBaseFilter *iface)
561 FIXME("(%p) filter hasn't implemented rate change!\n", iface);
566 static HRESULT WINAPI Parser_Seeking_QueryInterface(IMediaSeeking * iface, REFIID riid, LPVOID * ppv)
568 ParserImpl *This = impl_from_IMediaSeeking(iface);
570 return IUnknown_QueryInterface((IUnknown *)This, riid, ppv);
573 static ULONG WINAPI Parser_Seeking_AddRef(IMediaSeeking * iface)
575 ParserImpl *This = impl_from_IMediaSeeking(iface);
577 return IUnknown_AddRef((IUnknown *)This);
580 static ULONG WINAPI Parser_Seeking_Release(IMediaSeeking * iface)
582 ParserImpl *This = impl_from_IMediaSeeking(iface);
584 return IUnknown_Release((IUnknown *)This);
587 static const IMediaSeekingVtbl Parser_Seeking_Vtbl =
589 Parser_Seeking_QueryInterface,
590 Parser_Seeking_AddRef,
591 Parser_Seeking_Release,
592 MediaSeekingImpl_GetCapabilities,
593 MediaSeekingImpl_CheckCapabilities,
594 MediaSeekingImpl_IsFormatSupported,
595 MediaSeekingImpl_QueryPreferredFormat,
596 MediaSeekingImpl_GetTimeFormat,
597 MediaSeekingImpl_IsUsingTimeFormat,
598 MediaSeekingImpl_SetTimeFormat,
599 MediaSeekingImpl_GetDuration,
600 MediaSeekingImpl_GetStopPosition,
601 MediaSeekingImpl_GetCurrentPosition,
602 MediaSeekingImpl_ConvertTimeFormat,
603 MediaSeekingImpl_SetPositions,
604 MediaSeekingImpl_GetPositions,
605 MediaSeekingImpl_GetAvailable,
606 MediaSeekingImpl_SetRate,
607 MediaSeekingImpl_GetRate,
608 MediaSeekingImpl_GetPreroll
611 static HRESULT WINAPI Parser_OutputPin_GetMediaType(IPin *iface, int iPosition, AM_MEDIA_TYPE *pmt)
613 Parser_OutputPin *This = (Parser_OutputPin *)iface;
617 return VFW_S_NO_MORE_ITEMS;
618 CopyMediaType(pmt, This->pmt);
622 static HRESULT WINAPI Parser_OutputPin_QueryInterface(IPin * iface, REFIID riid, LPVOID * ppv)
624 Parser_OutputPin *This = (Parser_OutputPin *)iface;
626 TRACE("(%s, %p)\n", qzdebugstr_guid(riid), ppv);
630 if (IsEqualIID(riid, &IID_IUnknown))
632 else if (IsEqualIID(riid, &IID_IPin))
634 else if (IsEqualIID(riid, &IID_IMediaSeeking))
636 return IBaseFilter_QueryInterface(This->pin.pin.pinInfo.pFilter, &IID_IMediaSeeking, ppv);
641 IUnknown_AddRef((IUnknown *)(*ppv));
645 FIXME("No interface for %s!\n", qzdebugstr_guid(riid));
647 return E_NOINTERFACE;
650 static ULONG WINAPI Parser_OutputPin_Release(IPin * iface)
652 Parser_OutputPin *This = (Parser_OutputPin *)iface;
653 ULONG refCount = InterlockedDecrement(&This->pin.pin.refCount);
655 TRACE("(%p)->() Release from %d\n", iface, refCount + 1);
659 FreeMediaType(This->pmt);
660 CoTaskMemFree(This->pmt);
661 FreeMediaType(&This->pin.pin.mtCurrent);
668 static HRESULT WINAPI Parser_OutputPin_EnumMediaTypes(IPin * iface, IEnumMediaTypes ** ppEnum)
670 TRACE("(%p)\n", ppEnum);
672 /* override this method to allow enumeration of your types */
674 return EnumMediaTypes_Construct(iface, Parser_OutputPin_GetMediaType, BasePinImpl_GetMediaTypeVersion, ppEnum);
677 static HRESULT WINAPI Parser_OutputPin_Connect(IPin * iface, IPin * pReceivePin, const AM_MEDIA_TYPE * pmt)
679 Parser_OutputPin *This = (Parser_OutputPin *)iface;
680 ParserImpl *parser = (ParserImpl *)This->pin.pin.pinInfo.pFilter;
682 /* Set the allocator to our input pin's */
683 EnterCriticalSection(This->pin.pin.pCritSec);
684 This->pin.alloc = parser->pInputPin->pAlloc;
685 LeaveCriticalSection(This->pin.pin.pCritSec);
687 return OutputPin_Connect(iface, pReceivePin, pmt);
690 static HRESULT WINAPI Parser_OutputPin_QueryAccept(IPin *iface, const AM_MEDIA_TYPE * pmt)
692 Parser_OutputPin *This = (Parser_OutputPin *)iface;
695 dump_AM_MEDIA_TYPE(pmt);
697 return (memcmp(This->pmt, pmt, sizeof(AM_MEDIA_TYPE)) == 0);
700 static const IPinVtbl Parser_OutputPin_Vtbl =
702 Parser_OutputPin_QueryInterface,
704 Parser_OutputPin_Release,
705 Parser_OutputPin_Connect,
706 OutputPin_ReceiveConnection,
707 OutputPin_Disconnect,
708 BasePinImpl_ConnectedTo,
709 BasePinImpl_ConnectionMediaType,
710 BasePinImpl_QueryPinInfo,
711 BasePinImpl_QueryDirection,
713 Parser_OutputPin_QueryAccept,
714 Parser_OutputPin_EnumMediaTypes,
715 BasePinImpl_QueryInternalConnections,
716 OutputPin_EndOfStream,
717 OutputPin_BeginFlush,
722 static HRESULT WINAPI Parser_PullPin_Disconnect(IPin * iface)
725 PullPin *This = (PullPin *)iface;
729 EnterCriticalSection(&This->thread_lock);
730 EnterCriticalSection(This->pin.pCritSec);
732 if (This->pin.pConnectedTo)
735 ParserImpl *Parser = (ParserImpl *)This->pin.pinInfo.pFilter;
737 LeaveCriticalSection(This->pin.pCritSec);
738 hr = IBaseFilter_GetState(This->pin.pinInfo.pFilter, INFINITE, &state);
739 EnterCriticalSection(This->pin.pCritSec);
741 if (SUCCEEDED(hr) && (state == State_Stopped) && SUCCEEDED(Parser->fnDisconnect(Parser)))
743 LeaveCriticalSection(This->pin.pCritSec);
744 PullPin_Disconnect(iface);
745 EnterCriticalSection(This->pin.pCritSec);
746 hr = Parser_RemoveOutputPins((ParserImpl *)This->pin.pinInfo.pFilter);
749 hr = VFW_E_NOT_STOPPED;
754 LeaveCriticalSection(This->pin.pCritSec);
755 LeaveCriticalSection(&This->thread_lock);
760 static HRESULT WINAPI Parser_PullPin_ReceiveConnection(IPin * iface, IPin * pReceivePin, const AM_MEDIA_TYPE * pmt)
766 hr = PullPin_ReceiveConnection(iface, pReceivePin, pmt);
769 BasePin *This = (BasePin *)iface;
771 EnterCriticalSection(This->pCritSec);
772 Parser_RemoveOutputPins((ParserImpl *)This->pinInfo.pFilter);
773 LeaveCriticalSection(This->pCritSec);
779 static const IPinVtbl Parser_InputPin_Vtbl =
781 PullPin_QueryInterface,
785 Parser_PullPin_ReceiveConnection,
786 Parser_PullPin_Disconnect,
787 BasePinImpl_ConnectedTo,
788 BasePinImpl_ConnectionMediaType,
789 BasePinImpl_QueryPinInfo,
790 BasePinImpl_QueryDirection,
793 BasePinImpl_EnumMediaTypes,
794 BasePinImpl_QueryInternalConnections,