mirror of https://github.com/PCSX2/pcsx2.git
158 lines
6.0 KiB
C
158 lines
6.0 KiB
C
|
//------------------------------------------------------------------------------
|
||
|
// File: StrmCtl.h
|
||
|
//
|
||
|
// Desc: DirectShow base classes.
|
||
|
//
|
||
|
// Copyright (c) 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( const REFERENCE_TIME * pSampleStart,
|
||
|
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();
|
||
|
~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( 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
|