//------------------------------------------------------------------------------
//
// Copyright (c) Microsoft Corporation. All rights reserved.
//
// The use and distribution terms for this software are covered by the
// Microsoft Limited Public License (Ms-LPL)
// which can be found in the file MS-LPL.txt at the root of this distribution.
// By using this software in any fashion, you are agreeing to be bound by
// the terms of this license.
//
// The software is licensed “as-is.”
//
// You must not remove this notice, or any other, from this software.
//
//
//
// Demux code for Windows CE
//
//-------------------------------------------------------------------------
//======================================================================
// Demux code for Windows CE
//======================================================================
/*++
Module Name:
filter.h
Abstract:
This module contains the class declarations for the DirectShow
filter framework.
Revision History:
02-Jul-1999 created
--*/
#ifndef _mp2demux__filter_h
#define _mp2demux__filter_h
// declared/defined in main.cpp
extern AMOVIESETUP_FILTER g_sudTransportDemuxFilter ;
/*++
--*/
struct DEMUX_PIN_RECORD {
CBasePin * pDemuxPin ;
LONG m_cRefcount ;
PIN_DIRECTION PinDirection ;
LPWSTR pszPinID ;
#define GET_OUTPUT_PIN(pPinRecord) (pPinRecord -> PinDirection == PINDIR_OUTPUT ? static_cast (pPinRecord -> pDemuxPin) : NULL)
#define GET_INPUT_PIN(pPinRecord) (pPinRecord -> PinDirection == PINDIR_INPUT ? static_cast (pPinRecord -> pDemuxPin) : NULL)
DEMUX_PIN_RECORD (
IN CBasePin * inpDemuxPin,
IN LPWSTR inpszPinID,
IN PIN_DIRECTION inPinDirection,
OUT HRESULT * phr
) : pDemuxPin (inpDemuxPin),
m_cRefcount (1),
PinDirection (inPinDirection),
pszPinID (NULL)
{
TRACE_CONSTRUCTOR (TEXT ("DEMUX_PIN_RECORD")) ;
ASSERT (inpszPinID) ;
ASSERT (phr) ;
* phr = S_OK ;
// make a copy of the pin ID
pszPinID = new WCHAR [wcslen (inpszPinID) + 1] ;
if (pszPinID) {
wcscpy (pszPinID, inpszPinID) ;
}
else {
* phr = E_OUTOFMEMORY ;
}
ASSERT (pDemuxPin) ;
pDemuxPin -> GetOwner () -> AddRef () ;
}
~DEMUX_PIN_RECORD (
)
{
TRACE_DESTRUCTOR (TEXT ("DEMUX_PIN_RECORD")) ;
delete pszPinID ;
ASSERT (m_cRefcount == 0) ;
pDemuxPin -> GetOwner () -> Release () ;
}
// refcounting methods
ULONG
AddRef (
)
{
return InterlockedIncrement (& m_cRefcount) ;
}
ULONG
Release (
)
{
if (InterlockedDecrement (& m_cRefcount) == 0) {
delete this ;
return 0 ;
}
ASSERT (m_cRefcount > 0) ;
return m_cRefcount ;
}
// comparison method
static
int
__cdecl
Compare (
const void * pv1,
const void * pv2
)
{
ASSERT (pv1) ;
ASSERT (pv2) ;
return _wcsicmp (
(* (DEMUX_PIN_RECORD **) pv1) -> pszPinID,
(* (DEMUX_PIN_RECORD **) pv2) -> pszPinID
) ;
}
} ;
/*++
DirectShow interfaces to the MPEG2 demux
--*/
class CDShowMPEG2Demux :
public IMpeg2Demultiplexer,
public ISpecifyPropertyPages,
public IMpeg2DemultiplexerTesting // used by testing
{
CMPEG2Demultiplexer * m_pMPEG2Demux ;
ULONG m_NewPinID ; // increments through the life of the object
public :
CDShowMPEG2Demux (
IN CMPEG2Demultiplexer * punk // controlling unknown, always the filter
) ;
~CDShowMPEG2Demux (
) ;
// IUnknown
STDMETHODIMP
QueryInterface (
IN REFIID riid,
OUT void ** ppv
) ;
STDMETHODIMP_(ULONG)
AddRef (
) ;
STDMETHODIMP_(ULONG)
Release (
) ;
// ISpecifyPropertyPages --------------------------------------------
STDMETHODIMP
GetPages (
CAUUID * pPages
) ;
// -------------------------------------------------------------------
// see stubs.cpp for entry points
DECLARE_IPMEG2DEMULTIPLEXERTESTING () ;
// -------------------------------------------------------------------
// IMpeg2Demultiplexer
virtual STDMETHODIMP CreateOutputPin (AM_MEDIA_TYPE *, LPWSTR, IPin **) ;
virtual STDMETHODIMP SetOutputPinMediaType (LPWSTR, AM_MEDIA_TYPE *) ;
virtual STDMETHODIMP DeleteOutputPin (LPWSTR) ;
} ;
class CIInputStreamEvent
{
public :
virtual
HRESULT
InputStreamDiscontinuity (
) = 0 ;
} ;
/*++
CMPEG2Demultiplexer
--*/
class CMPEG2Demultiplexer :
public CBaseFilter,
public CPersistStream,
public IAMFilterMiscFlags,
public CIInputStreamEvent
{
friend class CMpeg2StreamAnalyzer ;
friend class CMPEG2DemuxInputPin ;
friend class CMPEG2DemuxOutputPin ;
friend class CDShowMPEG2Demux ;
// ------------------------------------------------------------------------
// persist methods
HRESULT
PersistOutputPin_ (
IN IStream *,
IN DEMUX_PIN_RECORD *
) ;
HRESULT
RestoreOutputPin_ (
IN IStream *,
OUT DEMUX_PIN_RECORD **
) ;
HRESULT
PersistPinPIDMaps_ (
IN IStream *,
IN DEMUX_PIN_RECORD *
) ;
HRESULT
RestorePinPIDMaps_ (
IN IStream *,
IN DEMUX_PIN_RECORD *
) ;
HRESULT
PersistPinStreamIdMaps_ (
IN IStream *,
IN DEMUX_PIN_RECORD *
) ;
HRESULT
RestorePinStreamIdMaps_ (
IN IStream *,
IN DEMUX_PIN_RECORD *
) ;
// creates a pin of the specified direction;
// optionally returns a refcounted DEMUX_PIN_RECORD;
// fails if a pin of the specified ID already exists
HRESULT
CreatePin_ (
IN LPWSTR pszPinID,
IN PIN_DIRECTION PinDirection,
IN AM_MEDIA_TYPE * pMediaType,
IN LONG lOutputPinBatchSize,
IN BOOL fOutputPinBatchExact,
IN DWORD dwOutputPinMediaSampleLen,
IN DWORD dwOutputPinMediaSamplePool,
OUT DEMUX_PIN_RECORD ** ppPinRecord
) ;
// creates an output pin specifically
HRESULT
CreateOutputPin_ (
IN LPWSTR pszPinID,
IN AM_MEDIA_TYPE * pMediaType,
OUT DEMUX_PIN_RECORD ** ppPinRecord = NULL
)
{
return CreatePin_ (
pszPinID,
PINDIR_OUTPUT,
pMediaType,
DEFAULT_SEND_BATCH_SIZE,
DEFAULT_SEND_BATCH_EXACT,
DEFAULT_OUTPUT_PIN_BUFFER_MAX,
DEFAULT_OUTPUT_PIN_BUFFER_POOL,
ppPinRecord
) ;
}
// always creates a very specific input pin; assumes
// the input pin does not yet exist -- ASSERTs to be exact
HRESULT
CreateInputPinLocked_ (
) ;
// deletes the specified pin; fails only if the pin exists
// and could not be deleted
HRESULT
DeletePin_ (
IN LPWSTR pszPinID
) ;
HRESULT
DeleteAllOutputPins_ (
) ;
// returns a refcounted DEMUX_PIN_RECORD; pin vector lock must
// be held when making the call
HRESULT
FindPinRecordLocked_ (
IN LPWSTR pszPinID,
OUT DEMUX_PIN_RECORD ** ppPinRecord,
OUT DWORD * pdwIndex = NULL
) ;
// creates a PID map for the specified parameters
HRESULT
CreateStreamMap_ (
IN DWORD cPID,
IN DWORD * pdwPID,
IN LPWSTR pszPinID,
IN DWORD dwMediaSampleContent,
IN DWORD dwStreamMask,
IN LPVOID pvParserArg = NULL
) ;
// deletes a PID map for the specified parameters
HRESULT
DeleteStreamMap_ (
IN DWORD cPID,
IN DWORD * pdwPID,
IN LPWSTR pszPinID,
IN DWORD dwStreamMask
) ;
// updates a pin's media type; negotiates with connected pin, etc...
HRESULT
SetPinMediaTypeLocked_ (
IN CBasePin * pIPin,
IN AM_MEDIA_TYPE * pNewMediaType
) ;
// resets the internal state of the demux - calls the controller's reset
HRESULT
Reset_ (
) ;
// resets the appropriate controller
HRESULT
ResetController_ (
) ;
// creates the PID map; caller must make sure the pin still exists in the
// filter's vector after the call returns i.e. there is no locking of
// the vector in this call
HRESULT
MapStreamToPinLocked_ (
IN ULONG cStream,
IN ULONG * pulStream,
IN ULONG ulMask,
IN CMPEG2DemuxOutputPin * pDemuxOutputPin,
IN DWORD dwMediaSampleContent,
IN LPVOID pvParserArg
) ;
// deletes the PID map;
HRESULT
UnmapStreamFromPinLocked_ (
IN ULONG cStream,
IN ULONG * pulStream,
IN ULONG ulMask,
IN CMPEG2DemuxOutputPin * pDemuxOutputPin
) ;
// ------------------------------------------------------------------------
// demux type
HRESULT
LoadMpeg2Transport_ (
) ;
HRESULT
LoadMpeg2Program_ (
) ;
// ------------------------------------------------------------------------
// properties
CMPEG2DemuxInputPin * m_pInputPin ;
CDShowMPEG2Demux * m_pDShowDemuxInterfaces ;
TSimpleVector m_Pins ;
CMpeg2Stats * m_pStats ;
HKEY m_hkeyRoot ;
CMPEG2PushClock * m_pMPEG2PushClock ;
BOOL m_fImplementPushClock ;
CRITICAL_SECTION m_csReceive ;
CMPEG2Controller * m_pMPEG2Controller ;
CMpeg2DemuxMediaSeekingCore * m_pSeekingCore ;
CRefCountedCritSec * m_pcrtSeekingLock ;
BOOL m_fCheckCanOperateInPullMode ; // registry configurable
public :
// constructor / destructor -----------------------------------------
CMPEG2Demultiplexer (
IN TCHAR * pClassName,
IN IUnknown * pIUnknown,
IN REFCLSID rclsid,
OUT HRESULT * pHr
) ;
~CMPEG2Demultiplexer (
) ;
// CBaseFilter overrides --------------------------------------------
LPAMOVIESETUP_FILTER
GetSetupData (
void
)
{
return & g_sudTransportDemuxFilter ;
}
int
GetPinCount (
void
) ;
CBasePin *
GetPin (
IN int Index
) ;
STDMETHODIMP
Pause (
) ;
STDMETHODIMP
Stop (
) ;
STDMETHODIMP
Run (
IN REFERENCE_TIME tStart
) ;
// Support can't cue; if we don't return VFW_S_CANT_CUE from
// the paused state, the filter graph never gets to run
STDMETHODIMP
GetState (
IN DWORD dwMSecs,
IN FILTER_STATE * pfs
)
{
CheckPointer (pfs, E_POINTER) ;
CAutoLock lck(m_pLock) ;
*pfs = m_State;
if (m_State == State_Paused) {
return VFW_S_CANT_CUE;
} else {
return S_OK;
}
}
// called by the DirectShow class factory code when the object
// is instantiated via CoCreateInstance call
static
CUnknown *
WINAPI
CreateInstance (
IN IUnknown * pIUnknown,
IN HRESULT * pHr
) ;
// IUnknown ---------------------------------------------------------
DECLARE_IUNKNOWN ;
STDMETHODIMP
NonDelegatingQueryInterface (
IN REFIID riid,
OUT void ** ppv
) ;
// CPersistStream ---------------------------------------------------
HRESULT
WriteToStream (
IN IStream * pIStream
) ;
HRESULT
ReadFromStream (
IN IStream * pIStream
) ;
int
SizeMax (
)
{
return 100 ;
}
STDMETHODIMP
GetClassID (
OUT CLSID * pCLSID
) ;
// class methods ----------------------------------------------------
// must hold the receiver lock
HRESULT
ProcessMediaSampleLocked (
IN IMediaSample * pIMediaSample
) ;
// must hold the receiver & filter locks
HRESULT
EndOfStreamLocked (
) ;
// must hold the receiver & filter locks
HRESULT
BeginFlushLocked (
) ;
// must hold the receiver & filter locks
HRESULT
EndFlushLocked (
) ;
STDMETHODIMP
SetSyncSource (
IN IReferenceClock *
) ;
BOOL ImplementPushClock () { return ((m_fImplementPushClock &&
m_pMPEG2PushClock &&
!IsInPullMode ()) ? TRUE : FALSE) ; }
BOOL IsInPullMode () ;
BOOL
CanOperateInPullMode (
) ;
HRESULT
InitPullModeStream (
IN IAsyncReader * pIAsyncReader
) ;
HRESULT
BreakConnectInput (
) ;
CMPEG2DemuxInputPin * GetInputPin () { return m_pInputPin ; }
BOOL
IsSeekable (
) ;
BOOL
IsSeekingPin (
IN CMPEG2DemuxOutputPin *
) ;
void SetTotalFileLength (IN LONGLONG ) ;
LONGLONG GetTotalFileLength () ;
void SetTotalFileDuration (IN REFERENCE_TIME ) ;
REFERENCE_TIME GetTotalFileDuration () ;
void SetPlaybackRate (IN double ) ;
// --------------------------------------------------------------------
BOOL IsStopped () { return (m_State == State_Stopped ? TRUE : FALSE) ; }
// --------------------------------------------------------------------
void LockReceive () { EnterCriticalSection (& m_csReceive) ; }
void UnlockReceive () { LeaveCriticalSection (& m_csReceive) ; }
void LockFilter () { m_pLock -> Lock () ; }
void UnlockFilter () { m_pLock -> Unlock () ; }
// ====================================================================
// CIInputStreamEvent
virtual
HRESULT
InputStreamDiscontinuity (
) ;
// -------------------------------------------------------------------
// IAMFilterMiscFlags method
STDMETHODIMP_(ULONG)
GetMiscFlags (
)
{
// we must implement this interface and return this value if we
// want to be selected as graph clock
return AM_FILTER_MISC_FLAGS_IS_SOURCE ;
}
// -------------------------------------------------------------------
// lazy load
HRESULT
SetStreamType (
IN DWORD Mpeg2StreamType
) ;
DWORD
GetStreamType (
) ;
// -------------------------------------------------------------------
// stride support
void
SetStrideLengths (
IN int iPreStrideLength,
IN int iPostStrideLength
) ;
} ;
#endif // _mp2demux__filter_h