~ubuntu-branches/ubuntu/wily/sflphone/wily

« back to all changes in this revision

Viewing changes to daemon/libs/pjproject-2.2.1/third_party/BaseClasses/amfilter.h

  • Committer: Package Import Robot
  • Author(s): Jonathan Riddell
  • Date: 2015-01-07 14:51:16 UTC
  • mfrom: (4.3.5 sid)
  • Revision ID: package-import@ubuntu.com-20150107145116-yxnafinf4lrdvrmx
Tags: 1.4.1-0.1ubuntu1
* Merge with Debian, remaining changes:
 - Drop soprano, nepomuk build-dep
* Drop ubuntu patches, now upstream

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
//------------------------------------------------------------------------------
 
2
// File: AMFilter.h
 
3
//
 
4
// Desc: DirectShow base classes - efines class hierarchy for streams
 
5
//       architecture.
 
6
//
 
7
// Copyright (c) 1992-2001 Microsoft Corporation.  All rights reserved.
 
8
//------------------------------------------------------------------------------
 
9
 
 
10
 
 
11
#ifndef __FILTER__
 
12
#define __FILTER__
 
13
 
 
14
/* The following classes are declared in this header: */
 
15
 
 
16
class CBaseMediaFilter;     // IMediaFilter support
 
17
class CBaseFilter;          // IBaseFilter,IMediaFilter support
 
18
class CBasePin;             // Abstract base class for IPin interface
 
19
class CEnumPins;            // Enumerate input and output pins
 
20
class CEnumMediaTypes;      // Enumerate the pin's preferred formats
 
21
class CBaseOutputPin;       // Adds data provider member functions
 
22
class CBaseInputPin;        // Implements IMemInputPin interface
 
23
class CMediaSample;         // Basic transport unit for IMemInputPin
 
24
class CBaseAllocator;       // General list guff for most allocators
 
25
class CMemAllocator;        // Implements memory buffer allocation
 
26
 
 
27
 
 
28
//=====================================================================
 
29
//=====================================================================
 
30
//
 
31
// QueryFilterInfo and QueryPinInfo AddRef the interface pointers
 
32
// they return.  You can use the macro below to release the interface.
 
33
//
 
34
//=====================================================================
 
35
//=====================================================================
 
36
 
 
37
#define QueryFilterInfoReleaseGraph(fi) if ((fi).pGraph) (fi).pGraph->Release();
 
38
 
 
39
#define QueryPinInfoReleaseFilter(pi) if ((pi).pFilter) (pi).pFilter->Release();
 
40
 
 
41
//=====================================================================
 
42
//=====================================================================
 
43
// Defines CBaseMediaFilter
 
44
//
 
45
// Abstract base class implementing IMediaFilter.
 
46
//
 
47
// Typically you will derive your filter from CBaseFilter rather than
 
48
// this,  unless you are implementing an object such as a plug-in
 
49
// distributor that needs to support IMediaFilter but not IBaseFilter.
 
50
//
 
51
// Note that IMediaFilter is derived from IPersist to allow query of
 
52
// class id.
 
53
//=====================================================================
 
54
//=====================================================================
 
55
 
 
56
class AM_NOVTABLE CBaseMediaFilter : public CUnknown,
 
57
                                     public IMediaFilter
 
58
{
 
59
 
 
60
protected:
 
61
 
 
62
    FILTER_STATE    m_State;            // current state: running, paused
 
63
    IReferenceClock *m_pClock;          // this filter's reference clock
 
64
    // note: all filters in a filter graph use the same clock
 
65
 
 
66
    // offset from stream time to reference time
 
67
    CRefTime        m_tStart;
 
68
 
 
69
    CLSID           m_clsid;            // This filters clsid
 
70
                                        // used for serialization
 
71
    CCritSec        *m_pLock;           // Object we use for locking
 
72
 
 
73
public:
 
74
 
 
75
    CBaseMediaFilter(
 
76
        __in_opt LPCTSTR pName,
 
77
        __inout_opt LPUNKNOWN pUnk,
 
78
        __in CCritSec  *pLock,
 
79
        REFCLSID   clsid);
 
80
 
 
81
    virtual ~CBaseMediaFilter();
 
82
 
 
83
    DECLARE_IUNKNOWN
 
84
 
 
85
    // override this to say what interfaces we support where
 
86
    STDMETHODIMP NonDelegatingQueryInterface(REFIID riid, __deref_out void ** ppv);
 
87
 
 
88
    //
 
89
    // --- IPersist method ---
 
90
    //
 
91
 
 
92
    STDMETHODIMP GetClassID(__out CLSID *pClsID);
 
93
 
 
94
    // --- IMediaFilter methods ---
 
95
 
 
96
    STDMETHODIMP GetState(DWORD dwMSecs, __out FILTER_STATE *State);
 
97
 
 
98
    STDMETHODIMP SetSyncSource(__inout_opt IReferenceClock *pClock);
 
99
 
 
100
    STDMETHODIMP GetSyncSource(__deref_out_opt IReferenceClock **pClock);
 
101
 
 
102
    // default implementation of Stop and Pause just record the
 
103
    // state. Override to activate or de-activate your filter.
 
104
    // Note that Run when called from Stopped state will call Pause
 
105
    // to ensure activation, so if you are a source or transform
 
106
    // you will probably not need to override Run.
 
107
    STDMETHODIMP Stop();
 
108
    STDMETHODIMP Pause();
 
109
 
 
110
 
 
111
    // the start parameter is the difference to be added to the
 
112
    // sample's stream time to get the reference time for
 
113
    // its presentation
 
114
    STDMETHODIMP Run(REFERENCE_TIME tStart);
 
115
 
 
116
    // --- helper methods ---
 
117
 
 
118
    // return the current stream time - ie find out what
 
119
    // stream time should be appearing now
 
120
    virtual HRESULT StreamTime(CRefTime& rtStream);
 
121
 
 
122
    // Is the filter currently active? (running or paused)
 
123
    BOOL IsActive() {
 
124
        CAutoLock cObjectLock(m_pLock);
 
125
        return ((m_State == State_Paused) || (m_State == State_Running));
 
126
    };
 
127
};
 
128
 
 
129
//=====================================================================
 
130
//=====================================================================
 
131
// Defines CBaseFilter
 
132
//
 
133
// An abstract class providing basic IBaseFilter support for pin
 
134
// enumeration and filter information reading.
 
135
//
 
136
// We cannot derive from CBaseMediaFilter since methods in IMediaFilter
 
137
// are also in IBaseFilter and would be ambiguous. Since much of the code
 
138
// assumes that they derive from a class that has m_State and other state
 
139
// directly available, we duplicate code from CBaseMediaFilter rather than
 
140
// having a member variable.
 
141
//
 
142
// Derive your filter from this, or from a derived object such as
 
143
// CTransformFilter.
 
144
//=====================================================================
 
145
//=====================================================================
 
146
 
 
147
 
 
148
class AM_NOVTABLE CBaseFilter : public CUnknown,        // Handles an IUnknown
 
149
                    public IBaseFilter,     // The Filter Interface
 
150
                    public IAMovieSetup     // For un/registration
 
151
{
 
152
 
 
153
friend class CBasePin;
 
154
 
 
155
protected:
 
156
    FILTER_STATE    m_State;            // current state: running, paused
 
157
    IReferenceClock *m_pClock;          // this graph's ref clock
 
158
    CRefTime        m_tStart;           // offset from stream time to reference time
 
159
    CLSID           m_clsid;            // This filters clsid
 
160
                                        // used for serialization
 
161
    CCritSec        *m_pLock;           // Object we use for locking
 
162
 
 
163
    WCHAR           *m_pName;           // Full filter name
 
164
    IFilterGraph    *m_pGraph;          // Graph we belong to
 
165
    IMediaEventSink *m_pSink;           // Called with notify events
 
166
    LONG            m_PinVersion;       // Current pin version
 
167
 
 
168
public:
 
169
 
 
170
    CBaseFilter(
 
171
        __in_opt LPCTSTR pName,   // Object description
 
172
        __inout_opt LPUNKNOWN pUnk,  // IUnknown of delegating object
 
173
        __in CCritSec  *pLock,    // Object who maintains lock
 
174
        REFCLSID   clsid);        // The clsid to be used to serialize this filter
 
175
 
 
176
    CBaseFilter(
 
177
        __in_opt LPCTSTR pName,    // Object description
 
178
        __in_opt LPUNKNOWN pUnk,  // IUnknown of delegating object
 
179
        __in CCritSec  *pLock,    // Object who maintains lock
 
180
        REFCLSID   clsid,         // The clsid to be used to serialize this filter
 
181
        __inout HRESULT   *phr);  // General OLE return code
 
182
#ifdef UNICODE
 
183
    CBaseFilter(
 
184
        __in_opt LPCSTR pName,    // Object description
 
185
        __in_opt LPUNKNOWN pUnk,  // IUnknown of delegating object
 
186
        __in CCritSec  *pLock,    // Object who maintains lock
 
187
        REFCLSID   clsid);        // The clsid to be used to serialize this filter
 
188
 
 
189
    CBaseFilter(
 
190
        __in_opt LPCSTR pName,     // Object description
 
191
        __in_opt LPUNKNOWN pUnk,  // IUnknown of delegating object
 
192
        __in CCritSec  *pLock,    // Object who maintains lock
 
193
        REFCLSID   clsid,         // The clsid to be used to serialize this filter
 
194
        __inout HRESULT   *phr);  // General OLE return code
 
195
#endif
 
196
    ~CBaseFilter();
 
197
 
 
198
    DECLARE_IUNKNOWN
 
199
 
 
200
    // override this to say what interfaces we support where
 
201
    STDMETHODIMP NonDelegatingQueryInterface(REFIID riid, __deref_out void ** ppv);
 
202
#ifdef DEBUG
 
203
    STDMETHODIMP_(ULONG) NonDelegatingRelease();
 
204
#endif
 
205
 
 
206
    //
 
207
    // --- IPersist method ---
 
208
    //
 
209
 
 
210
    STDMETHODIMP GetClassID(__out CLSID *pClsID);
 
211
 
 
212
    // --- IMediaFilter methods ---
 
213
 
 
214
    STDMETHODIMP GetState(DWORD dwMSecs, __out FILTER_STATE *State);
 
215
 
 
216
    STDMETHODIMP SetSyncSource(__in_opt IReferenceClock *pClock);
 
217
 
 
218
    STDMETHODIMP GetSyncSource(__deref_out_opt IReferenceClock **pClock);
 
219
 
 
220
 
 
221
    // override Stop and Pause so we can activate the pins.
 
222
    // Note that Run will call Pause first if activation needed.
 
223
    // Override these if you want to activate your filter rather than
 
224
    // your pins.
 
225
    STDMETHODIMP Stop();
 
226
    STDMETHODIMP Pause();
 
227
 
 
228
    // the start parameter is the difference to be added to the
 
229
    // sample's stream time to get the reference time for
 
230
    // its presentation
 
231
    STDMETHODIMP Run(REFERENCE_TIME tStart);
 
232
 
 
233
    // --- helper methods ---
 
234
 
 
235
    // return the current stream time - ie find out what
 
236
    // stream time should be appearing now
 
237
    virtual HRESULT StreamTime(CRefTime& rtStream);
 
238
 
 
239
    // Is the filter currently active?
 
240
    BOOL IsActive() {
 
241
        CAutoLock cObjectLock(m_pLock);
 
242
        return ((m_State == State_Paused) || (m_State == State_Running));
 
243
    };
 
244
 
 
245
    // Is this filter stopped (without locking)
 
246
    BOOL IsStopped() {
 
247
        return (m_State == State_Stopped);
 
248
    };
 
249
 
 
250
    //
 
251
    // --- IBaseFilter methods ---
 
252
    //
 
253
 
 
254
    // pin enumerator
 
255
    STDMETHODIMP EnumPins(
 
256
                    __deref_out IEnumPins ** ppEnum);
 
257
 
 
258
 
 
259
    // default behaviour of FindPin assumes pin ids are their names
 
260
    STDMETHODIMP FindPin(
 
261
        LPCWSTR Id,
 
262
        __deref_out IPin ** ppPin
 
263
    );
 
264
 
 
265
    STDMETHODIMP QueryFilterInfo(
 
266
                    __out FILTER_INFO * pInfo);
 
267
 
 
268
    STDMETHODIMP JoinFilterGraph(
 
269
                    __inout_opt IFilterGraph * pGraph,
 
270
                    __in_opt LPCWSTR pName);
 
271
 
 
272
    // return a Vendor information string. Optional - may return E_NOTIMPL.
 
273
    // memory returned should be freed using CoTaskMemFree
 
274
    // default implementation returns E_NOTIMPL
 
275
    STDMETHODIMP QueryVendorInfo(
 
276
                    __deref_out LPWSTR* pVendorInfo
 
277
            );
 
278
 
 
279
    // --- helper methods ---
 
280
 
 
281
    // send an event notification to the filter graph if we know about it.
 
282
    // returns S_OK if delivered, S_FALSE if the filter graph does not sink
 
283
    // events, or an error otherwise.
 
284
    HRESULT NotifyEvent(
 
285
        long EventCode,
 
286
        LONG_PTR EventParam1,
 
287
        LONG_PTR EventParam2);
 
288
 
 
289
    // return the filter graph we belong to
 
290
    __out_opt IFilterGraph *GetFilterGraph() {
 
291
        return m_pGraph;
 
292
    }
 
293
 
 
294
    // Request reconnect
 
295
    // pPin is the pin to reconnect
 
296
    // pmt is the type to reconnect with - can be NULL
 
297
    // Calls ReconnectEx on the filter graph
 
298
    HRESULT ReconnectPin(IPin *pPin, __in_opt AM_MEDIA_TYPE const *pmt);
 
299
 
 
300
    // find out the current pin version (used by enumerators)
 
301
    virtual LONG GetPinVersion();
 
302
    void IncrementPinVersion();
 
303
 
 
304
    // you need to supply these to access the pins from the enumerator
 
305
    // and for default Stop and Pause/Run activation.
 
306
    virtual int GetPinCount() PURE;
 
307
    virtual CBasePin *GetPin(int n) PURE;
 
308
 
 
309
    // --- IAMovieSetup methods ---
 
310
 
 
311
    STDMETHODIMP Register();    // ask filter to register itself
 
312
    STDMETHODIMP Unregister();  // and unregister itself
 
313
 
 
314
    // --- setup helper methods ---
 
315
    // (override to return filters setup data)
 
316
 
 
317
    virtual __out_opt LPAMOVIESETUP_FILTER GetSetupData(){ return NULL; }
 
318
 
 
319
};
 
320
 
 
321
 
 
322
//=====================================================================
 
323
//=====================================================================
 
324
// Defines CBasePin
 
325
//
 
326
// Abstract class that supports the basics of IPin
 
327
//=====================================================================
 
328
//=====================================================================
 
329
 
 
330
class  AM_NOVTABLE CBasePin : public CUnknown, public IPin, public IQualityControl
 
331
{
 
332
 
 
333
protected:
 
334
 
 
335
    WCHAR *         m_pName;                    // This pin's name
 
336
    IPin            *m_Connected;               // Pin we have connected to
 
337
    PIN_DIRECTION   m_dir;                      // Direction of this pin
 
338
    CCritSec        *m_pLock;                   // Object we use for locking
 
339
    bool            m_bRunTimeError;            // Run time error generated
 
340
    bool            m_bCanReconnectWhenActive;  // OK to reconnect when active
 
341
    bool            m_bTryMyTypesFirst;         // When connecting enumerate
 
342
                                                // this pin's types first
 
343
    CBaseFilter    *m_pFilter;                  // Filter we were created by
 
344
    IQualityControl *m_pQSink;                  // Target for Quality messages
 
345
    LONG            m_TypeVersion;              // Holds current type version
 
346
    CMediaType      m_mt;                       // Media type of connection
 
347
 
 
348
    CRefTime        m_tStart;                   // time from NewSegment call
 
349
    CRefTime        m_tStop;                    // time from NewSegment
 
350
    double          m_dRate;                    // rate from NewSegment
 
351
 
 
352
#ifdef DEBUG
 
353
    LONG            m_cRef;                     // Ref count tracing
 
354
#endif
 
355
 
 
356
    // displays pin connection information
 
357
 
 
358
#ifdef DEBUG
 
359
    void DisplayPinInfo(IPin *pReceivePin);
 
360
    void DisplayTypeInfo(IPin *pPin, const CMediaType *pmt);
 
361
#else
 
362
    void DisplayPinInfo(IPin *pReceivePin) {};
 
363
    void DisplayTypeInfo(IPin *pPin, const CMediaType *pmt) {};
 
364
#endif
 
365
 
 
366
    // used to agree a media type for a pin connection
 
367
 
 
368
    // given a specific media type, attempt a connection (includes
 
369
    // checking that the type is acceptable to this pin)
 
370
    HRESULT
 
371
    AttemptConnection(
 
372
        IPin* pReceivePin,      // connect to this pin
 
373
        const CMediaType* pmt   // using this type
 
374
    );
 
375
 
 
376
    // try all the media types in this enumerator - for each that
 
377
    // we accept, try to connect using ReceiveConnection.
 
378
    HRESULT TryMediaTypes(
 
379
                        IPin *pReceivePin,          // connect to this pin
 
380
                        __in_opt const CMediaType *pmt,  // proposed type from Connect
 
381
                        IEnumMediaTypes *pEnum);    // try this enumerator
 
382
 
 
383
    // establish a connection with a suitable mediatype. Needs to
 
384
    // propose a media type if the pmt pointer is null or partially
 
385
    // specified - use TryMediaTypes on both our and then the other pin's
 
386
    // enumerator until we find one that works.
 
387
    HRESULT AgreeMediaType(
 
388
                        IPin *pReceivePin,      // connect to this pin
 
389
                        const CMediaType *pmt);      // proposed type from Connect
 
390
 
 
391
public:
 
392
 
 
393
    CBasePin(
 
394
        __in_opt LPCTSTR pObjectName,         // Object description
 
395
        __in CBaseFilter *pFilter,       // Owning filter who knows about pins
 
396
        __in CCritSec *pLock,            // Object who implements the lock
 
397
        __inout HRESULT *phr,               // General OLE return code
 
398
        __in_opt LPCWSTR pName,              // Pin name for us
 
399
        PIN_DIRECTION dir);         // Either PINDIR_INPUT or PINDIR_OUTPUT
 
400
#ifdef UNICODE
 
401
    CBasePin(
 
402
        __in_opt LPCSTR pObjectName,         // Object description
 
403
        __in CBaseFilter *pFilter,       // Owning filter who knows about pins
 
404
        __in CCritSec *pLock,            // Object who implements the lock
 
405
        __inout HRESULT *phr,               // General OLE return code
 
406
        __in_opt LPCWSTR pName,              // Pin name for us
 
407
        PIN_DIRECTION dir);         // Either PINDIR_INPUT or PINDIR_OUTPUT
 
408
#endif
 
409
    virtual ~CBasePin();
 
410
 
 
411
    DECLARE_IUNKNOWN
 
412
 
 
413
    STDMETHODIMP NonDelegatingQueryInterface(REFIID riid, __deref_out void ** ppv);
 
414
    STDMETHODIMP_(ULONG) NonDelegatingRelease();
 
415
    STDMETHODIMP_(ULONG) NonDelegatingAddRef();
 
416
 
 
417
    // --- IPin methods ---
 
418
 
 
419
    // take lead role in establishing a connection. Media type pointer
 
420
    // may be null, or may point to partially-specified mediatype
 
421
    // (subtype or format type may be GUID_NULL).
 
422
    STDMETHODIMP Connect(
 
423
        IPin * pReceivePin,
 
424
        __in_opt const AM_MEDIA_TYPE *pmt   // optional media type
 
425
    );
 
426
 
 
427
    // (passive) accept a connection from another pin
 
428
    STDMETHODIMP ReceiveConnection(
 
429
        IPin * pConnector,      // this is the initiating connecting pin
 
430
        const AM_MEDIA_TYPE *pmt   // this is the media type we will exchange
 
431
    );
 
432
 
 
433
    STDMETHODIMP Disconnect();
 
434
 
 
435
    STDMETHODIMP ConnectedTo(__deref_out IPin **pPin);
 
436
 
 
437
    STDMETHODIMP ConnectionMediaType(__out AM_MEDIA_TYPE *pmt);
 
438
 
 
439
    STDMETHODIMP QueryPinInfo(
 
440
        __out PIN_INFO * pInfo
 
441
    );
 
442
 
 
443
    STDMETHODIMP QueryDirection(
 
444
        __out PIN_DIRECTION * pPinDir
 
445
    );
 
446
 
 
447
    STDMETHODIMP QueryId(
 
448
        __deref_out LPWSTR * Id
 
449
    );
 
450
 
 
451
    // does the pin support this media type
 
452
    STDMETHODIMP QueryAccept(
 
453
        const AM_MEDIA_TYPE *pmt
 
454
    );
 
455
 
 
456
    // return an enumerator for this pins preferred media types
 
457
    STDMETHODIMP EnumMediaTypes(
 
458
        __deref_out IEnumMediaTypes **ppEnum
 
459
    );
 
460
 
 
461
    // return an array of IPin* - the pins that this pin internally connects to
 
462
    // All pins put in the array must be AddReffed (but no others)
 
463
    // Errors: "Can't say" - FAIL, not enough slots - return S_FALSE
 
464
    // Default: return E_NOTIMPL
 
465
    // The filter graph will interpret NOT_IMPL as any input pin connects to
 
466
    // all visible output pins and vice versa.
 
467
    // apPin can be NULL if nPin==0 (not otherwise).
 
468
    STDMETHODIMP QueryInternalConnections(
 
469
        __out_ecount_part(*nPin,*nPin) IPin* *apPin,     // array of IPin*
 
470
        __inout ULONG *nPin                  // on input, the number of slots
 
471
                                             // on output  the number of pins
 
472
    ) { return E_NOTIMPL; }
 
473
 
 
474
    // Called when no more data will be sent
 
475
    STDMETHODIMP EndOfStream(void);
 
476
 
 
477
    // Begin/EndFlush still PURE
 
478
 
 
479
    // NewSegment notifies of the start/stop/rate applying to the data
 
480
    // about to be received. Default implementation records data and
 
481
    // returns S_OK.
 
482
    // Override this to pass downstream.
 
483
    STDMETHODIMP NewSegment(
 
484
                    REFERENCE_TIME tStart,
 
485
                    REFERENCE_TIME tStop,
 
486
                    double dRate);
 
487
 
 
488
    //================================================================================
 
489
    // IQualityControl methods
 
490
    //================================================================================
 
491
 
 
492
    STDMETHODIMP Notify(IBaseFilter * pSender, Quality q);
 
493
 
 
494
    STDMETHODIMP SetSink(IQualityControl * piqc);
 
495
 
 
496
    // --- helper methods ---
 
497
 
 
498
    // Returns true if the pin is connected. false otherwise.
 
499
    BOOL IsConnected(void) {return (m_Connected != NULL); };
 
500
    // Return the pin this is connected to (if any)
 
501
    IPin * GetConnected() { return m_Connected; };
 
502
 
 
503
    // Check if our filter is currently stopped
 
504
    BOOL IsStopped() {
 
505
        return (m_pFilter->m_State == State_Stopped);
 
506
    };
 
507
 
 
508
    // find out the current type version (used by enumerators)
 
509
    virtual LONG GetMediaTypeVersion();
 
510
    void IncrementTypeVersion();
 
511
 
 
512
    // switch the pin to active (paused or running) mode
 
513
    // not an error to call this if already active
 
514
    virtual HRESULT Active(void);
 
515
 
 
516
    // switch the pin to inactive state - may already be inactive
 
517
    virtual HRESULT Inactive(void);
 
518
 
 
519
    // Notify of Run() from filter
 
520
    virtual HRESULT Run(REFERENCE_TIME tStart);
 
521
 
 
522
    // check if the pin can support this specific proposed type and format
 
523
    virtual HRESULT CheckMediaType(const CMediaType *) PURE;
 
524
 
 
525
    // set the connection to use this format (previously agreed)
 
526
    virtual HRESULT SetMediaType(const CMediaType *);
 
527
 
 
528
    // check that the connection is ok before verifying it
 
529
    // can be overridden eg to check what interfaces will be supported.
 
530
    virtual HRESULT CheckConnect(IPin *);
 
531
 
 
532
    // Set and release resources required for a connection
 
533
    virtual HRESULT BreakConnect();
 
534
    virtual HRESULT CompleteConnect(IPin *pReceivePin);
 
535
 
 
536
    // returns the preferred formats for a pin
 
537
    virtual HRESULT GetMediaType(int iPosition, __inout CMediaType *pMediaType);
 
538
 
 
539
    // access to NewSegment values
 
540
    REFERENCE_TIME CurrentStopTime() {
 
541
        return m_tStop;
 
542
    }
 
543
    REFERENCE_TIME CurrentStartTime() {
 
544
        return m_tStart;
 
545
    }
 
546
    double CurrentRate() {
 
547
        return m_dRate;
 
548
    }
 
549
 
 
550
    //  Access name
 
551
    LPWSTR Name() { return m_pName; };
 
552
 
 
553
    //  Can reconnectwhen active?
 
554
    void SetReconnectWhenActive(bool bCanReconnect)
 
555
    {
 
556
        m_bCanReconnectWhenActive = bCanReconnect;
 
557
    }
 
558
 
 
559
    bool CanReconnectWhenActive()
 
560
    {
 
561
        return m_bCanReconnectWhenActive;
 
562
    }
 
563
 
 
564
protected:
 
565
    STDMETHODIMP DisconnectInternal();
 
566
};
 
567
 
 
568
 
 
569
//=====================================================================
 
570
//=====================================================================
 
571
// Defines CEnumPins
 
572
//
 
573
// Pin enumerator class that works by calling CBaseFilter. This interface
 
574
// is provided by CBaseFilter::EnumPins and calls GetPinCount() and
 
575
// GetPin() to enumerate existing pins. Needs to be a separate object so
 
576
// that it can be cloned (creating an existing object at the same
 
577
// position in the enumeration)
 
578
//
 
579
//=====================================================================
 
580
//=====================================================================
 
581
 
 
582
class CEnumPins : public IEnumPins      // The interface we support
 
583
{
 
584
    int m_Position;                 // Current ordinal position
 
585
    int m_PinCount;                 // Number of pins available
 
586
    CBaseFilter *m_pFilter;         // The filter who owns us
 
587
    LONG m_Version;                 // Pin version information
 
588
    LONG m_cRef;
 
589
 
 
590
    typedef CGenericList<CBasePin> CPinList;
 
591
 
 
592
    CPinList m_PinCache;            // These pointers have not been AddRef'ed and
 
593
                                    // so they should not be dereferenced.  They are
 
594
                                    // merely kept to ID which pins have been enumerated.
 
595
 
 
596
#ifdef DEBUG
 
597
    DWORD m_dwCookie;
 
598
#endif
 
599
 
 
600
    /* If while we are retrieving a pin for example from the filter an error
 
601
       occurs we assume that our internal state is stale with respect to the
 
602
       filter (someone may have deleted all the pins). We can check before
 
603
       starting whether or not the operation is likely to fail by asking the
 
604
       filter what it's current version number is. If the filter has not
 
605
       overriden the GetPinVersion method then this will always match */
 
606
 
 
607
    BOOL AreWeOutOfSync() {
 
608
        return (m_pFilter->GetPinVersion() == m_Version ? FALSE : TRUE);
 
609
    };
 
610
 
 
611
    /* This method performs the same operations as Reset, except is does not clear
 
612
       the cache of pins already enumerated. */
 
613
 
 
614
    STDMETHODIMP Refresh();
 
615
 
 
616
public:
 
617
 
 
618
    CEnumPins(
 
619
        __in CBaseFilter *pFilter,
 
620
        __in_opt CEnumPins *pEnumPins);
 
621
 
 
622
    virtual ~CEnumPins();
 
623
 
 
624
    // IUnknown
 
625
    STDMETHODIMP QueryInterface(REFIID riid, __deref_out void **ppv);
 
626
    STDMETHODIMP_(ULONG) AddRef();
 
627
    STDMETHODIMP_(ULONG) Release();
 
628
 
 
629
    // IEnumPins
 
630
    STDMETHODIMP Next(
 
631
        ULONG cPins,         // place this many pins...
 
632
        __out_ecount(cPins) IPin ** ppPins,    // ...in this array of IPin*
 
633
        __out_opt ULONG * pcFetched    // actual count passed returned here
 
634
    );
 
635
 
 
636
    STDMETHODIMP Skip(ULONG cPins);
 
637
    STDMETHODIMP Reset();
 
638
    STDMETHODIMP Clone(__deref_out IEnumPins **ppEnum);
 
639
 
 
640
 
 
641
};
 
642
 
 
643
 
 
644
//=====================================================================
 
645
//=====================================================================
 
646
// Defines CEnumMediaTypes
 
647
//
 
648
// Enumerates the preferred formats for input and output pins
 
649
//=====================================================================
 
650
//=====================================================================
 
651
 
 
652
class CEnumMediaTypes : public IEnumMediaTypes    // The interface we support
 
653
{
 
654
    int m_Position;           // Current ordinal position
 
655
    CBasePin *m_pPin;         // The pin who owns us
 
656
    LONG m_Version;           // Media type version value
 
657
    LONG m_cRef;
 
658
#ifdef DEBUG
 
659
    DWORD m_dwCookie;
 
660
#endif
 
661
 
 
662
    /* The media types a filter supports can be quite dynamic so we add to
 
663
       the general IEnumXXXX interface the ability to be signaled when they
 
664
       change via an event handle the connected filter supplies. Until the
 
665
       Reset method is called after the state changes all further calls to
 
666
       the enumerator (except Reset) will return E_UNEXPECTED error code */
 
667
 
 
668
    BOOL AreWeOutOfSync() {
 
669
        return (m_pPin->GetMediaTypeVersion() == m_Version ? FALSE : TRUE);
 
670
    };
 
671
 
 
672
public:
 
673
 
 
674
    CEnumMediaTypes(
 
675
        __in CBasePin *pPin,
 
676
        __in_opt CEnumMediaTypes *pEnumMediaTypes);
 
677
 
 
678
    virtual ~CEnumMediaTypes();
 
679
 
 
680
    // IUnknown
 
681
    STDMETHODIMP QueryInterface(REFIID riid, __deref_out void **ppv);
 
682
    STDMETHODIMP_(ULONG) AddRef();
 
683
    STDMETHODIMP_(ULONG) Release();
 
684
 
 
685
    // IEnumMediaTypes
 
686
    STDMETHODIMP Next(
 
687
        ULONG cMediaTypes,          // place this many pins...
 
688
        __out_ecount(cMediaTypes) AM_MEDIA_TYPE ** ppMediaTypes,  // ...in this array
 
689
        __out_opt ULONG * pcFetched           // actual count passed
 
690
    );
 
691
 
 
692
    STDMETHODIMP Skip(ULONG cMediaTypes);
 
693
    STDMETHODIMP Reset();
 
694
    STDMETHODIMP Clone(__deref_out IEnumMediaTypes **ppEnum);
 
695
};
 
696
 
 
697
 
 
698
 
 
699
 
 
700
//=====================================================================
 
701
//=====================================================================
 
702
// Defines CBaseOutputPin
 
703
//
 
704
// class derived from CBasePin that can pass buffers to a connected pin
 
705
// that supports IMemInputPin. Supports IPin.
 
706
//
 
707
// Derive your output pin from this.
 
708
//
 
709
//=====================================================================
 
710
//=====================================================================
 
711
 
 
712
class  AM_NOVTABLE CBaseOutputPin : public CBasePin
 
713
{
 
714
 
 
715
protected:
 
716
 
 
717
    IMemAllocator *m_pAllocator;
 
718
    IMemInputPin *m_pInputPin;        // interface on the downstreaminput pin
 
719
                                      // set up in CheckConnect when we connect.
 
720
 
 
721
public:
 
722
 
 
723
    CBaseOutputPin(
 
724
        __in_opt LPCTSTR pObjectName,
 
725
        __in CBaseFilter *pFilter,
 
726
        __in CCritSec *pLock,
 
727
        __inout HRESULT *phr,
 
728
        __in_opt LPCWSTR pName);
 
729
#ifdef UNICODE
 
730
    CBaseOutputPin(
 
731
        __in_opt LPCSTR pObjectName,
 
732
        __in CBaseFilter *pFilter,
 
733
        __in CCritSec *pLock,
 
734
        __inout HRESULT *phr,
 
735
        __in_opt LPCWSTR pName);
 
736
#endif
 
737
    // override CompleteConnect() so we can negotiate an allocator
 
738
    virtual HRESULT CompleteConnect(IPin *pReceivePin);
 
739
 
 
740
    // negotiate the allocator and its buffer size/count and other properties
 
741
    // Calls DecideBufferSize to set properties
 
742
    virtual HRESULT DecideAllocator(IMemInputPin * pPin, __deref_out IMemAllocator ** pAlloc);
 
743
 
 
744
    // override this to set the buffer size and count. Return an error
 
745
    // if the size/count is not to your liking.
 
746
    // The allocator properties passed in are those requested by the
 
747
    // input pin - use eg the alignment and prefix members if you have
 
748
    // no preference on these.
 
749
    virtual HRESULT DecideBufferSize(
 
750
        IMemAllocator * pAlloc,
 
751
        __inout ALLOCATOR_PROPERTIES * ppropInputRequest
 
752
    ) PURE;
 
753
 
 
754
    // returns an empty sample buffer from the allocator
 
755
    virtual HRESULT GetDeliveryBuffer(__deref_out IMediaSample ** ppSample,
 
756
                                      __in_opt REFERENCE_TIME * pStartTime,
 
757
                                      __in_opt REFERENCE_TIME * pEndTime,
 
758
                                      DWORD dwFlags);
 
759
 
 
760
    // deliver a filled-in sample to the connected input pin
 
761
    // note - you need to release it after calling this. The receiving
 
762
    // pin will addref the sample if it needs to hold it beyond the
 
763
    // call.
 
764
    virtual HRESULT Deliver(IMediaSample *);
 
765
 
 
766
    // override this to control the connection
 
767
    virtual HRESULT InitAllocator(__deref_out IMemAllocator **ppAlloc);
 
768
    HRESULT CheckConnect(IPin *pPin);
 
769
    HRESULT BreakConnect();
 
770
 
 
771
    // override to call Commit and Decommit
 
772
    HRESULT Active(void);
 
773
    HRESULT Inactive(void);
 
774
 
 
775
    // we have a default handling of EndOfStream which is to return
 
776
    // an error, since this should be called on input pins only
 
777
    STDMETHODIMP EndOfStream(void);
 
778
 
 
779
    // called from elsewhere in our filter to pass EOS downstream to
 
780
    // our connected input pin
 
781
    virtual HRESULT DeliverEndOfStream(void);
 
782
 
 
783
    // same for Begin/EndFlush - we handle Begin/EndFlush since it
 
784
    // is an error on an output pin, and we have Deliver methods to
 
785
    // call the methods on the connected pin
 
786
    STDMETHODIMP BeginFlush(void);
 
787
    STDMETHODIMP EndFlush(void);
 
788
    virtual HRESULT DeliverBeginFlush(void);
 
789
    virtual HRESULT DeliverEndFlush(void);
 
790
 
 
791
    // deliver NewSegment to connected pin - you will need to
 
792
    // override this if you queue any data in your output pin.
 
793
    virtual HRESULT DeliverNewSegment(
 
794
                        REFERENCE_TIME tStart,
 
795
                        REFERENCE_TIME tStop,
 
796
                        double dRate);
 
797
 
 
798
    //================================================================================
 
799
    // IQualityControl methods
 
800
    //================================================================================
 
801
 
 
802
    // All inherited from CBasePin and not overridden here.
 
803
    // STDMETHODIMP Notify(IBaseFilter * pSender, Quality q);
 
804
    // STDMETHODIMP SetSink(IQualityControl * piqc);
 
805
};
 
806
 
 
807
 
 
808
//=====================================================================
 
809
//=====================================================================
 
810
// Defines CBaseInputPin
 
811
//
 
812
// derive your standard input pin from this.
 
813
// you need to supply GetMediaType and CheckConnect etc (see CBasePin),
 
814
// and you need to supply Receive to do something more useful.
 
815
//
 
816
//=====================================================================
 
817
//=====================================================================
 
818
 
 
819
class AM_NOVTABLE CBaseInputPin : public CBasePin,
 
820
                                  public IMemInputPin
 
821
{
 
822
 
 
823
protected:
 
824
 
 
825
    IMemAllocator *m_pAllocator;    // Default memory allocator
 
826
 
 
827
    // allocator is read-only, so received samples
 
828
    // cannot be modified (probably only relevant to in-place
 
829
    // transforms
 
830
    BYTE m_bReadOnly;
 
831
 
 
832
    // in flushing state (between BeginFlush and EndFlush)
 
833
    // if TRUE, all Receives are returned with S_FALSE
 
834
    BYTE m_bFlushing;
 
835
 
 
836
    // Sample properties - initalized in Receive
 
837
    AM_SAMPLE2_PROPERTIES m_SampleProps;
 
838
 
 
839
public:
 
840
 
 
841
    CBaseInputPin(
 
842
        __in_opt LPCTSTR pObjectName,
 
843
        __in CBaseFilter *pFilter,
 
844
        __in CCritSec *pLock,
 
845
        __inout HRESULT *phr,
 
846
        __in_opt LPCWSTR pName);
 
847
#ifdef UNICODE
 
848
    CBaseInputPin(
 
849
        __in_opt LPCSTR pObjectName,
 
850
        __in CBaseFilter *pFilter,
 
851
        __in CCritSec *pLock,
 
852
        __inout HRESULT *phr,
 
853
        __in_opt LPCWSTR pName);
 
854
#endif
 
855
    virtual ~CBaseInputPin();
 
856
 
 
857
    DECLARE_IUNKNOWN
 
858
 
 
859
    // override this to publicise our interfaces
 
860
    STDMETHODIMP NonDelegatingQueryInterface(REFIID riid, __deref_out void **ppv);
 
861
 
 
862
    // return the allocator interface that this input pin
 
863
    // would like the output pin to use
 
864
    STDMETHODIMP GetAllocator(__deref_out IMemAllocator ** ppAllocator);
 
865
 
 
866
    // tell the input pin which allocator the output pin is actually
 
867
    // going to use.
 
868
    STDMETHODIMP NotifyAllocator(
 
869
                    IMemAllocator * pAllocator,
 
870
                    BOOL bReadOnly);
 
871
 
 
872
    // do something with this media sample
 
873
    STDMETHODIMP Receive(IMediaSample *pSample);
 
874
 
 
875
    // do something with these media samples
 
876
    STDMETHODIMP ReceiveMultiple (
 
877
        __in_ecount(nSamples) IMediaSample **pSamples,
 
878
        long nSamples,
 
879
        __out long *nSamplesProcessed);
 
880
 
 
881
    // See if Receive() blocks
 
882
    STDMETHODIMP ReceiveCanBlock();
 
883
 
 
884
    // Default handling for BeginFlush - call at the beginning
 
885
    // of your implementation (makes sure that all Receive calls
 
886
    // fail). After calling this, you need to free any queued data
 
887
    // and then call downstream.
 
888
    STDMETHODIMP BeginFlush(void);
 
889
 
 
890
    // default handling for EndFlush - call at end of your implementation
 
891
    // - before calling this, ensure that there is no queued data and no thread
 
892
    // pushing any more without a further receive, then call downstream,
 
893
    // then call this method to clear the m_bFlushing flag and re-enable
 
894
    // receives
 
895
    STDMETHODIMP EndFlush(void);
 
896
 
 
897
    // this method is optional (can return E_NOTIMPL).
 
898
    // default implementation returns E_NOTIMPL. Override if you have
 
899
    // specific alignment or prefix needs, but could use an upstream
 
900
    // allocator
 
901
    STDMETHODIMP GetAllocatorRequirements(__out ALLOCATOR_PROPERTIES*pProps);
 
902
 
 
903
    // Release the pin's allocator.
 
904
    HRESULT BreakConnect();
 
905
 
 
906
    // helper method to check the read-only flag
 
907
    BOOL IsReadOnly() {
 
908
        return m_bReadOnly;
 
909
    };
 
910
 
 
911
    // helper method to see if we are flushing
 
912
    BOOL IsFlushing() {
 
913
        return m_bFlushing;
 
914
    };
 
915
 
 
916
    //  Override this for checking whether it's OK to process samples
 
917
    //  Also call this from EndOfStream.
 
918
    virtual HRESULT CheckStreaming();
 
919
 
 
920
    // Pass a Quality notification on to the appropriate sink
 
921
    HRESULT PassNotify(Quality& q);
 
922
 
 
923
 
 
924
    //================================================================================
 
925
    // IQualityControl methods (from CBasePin)
 
926
    //================================================================================
 
927
 
 
928
    STDMETHODIMP Notify(IBaseFilter * pSender, Quality q);
 
929
 
 
930
    // no need to override:
 
931
    // STDMETHODIMP SetSink(IQualityControl * piqc);
 
932
 
 
933
 
 
934
    // switch the pin to inactive state - may already be inactive
 
935
    virtual HRESULT Inactive(void);
 
936
 
 
937
    // Return sample properties pointer
 
938
    AM_SAMPLE2_PROPERTIES * SampleProps() {
 
939
        ASSERT(m_SampleProps.cbData != 0);
 
940
        return &m_SampleProps;
 
941
    }
 
942
 
 
943
};
 
944
 
 
945
///////////////////////////////////////////////////////////////////////////
 
946
// CDynamicOutputPin
 
947
//
 
948
 
 
949
class CDynamicOutputPin : public CBaseOutputPin,
 
950
                          public IPinFlowControl
 
951
{
 
952
public:
 
953
#ifdef UNICODE
 
954
    CDynamicOutputPin(
 
955
        __in_opt LPCSTR pObjectName,
 
956
        __in CBaseFilter *pFilter,
 
957
        __in CCritSec *pLock,
 
958
        __inout HRESULT *phr,
 
959
        __in_opt LPCWSTR pName);
 
960
#endif
 
961
 
 
962
    CDynamicOutputPin(
 
963
        __in_opt LPCTSTR pObjectName,
 
964
        __in CBaseFilter *pFilter,
 
965
        __in CCritSec *pLock,
 
966
        __inout HRESULT *phr,
 
967
        __in_opt LPCWSTR pName);
 
968
 
 
969
    ~CDynamicOutputPin();
 
970
 
 
971
    // IUnknown Methods
 
972
    DECLARE_IUNKNOWN
 
973
    STDMETHODIMP NonDelegatingQueryInterface(REFIID riid, __deref_out void **ppv);
 
974
 
 
975
    // IPin Methods
 
976
    STDMETHODIMP Disconnect(void);
 
977
 
 
978
    // IPinFlowControl Methods
 
979
    STDMETHODIMP Block(DWORD dwBlockFlags, HANDLE hEvent);
 
980
 
 
981
    //  Set graph config info
 
982
    void SetConfigInfo(IGraphConfig *pGraphConfig, HANDLE hStopEvent);
 
983
 
 
984
    #ifdef DEBUG
 
985
    virtual HRESULT Deliver(IMediaSample *pSample);
 
986
    virtual HRESULT DeliverEndOfStream(void);
 
987
    virtual HRESULT DeliverNewSegment(REFERENCE_TIME tStart, REFERENCE_TIME tStop, double dRate);
 
988
    #endif // DEBUG
 
989
 
 
990
    HRESULT DeliverBeginFlush(void);
 
991
    HRESULT DeliverEndFlush(void);
 
992
 
 
993
    HRESULT Inactive(void);
 
994
    HRESULT Active(void);
 
995
    virtual HRESULT CompleteConnect(IPin *pReceivePin);
 
996
 
 
997
    virtual HRESULT StartUsingOutputPin(void);
 
998
    virtual void StopUsingOutputPin(void);
 
999
    virtual bool StreamingThreadUsingOutputPin(void);
 
1000
 
 
1001
    HRESULT ChangeOutputFormat
 
1002
        (
 
1003
        const AM_MEDIA_TYPE *pmt,
 
1004
        REFERENCE_TIME tSegmentStart,
 
1005
        REFERENCE_TIME tSegmentStop,
 
1006
        double dSegmentRate
 
1007
        );
 
1008
    HRESULT ChangeMediaType(const CMediaType *pmt);
 
1009
    HRESULT DynamicReconnect(const CMediaType *pmt);
 
1010
 
 
1011
protected:
 
1012
    HRESULT SynchronousBlockOutputPin(void);
 
1013
    HRESULT AsynchronousBlockOutputPin(HANDLE hNotifyCallerPinBlockedEvent);
 
1014
    HRESULT UnblockOutputPin(void);
 
1015
 
 
1016
    void BlockOutputPin(void);
 
1017
    void ResetBlockState(void);
 
1018
 
 
1019
    static HRESULT WaitEvent(HANDLE hEvent);
 
1020
 
 
1021
    enum BLOCK_STATE
 
1022
    {
 
1023
        NOT_BLOCKED,
 
1024
        PENDING,
 
1025
        BLOCKED
 
1026
    };
 
1027
 
 
1028
    // This lock should be held when the following class members are
 
1029
    // being used: m_hNotifyCallerPinBlockedEvent, m_BlockState,
 
1030
    // m_dwBlockCallerThreadID and m_dwNumOutstandingOutputPinUsers.
 
1031
    CCritSec m_BlockStateLock;
 
1032
 
 
1033
    // This event should be signaled when the output pin is
 
1034
    // not blocked.  This is a manual reset event.  For more
 
1035
    // information on events, see the documentation for
 
1036
    // CreateEvent() in the Windows SDK.
 
1037
    HANDLE m_hUnblockOutputPinEvent;
 
1038
 
 
1039
    // This event will be signaled when block operation succeedes or
 
1040
    // when the user cancels the block operation.  The block operation
 
1041
    // can be canceled by calling IPinFlowControl2::Block( 0, NULL )
 
1042
    // while the block operation is pending.
 
1043
    HANDLE m_hNotifyCallerPinBlockedEvent;
 
1044
 
 
1045
    // The state of the current block operation.
 
1046
    BLOCK_STATE m_BlockState;
 
1047
 
 
1048
    // The ID of the thread which last called IPinFlowControl::Block().
 
1049
    // For more information on thread IDs, see the documentation for
 
1050
    // GetCurrentThreadID() in the Windows SDK.
 
1051
    DWORD m_dwBlockCallerThreadID;
 
1052
 
 
1053
    // The number of times StartUsingOutputPin() has been sucessfully
 
1054
    // called and a corresponding call to StopUsingOutputPin() has not
 
1055
    // been made.  When this variable is greater than 0, the streaming
 
1056
    // thread is calling IPin::NewSegment(), IPin::EndOfStream(),
 
1057
    // IMemInputPin::Receive() or IMemInputPin::ReceiveMultiple().  The
 
1058
    // streaming thread could also be calling: DynamicReconnect(),
 
1059
    // ChangeMediaType() or ChangeOutputFormat().  The output pin cannot
 
1060
    // be blocked while the output pin is being used.
 
1061
    DWORD m_dwNumOutstandingOutputPinUsers;
 
1062
 
 
1063
    // This event should be set when the IMediaFilter::Stop() is called.
 
1064
    // This is a manual reset event.  It is also set when the output pin
 
1065
    // delivers a flush to the connected input pin.
 
1066
    HANDLE m_hStopEvent;
 
1067
    IGraphConfig* m_pGraphConfig;
 
1068
 
 
1069
    // TRUE if the output pin's allocator's samples are read only.
 
1070
    // Otherwise FALSE.  For more information, see the documentation
 
1071
    // for IMemInputPin::NotifyAllocator().
 
1072
    BOOL m_bPinUsesReadOnlyAllocator;
 
1073
 
 
1074
private:
 
1075
    HRESULT Initialize(void);
 
1076
    HRESULT ChangeMediaTypeHelper(const CMediaType *pmt);
 
1077
 
 
1078
    #ifdef DEBUG
 
1079
    void AssertValid(void);
 
1080
    #endif // DEBUG
 
1081
};
 
1082
 
 
1083
class CAutoUsingOutputPin
 
1084
{
 
1085
public:
 
1086
    CAutoUsingOutputPin( __in CDynamicOutputPin* pOutputPin, __inout HRESULT* phr );
 
1087
    ~CAutoUsingOutputPin();
 
1088
 
 
1089
private:
 
1090
    CDynamicOutputPin* m_pOutputPin;
 
1091
};
 
1092
 
 
1093
inline CAutoUsingOutputPin::CAutoUsingOutputPin( __in CDynamicOutputPin* pOutputPin, __inout HRESULT* phr ) :
 
1094
    m_pOutputPin(NULL)
 
1095
{
 
1096
    // The caller should always pass in valid pointers.
 
1097
    ASSERT( NULL != pOutputPin );
 
1098
    ASSERT( NULL != phr );
 
1099
 
 
1100
    // Make sure the user initialized phr.
 
1101
    ASSERT( S_OK == *phr );
 
1102
 
 
1103
    HRESULT hr = pOutputPin->StartUsingOutputPin();
 
1104
    if( FAILED( hr ) )
 
1105
    {
 
1106
        *phr = hr;
 
1107
        return;
 
1108
    }
 
1109
 
 
1110
    m_pOutputPin = pOutputPin;
 
1111
}
 
1112
 
 
1113
inline CAutoUsingOutputPin::~CAutoUsingOutputPin()
 
1114
{
 
1115
    if( NULL != m_pOutputPin )
 
1116
    {
 
1117
        m_pOutputPin->StopUsingOutputPin();
 
1118
    }
 
1119
}
 
1120
 
 
1121
#ifdef DEBUG
 
1122
 
 
1123
inline HRESULT CDynamicOutputPin::Deliver(IMediaSample *pSample)
 
1124
{
 
1125
    // The caller should call StartUsingOutputPin() before calling this
 
1126
    // method.
 
1127
    ASSERT(StreamingThreadUsingOutputPin());
 
1128
 
 
1129
    return CBaseOutputPin::Deliver(pSample);
 
1130
}
 
1131
 
 
1132
inline HRESULT CDynamicOutputPin::DeliverEndOfStream(void)
 
1133
{
 
1134
    // The caller should call StartUsingOutputPin() before calling this
 
1135
    // method.
 
1136
    ASSERT( StreamingThreadUsingOutputPin() );
 
1137
 
 
1138
    return CBaseOutputPin::DeliverEndOfStream();
 
1139
}
 
1140
 
 
1141
inline HRESULT CDynamicOutputPin::DeliverNewSegment(REFERENCE_TIME tStart, REFERENCE_TIME tStop, double dRate)
 
1142
{
 
1143
    // The caller should call StartUsingOutputPin() before calling this
 
1144
    // method.
 
1145
    ASSERT(StreamingThreadUsingOutputPin());
 
1146
 
 
1147
    return CBaseOutputPin::DeliverNewSegment(tStart, tStop, dRate);
 
1148
}
 
1149
 
 
1150
#endif // DEBUG
 
1151
 
 
1152
//=====================================================================
 
1153
//=====================================================================
 
1154
// Memory allocators
 
1155
//
 
1156
// the shared memory transport between pins requires the input pin
 
1157
// to provide a memory allocator that can provide sample objects. A
 
1158
// sample object supports the IMediaSample interface.
 
1159
//
 
1160
// CBaseAllocator handles the management of free and busy samples. It
 
1161
// allocates CMediaSample objects. CBaseAllocator is an abstract class:
 
1162
// in particular it has no method of initializing the list of free
 
1163
// samples. CMemAllocator is derived from CBaseAllocator and initializes
 
1164
// the list of samples using memory from the standard IMalloc interface.
 
1165
//
 
1166
// If you want your buffers to live in some special area of memory,
 
1167
// derive your allocator object from CBaseAllocator. If you derive your
 
1168
// IMemInputPin interface object from CBaseMemInputPin, you will get
 
1169
// CMemAllocator-based allocation etc for free and will just need to
 
1170
// supply the Receive handling, and media type / format negotiation.
 
1171
//=====================================================================
 
1172
//=====================================================================
 
1173
 
 
1174
 
 
1175
//=====================================================================
 
1176
//=====================================================================
 
1177
// Defines CMediaSample
 
1178
//
 
1179
// an object of this class supports IMediaSample and represents a buffer
 
1180
// for media data with some associated properties. Releasing it returns
 
1181
// it to a freelist managed by a CBaseAllocator derived object.
 
1182
//=====================================================================
 
1183
//=====================================================================
 
1184
 
 
1185
class CMediaSample : public IMediaSample2    // The interface we support
 
1186
{
 
1187
 
 
1188
protected:
 
1189
 
 
1190
    friend class CBaseAllocator;
 
1191
 
 
1192
    /*  Values for dwFlags - these are used for backward compatiblity
 
1193
        only now - use AM_SAMPLE_xxx
 
1194
    */
 
1195
    enum { Sample_SyncPoint       = 0x01,   /* Is this a sync point */
 
1196
           Sample_Preroll         = 0x02,   /* Is this a preroll sample */
 
1197
           Sample_Discontinuity   = 0x04,   /* Set if start of new segment */
 
1198
           Sample_TypeChanged     = 0x08,   /* Has the type changed */
 
1199
           Sample_TimeValid       = 0x10,   /* Set if time is valid */
 
1200
           Sample_MediaTimeValid  = 0x20,   /* Is the media time valid */
 
1201
           Sample_TimeDiscontinuity = 0x40, /* Time discontinuity */
 
1202
           Sample_StopValid       = 0x100,  /* Stop time valid */
 
1203
           Sample_ValidFlags      = 0x1FF
 
1204
         };
 
1205
 
 
1206
    /* Properties, the media sample class can be a container for a format
 
1207
       change in which case we take a copy of a type through the SetMediaType
 
1208
       interface function and then return it when GetMediaType is called. As
 
1209
       we do no internal processing on it we leave it as a pointer */
 
1210
 
 
1211
    DWORD            m_dwFlags;         /* Flags for this sample */
 
1212
                                        /* Type specific flags are packed
 
1213
                                           into the top word
 
1214
                                        */
 
1215
    DWORD            m_dwTypeSpecificFlags; /* Media type specific flags */
 
1216
    __field_ecount_opt(m_cbBuffer) LPBYTE           m_pBuffer;         /* Pointer to the complete buffer */
 
1217
    LONG             m_lActual;         /* Length of data in this sample */
 
1218
    LONG             m_cbBuffer;        /* Size of the buffer */
 
1219
    CBaseAllocator  *m_pAllocator;      /* The allocator who owns us */
 
1220
    CMediaSample     *m_pNext;          /* Chaining in free list */
 
1221
    REFERENCE_TIME   m_Start;           /* Start sample time */
 
1222
    REFERENCE_TIME   m_End;             /* End sample time */
 
1223
    LONGLONG         m_MediaStart;      /* Real media start position */
 
1224
    LONG             m_MediaEnd;        /* A difference to get the end */
 
1225
    AM_MEDIA_TYPE    *m_pMediaType;     /* Media type change data */
 
1226
    DWORD            m_dwStreamId;      /* Stream id */
 
1227
public:
 
1228
    LONG             m_cRef;            /* Reference count */
 
1229
 
 
1230
 
 
1231
public:
 
1232
 
 
1233
    CMediaSample(
 
1234
        __in_opt LPCTSTR pName,
 
1235
        __in_opt CBaseAllocator *pAllocator,
 
1236
        __inout_opt HRESULT *phr,
 
1237
        __in_bcount_opt(length) LPBYTE pBuffer = NULL,
 
1238
        LONG length = 0);
 
1239
#ifdef UNICODE
 
1240
    CMediaSample(
 
1241
        __in_opt LPCSTR pName,
 
1242
        __in_opt CBaseAllocator *pAllocator,
 
1243
        __inout_opt HRESULT *phr,
 
1244
        __in_bcount_opt(length) LPBYTE pBuffer = NULL,
 
1245
        LONG length = 0);
 
1246
#endif
 
1247
 
 
1248
    virtual ~CMediaSample();
 
1249
 
 
1250
    /* Note the media sample does not delegate to its owner */
 
1251
 
 
1252
    STDMETHODIMP QueryInterface(REFIID riid, __deref_out void **ppv);
 
1253
    STDMETHODIMP_(ULONG) AddRef();
 
1254
    STDMETHODIMP_(ULONG) Release();
 
1255
 
 
1256
    // set the buffer pointer and length. Used by allocators that
 
1257
    // want variable sized pointers or pointers into already-read data.
 
1258
    // This is only available through a CMediaSample* not an IMediaSample*
 
1259
    // and so cannot be changed by clients.
 
1260
    HRESULT SetPointer(__in_bcount(cBytes) BYTE * ptr, LONG cBytes);
 
1261
 
 
1262
    // Get me a read/write pointer to this buffer's memory.
 
1263
    STDMETHODIMP GetPointer(__deref_out BYTE ** ppBuffer);
 
1264
 
 
1265
    STDMETHODIMP_(LONG) GetSize(void);
 
1266
 
 
1267
    // get the stream time at which this sample should start and finish.
 
1268
    STDMETHODIMP GetTime(
 
1269
        __out REFERENCE_TIME * pTimeStart,     // put time here
 
1270
        __out REFERENCE_TIME * pTimeEnd
 
1271
    );
 
1272
 
 
1273
    // Set the stream time at which this sample should start and finish.
 
1274
    STDMETHODIMP SetTime(
 
1275
        __in_opt REFERENCE_TIME * pTimeStart,     // put time here
 
1276
        __in_opt REFERENCE_TIME * pTimeEnd
 
1277
    );
 
1278
    STDMETHODIMP IsSyncPoint(void);
 
1279
    STDMETHODIMP SetSyncPoint(BOOL bIsSyncPoint);
 
1280
    STDMETHODIMP IsPreroll(void);
 
1281
    STDMETHODIMP SetPreroll(BOOL bIsPreroll);
 
1282
 
 
1283
    STDMETHODIMP_(LONG) GetActualDataLength(void);
 
1284
    STDMETHODIMP SetActualDataLength(LONG lActual);
 
1285
 
 
1286
    // these allow for limited format changes in band
 
1287
 
 
1288
    STDMETHODIMP GetMediaType(__deref_out AM_MEDIA_TYPE **ppMediaType);
 
1289
    STDMETHODIMP SetMediaType(__in_opt AM_MEDIA_TYPE *pMediaType);
 
1290
 
 
1291
    // returns S_OK if there is a discontinuity in the data (this same is
 
1292
    // not a continuation of the previous stream of data
 
1293
    // - there has been a seek).
 
1294
    STDMETHODIMP IsDiscontinuity(void);
 
1295
    // set the discontinuity property - TRUE if this sample is not a
 
1296
    // continuation, but a new sample after a seek.
 
1297
    STDMETHODIMP SetDiscontinuity(BOOL bDiscontinuity);
 
1298
 
 
1299
    // get the media times for this sample
 
1300
    STDMETHODIMP GetMediaTime(
 
1301
        __out LONGLONG * pTimeStart,
 
1302
            __out LONGLONG * pTimeEnd
 
1303
    );
 
1304
 
 
1305
    // Set the media times for this sample
 
1306
    STDMETHODIMP SetMediaTime(
 
1307
        __in_opt LONGLONG * pTimeStart,
 
1308
            __in_opt LONGLONG * pTimeEnd
 
1309
    );
 
1310
 
 
1311
    // Set and get properties (IMediaSample2)
 
1312
    STDMETHODIMP GetProperties(
 
1313
        DWORD cbProperties,
 
1314
        __out_bcount(cbProperties) BYTE * pbProperties
 
1315
    );
 
1316
 
 
1317
    STDMETHODIMP SetProperties(
 
1318
        DWORD cbProperties,
 
1319
        __in_bcount(cbProperties) const BYTE * pbProperties
 
1320
    );
 
1321
};
 
1322
 
 
1323
 
 
1324
//=====================================================================
 
1325
//=====================================================================
 
1326
// Defines CBaseAllocator
 
1327
//
 
1328
// Abstract base class that manages a list of media samples
 
1329
//
 
1330
// This class provides support for getting buffers from the free list,
 
1331
// including handling of commit and (asynchronous) decommit.
 
1332
//
 
1333
// Derive from this class and override the Alloc and Free functions to
 
1334
// allocate your CMediaSample (or derived) objects and add them to the
 
1335
// free list, preparing them as necessary.
 
1336
//=====================================================================
 
1337
//=====================================================================
 
1338
 
 
1339
class AM_NOVTABLE CBaseAllocator : public CUnknown,// A non delegating IUnknown
 
1340
                       public IMemAllocatorCallbackTemp, // The interface we support
 
1341
                       public CCritSec             // Provides object locking
 
1342
{
 
1343
    class CSampleList;
 
1344
    friend class CSampleList;
 
1345
 
 
1346
    /*  Trick to get at protected member in CMediaSample */
 
1347
    static CMediaSample * &NextSample(__in CMediaSample *pSample)
 
1348
    {
 
1349
        return pSample->m_pNext;
 
1350
    };
 
1351
 
 
1352
    /*  Mini list class for the free list */
 
1353
    class CSampleList
 
1354
    {
 
1355
    public:
 
1356
        CSampleList() : m_List(NULL), m_nOnList(0) {};
 
1357
#ifdef DEBUG
 
1358
        ~CSampleList()
 
1359
        {
 
1360
            ASSERT(m_nOnList == 0);
 
1361
        };
 
1362
#endif
 
1363
        CMediaSample *Head() const { return m_List; };
 
1364
        CMediaSample *Next(__in CMediaSample *pSample) const { return CBaseAllocator::NextSample(pSample); };
 
1365
        int GetCount() const { return m_nOnList; };
 
1366
        void Add(__inout CMediaSample *pSample)
 
1367
        {
 
1368
            ASSERT(pSample != NULL);
 
1369
            CBaseAllocator::NextSample(pSample) = m_List;
 
1370
            m_List = pSample;
 
1371
            m_nOnList++;
 
1372
        };
 
1373
        CMediaSample *RemoveHead()
 
1374
        {
 
1375
            CMediaSample *pSample = m_List;
 
1376
            if (pSample != NULL) {
 
1377
                m_List = CBaseAllocator::NextSample(m_List);
 
1378
                m_nOnList--;
 
1379
            }
 
1380
            return pSample;
 
1381
        };
 
1382
        void Remove(__inout CMediaSample *pSample);
 
1383
 
 
1384
    public:
 
1385
        CMediaSample *m_List;
 
1386
        int           m_nOnList;
 
1387
    };
 
1388
protected:
 
1389
 
 
1390
    CSampleList m_lFree;        // Free list
 
1391
 
 
1392
    /*  Note to overriders of CBaseAllocator.
 
1393
 
 
1394
        We use a lazy signalling mechanism for waiting for samples.
 
1395
        This means we don't call the OS if no waits occur.
 
1396
 
 
1397
        In order to implement this:
 
1398
 
 
1399
        1. When a new sample is added to m_lFree call NotifySample() which
 
1400
           calls ReleaseSemaphore on m_hSem with a count of m_lWaiting and
 
1401
           sets m_lWaiting to 0.
 
1402
           This must all be done holding the allocator's critical section.
 
1403
 
 
1404
        2. When waiting for a sample call SetWaiting() which increments
 
1405
           m_lWaiting BEFORE leaving the allocator's critical section.
 
1406
 
 
1407
        3. Actually wait by calling WaitForSingleObject(m_hSem, INFINITE)
 
1408
           having left the allocator's critical section.  The effect of
 
1409
           this is to remove 1 from the semaphore's count.  You MUST call
 
1410
           this once having incremented m_lWaiting.
 
1411
 
 
1412
        The following are then true when the critical section is not held :
 
1413
            (let nWaiting = number about to wait or waiting)
 
1414
 
 
1415
            (1) if (m_lFree.GetCount() != 0) then (m_lWaiting == 0)
 
1416
            (2) m_lWaiting + Semaphore count == nWaiting
 
1417
 
 
1418
        We would deadlock if
 
1419
           nWaiting != 0 &&
 
1420
           m_lFree.GetCount() != 0 &&
 
1421
           Semaphore count == 0
 
1422
 
 
1423
           But from (1) if m_lFree.GetCount() != 0 then m_lWaiting == 0 so
 
1424
           from (2) Semaphore count == nWaiting (which is non-0) so the
 
1425
           deadlock can't happen.
 
1426
    */
 
1427
 
 
1428
    HANDLE m_hSem;              // For signalling
 
1429
    long m_lWaiting;            // Waiting for a free element
 
1430
    long m_lCount;              // how many buffers we have agreed to provide
 
1431
    long m_lAllocated;          // how many buffers are currently allocated
 
1432
    long m_lSize;               // agreed size of each buffer
 
1433
    long m_lAlignment;          // agreed alignment
 
1434
    long m_lPrefix;             // agreed prefix (preceeds GetPointer() value)
 
1435
    BOOL m_bChanged;            // Have the buffer requirements changed
 
1436
 
 
1437
    // if true, we are decommitted and can't allocate memory
 
1438
    BOOL m_bCommitted;
 
1439
    // if true, the decommit has happened, but we haven't called Free yet
 
1440
    // as there are still outstanding buffers
 
1441
    BOOL m_bDecommitInProgress;
 
1442
 
 
1443
    //  Notification interface
 
1444
    IMemAllocatorNotifyCallbackTemp *m_pNotify;
 
1445
 
 
1446
    BOOL m_fEnableReleaseCallback;
 
1447
 
 
1448
    // called to decommit the memory when the last buffer is freed
 
1449
    // pure virtual - need to override this
 
1450
    virtual void Free(void) PURE;
 
1451
 
 
1452
    // override to allocate the memory when commit called
 
1453
    virtual HRESULT Alloc(void);
 
1454
 
 
1455
public:
 
1456
 
 
1457
    CBaseAllocator(
 
1458
        __in_opt LPCTSTR , __inout_opt LPUNKNOWN, __inout HRESULT *,
 
1459
        BOOL bEvent = TRUE, BOOL fEnableReleaseCallback = FALSE);
 
1460
#ifdef UNICODE
 
1461
    CBaseAllocator(
 
1462
        __in_opt LPCSTR , __inout_opt LPUNKNOWN, __inout HRESULT *,
 
1463
        BOOL bEvent = TRUE, BOOL fEnableReleaseCallback = FALSE);
 
1464
#endif
 
1465
    virtual ~CBaseAllocator();
 
1466
 
 
1467
    DECLARE_IUNKNOWN
 
1468
 
 
1469
    // override this to publicise our interfaces
 
1470
    STDMETHODIMP NonDelegatingQueryInterface(REFIID riid, __deref_out void **ppv);
 
1471
 
 
1472
    STDMETHODIMP SetProperties(
 
1473
                    __in ALLOCATOR_PROPERTIES* pRequest,
 
1474
                    __out ALLOCATOR_PROPERTIES* pActual);
 
1475
 
 
1476
    // return the properties actually being used on this allocator
 
1477
    STDMETHODIMP GetProperties(
 
1478
                    __out ALLOCATOR_PROPERTIES* pProps);
 
1479
 
 
1480
    // override Commit to allocate memory. We handle the GetBuffer
 
1481
    //state changes
 
1482
    STDMETHODIMP Commit();
 
1483
 
 
1484
    // override this to handle the memory freeing. We handle any outstanding
 
1485
    // GetBuffer calls
 
1486
    STDMETHODIMP Decommit();
 
1487
 
 
1488
    // get container for a sample. Blocking, synchronous call to get the
 
1489
    // next free buffer (as represented by an IMediaSample interface).
 
1490
    // on return, the time etc properties will be invalid, but the buffer
 
1491
    // pointer and size will be correct. The two time parameters are
 
1492
    // optional and either may be NULL, they may alternatively be set to
 
1493
    // the start and end times the sample will have attached to it
 
1494
    // bPrevFramesSkipped is not used (used only by the video renderer's
 
1495
    // allocator where it affects quality management in direct draw).
 
1496
 
 
1497
    STDMETHODIMP GetBuffer(__deref_out IMediaSample **ppBuffer,
 
1498
                           __in_opt REFERENCE_TIME * pStartTime,
 
1499
                           __in_opt REFERENCE_TIME * pEndTime,
 
1500
                           DWORD dwFlags);
 
1501
 
 
1502
    // final release of a CMediaSample will call this
 
1503
    STDMETHODIMP ReleaseBuffer(IMediaSample *pBuffer);
 
1504
    // obsolete:: virtual void PutOnFreeList(CMediaSample * pSample);
 
1505
 
 
1506
    STDMETHODIMP SetNotify(IMemAllocatorNotifyCallbackTemp *pNotify);
 
1507
 
 
1508
    STDMETHODIMP GetFreeCount(__out LONG *plBuffersFree);
 
1509
 
 
1510
    // Notify that a sample is available
 
1511
    void NotifySample();
 
1512
 
 
1513
    // Notify that we're waiting for a sample
 
1514
    void SetWaiting() { m_lWaiting++; };
 
1515
};
 
1516
 
 
1517
 
 
1518
//=====================================================================
 
1519
//=====================================================================
 
1520
// Defines CMemAllocator
 
1521
//
 
1522
// this is an allocator based on CBaseAllocator that allocates sample
 
1523
// buffers in main memory (from 'new'). You must call SetProperties
 
1524
// before calling Commit.
 
1525
//
 
1526
// we don't free the memory when going into Decommit state. The simplest
 
1527
// way to implement this without complicating CBaseAllocator is to
 
1528
// have a Free() function, called to go into decommit state, that does
 
1529
// nothing and a ReallyFree function called from our destructor that
 
1530
// actually frees the memory.
 
1531
//=====================================================================
 
1532
//=====================================================================
 
1533
 
 
1534
//  Make me one from quartz.dll
 
1535
STDAPI CreateMemoryAllocator(__deref_out IMemAllocator **ppAllocator);
 
1536
 
 
1537
class CMemAllocator : public CBaseAllocator
 
1538
{
 
1539
 
 
1540
protected:
 
1541
 
 
1542
    LPBYTE m_pBuffer;   // combined memory for all buffers
 
1543
 
 
1544
    // override to free the memory when decommit completes
 
1545
    // - we actually do nothing, and save the memory until deletion.
 
1546
    void Free(void);
 
1547
 
 
1548
    // called from the destructor (and from Alloc if changing size/count) to
 
1549
    // actually free up the memory
 
1550
    void ReallyFree(void);
 
1551
 
 
1552
    // overriden to allocate the memory when commit called
 
1553
    HRESULT Alloc(void);
 
1554
 
 
1555
public:
 
1556
    /* This goes in the factory template table to create new instances */
 
1557
    static CUnknown *CreateInstance(__inout_opt LPUNKNOWN, __inout HRESULT *);
 
1558
 
 
1559
    STDMETHODIMP SetProperties(
 
1560
                    __in ALLOCATOR_PROPERTIES* pRequest,
 
1561
                    __out ALLOCATOR_PROPERTIES* pActual);
 
1562
 
 
1563
    CMemAllocator(__in_opt LPCTSTR , __inout_opt LPUNKNOWN, __inout HRESULT *);
 
1564
#ifdef UNICODE
 
1565
    CMemAllocator(__in_opt LPCSTR , __inout_opt LPUNKNOWN, __inout HRESULT *);
 
1566
#endif
 
1567
    ~CMemAllocator();
 
1568
};
 
1569
 
 
1570
// helper used by IAMovieSetup implementation
 
1571
STDAPI
 
1572
AMovieSetupRegisterFilter( const AMOVIESETUP_FILTER * const psetupdata
 
1573
                         , IFilterMapper *                  pIFM
 
1574
                         , BOOL                             bRegister  );
 
1575
 
 
1576
 
 
1577
///////////////////////////////////////////////////////////////////////////
 
1578
// ------------------------------------------------------------------------
 
1579
// ------------------------------------------------------------------------
 
1580
// ------------------------------------------------------------------------
 
1581
// ------------------------------------------------------------------------
 
1582
///////////////////////////////////////////////////////////////////////////
 
1583
 
 
1584
#endif /* __FILTER__ */
 
1585
 
 
1586
 
 
1587