forked from krkrz/baseclasses
-
Notifications
You must be signed in to change notification settings - Fork 1
/
amfilter.h
1587 lines (1251 loc) · 55.6 KB
/
amfilter.h
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
//------------------------------------------------------------------------------
// File: AMFilter.h
//
// Desc: DirectShow base classes - efines class hierarchy for streams
// architecture.
//
// Copyright (c) 1992-2001 Microsoft Corporation. All rights reserved.
//------------------------------------------------------------------------------
#ifndef __FILTER__
#define __FILTER__
/* The following classes are declared in this header: */
class CBaseMediaFilter; // IMediaFilter support
class CBaseFilter; // IBaseFilter,IMediaFilter support
class CBasePin; // Abstract base class for IPin interface
class CEnumPins; // Enumerate input and output pins
class CEnumMediaTypes; // Enumerate the pin's preferred formats
class CBaseOutputPin; // Adds data provider member functions
class CBaseInputPin; // Implements IMemInputPin interface
class CMediaSample; // Basic transport unit for IMemInputPin
class CBaseAllocator; // General list guff for most allocators
class CMemAllocator; // Implements memory buffer allocation
//=====================================================================
//=====================================================================
//
// QueryFilterInfo and QueryPinInfo AddRef the interface pointers
// they return. You can use the macro below to release the interface.
//
//=====================================================================
//=====================================================================
#define QueryFilterInfoReleaseGraph(fi) if ((fi).pGraph) (fi).pGraph->Release();
#define QueryPinInfoReleaseFilter(pi) if ((pi).pFilter) (pi).pFilter->Release();
//=====================================================================
//=====================================================================
// Defines CBaseMediaFilter
//
// Abstract base class implementing IMediaFilter.
//
// Typically you will derive your filter from CBaseFilter rather than
// this, unless you are implementing an object such as a plug-in
// distributor that needs to support IMediaFilter but not IBaseFilter.
//
// Note that IMediaFilter is derived from IPersist to allow query of
// class id.
//=====================================================================
//=====================================================================
class AM_NOVTABLE CBaseMediaFilter : public CUnknown,
public IMediaFilter
{
protected:
FILTER_STATE m_State; // current state: running, paused
IReferenceClock *m_pClock; // this filter's reference clock
// note: all filters in a filter graph use the same clock
// offset from stream time to reference time
CRefTime m_tStart;
CLSID m_clsid; // This filters clsid
// used for serialization
CCritSec *m_pLock; // Object we use for locking
public:
CBaseMediaFilter(
__in_opt LPCTSTR pName,
__inout_opt LPUNKNOWN pUnk,
__in CCritSec *pLock,
REFCLSID clsid);
virtual ~CBaseMediaFilter();
DECLARE_IUNKNOWN
// override this to say what interfaces we support where
STDMETHODIMP NonDelegatingQueryInterface(REFIID riid, __deref_out void ** ppv);
//
// --- IPersist method ---
//
STDMETHODIMP GetClassID(__out CLSID *pClsID);
// --- IMediaFilter methods ---
STDMETHODIMP GetState(DWORD dwMSecs, __out FILTER_STATE *State);
STDMETHODIMP SetSyncSource(__inout_opt IReferenceClock *pClock);
STDMETHODIMP GetSyncSource(__deref_out_opt IReferenceClock **pClock);
// default implementation of Stop and Pause just record the
// state. Override to activate or de-activate your filter.
// Note that Run when called from Stopped state will call Pause
// to ensure activation, so if you are a source or transform
// you will probably not need to override Run.
STDMETHODIMP Stop();
STDMETHODIMP Pause();
// the start parameter is the difference to be added to the
// sample's stream time to get the reference time for
// its presentation
STDMETHODIMP Run(REFERENCE_TIME tStart);
// --- helper methods ---
// return the current stream time - ie find out what
// stream time should be appearing now
virtual HRESULT StreamTime(CRefTime& rtStream);
// Is the filter currently active? (running or paused)
BOOL IsActive() {
CAutoLock cObjectLock(m_pLock);
return ((m_State == State_Paused) || (m_State == State_Running));
};
};
//=====================================================================
//=====================================================================
// Defines CBaseFilter
//
// An abstract class providing basic IBaseFilter support for pin
// enumeration and filter information reading.
//
// We cannot derive from CBaseMediaFilter since methods in IMediaFilter
// are also in IBaseFilter and would be ambiguous. Since much of the code
// assumes that they derive from a class that has m_State and other state
// directly available, we duplicate code from CBaseMediaFilter rather than
// having a member variable.
//
// Derive your filter from this, or from a derived object such as
// CTransformFilter.
//=====================================================================
//=====================================================================
class AM_NOVTABLE CBaseFilter : public CUnknown, // Handles an IUnknown
public IBaseFilter, // The Filter Interface
public IAMovieSetup // For un/registration
{
friend class CBasePin;
protected:
FILTER_STATE m_State; // current state: running, paused
IReferenceClock *m_pClock; // this graph's ref clock
CRefTime m_tStart; // offset from stream time to reference time
CLSID m_clsid; // This filters clsid
// used for serialization
CCritSec *m_pLock; // Object we use for locking
WCHAR *m_pName; // Full filter name
IFilterGraph *m_pGraph; // Graph we belong to
IMediaEventSink *m_pSink; // Called with notify events
LONG m_PinVersion; // Current pin version
public:
CBaseFilter(
__in_opt LPCTSTR pName, // Object description
__inout_opt LPUNKNOWN pUnk, // IUnknown of delegating object
__in CCritSec *pLock, // Object who maintains lock
REFCLSID clsid); // The clsid to be used to serialize this filter
CBaseFilter(
__in_opt LPCTSTR pName, // Object description
__in_opt LPUNKNOWN pUnk, // IUnknown of delegating object
__in CCritSec *pLock, // Object who maintains lock
REFCLSID clsid, // The clsid to be used to serialize this filter
__inout HRESULT *phr); // General OLE return code
#ifdef UNICODE
CBaseFilter(
__in_opt LPCSTR pName, // Object description
__in_opt LPUNKNOWN pUnk, // IUnknown of delegating object
__in CCritSec *pLock, // Object who maintains lock
REFCLSID clsid); // The clsid to be used to serialize this filter
CBaseFilter(
__in_opt LPCSTR pName, // Object description
__in_opt LPUNKNOWN pUnk, // IUnknown of delegating object
__in CCritSec *pLock, // Object who maintains lock
REFCLSID clsid, // The clsid to be used to serialize this filter
__inout HRESULT *phr); // General OLE return code
#endif
~CBaseFilter();
DECLARE_IUNKNOWN
// override this to say what interfaces we support where
STDMETHODIMP NonDelegatingQueryInterface(REFIID riid, __deref_out void ** ppv);
#ifdef DEBUG
STDMETHODIMP_(ULONG) NonDelegatingRelease();
#endif
//
// --- IPersist method ---
//
STDMETHODIMP GetClassID(__out CLSID *pClsID);
// --- IMediaFilter methods ---
STDMETHODIMP GetState(DWORD dwMSecs, __out FILTER_STATE *State);
STDMETHODIMP SetSyncSource(__in_opt IReferenceClock *pClock);
STDMETHODIMP GetSyncSource(__deref_out_opt IReferenceClock **pClock);
// override Stop and Pause so we can activate the pins.
// Note that Run will call Pause first if activation needed.
// Override these if you want to activate your filter rather than
// your pins.
STDMETHODIMP Stop();
STDMETHODIMP Pause();
// the start parameter is the difference to be added to the
// sample's stream time to get the reference time for
// its presentation
STDMETHODIMP Run(REFERENCE_TIME tStart);
// --- helper methods ---
// return the current stream time - ie find out what
// stream time should be appearing now
virtual HRESULT StreamTime(CRefTime& rtStream);
// Is the filter currently active?
BOOL IsActive() {
CAutoLock cObjectLock(m_pLock);
return ((m_State == State_Paused) || (m_State == State_Running));
};
// Is this filter stopped (without locking)
BOOL IsStopped() {
return (m_State == State_Stopped);
};
//
// --- IBaseFilter methods ---
//
// pin enumerator
STDMETHODIMP EnumPins(
__deref_out IEnumPins ** ppEnum);
// default behaviour of FindPin assumes pin ids are their names
STDMETHODIMP FindPin(
LPCWSTR Id,
__deref_out IPin ** ppPin
);
STDMETHODIMP QueryFilterInfo(
__out FILTER_INFO * pInfo);
STDMETHODIMP JoinFilterGraph(
__inout_opt IFilterGraph * pGraph,
__in_opt LPCWSTR pName);
// return a Vendor information string. Optional - may return E_NOTIMPL.
// memory returned should be freed using CoTaskMemFree
// default implementation returns E_NOTIMPL
STDMETHODIMP QueryVendorInfo(
__deref_out LPWSTR* pVendorInfo
);
// --- helper methods ---
// send an event notification to the filter graph if we know about it.
// returns S_OK if delivered, S_FALSE if the filter graph does not sink
// events, or an error otherwise.
HRESULT NotifyEvent(
long EventCode,
LONG_PTR EventParam1,
LONG_PTR EventParam2);
// return the filter graph we belong to
__out_opt IFilterGraph *GetFilterGraph() {
return m_pGraph;
}
// Request reconnect
// pPin is the pin to reconnect
// pmt is the type to reconnect with - can be NULL
// Calls ReconnectEx on the filter graph
HRESULT ReconnectPin(IPin *pPin, __in_opt AM_MEDIA_TYPE const *pmt);
// find out the current pin version (used by enumerators)
virtual LONG GetPinVersion();
void IncrementPinVersion();
// you need to supply these to access the pins from the enumerator
// and for default Stop and Pause/Run activation.
virtual int GetPinCount() PURE;
virtual CBasePin *GetPin(int n) PURE;
// --- IAMovieSetup methods ---
STDMETHODIMP Register(); // ask filter to register itself
STDMETHODIMP Unregister(); // and unregister itself
// --- setup helper methods ---
// (override to return filters setup data)
virtual __out_opt LPAMOVIESETUP_FILTER GetSetupData(){ return NULL; }
};
//=====================================================================
//=====================================================================
// Defines CBasePin
//
// Abstract class that supports the basics of IPin
//=====================================================================
//=====================================================================
class AM_NOVTABLE CBasePin : public CUnknown, public IPin, public IQualityControl
{
protected:
WCHAR * m_pName; // This pin's name
IPin *m_Connected; // Pin we have connected to
PIN_DIRECTION m_dir; // Direction of this pin
CCritSec *m_pLock; // Object we use for locking
bool m_bRunTimeError; // Run time error generated
bool m_bCanReconnectWhenActive; // OK to reconnect when active
bool m_bTryMyTypesFirst; // When connecting enumerate
// this pin's types first
CBaseFilter *m_pFilter; // Filter we were created by
IQualityControl *m_pQSink; // Target for Quality messages
LONG m_TypeVersion; // Holds current type version
CMediaType m_mt; // Media type of connection
CRefTime m_tStart; // time from NewSegment call
CRefTime m_tStop; // time from NewSegment
double m_dRate; // rate from NewSegment
#ifdef DEBUG
LONG m_cRef; // Ref count tracing
#endif
// displays pin connection information
#ifdef DEBUG
void DisplayPinInfo(IPin *pReceivePin);
void DisplayTypeInfo(IPin *pPin, const CMediaType *pmt);
#else
void DisplayPinInfo(IPin *pReceivePin) {};
void DisplayTypeInfo(IPin *pPin, const CMediaType *pmt) {};
#endif
// used to agree a media type for a pin connection
// given a specific media type, attempt a connection (includes
// checking that the type is acceptable to this pin)
HRESULT
AttemptConnection(
IPin* pReceivePin, // connect to this pin
const CMediaType* pmt // using this type
);
// try all the media types in this enumerator - for each that
// we accept, try to connect using ReceiveConnection.
HRESULT TryMediaTypes(
IPin *pReceivePin, // connect to this pin
__in_opt const CMediaType *pmt, // proposed type from Connect
IEnumMediaTypes *pEnum); // try this enumerator
// establish a connection with a suitable mediatype. Needs to
// propose a media type if the pmt pointer is null or partially
// specified - use TryMediaTypes on both our and then the other pin's
// enumerator until we find one that works.
HRESULT AgreeMediaType(
IPin *pReceivePin, // connect to this pin
const CMediaType *pmt); // proposed type from Connect
public:
CBasePin(
__in_opt LPCTSTR pObjectName, // Object description
__in CBaseFilter *pFilter, // Owning filter who knows about pins
__in CCritSec *pLock, // Object who implements the lock
__inout HRESULT *phr, // General OLE return code
__in_opt LPCWSTR pName, // Pin name for us
PIN_DIRECTION dir); // Either PINDIR_INPUT or PINDIR_OUTPUT
#ifdef UNICODE
CBasePin(
__in_opt LPCSTR pObjectName, // Object description
__in CBaseFilter *pFilter, // Owning filter who knows about pins
__in CCritSec *pLock, // Object who implements the lock
__inout HRESULT *phr, // General OLE return code
__in_opt LPCWSTR pName, // Pin name for us
PIN_DIRECTION dir); // Either PINDIR_INPUT or PINDIR_OUTPUT
#endif
virtual ~CBasePin();
DECLARE_IUNKNOWN
STDMETHODIMP NonDelegatingQueryInterface(REFIID riid, __deref_out void ** ppv);
STDMETHODIMP_(ULONG) NonDelegatingRelease();
STDMETHODIMP_(ULONG) NonDelegatingAddRef();
// --- IPin methods ---
// take lead role in establishing a connection. Media type pointer
// may be null, or may point to partially-specified mediatype
// (subtype or format type may be GUID_NULL).
STDMETHODIMP Connect(
IPin * pReceivePin,
__in_opt const AM_MEDIA_TYPE *pmt // optional media type
);
// (passive) accept a connection from another pin
STDMETHODIMP ReceiveConnection(
IPin * pConnector, // this is the initiating connecting pin
const AM_MEDIA_TYPE *pmt // this is the media type we will exchange
);
STDMETHODIMP Disconnect();
STDMETHODIMP ConnectedTo(__deref_out IPin **pPin);
STDMETHODIMP ConnectionMediaType(__out AM_MEDIA_TYPE *pmt);
STDMETHODIMP QueryPinInfo(
__out PIN_INFO * pInfo
);
STDMETHODIMP QueryDirection(
__out PIN_DIRECTION * pPinDir
);
STDMETHODIMP QueryId(
__deref_out LPWSTR * Id
);
// does the pin support this media type
STDMETHODIMP QueryAccept(
const AM_MEDIA_TYPE *pmt
);
// return an enumerator for this pins preferred media types
STDMETHODIMP EnumMediaTypes(
__deref_out IEnumMediaTypes **ppEnum
);
// return an array of IPin* - the pins that this pin internally connects to
// All pins put in the array must be AddReffed (but no others)
// Errors: "Can't say" - FAIL, not enough slots - return S_FALSE
// Default: return E_NOTIMPL
// The filter graph will interpret NOT_IMPL as any input pin connects to
// all visible output pins and vice versa.
// apPin can be NULL if nPin==0 (not otherwise).
STDMETHODIMP QueryInternalConnections(
__out_ecount_part(*nPin,*nPin) IPin* *apPin, // array of IPin*
__inout ULONG *nPin // on input, the number of slots
// on output the number of pins
) { return E_NOTIMPL; }
// Called when no more data will be sent
STDMETHODIMP EndOfStream(void);
// Begin/EndFlush still PURE
// NewSegment notifies of the start/stop/rate applying to the data
// about to be received. Default implementation records data and
// returns S_OK.
// Override this to pass downstream.
STDMETHODIMP NewSegment(
REFERENCE_TIME tStart,
REFERENCE_TIME tStop,
double dRate);
//================================================================================
// IQualityControl methods
//================================================================================
STDMETHODIMP Notify(IBaseFilter * pSender, Quality q);
STDMETHODIMP SetSink(IQualityControl * piqc);
// --- helper methods ---
// Returns true if the pin is connected. false otherwise.
BOOL IsConnected(void) {return (m_Connected != NULL); };
// Return the pin this is connected to (if any)
IPin * GetConnected() { return m_Connected; };
// Check if our filter is currently stopped
BOOL IsStopped() {
return (m_pFilter->m_State == State_Stopped);
};
// find out the current type version (used by enumerators)
virtual LONG GetMediaTypeVersion();
void IncrementTypeVersion();
// switch the pin to active (paused or running) mode
// not an error to call this if already active
virtual HRESULT Active(void);
// switch the pin to inactive state - may already be inactive
virtual HRESULT Inactive(void);
// Notify of Run() from filter
virtual HRESULT Run(REFERENCE_TIME tStart);
// check if the pin can support this specific proposed type and format
virtual HRESULT CheckMediaType(const CMediaType *) PURE;
// set the connection to use this format (previously agreed)
virtual HRESULT SetMediaType(const CMediaType *);
// check that the connection is ok before verifying it
// can be overridden eg to check what interfaces will be supported.
virtual HRESULT CheckConnect(IPin *);
// Set and release resources required for a connection
virtual HRESULT BreakConnect();
virtual HRESULT CompleteConnect(IPin *pReceivePin);
// returns the preferred formats for a pin
virtual HRESULT GetMediaType(int iPosition, __inout CMediaType *pMediaType);
// access to NewSegment values
REFERENCE_TIME CurrentStopTime() {
return m_tStop;
}
REFERENCE_TIME CurrentStartTime() {
return m_tStart;
}
double CurrentRate() {
return m_dRate;
}
// Access name
LPWSTR Name() { return m_pName; };
// Can reconnectwhen active?
void SetReconnectWhenActive(bool bCanReconnect)
{
m_bCanReconnectWhenActive = bCanReconnect;
}
bool CanReconnectWhenActive()
{
return m_bCanReconnectWhenActive;
}
protected:
STDMETHODIMP DisconnectInternal();
};
//=====================================================================
//=====================================================================
// Defines CEnumPins
//
// Pin enumerator class that works by calling CBaseFilter. This interface
// is provided by CBaseFilter::EnumPins and calls GetPinCount() and
// GetPin() to enumerate existing pins. Needs to be a separate object so
// that it can be cloned (creating an existing object at the same
// position in the enumeration)
//
//=====================================================================
//=====================================================================
class CEnumPins : public IEnumPins // The interface we support
{
int m_Position; // Current ordinal position
int m_PinCount; // Number of pins available
CBaseFilter *m_pFilter; // The filter who owns us
LONG m_Version; // Pin version information
LONG m_cRef;
typedef CGenericList<CBasePin> CPinList;
CPinList m_PinCache; // These pointers have not been AddRef'ed and
// so they should not be dereferenced. They are
// merely kept to ID which pins have been enumerated.
#ifdef DEBUG
DWORD m_dwCookie;
#endif
/* If while we are retrieving a pin for example from the filter an error
occurs we assume that our internal state is stale with respect to the
filter (someone may have deleted all the pins). We can check before
starting whether or not the operation is likely to fail by asking the
filter what it's current version number is. If the filter has not
overriden the GetPinVersion method then this will always match */
BOOL AreWeOutOfSync() {
return (m_pFilter->GetPinVersion() == m_Version ? FALSE : TRUE);
};
/* This method performs the same operations as Reset, except is does not clear
the cache of pins already enumerated. */
STDMETHODIMP Refresh();
public:
CEnumPins(
__in CBaseFilter *pFilter,
__in_opt CEnumPins *pEnumPins);
virtual ~CEnumPins();
// IUnknown
STDMETHODIMP QueryInterface(REFIID riid, __deref_out void **ppv);
STDMETHODIMP_(ULONG) AddRef();
STDMETHODIMP_(ULONG) Release();
// IEnumPins
STDMETHODIMP Next(
ULONG cPins, // place this many pins...
__out_ecount(cPins) IPin ** ppPins, // ...in this array of IPin*
__out_opt ULONG * pcFetched // actual count passed returned here
);
STDMETHODIMP Skip(ULONG cPins);
STDMETHODIMP Reset();
STDMETHODIMP Clone(__deref_out IEnumPins **ppEnum);
};
//=====================================================================
//=====================================================================
// Defines CEnumMediaTypes
//
// Enumerates the preferred formats for input and output pins
//=====================================================================
//=====================================================================
class CEnumMediaTypes : public IEnumMediaTypes // The interface we support
{
int m_Position; // Current ordinal position
CBasePin *m_pPin; // The pin who owns us
LONG m_Version; // Media type version value
LONG m_cRef;
#ifdef DEBUG
DWORD m_dwCookie;
#endif
/* The media types a filter supports can be quite dynamic so we add to
the general IEnumXXXX interface the ability to be signaled when they
change via an event handle the connected filter supplies. Until the
Reset method is called after the state changes all further calls to
the enumerator (except Reset) will return E_UNEXPECTED error code */
BOOL AreWeOutOfSync() {
return (m_pPin->GetMediaTypeVersion() == m_Version ? FALSE : TRUE);
};
public:
CEnumMediaTypes(
__in CBasePin *pPin,
__in_opt CEnumMediaTypes *pEnumMediaTypes);
virtual ~CEnumMediaTypes();
// IUnknown
STDMETHODIMP QueryInterface(REFIID riid, __deref_out void **ppv);
STDMETHODIMP_(ULONG) AddRef();
STDMETHODIMP_(ULONG) Release();
// IEnumMediaTypes
STDMETHODIMP Next(
ULONG cMediaTypes, // place this many pins...
__out_ecount(cMediaTypes) AM_MEDIA_TYPE ** ppMediaTypes, // ...in this array
__out_opt ULONG * pcFetched // actual count passed
);
STDMETHODIMP Skip(ULONG cMediaTypes);
STDMETHODIMP Reset();
STDMETHODIMP Clone(__deref_out IEnumMediaTypes **ppEnum);
};
//=====================================================================
//=====================================================================
// Defines CBaseOutputPin
//
// class derived from CBasePin that can pass buffers to a connected pin
// that supports IMemInputPin. Supports IPin.
//
// Derive your output pin from this.
//
//=====================================================================
//=====================================================================
class AM_NOVTABLE CBaseOutputPin : public CBasePin
{
protected:
IMemAllocator *m_pAllocator;
IMemInputPin *m_pInputPin; // interface on the downstreaminput pin
// set up in CheckConnect when we connect.
public:
CBaseOutputPin(
__in_opt LPCTSTR pObjectName,
__in CBaseFilter *pFilter,
__in CCritSec *pLock,
__inout HRESULT *phr,
__in_opt LPCWSTR pName);
#ifdef UNICODE
CBaseOutputPin(
__in_opt LPCSTR pObjectName,
__in CBaseFilter *pFilter,
__in CCritSec *pLock,
__inout HRESULT *phr,
__in_opt LPCWSTR pName);
#endif
// override CompleteConnect() so we can negotiate an allocator
virtual HRESULT CompleteConnect(IPin *pReceivePin);
// negotiate the allocator and its buffer size/count and other properties
// Calls DecideBufferSize to set properties
virtual HRESULT DecideAllocator(IMemInputPin * pPin, __deref_out IMemAllocator ** pAlloc);
// override this to set the buffer size and count. Return an error
// if the size/count is not to your liking.
// The allocator properties passed in are those requested by the
// input pin - use eg the alignment and prefix members if you have
// no preference on these.
virtual HRESULT DecideBufferSize(
IMemAllocator * pAlloc,
__inout ALLOCATOR_PROPERTIES * ppropInputRequest
) PURE;
// returns an empty sample buffer from the allocator
virtual HRESULT GetDeliveryBuffer(__deref_out IMediaSample ** ppSample,
__in_opt REFERENCE_TIME * pStartTime,
__in_opt REFERENCE_TIME * pEndTime,
DWORD dwFlags);
// deliver a filled-in sample to the connected input pin
// note - you need to release it after calling this. The receiving
// pin will addref the sample if it needs to hold it beyond the
// call.
virtual HRESULT Deliver(IMediaSample *);
// override this to control the connection
virtual HRESULT InitAllocator(__deref_out IMemAllocator **ppAlloc);
HRESULT CheckConnect(IPin *pPin);
HRESULT BreakConnect();
// override to call Commit and Decommit
HRESULT Active(void);
HRESULT Inactive(void);
// we have a default handling of EndOfStream which is to return
// an error, since this should be called on input pins only
STDMETHODIMP EndOfStream(void);
// called from elsewhere in our filter to pass EOS downstream to
// our connected input pin
virtual HRESULT DeliverEndOfStream(void);
// same for Begin/EndFlush - we handle Begin/EndFlush since it
// is an error on an output pin, and we have Deliver methods to
// call the methods on the connected pin
STDMETHODIMP BeginFlush(void);
STDMETHODIMP EndFlush(void);
virtual HRESULT DeliverBeginFlush(void);
virtual HRESULT DeliverEndFlush(void);
// deliver NewSegment to connected pin - you will need to
// override this if you queue any data in your output pin.
virtual HRESULT DeliverNewSegment(
REFERENCE_TIME tStart,
REFERENCE_TIME tStop,
double dRate);
//================================================================================
// IQualityControl methods
//================================================================================
// All inherited from CBasePin and not overridden here.
// STDMETHODIMP Notify(IBaseFilter * pSender, Quality q);
// STDMETHODIMP SetSink(IQualityControl * piqc);
};
//=====================================================================
//=====================================================================
// Defines CBaseInputPin
//
// derive your standard input pin from this.
// you need to supply GetMediaType and CheckConnect etc (see CBasePin),
// and you need to supply Receive to do something more useful.
//
//=====================================================================
//=====================================================================
class AM_NOVTABLE CBaseInputPin : public CBasePin,
public IMemInputPin
{
protected:
IMemAllocator *m_pAllocator; // Default memory allocator
// allocator is read-only, so received samples
// cannot be modified (probably only relevant to in-place
// transforms
BYTE m_bReadOnly;
// in flushing state (between BeginFlush and EndFlush)
// if TRUE, all Receives are returned with S_FALSE
BYTE m_bFlushing;
// Sample properties - initalized in Receive
AM_SAMPLE2_PROPERTIES m_SampleProps;
public:
CBaseInputPin(
__in_opt LPCTSTR pObjectName,
__in CBaseFilter *pFilter,
__in CCritSec *pLock,
__inout HRESULT *phr,
__in_opt LPCWSTR pName);
#ifdef UNICODE
CBaseInputPin(
__in_opt LPCSTR pObjectName,
__in CBaseFilter *pFilter,
__in CCritSec *pLock,
__inout HRESULT *phr,
__in_opt LPCWSTR pName);
#endif
virtual ~CBaseInputPin();
DECLARE_IUNKNOWN
// override this to publicise our interfaces
STDMETHODIMP NonDelegatingQueryInterface(REFIID riid, __deref_out void **ppv);
// return the allocator interface that this input pin
// would like the output pin to use
STDMETHODIMP GetAllocator(__deref_out IMemAllocator ** ppAllocator);
// tell the input pin which allocator the output pin is actually
// going to use.
STDMETHODIMP NotifyAllocator(
IMemAllocator * pAllocator,
BOOL bReadOnly);
// do something with this media sample
STDMETHODIMP Receive(IMediaSample *pSample);
// do something with these media samples
STDMETHODIMP ReceiveMultiple (
__in_ecount(nSamples) IMediaSample **pSamples,
long nSamples,
__out long *nSamplesProcessed);
// See if Receive() blocks
STDMETHODIMP ReceiveCanBlock();
// Default handling for BeginFlush - call at the beginning
// of your implementation (makes sure that all Receive calls
// fail). After calling this, you need to free any queued data
// and then call downstream.
STDMETHODIMP BeginFlush(void);
// default handling for EndFlush - call at end of your implementation
// - before calling this, ensure that there is no queued data and no thread
// pushing any more without a further receive, then call downstream,
// then call this method to clear the m_bFlushing flag and re-enable
// receives
STDMETHODIMP EndFlush(void);
// this method is optional (can return E_NOTIMPL).
// default implementation returns E_NOTIMPL. Override if you have
// specific alignment or prefix needs, but could use an upstream
// allocator
STDMETHODIMP GetAllocatorRequirements(__out ALLOCATOR_PROPERTIES*pProps);
// Release the pin's allocator.
HRESULT BreakConnect();
// helper method to check the read-only flag
BOOL IsReadOnly() {
return m_bReadOnly;
};
// helper method to see if we are flushing
BOOL IsFlushing() {
return m_bFlushing;
};
// Override this for checking whether it's OK to process samples
// Also call this from EndOfStream.
virtual HRESULT CheckStreaming();
// Pass a Quality notification on to the appropriate sink
HRESULT PassNotify(Quality& q);
//================================================================================
// IQualityControl methods (from CBasePin)
//================================================================================
STDMETHODIMP Notify(IBaseFilter * pSender, Quality q);
// no need to override:
// STDMETHODIMP SetSink(IQualityControl * piqc);
// switch the pin to inactive state - may already be inactive
virtual HRESULT Inactive(void);
// Return sample properties pointer
AM_SAMPLE2_PROPERTIES * SampleProps() {
ASSERT(m_SampleProps.cbData != 0);
return &m_SampleProps;
}
};
///////////////////////////////////////////////////////////////////////////
// CDynamicOutputPin
//
class CDynamicOutputPin : public CBaseOutputPin,
public IPinFlowControl
{
public:
#ifdef UNICODE
CDynamicOutputPin(
__in_opt LPCSTR pObjectName,
__in CBaseFilter *pFilter,
__in CCritSec *pLock,
__inout HRESULT *phr,
__in_opt LPCWSTR pName);
#endif
CDynamicOutputPin(
__in_opt LPCTSTR pObjectName,
__in CBaseFilter *pFilter,
__in CCritSec *pLock,
__inout HRESULT *phr,
__in_opt LPCWSTR pName);
~CDynamicOutputPin();
// IUnknown Methods
DECLARE_IUNKNOWN
STDMETHODIMP NonDelegatingQueryInterface(REFIID riid, __deref_out void **ppv);
// IPin Methods
STDMETHODIMP Disconnect(void);
// IPinFlowControl Methods
STDMETHODIMP Block(DWORD dwBlockFlags, HANDLE hEvent);
// Set graph config info
void SetConfigInfo(IGraphConfig *pGraphConfig, HANDLE hStopEvent);
#ifdef DEBUG
virtual HRESULT Deliver(IMediaSample *pSample);
virtual HRESULT DeliverEndOfStream(void);
virtual HRESULT DeliverNewSegment(REFERENCE_TIME tStart, REFERENCE_TIME tStop, double dRate);
#endif // DEBUG
HRESULT DeliverBeginFlush(void);
HRESULT DeliverEndFlush(void);
HRESULT Inactive(void);
HRESULT Active(void);
virtual HRESULT CompleteConnect(IPin *pReceivePin);
virtual HRESULT StartUsingOutputPin(void);
virtual void StopUsingOutputPin(void);
virtual bool StreamingThreadUsingOutputPin(void);