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