| //------------------------------------------------------------------------------ | |
| // 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 |