ad_faad: Make work with -demuxer lavf
[mplayer/glamo.git] / loader / dshow / inputpin.c
blob3227339bee019d72ebb42bc55648c6c40041a0b3
1 /*
2 * Modified for use with MPlayer, detailed changelog at
3 * http://svn.mplayerhq.hu/mplayer/trunk/
4 */
6 #include "inputpin.h"
7 #include "mediatype.h"
8 #include "loader/wine/winerror.h"
9 #include <string.h>
10 #include <stdio.h>
11 #include <stdlib.h>
13 static inline int unimplemented(const char* s, void* p)
15 Debug printf("%s(%p) called (UNIMPLEMENTED)", s, p);
16 return E_NOTIMPL;
19 /***********
20 * EnumPins
21 ***********/
23 typedef struct
25 IEnumPins_vt* vt;
26 DECLARE_IUNKNOWN();
27 IPin* pin1;
28 IPin* pin2;
29 int counter;
30 GUID interfaces[2];
31 } CEnumPins;
33 /**
34 * \brief IEnumPins:Next (retrives a specified number of pins )
36 * \param[in] This pointer to CEnumPins object
37 * \param[in] cMediaTypes number of pins to retrive
38 * \param[out] ppMediaTypes array of IPin interface pointers of size cMediaTypes
39 * \param[out] pcFetched address of variables that receives number of returned pins
41 * \return S_OK - success
42 * \return S_FALSE - did not return as meny pins as requested
43 * \return E_INVALIDARG Invalid argument
44 * \return E_POINTER Null pointer
45 * \return VFW_E_ENUM_OUT_OF_SYNC - filter's state has changed and is now inconsistent with enumerator
48 static long STDCALL CEnumPins_Next(IEnumPins* This,
49 /* [in] */ unsigned long cMediaTypes,
50 /* [size_is][out] */ IPin** ppMediaTypes,
51 /* [out] */ unsigned long* pcFetched)
53 CEnumPins* pin = (CEnumPins*)This;
55 Debug printf("CEnumPins_Next(%p) called\n", This);
56 if (!ppMediaTypes)
57 return E_INVALIDARG;
58 if (!pcFetched && (cMediaTypes!=1))
59 return E_INVALIDARG;
60 if (cMediaTypes<=0)
61 return 0;
63 //lcounter = ((CEnumPins*)This)->counter;
64 //lpin1 = ((CEnumPins*)This)->pin1;
65 //lpin2 = ((CEnumPins*)This)->pin2;
66 if (((pin->counter == 2) && pin->pin2)
67 || ((pin->counter == 1) && !pin->pin2))
69 if (pcFetched)
70 *pcFetched=0;
71 return 1;
74 if (pcFetched)
75 *pcFetched=1;
76 if (pin->counter==0)
78 *ppMediaTypes = pin->pin1;
79 pin->pin1->vt->AddRef((IUnknown*)pin->pin1);
81 else
83 *ppMediaTypes = pin->pin2;
84 pin->pin2->vt->AddRef((IUnknown*)pin->pin2);
86 pin->counter++;
87 if (cMediaTypes == 1)
88 return 0;
89 return 1;
92 /**
93 * \brief IEnumPins::Skip (skips over a specified number of pins)
95 * \param[in] This pointer to CEnumPinss object
96 * \param[in] cMediaTypes number of pins to skip
98 * \return S_OK - success
99 * \return S_FALSE - skipped past the end of the sequence
100 * \return VFW_E_ENUM_OUT_OF_SYNC - filter's state has changed and is now inconsistent with enumerator
103 static long STDCALL CEnumPins_Skip(IEnumPins* This,
104 /* [in] */ unsigned long cMediaTypes)
106 Debug unimplemented("CEnumPins_Skip", This);
107 return E_NOTIMPL;
111 * \brief IEnumPins::Reset (resets enumeration sequence to beginning)
113 * \param[in] This pointer to CEnumPins object
115 * \return S_OK - success
118 static long STDCALL CEnumPins_Reset(IEnumPins* This)
120 Debug printf("CEnumPins_Reset(%p) called\n", This);
121 ((CEnumPins*)This)->counter = 0;
122 return 0;
126 * \brief IEnumPins::Clone (makes a copy of enumerator, returned object
127 * starts at the same position as original)
129 * \param[in] This pointer to CEnumPins object
130 * \param[out] ppEnum address of variable that receives pointer to IEnumPins interface
132 * \return S_OK - success
133 * \return E_OUTOFMEMRY - Insufficient memory
134 * \return E_POINTER - Null pointer
135 * \return VFW_E_ENUM_OUT_OF_SYNC - filter's state has changed and is now inconsistent with enumerator
138 static long STDCALL CEnumPins_Clone(IEnumPins* This,
139 /* [out] */ IEnumPins** ppEnum)
141 Debug unimplemented("CEnumPins_Clone", This);
142 return E_NOTIMPL;
146 * \brief CEnumPins destructor
148 * \param[in] This pointer to CEnumPins object
151 static void CEnumPins_Destroy(CEnumPins* This)
153 free(This->vt);
154 free(This);
157 IMPLEMENT_IUNKNOWN(CEnumPins)
160 * \brief CEnumPins constructor
162 * \param[in] p first pin for enumerator
163 * \param[in] pp second pin for enumerator
165 * \return pointer to CEnumPins object or NULL if error occured
168 static CEnumPins* CEnumPinsCreate(IPin* p, IPin* pp)
170 CEnumPins* This = malloc(sizeof(CEnumPins));
172 if (!This)
173 return NULL;
175 This->refcount = 1;
176 This->pin1 = p;
177 This->pin2 = pp;
178 This->counter = 0;
180 This->vt = malloc(sizeof(IEnumPins_vt));
181 if (!This->vt)
183 free(This);
184 return NULL;
186 This->vt->QueryInterface = CEnumPins_QueryInterface;
187 This->vt->AddRef = CEnumPins_AddRef;
188 This->vt->Release = CEnumPins_Release;
189 This->vt->Next = CEnumPins_Next;
190 This->vt->Skip = CEnumPins_Skip;
191 This->vt->Reset = CEnumPins_Reset;
192 This->vt->Clone = CEnumPins_Clone;
194 This->interfaces[0] = IID_IUnknown;
195 This->interfaces[1] = IID_IEnumPins;
197 return This;
202 /***********
203 * InputPin
205 * WARNING:
206 * This is implementation of OUTPUT pin in DirectShow's terms
208 ***********/
211 * \brief IPin::Connect (connects pin to another pin)
213 * \param[in] This pointer to IPin interface
214 * \param[in] pReceivePin pointer to IPin interface of remote pin
215 * \param[in] pmt suggested media type for link. Can be NULL (any media type)
217 * \return S_OK - success.
218 * \return VFW_E_ALREADY_CONNECTED - pin already connected
219 * \return VFW_E_NOT_STOPPED - filter is active
220 * \return VFW_E_TYPE_NOT_ACCEPT - type is not acceptable
221 * \return Apropriate error code otherwise.
224 static long STDCALL CInputPin_Connect(IPin* This,
225 /* [in] */ IPin* pReceivePin,
226 /* [in] */ AM_MEDIA_TYPE* pmt)
228 Debug unimplemented("CInputPin_Connect", This);
229 return E_NOTIMPL;
233 * \brief IPin::ReceiveConnection (accepts a connection from another pin)
235 * \param[in] This pointer to IPin interface
236 * \param[in] pConnector connecting pin's IPin interface
237 * \param[in] pmt suggested media type for connection
239 * \return S_OK - success
240 * \return E_POINTER - Null pointer
241 * \return VFW_E_ALREADY_CONNECTED - pin already connected
242 * \return VFW_E_NOT_STOPPED - filter is active
243 * \return VFW_E_TYPE_NOT_ACCEPT - type is not acceptable
245 * \note
246 * When returning S_OK method should also do the following:
247 * - store media type and return the same type in IPin::ConnectionMediaType
248 * - store pConnector and return it in IPin::ConnectedTo
251 static long STDCALL CInputPin_ReceiveConnection(IPin* This,
252 /* [in] */ IPin* pConnector,
253 /* [in] */ const AM_MEDIA_TYPE *pmt)
255 Debug unimplemented("CInputPin_ReceiveConnection", This);
256 return E_NOTIMPL;
260 * \brief IPin::Disconnect (accepts a connection from another pin)
262 * \param[in] This pointer to IPin interface
264 * \return S_OK - success
265 * \return S_FALSE - pin was not connected
266 * \return VFW_E_NOT_STOPPED - filter is active
268 * \note
269 * To break connection you have to also call Disconnect on other pin
271 static long STDCALL CInputPin_Disconnect(IPin* This)
273 Debug unimplemented("CInputPin_Disconnect", This);
274 return E_NOTIMPL;
278 * \brief IPin::ConnectedTo (retrieves pointer to the connected pin, if such exist)
280 * \param[in] This pointer to IPin interface
281 * \param[out] pPin pointer to remote pin's IPin interface
283 * \return S_OK - success
284 * \return E_POINTER - Null pointer
285 * \return VFW_E_NOT_CONNECTED - pin is not connected
287 * \note
288 * Caller must call Release on received IPin, when done
290 static long STDCALL CInputPin_ConnectedTo(IPin* This,
291 /* [out] */ IPin** pPin)
293 Debug unimplemented("CInputPin_ConnectedTo", This);
294 return E_NOTIMPL;
298 * \brief IPin::ConnectionMediaType (retrieves media type for connection, if such exist)
300 * \param[in] This pointer to IPin interface
301 * \param[out] pmt pointer to AM_MEDIA_TYPE, that receives connection media type
303 * \return S_OK - success
304 * \return E_POINTER - Null pointer
305 * \return VFW_E_NOT_CONNECTED - pin is not connected
308 static long STDCALL CInputPin_ConnectionMediaType(IPin* This,
309 /* [out] */ AM_MEDIA_TYPE *pmt)
311 Debug printf("CInputPin_ConnectionMediaType(%p) called\n", This);
312 if (!pmt)
313 return E_INVALIDARG;
314 CopyMediaType(pmt,&(((CInputPin*)This)->type));
315 return 0;
319 * \brief IPin::QueryPinInfo (retrieves information about the pin)
321 * \param[in] This pointer to IPin interface
322 * \param[out] pInfo pointer to PIN_INFO structure, that receives pin info
324 * \return S_OK - success
325 * \return E_POINTER - Null pointer
327 * \note
328 * If pInfo->pFilter is not NULL, then caller must call Release on pInfo->pFilter when done
331 static long STDCALL CInputPin_QueryPinInfo(IPin* This,
332 /* [out] */ PIN_INFO *pInfo)
334 CBaseFilter* lparent=((CInputPin*)This)->parent;
335 Debug printf("CInputPin_QueryPinInfo(%p) called\n", This);
336 pInfo->dir = PINDIR_OUTPUT;
337 pInfo->pFilter = (IBaseFilter*) lparent;
338 lparent->vt->AddRef((IUnknown*)lparent);
339 pInfo->achName[0] = 0;
340 return 0;
344 * \brief IPin::QueryDirection (retrieves pin direction)
346 * \param[in] This pointer to IPin interface
347 * \param[out] pPinDir pointer to variable, that receives pin direction (PINDIR_INPUT,PINDIR_OUTPUT)
349 * \return S_OK - success
350 * \return E_POINTER - Null pointer
353 static long STDCALL CInputPin_QueryDirection(IPin* This,
354 /* [out] */ PIN_DIRECTION *pPinDir)
356 *pPinDir = PINDIR_OUTPUT;
357 Debug printf("CInputPin_QueryDirection(%p) called\n", This);
358 return 0;
362 * \brief IPin::QueryId (retrieves pin identificator)
364 * \param[in] This pointer to IPin interface
365 * \param[out] Id adress of variable, that receives string with pin's Id.
367 * \return S_OK - success
368 * \return E_OUTOFMEMORY - Insufficient memory
369 * \return E_POINTER - Null pointer
371 * \note
372 * Pin's Id is not the same as pin's name
375 static long STDCALL CInputPin_QueryId(IPin* This,
376 /* [out] */ unsigned short* *Id)
378 Debug unimplemented("CInputPin_QueryId", This);
379 return E_NOTIMPL;
383 * \brief IPin::QueryAccept (determines can media type be accepted or not)
385 * \param[in] This pointer to IPin interface
386 * \param[in] pmt Media type to check
388 * \return S_OK - success
389 * \return S_FALSE - pin rejects media type
392 static long STDCALL CInputPin_QueryAccept(IPin* This,
393 /* [in] */ const AM_MEDIA_TYPE* pmt)
395 Debug unimplemented("CInputPin_QueryAccept", This);
396 return E_NOTIMPL;
400 * \brief IPin::EnumMediaTypes (enumerates the pin's preferred media types)
402 * \param[in] This pointer to IPin interface
403 * \param[out] ppEnum adress of variable that receives pointer to IEnumMEdiaTypes interface
405 * \return S_OK - success
406 * \return E_OUTOFMEMORY - Insufficient memory
407 * \return E_POINTER - Null pointer
409 * \note
410 * Caller must call Release on received interface when done
413 static long STDCALL CInputPin_EnumMediaTypes(IPin* This,
414 /* [out] */ IEnumMediaTypes** ppEnum)
416 Debug unimplemented("CInputPin_EnumMediaTypes", This);
417 return E_NOTIMPL;
421 * \brief IPin::QueryInternalConnections (retries pin's internal connections)
423 * \param[in] This pointer to IPin interface
424 * \param[out] apPin Array that receives pins, internally connected to this
425 * \param[in,out] nPint Size of an array
427 * \return S_OK - success
428 * \return S_FALSE - pin rejects media type
429 * \return E_NOTIMPL - not implemented
432 static long STDCALL CInputPin_QueryInternalConnections(IPin* This,
433 /* [out] */ IPin** apPin,
434 /* [out][in] */ unsigned long *nPin)
436 Debug unimplemented("CInputPin_QueryInternalConnections", This);
437 return E_NOTIMPL;
441 * \brief IPin::EndOfStream (notifies pin, that no data is expected, until new run command)
443 * \param[in] This pointer to IPin interface
445 * \return S_OK - success
446 * \return E_UNEXPECTED - The pin is output pin
448 * \note
449 * IMemoryInputPin::Receive,IMemoryInputPin::ReceiveMultiple, IMemoryInputPin::EndOfStream,
450 * IMemAllocator::GetBuffer runs in different (streaming) thread then other
451 * methods (application thread).
452 * IMemoryInputPin::NewSegment runs either in streaming or application thread.
453 * Developer must use critical sections for thread-safing work.
456 static long STDCALL CInputPin_EndOfStream(IPin * This)
458 Debug unimplemented("CInputPin_EndOfStream", This);
459 return E_NOTIMPL;
464 * \brief IPin::BeginFlush (begins a flush operation)
466 * \param[in] This pointer to IPin interface
468 * \return S_OK - success
469 * \return E_UNEXPECTED - The pin is output pin
472 static long STDCALL CInputPin_BeginFlush(IPin * This)
474 Debug unimplemented("CInputPin_BeginFlush", This);
475 return E_NOTIMPL;
480 * \brief IPin::EndFlush (ends a flush operation)
482 * \param[in] This pointer to IPin interface
484 * \return S_OK - success
485 * \return E_UNEXPECTED - The pin is output pin
488 static long STDCALL CInputPin_EndFlush(IPin* This)
490 Debug unimplemented("CInputPin_EndFlush", This);
491 return E_NOTIMPL;
495 * \brief IPin::NewSegment (media sample received after this call grouped as segment with common
496 * start,stop time and rate)
498 * \param[in] This pointer to IPin interface
499 * \param[in] tStart start time of new segment
500 * \param[in] tStop end time of new segment
501 * \param[in] dRate rate at wich segment should be processed
503 * \return S_OK - success
504 * \return E_UNEXPECTED - The pin is output pin
507 static long STDCALL CInputPin_NewSegment(IPin* This,
508 /* [in] */ REFERENCE_TIME tStart,
509 /* [in] */ REFERENCE_TIME tStop,
510 /* [in] */ double dRate)
512 Debug unimplemented("CInputPin_NewSegment", This);
513 return E_NOTIMPL;
517 * \brief CInputPin destructor
519 * \param[in] This pointer to CInputPin class
522 static void CInputPin_Destroy(CInputPin* This)
524 free(This->vt);
525 FreeMediaType(&(This->type));
526 free(This);
529 IMPLEMENT_IUNKNOWN(CInputPin)
532 * \brief CInputPin constructor
534 * \param[in] amt media type for pin
536 * \return pointer to CInputPin if success
537 * \return NULL if error occured
540 CInputPin* CInputPinCreate(CBaseFilter* p, const AM_MEDIA_TYPE* amt)
542 CInputPin* This = malloc(sizeof(CInputPin));
544 if (!This)
545 return NULL;
547 This->refcount = 1;
548 This->parent = p;
549 CopyMediaType(&(This->type),amt);
551 This->vt= malloc(sizeof(IPin_vt));
553 if (!This->vt)
555 free(This);
556 return NULL;
559 This->vt->QueryInterface = CInputPin_QueryInterface;
560 This->vt->AddRef = CInputPin_AddRef;
561 This->vt->Release = CInputPin_Release;
562 This->vt->Connect = CInputPin_Connect;
563 This->vt->ReceiveConnection = CInputPin_ReceiveConnection;
564 This->vt->Disconnect = CInputPin_Disconnect;
565 This->vt->ConnectedTo = CInputPin_ConnectedTo;
566 This->vt->ConnectionMediaType = CInputPin_ConnectionMediaType;
567 This->vt->QueryPinInfo = CInputPin_QueryPinInfo;
568 This->vt->QueryDirection = CInputPin_QueryDirection;
569 This->vt->QueryId = CInputPin_QueryId;
570 This->vt->QueryAccept = CInputPin_QueryAccept;
571 This->vt->EnumMediaTypes = CInputPin_EnumMediaTypes;
572 This->vt->QueryInternalConnections = CInputPin_QueryInternalConnections;
573 This->vt->EndOfStream = CInputPin_EndOfStream;
574 This->vt->BeginFlush = CInputPin_BeginFlush;
575 This->vt->EndFlush = CInputPin_EndFlush;
576 This->vt->NewSegment = CInputPin_NewSegment;
578 This->interfaces[0]=IID_IUnknown;
580 return This;
584 /*************
585 * BaseFilter
586 *************/
588 static long STDCALL CBaseFilter_GetClassID(IBaseFilter * This,
589 /* [out] */ CLSID *pClassID)
591 Debug unimplemented("CBaseFilter_GetClassID", This);
592 return E_NOTIMPL;
596 * \brief IMediaFilter::Stop (stops the filter)
598 * \param[in] This pointer to IBaseFilter interface
600 * \return S_OK success
601 * \return S_FALSE transition is not complete
603 * \remarks
604 * When filter is stopped it does onot deliver or process any samples and rejects any samples
605 * from upstream filter.
606 * Transition may be asynchronous. In this case method should return S_FALSE.
607 * Method always sets filter's state to State_Stopped even if error occured.
610 static long STDCALL CBaseFilter_Stop(IBaseFilter* This)
612 Debug unimplemented("CBaseFilter_Stop", This);
613 return E_NOTIMPL;
617 * \brief IMediaFilter::Pause (pauses filter)
619 * \param[in] This pointer to IBaseFilter interface
621 * \return S_OK success
622 * \return S_FALSE transition is not complete
624 * \remarks
625 * When filter is paused it can receive, process and deliver samples.
626 * Live source filters do not deliver any samples while paused.
627 * Transition may be asynchronous. In this case method should return S_FALSE.
628 * Method always sets filter's state to State_Stopped even if error occured.
631 static long STDCALL CBaseFilter_Pause(IBaseFilter* This)
633 Debug unimplemented("CBaseFilter_Pause", This);
634 return E_NOTIMPL;
638 * \brief IMediaFilter::Run (runs the filter)
640 * \param[in] This pointer to IBaseFilter interface
641 * \param[in] tStart Reference time corresponding to stream time 0.
643 * \return S_OK success
644 * \return S_FALSE transition is not complete
646 * \remarks
647 * When filter is running it can receive, process and deliver samples. Source filters
648 * generatesnew samples, and renderers renders them.
649 * Stream time is calculated as the current reference time minus tStart.
650 * Graph Manager sets tStart slightly in the future according to graph latency.
653 static long STDCALL CBaseFilter_Run(IBaseFilter* This, REFERENCE_TIME tStart)
655 Debug unimplemented("CBaseFilter_Run", This);
656 return E_NOTIMPL;
660 * \brief IMediaFilter::GetState (retrieves the filter's state (running, stopped or paused))
662 * \param[in] This pointer to IBaseFilter interface
663 * \param[in] dwMilliSecsTimeout Timeout interval in milliseconds. To block indifinitely pass
664 * INFINITE.
665 * \param[out] State pointer to variable that receives a member of FILTER_STATE enumeration.
667 * \return S_OK success
668 * \return E_POINTER Null pointer
669 * \return VFW_S_STATE_INTERMEDATE Intermediate state
670 * \return VFW_S_CANT_CUE The filter is active, but cannot deliver data.
673 static long STDCALL CBaseFilter_GetState(IBaseFilter* This,
674 /* [in] */ unsigned long dwMilliSecsTimeout,
675 // /* [out] */ FILTER_STATE *State)
676 void* State)
678 Debug unimplemented("CBaseFilter_GetState", This);
679 return E_NOTIMPL;
683 * \brief IMediaFilter::SetSyncSource (sets the reference clock)
685 * \param[in] This pointer to IBaseFilter interface
686 * \param[in] pClock IReferenceClock interface of reference clock
688 * \return S_OK success
689 * \return apripriate error otherwise
692 static long STDCALL CBaseFilter_SetSyncSource(IBaseFilter* This,
693 /* [in] */ IReferenceClock *pClock)
695 Debug unimplemented("CBaseFilter_SetSyncSource", This);
696 return E_NOTIMPL;
700 * \brief IMediafilter::GetSyncSource (gets current reference clock)
702 * \param[in] This pointer to IBaseFilter interface
703 * \param[out] pClock address of variable that receives pointer to clock's
704 * IReferenceClock interface
706 * \return S_OK success
707 * \return E_POINTER Null pointer
710 static long STDCALL CBaseFilter_GetSyncSource(IBaseFilter* This,
711 /* [out] */ IReferenceClock **pClock)
713 Debug unimplemented("CBaseFilter_GetSyncSource", This);
714 return E_NOTIMPL;
719 * \brief IBaseFilter::EnumPins (enumerates the pins of this filter)
721 * \param[in] This pointer to IBaseFilter interface
722 * \param[out] ppEnum address of variable that receives pointer to IEnumPins interface
724 * \return S_OK success
725 * \return E_OUTOFMEMORY Insufficient memory
726 * \return E_POINTER Null pointer
729 static long STDCALL CBaseFilter_EnumPins(IBaseFilter* This,
730 /* [out] */ IEnumPins **ppEnum)
732 Debug printf("CBaseFilter_EnumPins(%p) called\n", This);
733 *ppEnum = (IEnumPins*) CEnumPinsCreate(((CBaseFilter*)This)->pin, ((CBaseFilter*)This)->unused_pin);
734 return 0;
738 * \brief IBaseFilter::FindPin (retrieves the pin with specified id)
740 * \param[in] This pointer to IBaseFilter interface
741 * \param[in] Id constant wide string, containing pin id
742 * \param[out] ppPin address of variable that receives pointer to pin's IPin interface
744 * \return S_OK success
745 * \return E_POINTER Null pointer
746 * \return VFW_E_NOT_FOUND Could not find a pin with specified id
748 * \note
749 * Be sure to release the interface after use.
752 static long STDCALL CBaseFilter_FindPin(IBaseFilter* This,
753 /* [string][in] */ const unsigned short* Id,
754 /* [out] */ IPin **ppPin)
756 Debug unimplemented("CBaseFilter_FindPin\n", This);
757 return E_NOTIMPL;
761 * \brief IBaseFilter::QueryFilterInfo (retrieves information aboud the filter)
763 * \param[in] This pointer to IBaseFilter interface
764 * \param[out] pInfo pointer to FILTER_INFO structure
766 * \return S_OK success
767 * \return E_POINTER Null pointer
769 * \note
770 * If pGraph member of FILTER_INFO is not NULL, be sure to release IFilterGraph interface after use.
773 static long STDCALL CBaseFilter_QueryFilterInfo(IBaseFilter* This,
774 // /* [out] */ FILTER_INFO *pInfo)
775 void* pInfo)
777 Debug unimplemented("CBaseFilter_QueryFilterInfo", This);
778 return E_NOTIMPL;
782 * \brief IBaseFilter::JoinFilterGraph (notifies the filter that it has joined of left filter graph)
784 * \param[in] This pointer to IBaseFilter interface
785 * \param[in] pInfo pointer to graph's IFilterGraph interface or NULL if filter is leaving graph
786 * \param[in] pName pointer to wide character string that specifies a name for the filter
788 * \return S_OK success
789 * \return apropriate error code otherwise
791 * \remarks
792 * Filter should not call to graph's AddRef method.
793 * The IFilterGraph is guaranteed to be valid until graph manager calls this method again with
794 * the value NULL.
797 static long STDCALL CBaseFilter_JoinFilterGraph(IBaseFilter* This,
798 /* [in] */ IFilterGraph* pGraph,
799 /* [string][in] */ const unsigned short* pName)
801 Debug unimplemented("CBaseFilter_JoinFilterGraph", This);
802 return E_NOTIMPL;
806 * \brief IBaseFilter::QueryVendorInfo (retrieves a string containing vendor info)
808 * \param[in] This pointer to IBaseFilter interface
809 * \param[out] address of variable that receives pointer to a string containing vendor info
811 * \return S_OK success
812 * \return E_POINTER Null pointer
813 * \return E_NOTIMPL Not implemented
815 * \remarks
816 * Call to CoTaskMemFree to free memory allocated for string
819 static long STDCALL CBaseFilter_QueryVendorInfo(IBaseFilter* This,
820 /* [string][out] */ unsigned short** pVendorInfo)
822 Debug unimplemented("CBaseFilter_QueryVendorInfo", This);
823 return E_NOTIMPL;
827 * \brief CBaseFilter::GetPin (gets used pin)
829 * \param[in] This pointer to CBaseFilter object
831 * \return pointer to used pin's IPin interface
834 static IPin* CBaseFilter_GetPin(CBaseFilter* This)
836 return This->pin;
840 * \brief CBaseFilter::GetUnusedPin (gets used pin)
842 * \param[in] This pointer to CBaseFilter object
844 * \return pointer to unused pin's IPin interface
847 static IPin* CBaseFilter_GetUnusedPin(CBaseFilter* This)
849 return This->unused_pin;
853 * \brief CBaseFilter destructor
855 * \param[in] This pointer to CBaseFilter object
858 static void CBaseFilter_Destroy(CBaseFilter* This)
860 if (This->vt)
861 free(This->vt);
862 if (This->pin)
863 This->pin->vt->Release((IUnknown*)This->pin);
864 if (This->unused_pin)
865 This->unused_pin->vt->Release((IUnknown*)This->unused_pin);
866 free(This);
869 IMPLEMENT_IUNKNOWN(CBaseFilter)
872 * \brief CBaseFilter constructor
874 * \param[in] type Pointer to media type for connection
875 * \param[in] parent Pointer to parent CBaseFilter2 object
877 * \return pointer to CBaseFilter object or NULL if error occured
880 CBaseFilter* CBaseFilterCreate(const AM_MEDIA_TYPE* type, CBaseFilter2* parent)
882 CBaseFilter* This = malloc(sizeof(CBaseFilter));
883 if (!This)
884 return NULL;
886 This->refcount = 1;
888 This->pin = (IPin*) CInputPinCreate(This, type);
889 This->unused_pin = (IPin*) CRemotePinCreate(This, parent->GetPin(parent));
891 This->vt = malloc(sizeof(IBaseFilter_vt));
892 if (!This->vt || !This->pin || !This->unused_pin)
894 CBaseFilter_Destroy(This);
895 return NULL;
898 This->vt->QueryInterface = CBaseFilter_QueryInterface;
899 This->vt->AddRef = CBaseFilter_AddRef;
900 This->vt->Release = CBaseFilter_Release;
901 This->vt->GetClassID = CBaseFilter_GetClassID;
902 This->vt->Stop = CBaseFilter_Stop;
903 This->vt->Pause = CBaseFilter_Pause;
904 This->vt->Run = CBaseFilter_Run;
905 This->vt->GetState = CBaseFilter_GetState;
906 This->vt->SetSyncSource = CBaseFilter_SetSyncSource;
907 This->vt->GetSyncSource = CBaseFilter_GetSyncSource;
908 This->vt->EnumPins = CBaseFilter_EnumPins;
909 This->vt->FindPin = CBaseFilter_FindPin;
910 This->vt->QueryFilterInfo = CBaseFilter_QueryFilterInfo;
911 This->vt->JoinFilterGraph = CBaseFilter_JoinFilterGraph;
912 This->vt->QueryVendorInfo = CBaseFilter_QueryVendorInfo;
914 This->interfaces[0] = IID_IUnknown;
915 This->interfaces[1] = IID_IBaseFilter;
917 This->GetPin = CBaseFilter_GetPin;
918 This->GetUnusedPin = CBaseFilter_GetUnusedPin;
920 return This;
924 /**************
925 * BaseFilter2
926 **************/
929 static long STDCALL CBaseFilter2_GetClassID(IBaseFilter* This,
930 /* [out] */ CLSID* pClassID)
932 Debug unimplemented("CBaseFilter2_GetClassID", This);
933 return E_NOTIMPL;
937 * \brief IMediaFilter::Stop (stops the filter)
939 * \param[in] This pointer to IBaseFilter interface
941 * \return S_OK success
942 * \return S_FALSE transition is not complete
944 * \remarks
945 * When filter is stopped it does onot deliver or process any samples and rejects any samples
946 * from upstream filter.
947 * Transition may be asynchronous. In this case method should return S_FALSE.
948 * Method always sets filter's state to State_Stopped even if error occured.
951 static long STDCALL CBaseFilter2_Stop(IBaseFilter* This)
953 Debug unimplemented("CBaseFilter2_Stop", This);
954 return E_NOTIMPL;
958 * \brief IMediaFilter::Pause (pauses filter)
960 * \param[in] This pointer to IBaseFilter interface
962 * \return S_OK success
963 * \return S_FALSE transition is not complete
965 * \remarks
966 * When filter is paused it can receive, process and deliver samples.
967 * Live source filters do not deliver any samples while paused.
968 * Transition may be asynchronous. In this case method should return S_FALSE.
969 * Method always sets filter's state to State_Stopped even if error occured.
972 static long STDCALL CBaseFilter2_Pause(IBaseFilter* This)
974 Debug unimplemented("CBaseFilter2_Pause", This);
975 return E_NOTIMPL;
979 * \brief IMediaFilter::Run (runs the filter)
981 * \param[in] This pointer to IBaseFilter interface
982 * \param[in] tStart Reference time corresponding to stream time 0.
984 * \return S_OK success
985 * \return S_FALSE transition is not complete
987 * \remarks
988 * When filter is running it can receive, process and deliver samples. Source filters
989 * generatesnew samples, and renderers renders them.
990 * Stream time is calculated as the current reference time minus tStart.
991 * Graph Manager sets tStart slightly in the future according to graph latency.
994 static long STDCALL CBaseFilter2_Run(IBaseFilter* This, REFERENCE_TIME tStart)
996 Debug unimplemented("CBaseFilter2_Run", This);
997 return E_NOTIMPL;
1002 * \brief IMediaFilter::GetState (retrieves the filter's state (running, stopped or paused))
1004 * \param[in] This pointer to IBaseFilter interface
1005 * \param[in] dwMilliSecsTimeout Timeout interval in milliseconds. To block indifinitely pass
1006 * INFINITE.
1007 * \param[out] State pointer to variable that receives a member of FILTER_STATE enumeration.
1009 * \return S_OK success
1010 * \return E_POINTER Null pointer
1011 * \return VFW_S_STATE_INTERMEDATE Intermediate state
1012 * \return VFW_S_CANT_CUE The filter is active, but cannot deliver data.
1015 static long STDCALL CBaseFilter2_GetState(IBaseFilter* This,
1016 /* [in] */ unsigned long dwMilliSecsTimeout,
1017 // /* [out] */ FILTER_STATE *State)
1018 void* State)
1020 Debug unimplemented("CBaseFilter2_GetState", This);
1021 return E_NOTIMPL;
1025 * \brief IMediaFilter::SetSyncSource (sets the reference clock)
1027 * \param[in] This pointer to IBaseFilter interface
1028 * \param[in] pClock IReferenceClock interface of reference clock
1030 * \return S_OK success
1031 * \return apripriate error otherwise
1034 static long STDCALL CBaseFilter2_SetSyncSource(IBaseFilter* This,
1035 /* [in] */ IReferenceClock* pClock)
1037 Debug unimplemented("CBaseFilter2_SetSyncSource", This);
1038 return E_NOTIMPL;
1042 * \brief IMediafilter::GetSyncSource (gets current reference clock)
1044 * \param[in] This pointer to IBaseFilter interface
1045 * \param[out] pClock address of variable that receives pointer to clock's
1046 * IReferenceClock interface
1048 * \return S_OK success
1049 * \return E_POINTER Null pointer
1052 static long STDCALL CBaseFilter2_GetSyncSource(IBaseFilter* This,
1053 /* [out] */ IReferenceClock** pClock)
1055 Debug unimplemented("CBaseFilter2_GetSyncSource", This);
1056 return E_NOTIMPL;
1060 * \brief IBaseFilter::EnumPins (enumerates the pins of this filter)
1062 * \param[in] This pointer to IBaseFilter interface
1063 * \param[out] ppEnum address of variable that receives pointer to IEnumPins interface
1065 * \return S_OK success
1066 * \return E_OUTOFMEMORY Insufficient memory
1067 * \return E_POINTER Null pointer
1070 static long STDCALL CBaseFilter2_EnumPins(IBaseFilter* This,
1071 /* [out] */ IEnumPins** ppEnum)
1073 Debug printf("CBaseFilter2_EnumPins(%p) called\n", This);
1074 *ppEnum = (IEnumPins*) CEnumPinsCreate(((CBaseFilter2*)This)->pin, 0);
1075 return 0;
1079 * \brief IBaseFilter::FindPin (retrieves the pin with specified id)
1081 * \param[in] This pointer to IBaseFilter interface
1082 * \param[in] Id constant wide string, containing pin id
1083 * \param[out] ppPin address of variable that receives pointer to pin's IPin interface
1085 * \return S_OK success
1086 * \return E_POINTER Null pointer
1087 * \return VFW_E_NOT_FOUND Could not find a pin with specified id
1089 * \note
1090 * Be sure to release the interface after use.
1093 static long STDCALL CBaseFilter2_FindPin(IBaseFilter* This,
1094 /* [string][in] */ const unsigned short* Id,
1095 /* [out] */ IPin** ppPin)
1097 Debug unimplemented("CBaseFilter2_FindPin", This);
1098 return E_NOTIMPL;
1102 * \brief IBaseFilter::QueryFilterInfo (retrieves information aboud the filter)
1104 * \param[in] This pointer to IBaseFilter interface
1105 * \param[out] pInfo pointer to FILTER_INFO structure
1107 * \return S_OK success
1108 * \return E_POINTER Null pointer
1110 * \note
1111 * If pGraph member of FILTER_INFO is not NULL, be sure to release IFilterGraph interface after use.
1114 static long STDCALL CBaseFilter2_QueryFilterInfo(IBaseFilter* This,
1115 // /* [out] */ FILTER_INFO *pInfo)
1116 void* pInfo)
1118 Debug unimplemented("CBaseFilter2_QueryFilterInfo", This);
1119 return E_NOTIMPL;
1123 * \brief IBaseFilter::JoinFilterGraph (notifies the filter that it has joined of left filter graph)
1125 * \param[in] This pointer to IBaseFilter interface
1126 * \param[in] pInfo pointer to graph's IFilterGraph interface or NULL if filter is leaving graph
1127 * \param[in] pName pointer to wide character string that specifies a name for the filter
1129 * \return S_OK success
1130 * \return apropriate error code otherwise
1132 * \remarks
1133 * Filter should not call to graph's AddRef method.
1134 * The IFilterGraph is guaranteed to be valid until graph manager calls this method again with
1135 * the value NULL.
1138 static long STDCALL CBaseFilter2_JoinFilterGraph(IBaseFilter* This,
1139 /* [in] */ IFilterGraph* pGraph,
1140 /* [string][in] */
1141 const unsigned short* pName)
1143 Debug unimplemented("CBaseFilter2_JoinFilterGraph", This);
1144 return E_NOTIMPL;
1148 * \brief IBaseFilter::QueryVendorInfo (retrieves a string containing vendor info)
1150 * \param[in] This pointer to IBaseFilter interface
1151 * \param[out] address of variable that receives pointer to a string containing vendor info
1153 * \return S_OK success
1154 * \return E_POINTER Null pointer
1155 * \return E_NOTIMPL Not implemented
1157 * \remarks
1158 * Call to CoTaskMemFree to free memory allocated for string
1161 static long STDCALL CBaseFilter2_QueryVendorInfo(IBaseFilter* This,
1162 /* [string][out] */
1163 unsigned short** pVendorInfo)
1165 Debug unimplemented("CBaseFilter2_QueryVendorInfo", This);
1166 return E_NOTIMPL;
1170 * \brief CBaseFilter2::GetPin (gets used pin)
1172 * \param[in] This pointer to CBaseFilter2 object
1174 * \return pointer to used pin's IPin interface
1177 static IPin* CBaseFilter2_GetPin(CBaseFilter2* This)
1179 return This->pin;
1183 * \brief CBaseFilter2 destructor
1185 * \param[in] This pointer to CBaseFilter2 object
1188 static void CBaseFilter2_Destroy(CBaseFilter2* This)
1190 Debug printf("CBaseFilter2_Destroy(%p) called\n", This);
1191 if (This->pin)
1192 This->pin->vt->Release((IUnknown*) This->pin);
1193 if (This->vt)
1194 free(This->vt);
1195 free(This);
1198 IMPLEMENT_IUNKNOWN(CBaseFilter2)
1200 static GUID CBaseFilter2_interf1 =
1201 {0x76c61a30, 0xebe1, 0x11cf, {0x89, 0xf9, 0x00, 0xa0, 0xc9, 0x03, 0x49, 0xcb}};
1202 /// IID_IAMNetShowPreroll
1203 static GUID CBaseFilter2_interf2 =
1204 {0xaae7e4e2, 0x6388, 0x11d1, {0x8d, 0x93, 0x00, 0x60, 0x97, 0xc9, 0xa2, 0xb2}};
1205 /// IID_IAMRebuild
1206 static GUID CBaseFilter2_interf3 =
1207 {0x02ef04dd, 0x7580, 0x11d1, {0xbe, 0xce, 0x00, 0xc0, 0x4f, 0xb6, 0xe9, 0x37}};
1210 * \brief CBaseFilter2 constructor
1212 * \return pointer to CBaseFilter2 object or NULL if error occured
1215 CBaseFilter2* CBaseFilter2Create()
1217 CBaseFilter2* This = malloc(sizeof(CBaseFilter2));
1219 if (!This)
1220 return NULL;
1222 This->refcount = 1;
1223 This->pin = (IPin*) CRemotePin2Create(This);
1225 This->vt = malloc(sizeof(IBaseFilter_vt));
1227 if (!This->pin || !This->vt)
1229 CBaseFilter2_Destroy(This);
1230 return NULL;
1233 memset(This->vt, 0, sizeof(IBaseFilter_vt));
1234 This->vt->QueryInterface = CBaseFilter2_QueryInterface;
1235 This->vt->AddRef = CBaseFilter2_AddRef;
1236 This->vt->Release = CBaseFilter2_Release;
1237 This->vt->GetClassID = CBaseFilter2_GetClassID;
1238 This->vt->Stop = CBaseFilter2_Stop;
1239 This->vt->Pause = CBaseFilter2_Pause;
1240 This->vt->Run = CBaseFilter2_Run;
1241 This->vt->GetState = CBaseFilter2_GetState;
1242 This->vt->SetSyncSource = CBaseFilter2_SetSyncSource;
1243 This->vt->GetSyncSource = CBaseFilter2_GetSyncSource;
1244 This->vt->EnumPins = CBaseFilter2_EnumPins;
1245 This->vt->FindPin = CBaseFilter2_FindPin;
1246 This->vt->QueryFilterInfo = CBaseFilter2_QueryFilterInfo;
1247 This->vt->JoinFilterGraph = CBaseFilter2_JoinFilterGraph;
1248 This->vt->QueryVendorInfo = CBaseFilter2_QueryVendorInfo;
1250 This->GetPin = CBaseFilter2_GetPin;
1252 This->interfaces[0] = IID_IUnknown;
1253 This->interfaces[1] = IID_IBaseFilter;
1254 This->interfaces[2] = CBaseFilter2_interf1;
1255 This->interfaces[3] = CBaseFilter2_interf2;
1256 This->interfaces[4] = CBaseFilter2_interf3;
1258 return This;
1262 /*************
1263 * CRemotePin
1264 *************/
1268 * \brief IPin::ConnectedTo (retrieves pointer to the connected pin, if such exist)
1270 * \param[in] This pointer to IPin interface
1271 * \param[out] pPin pointer to remote pin's IPin interface
1273 * \return S_OK - success
1274 * \return E_POINTER - Null pointer
1275 * \return VFW_E_NOT_CONNECTED - pin is not connected
1277 * \note
1278 * Caller must call Release on received IPin, when done
1280 static long STDCALL CRemotePin_ConnectedTo(IPin* This, /* [out] */ IPin** pPin)
1282 Debug printf("CRemotePin_ConnectedTo(%p) called\n", This);
1283 if (!pPin)
1284 return E_INVALIDARG;
1285 *pPin = ((CRemotePin*)This)->remote_pin;
1286 (*pPin)->vt->AddRef((IUnknown*)(*pPin));
1287 return 0;
1291 * \brief IPin::QueryDirection (retrieves pin direction)
1293 * \param[in] This pointer to IPin interface
1294 * \param[out] pPinDir pointer to variable, that receives pin direction (PINDIR_INPUT,PINDIR_OUTPUT)
1296 * \return S_OK - success
1297 * \return E_POINTER - Null pointer
1300 static long STDCALL CRemotePin_QueryDirection(IPin* This,
1301 /* [out] */ PIN_DIRECTION* pPinDir)
1303 Debug printf("CRemotePin_QueryDirection(%p) called\n", This);
1304 if (!pPinDir)
1305 return E_INVALIDARG;
1306 *pPinDir=PINDIR_INPUT;
1307 return 0;
1311 * \brief IPin::ConnectionMediaType (retrieves media type for connection, if such exist)
1313 * \param[in] This pointer to IPin interface
1314 * \param[out] pmt pointer to AM_MEDIA_TYPE, that receives connection media type
1316 * \return S_OK - success
1317 * \return E_POINTER - Null pointer
1318 * \return VFW_E_NOT_CONNECTED - pin is not connected
1321 static long STDCALL CRemotePin_ConnectionMediaType(IPin* This, /* [out] */ AM_MEDIA_TYPE* pmt)
1323 Debug unimplemented("CRemotePin_ConnectionMediaType", This);
1324 return E_NOTIMPL;
1328 * \brief IPin::QueryPinInfo (retrieves information about the pin)
1330 * \param[in] This pointer to IPin interface
1331 * \param[out] pInfo pointer to PIN_INFO structure, that receives pin info
1333 * \return S_OK - success
1334 * \return E_POINTER - Null pointer
1336 * \note
1337 * If pInfo->pFilter is not NULL, then caller must call Release on pInfo->pFilter when done
1340 static long STDCALL CRemotePin_QueryPinInfo(IPin* This, /* [out] */ PIN_INFO* pInfo)
1342 CBaseFilter* lparent = ((CRemotePin*)This)->parent;
1343 Debug printf("CRemotePin_QueryPinInfo(%p) called\n", This);
1344 pInfo->dir= PINDIR_INPUT;
1345 pInfo->pFilter = (IBaseFilter*) lparent;
1346 lparent->vt->AddRef((IUnknown*)lparent);
1347 pInfo->achName[0]=0;
1348 return 0;
1352 * \brief CRemotePin destructor
1354 * \param[in] This pointer to CRemotePin object
1357 static void CRemotePin_Destroy(CRemotePin* This)
1359 Debug printf("CRemotePin_Destroy(%p) called\n", This);
1360 free(This->vt);
1361 free(This);
1364 IMPLEMENT_IUNKNOWN(CRemotePin)
1367 * \brief CRemotePin constructor
1369 * \param[in] pt parent filter
1370 * \param[in] rpin remote pin
1372 * \return pointer to CRemotePin or NULL if error occured
1375 CRemotePin* CRemotePinCreate(CBaseFilter* pt, IPin* rpin)
1377 CRemotePin* This = malloc(sizeof(CRemotePin));
1379 if (!This)
1380 return NULL;
1382 Debug printf("CRemotePinCreate() called -> %p\n", This);
1384 This->parent = pt;
1385 This->remote_pin = rpin;
1386 This->refcount = 1;
1388 This->vt = malloc(sizeof(IPin_vt));
1390 if (!This->vt)
1392 free(This);
1393 return NULL;
1396 memset(This->vt, 0, sizeof(IPin_vt));
1397 This->vt->QueryInterface = CRemotePin_QueryInterface;
1398 This->vt->AddRef = CRemotePin_AddRef;
1399 This->vt->Release = CRemotePin_Release;
1400 This->vt->QueryDirection = CRemotePin_QueryDirection;
1401 This->vt->ConnectedTo = CRemotePin_ConnectedTo;
1402 This->vt->ConnectionMediaType = CRemotePin_ConnectionMediaType;
1403 This->vt->QueryPinInfo = CRemotePin_QueryPinInfo;
1405 This->interfaces[0] = IID_IUnknown;
1407 return This;
1411 /*************
1412 * CRemotePin2
1413 *************/
1417 * \brief IPin::QueryPinInfo (retrieves information about the pin)
1419 * \param[in] This pointer to IPin interface
1420 * \param[out] pInfo pointer to PIN_INFO structure, that receives pin info
1422 * \return S_OK - success
1423 * \return E_POINTER - Null pointer
1425 * \note
1426 * If pInfo->pFilter is not NULL, then caller must call Release on pInfo->pFilter when done
1429 static long STDCALL CRemotePin2_QueryPinInfo(IPin* This,
1430 /* [out] */ PIN_INFO* pInfo)
1432 CBaseFilter2* lparent=((CRemotePin2*)This)->parent;
1433 Debug printf("CRemotePin2_QueryPinInfo(%p) called\n", This);
1434 pInfo->pFilter=(IBaseFilter*)lparent;
1435 lparent->vt->AddRef((IUnknown*)lparent);
1436 pInfo->dir=PINDIR_OUTPUT;
1437 pInfo->achName[0]=0;
1438 return 0;
1442 * \brief CremotePin2 destructor
1444 * \param This pointer to CRemotePin2 object
1446 * FIXME - not being released!
1448 static void CRemotePin2_Destroy(CRemotePin2* This)
1450 Debug printf("CRemotePin2_Destroy(%p) called\n", This);
1451 free(This->vt);
1452 free(This);
1455 IMPLEMENT_IUNKNOWN(CRemotePin2)
1458 * \brief CRemotePin2 contructor
1460 * \param[in] p pointer to parent CBaseFilter2 object
1462 * \return pointer to CRemotePin2 object or NULL if error occured
1465 CRemotePin2* CRemotePin2Create(CBaseFilter2* p)
1467 CRemotePin2* This = malloc(sizeof(CRemotePin2));
1469 if (!This)
1470 return NULL;
1472 Debug printf("CRemotePin2Create() called -> %p\n", This);
1474 This->parent = p;
1475 This->refcount = 1;
1477 This->vt = malloc(sizeof(IPin_vt));
1479 if (!This->vt)
1481 free(This);
1482 return NULL;
1485 memset(This->vt, 0, sizeof(IPin_vt));
1486 This->vt->QueryInterface = CRemotePin2_QueryInterface;
1487 This->vt->AddRef = CRemotePin2_AddRef;
1488 This->vt->Release = CRemotePin2_Release;
1489 This->vt->QueryPinInfo = CRemotePin2_QueryPinInfo;
1491 This->interfaces[0] = IID_IUnknown;
1493 return This;