158 lines
		
	
	
		
			6.1 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
			
		
		
	
	
			158 lines
		
	
	
		
			6.1 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
| //------------------------------------------------------------------------------
 | |
| // File: StrmCtl.h
 | |
| //
 | |
| // Desc: DirectShow base classes.
 | |
| //
 | |
| // Copyright (c) 1996-2001 Microsoft Corporation.  All rights reserved.
 | |
| //------------------------------------------------------------------------------
 | |
| 
 | |
| 
 | |
| #ifndef __strmctl_h__
 | |
| #define __strmctl_h__
 | |
| 
 | |
| class CBaseStreamControl : public IAMStreamControl
 | |
| {
 | |
| public:
 | |
|     // Used by the implementation
 | |
|     enum StreamControlState
 | |
|     { STREAM_FLOWING = 0x1000,
 | |
|       STREAM_DISCARDING
 | |
|     };
 | |
| 
 | |
| private:
 | |
|     enum StreamControlState	m_StreamState;		// Current stream state
 | |
|     enum StreamControlState	m_StreamStateOnStop;	// State after next stop
 | |
| 						// (i.e.Blocking or Discarding)
 | |
| 
 | |
|     REFERENCE_TIME	m_tStartTime;	    // MAX_TIME implies none
 | |
|     REFERENCE_TIME	m_tStopTime;	    // MAX_TIME implies none
 | |
|     DWORD		m_dwStartCookie;    // Cookie for notification to app
 | |
|     DWORD		m_dwStopCookie;	    // Cookie for notification to app
 | |
|     volatile BOOL       m_bIsFlushing;        // No optimization pls!
 | |
|     volatile BOOL	m_bStopSendExtra;   // bSendExtra was set
 | |
|     volatile BOOL	m_bStopExtraSent;   // the extra one was sent
 | |
| 
 | |
|     CCritSec		m_CritSec;	    // CritSec to guard above attributes
 | |
| 
 | |
|     // Event to fire when we can come
 | |
|     // out of blocking, or to come out of waiting
 | |
|     // to discard if we change our minds.
 | |
|     //
 | |
|     CAMEvent			m_StreamEvent;
 | |
| 
 | |
|     // All of these methods execute immediately.  Helpers for others.
 | |
|     //
 | |
|     void ExecuteStop();
 | |
|     void ExecuteStart();
 | |
|     void CancelStop();
 | |
|     void CancelStart();
 | |
| 
 | |
|     // Some things we need to be told by our owning filter
 | |
|     // Your pin must also expose IAMStreamControl when QI'd for it!
 | |
|     //
 | |
|     IReferenceClock *	m_pRefClock;	    // Need it to set advises
 | |
| 					    // Filter must tell us via
 | |
| 					    // SetSyncSource
 | |
|     IMediaEventSink *   m_pSink;            // Event sink
 | |
| 					    // Filter must tell us after it
 | |
| 					    // creates it in JoinFilterGraph()
 | |
|     FILTER_STATE	m_FilterState;	    // Just need it!
 | |
| 					    // Filter must tell us via
 | |
| 					    // NotifyFilterState
 | |
|     REFERENCE_TIME	m_tRunStart;	    // Per the Run call to the filter
 | |
| 
 | |
|     // This guy will return one of the three StreamControlState's.  Here's what
 | |
|     // the caller should do for each one:
 | |
|     //
 | |
|     // STREAM_FLOWING:		Proceed as usual (render or pass the sample on)
 | |
|     // STREAM_DISCARDING:	Calculate the time 'til *pSampleStop and wait
 | |
|     //				that long for the event handle
 | |
|     //				(GetStreamEventHandle()).  If the wait
 | |
|     //				expires, throw the sample away.  If the event
 | |
|     //				fires, call me back - I've changed my mind.
 | |
|     //
 | |
|     enum StreamControlState CheckSampleTimes( __in const REFERENCE_TIME * pSampleStart,
 | |
| 					      __in const REFERENCE_TIME * pSampleStop );
 | |
| 
 | |
| public:
 | |
|     // You don't have to tell us much when we're created, but there are other
 | |
|     // obligations that must be met.  See SetSyncSource & NotifyFilterState
 | |
|     // below.
 | |
|     //
 | |
|     CBaseStreamControl(__inout_opt HRESULT *phr = NULL);
 | |
|     ~CBaseStreamControl();
 | |
| 
 | |
|     // If you want this class to work properly, there are thing you need to
 | |
|     // (keep) telling it.  Filters with pins that use this class
 | |
|     // should ensure that they pass through to this method any calls they
 | |
|     // receive on their SetSyncSource.
 | |
| 
 | |
|     // We need a clock to see what time it is.  This is for the
 | |
|     // "discard in a timely fashion" logic.  If we discard everything as
 | |
|     // quick as possible, a whole 60 minute file could get discarded in the
 | |
|     // first 10 seconds, and if somebody wants to turn streaming on at 30 
 | |
|     // minutes into the file, and they make the call more than a few seconds
 | |
|     // after the graph is run, it may be too late!
 | |
|     // So we hold every sample until it's time has gone, then we discard it.
 | |
|     // The filter should call this when it gets a SetSyncSource
 | |
|     //
 | |
|     void SetSyncSource( IReferenceClock * pRefClock )
 | |
|     {
 | |
| 	CAutoLock lck(&m_CritSec);
 | |
| 	if (m_pRefClock) m_pRefClock->Release();
 | |
| 	m_pRefClock = pRefClock;
 | |
| 	if (m_pRefClock) m_pRefClock->AddRef();
 | |
|     }
 | |
| 
 | |
|     // Set event sink for notifications
 | |
|     // The filter should call this in its JoinFilterGraph after it creates the
 | |
|     // IMediaEventSink
 | |
|     //
 | |
|     void SetFilterGraph( IMediaEventSink *pSink ) {
 | |
|         m_pSink = pSink;
 | |
|     }
 | |
| 
 | |
|     // Since we schedule in stream time, we need the tStart and must track the
 | |
|     // state of our owning filter.
 | |
|     // The app should call this ever state change
 | |
|     //
 | |
|     void NotifyFilterState( FILTER_STATE new_state, REFERENCE_TIME tStart = 0 );
 | |
| 
 | |
|     // Filter should call Flushing(TRUE) in BeginFlush,
 | |
|     // and Flushing(FALSE) in EndFlush.
 | |
|     //
 | |
|     void Flushing( BOOL bInProgress );
 | |
| 
 | |
| 
 | |
|     // The two main methods of IAMStreamControl
 | |
| 
 | |
|     // Class adds default values suitable for immediate
 | |
|     // muting and unmuting of the stream.
 | |
| 
 | |
|     STDMETHODIMP StopAt( const REFERENCE_TIME * ptStop = NULL,
 | |
| 			 BOOL bSendExtra = FALSE,
 | |
| 			 DWORD dwCookie = 0 );
 | |
|     STDMETHODIMP StartAt( const REFERENCE_TIME * ptStart = NULL,
 | |
| 		    	  DWORD dwCookie = 0 );
 | |
|     STDMETHODIMP GetInfo( __out AM_STREAM_INFO *pInfo);
 | |
| 
 | |
|     // Helper function for pin's receive method.  Call this with
 | |
|     // the sample and we'll tell you what to do with it.  We'll do a
 | |
|     // WaitForSingleObject within this call if one is required.  This is
 | |
|     // a "What should I do with this sample?" kind of call. We'll tell the
 | |
|     // caller to either flow it or discard it.
 | |
|     // If pSample is NULL we evaluate based on the current state
 | |
|     // settings
 | |
|     enum StreamControlState CheckStreamState( IMediaSample * pSample );
 | |
| 
 | |
| private:
 | |
|     // These don't require locking, but we are relying on the fact that
 | |
|     // m_StreamState can be retrieved with integrity, and is a snap shot that
 | |
|     // may have just been, or may be just about to be, changed.
 | |
|     HANDLE GetStreamEventHandle() const { return m_StreamEvent; }
 | |
|     enum StreamControlState GetStreamState() const { return m_StreamState; }
 | |
|     BOOL IsStreaming() const { return m_StreamState == STREAM_FLOWING; }
 | |
| };
 | |
| 
 | |
| #endif
 |