/*++ Copyright (c) 2001 Microsoft Corporation Module Name: DTFilter.h Abstract: This module contains the Encrypter/Tagger filter declarations Author: John Bradstreet (johnbrad) Revision History: 07-Mar-2002 created --*/ #ifndef __EncDec__DTFilter_h #define __EncDec__DTFilter_h #include // needed for IBroadcastEvent #include #include #include #include // EVENTID_TuningChanged, XDS_RatingsPacket #include "DTFilter_res.h" #include "PackTvRat.h" // packed TvRating definitions #include "MediaSampleAttr.h" // from the IDL file //#include "MediaAttrib.h" // IMediaSampleAttrGet/Set definitions, CAttributedMediaSample #include "..\Attrib\MediaAttrib.h" // IMediaSampleAttrGet/Set definitions, CAttributedMediaSample #include "AttrBlock.h" // attributed block definitions #include "DRMEncDec.h" // drm encryption/decryption definitions... #include "DRMSecure.h" // IDRMSecureChannel #if 1 #include "rateseg.h" // before integration - I stole the code #else #include "dvrutil.h" // when we eventually integrate #endif #define DT_FILTER_NAME "Decrypt/DeTag" #define DT_INPIN_NAME "In(Enc/Tag)" #define DT_OUTPIN_NAME "Out" extern AMOVIESETUP_FILTER g_sudDTFilter; // forward declarations class CDTFilter; class CDTFilterInput; class CDTFilterOutput; // -------------------------------------------------------------------- // class CDTFilterInput // -------------------------------------------------------------------- class CDTFilterInput : public IKsPropertySet, public CBaseInputPin { private: CDTFilter * m_pHostDTFilter ; CCritSec m_StreamingLock; DECLARE_IUNKNOWN; // needed when have IKsPropertySet public : CDTFilterInput ( IN TCHAR * pszPinName, IN CDTFilter * pDTFilter, IN CCritSec * pFilterLock, // NULL or a passed in lock OUT HRESULT * phr ) ; ~CDTFilterInput ();; STDMETHODIMP NonDelegatingQueryInterface ( IN REFIID riid, OUT void ** ppv ) ; // -------------------------------------------------------------------- // CBasePin methods HRESULT CheckMediaType ( IN const CMediaType * ) ; HRESULT CompleteConnect ( IN IPin * pIPin ) ; HRESULT BreakConnect ( ) ; // -------------------------------------------------------------------- // CBaseInputPin methods STDMETHODIMP Receive ( IN IMediaSample * pIMediaSample ) ; STDMETHODIMP BeginFlush ( ) ; STDMETHODIMP EndFlush ( ) ; STDMETHODIMP EndOfStream ( ); // -------------------------------------------------------------------- // IKSPropertySet methods (Forward all calls to the output pin) STDMETHODIMP Set( IN REFGUID guidPropSet, IN DWORD dwPropID, IN LPVOID pInstanceData, IN DWORD cbInstanceData, IN LPVOID pPropData, IN DWORD cbPropData ); STDMETHODIMP Get( IN REFGUID guidPropSet, IN DWORD dwPropID, IN LPVOID pInstanceData, IN DWORD cbInstanceData, OUT LPVOID pPropData, IN DWORD cbPropData, OUT DWORD *pcbReturned ); STDMETHODIMP QuerySupported( IN REFGUID guidPropSet, IN DWORD dwPropID, OUT DWORD *pTypeSupport ); // -------------------------------------------------------------------- // class methods HRESULT StreamingLock ( ); HRESULT StreamingUnlock ( ); HRESULT SetAllocatorProperties ( IN ALLOCATOR_PROPERTIES * ppropInputRequest ) ; HRESULT GetRefdConnectionAllocator ( OUT IMemAllocator ** ppAlloc ) ; } ; // -------------------------------------------------------------------- // class CDTFilterOutput // -------------------------------------------------------------------- class CDTFilterOutput : public CBaseOutputPin { CDTFilter * m_pHostDTFilter ; // void FilterLock_ () { m_pLock -> Lock () ; } // void FilterUnlock_ () { m_pLock -> Unlock () ; } public : CDTFilterOutput ( IN TCHAR * pszPinName, IN CDTFilter * pDTFilter, IN CCritSec * pFilterLock, OUT HRESULT * phr ) ; ~CDTFilterOutput ( ); DECLARE_IUNKNOWN ; HRESULT SendSample ( IN IMediaSample * pIMS ) ; STDMETHODIMP NonDelegatingQueryInterface ( IN REFIID riid, OUT void ** ppv ) ; // -------------------------------------------------------------------- // CBasePin methods HRESULT DecideBufferSize ( IN IMemAllocator * pAlloc, IN ALLOCATOR_PROPERTIES * ppropInputRequest ) ; HRESULT GetMediaType ( IN int iPosition, OUT CMediaType * pmt ) ; HRESULT CheckMediaType ( IN const CMediaType * ) ; HRESULT CompleteConnect ( IN IPin * pIPin ) ; HRESULT BreakConnect ( ) ; HRESULT DecideAllocator ( IN IMemInputPin * pPin, IN IMemAllocator ** ppAlloc ) ; STDMETHOD(Notify) ( IBaseFilter *pSender, Quality q ); // Class methods /* HRESULT SendLock ( ); HRESULT SendUnlock ( ); */ // IKSPropertySet forwarding methods.... HRESULT IsInterfaceOnPinConnectedTo_Supported( IN REFIID riid ); HRESULT KSPropSetFwd_Set( IN REFGUID guidPropSet, IN DWORD dwPropID, IN LPVOID pInstanceData, IN DWORD cbInstanceData, IN LPVOID pPropData, IN DWORD cbPropData ); HRESULT KSPropSetFwd_Get( IN REFGUID guidPropSet, IN DWORD dwPropID, IN LPVOID pInstanceData, IN DWORD cbInstanceData, OUT LPVOID pPropData, IN DWORD cbPropData, OUT DWORD *pcbReturned ); HRESULT KSPropSetFwd_QuerySupported( IN REFGUID guidPropSet, IN DWORD dwPropID, OUT DWORD *pTypeSupport ); } ; // -------------------------------------------------------------------- // class CDTFilter // -------------------------------------------------------------------- class CDTFilter : public CBaseFilter, // dshow base class public ISpecifyPropertyPages, public IDTFilter, public IDTFilterConfig, public IBroadcastEvent { friend CDTFilterInput; // so input pin can call FlushDropQueue on BeginFlush() CDTFilterInput * m_pInputPin ; CDTFilterOutput * m_pOutputPin ; CCritSec m_CritSecDropQueue; CCritSec m_CritSecAdviseTime; BOOL CompareConnectionMediaType_ ( IN const AM_MEDIA_TYPE * pmt, IN CBasePin * pPin ) ; BOOL CheckInputMediaType_ ( IN const AM_MEDIA_TYPE * pmt ) ; BOOL CheckOutputMediaType_ ( IN const AM_MEDIA_TYPE * pmt ) ; public : CDTFilter ( IN TCHAR * pszFilterName, IN IUnknown * punkControlling, IN REFCLSID rCLSID, OUT HRESULT * phr ) ; ~CDTFilter () ; static CUnknown * CreateInstance ( IN IUnknown * punk, OUT HRESULT * phr ) ; static void CALLBACK // used to create a global crit sec InitInstance ( IN BOOL bLoading, IN const CLSID *rclsid ); STDMETHODIMP NonDelegatingQueryInterface ( IN REFIID riid, OUT void ** ppv ) ; DECLARE_IUNKNOWN ; // ===================================================================== // Worker Methods // tell folk we got something... HRESULT FireBroadcastEvent(IN const GUID &eventID); HRESULT ProposeNewOutputMediaType ( IN CMediaType * pmt, OUT CMediaType * pmtOut ); HRESULT BindDRMLicense( IN LONG cbKID, IN BYTE * pbKID ); HRESULT UnBindDRMLicenses( ); // ===================================================================== // IDTFilter STDMETHODIMP get_EvalRatObjOK( OUT HRESULT *pHrCoCreateRetVal ); STDMETHOD(GetCurrRating)( OUT EnTvRat_System *pEnSystem, OUT EnTvRat_GenericLevel *pEnRating, OUT LONG *plbfEnAttr //BfEnTvRat_GenericAttributes ); STDMETHOD(get_BlockedRatingAttributes)( IN EnTvRat_System enSystem, IN EnTvRat_GenericLevel enLevel, OUT LONG *plbfEnAttr // BfEnTvRat_GenericAttributes ); STDMETHOD(put_BlockedRatingAttributes)( IN EnTvRat_System enSystem, IN EnTvRat_GenericLevel enLevel, IN LONG lbfEnAttrs // BfEnTvRat_GenericAttributes ); STDMETHOD(get_BlockUnRated)( OUT BOOL *pmfBlockUnRatedShows ); STDMETHOD(put_BlockUnRated)( IN BOOL fBlockUnRatedShows ); STDMETHOD(get_BlockUnRatedDelay)( OUT LONG *pmsecsDelayBeforeBlock ); STDMETHOD(put_BlockUnRatedDelay)( IN LONG msecsDelayBeforeBlock ); HRESULT // helper non interface method - returns S_FALSE if cahgned SetCurrRating( IN EnTvRat_System enSystem, IN EnTvRat_GenericLevel enRating, IN LONG lbfEnAttr ); // ==================================================================== // IDTFilterConfig STDMETHOD(GetSecureChannelObject)( OUT IUnknown **ppUnkDRMSecureChannel // an IDRMSecureChannel ) { if(NULL == ppUnkDRMSecureChannel) return E_POINTER; #ifdef BUILD_WITH_DRM *ppUnkDRMSecureChannel = NULL; if(m_spDRMSecureChannel == NULL) return E_NOINTERFACE; return m_spDRMSecureChannel->QueryInterface(IID_IUnknown, (void**)ppUnkDRMSecureChannel); #else return E_NOINTERFACE; // not supported.. #endif } // ==================================================================== // CFilterBase virtual methods in base class int GetPinCount ( ) ; CBasePin * GetPin ( IN int ) ; STDMETHOD(JoinFilterGraph) ( IFilterGraph *pGraph, LPCWSTR pName ); STDMETHOD(Stop) ( ) ; STDMETHOD(Pause) ( ) ; STDMETHOD(Run) ( REFERENCE_TIME tStart ); // ==================================================================== // class methods HRESULT DeliverBeginFlush ( ) ; HRESULT DeliverEndFlush ( ) ; HRESULT DeliverEndOfStream( ); BOOL CheckDecrypterMediaType ( IN PIN_DIRECTION, // caller IN const CMediaType * ) ; HRESULT Process ( IN IMediaSample * ) ; HRESULT OnCompleteConnect ( IN PIN_DIRECTION // caller ) ; HRESULT OnBreakConnect ( IN PIN_DIRECTION // caller ) ; HRESULT UpdateAllocatorProperties ( IN ALLOCATOR_PROPERTIES * ) ; HRESULT OnOutputGetMediaType ( OUT CMediaType * pmt ) ; HRESULT GetRefdInputAllocator ( OUT IMemAllocator ** ) ; // ISpecifyPropertyPages -------------------------------------------- STDMETHODIMP GetPages ( CAUUID * pPages ) ; // IKSPropertySet forwarding from the input pin to the output pin (or visa versa) HRESULT IsInterfaceOnPinConnectedTo_Supported( IN PIN_DIRECTION PinDir, // either PINDIR_INPUT of PINDIR_OUTPUT IN REFIID riid ); HRESULT KSPropSetFwd_Set( IN PIN_DIRECTION PinDir, IN REFGUID guidPropSet, IN DWORD dwPropID, IN LPVOID pInstanceData, IN DWORD cbInstanceData, IN LPVOID pPropData, IN DWORD cbPropData ); HRESULT KSPropSetFwd_Get( IN PIN_DIRECTION PinDir, IN REFGUID guidPropSet, IN DWORD dwPropID, IN LPVOID pInstanceData, IN DWORD cbInstanceData, OUT LPVOID pPropData, IN DWORD cbPropData, OUT DWORD *pcbReturned ); HRESULT KSPropSetFwd_QuerySupported( IN PIN_DIRECTION PinDir, IN REFGUID guidPropSet, IN DWORD dwPropID, OUT DWORD *pTypeSupport ); // IBroadcastEvent STDMETHOD(Fire)(GUID eventID); // this comes from the Graph's events - call our own method private: // global filter CritSec (to keep multiple instances of this filter from colliding) static CCritSec *m_pCritSectGlobalFilt; // ***always*** inside the FilterLock (m_pLock) static LONG m_gFilterID; // used to distinqish instances from each other... LONG m_FilterID; // actual one for this filter // graph broadcast events HRESULT HookupGraphEventService(); HRESULT UnhookGraphEventService(); CComPtr m_spBCastEvents; HRESULT RegisterForBroadcastEvents(); HRESULT UnRegisterForBroadcastEvents(); enum {kBadCookie = -1}; DWORD m_dwBroadcastEventsCookie; BOOL m_fFireEvents; // set to false to avoid firing (duplicate) events // current rating CComPtr m_spEvalRat; HRESULT m_hrEvalRatCoCreateRetValue; BOOL m_fRatingsValid; // have they been set yet? EnTvRat_System m_EnSystemCurr; EnTvRat_GenericLevel m_EnLevelCurr; LONG m_lbfEnAttrCurr; // bitfield of BfEnTvRat_GenericAttributes CComPtr m_spTuner; //CComQIPtr m_spVidTuner; // block delay BOOL m_fHaltedDelivery; // halting delivery LONG m_milsecsDelayBeforeBlock; // delay time before blocking in micro-secs BOOL m_fDoingDelayBeforeBlock; BOOL m_fRunningInSlowMo; // set to true to turn of delay in starting the Ratings block REFERENCE_TIME m_refTimeToStartBlock; BOOL m_fForceNoRatBlocks; // special flag (SUPPORT_REGISTRY_KEY_TO_TURN_OFF_RATINGS) to avoid blocks BOOL m_fDataFormatHasBeenBad; // set when get bad data (toggle for ok/failure event pair) // LONG m_milsecsNoRatingsBeforeUnrated; // delay time before no ratings count as don't know REFERENCE_TIME m_refTimeFreshRating; // get ClockTime for last 'fresh' rating enum {kMax10kSpeedToCountAsSlowMo = 9001}; // abs(speed)* 10,000 to count as slow motion for delayed block REFERENCE_TIME m_refTimeLastEvent; GUID m_lastEventID; enum {kMaxMSecsBetweenEvents = 10*1000}; // max time between ratings events (in 10^-3 secs) HRESULT PossiblyUpdateBroadcastEvent(); // media sample attributes CAttrSubBlock_List m_attrSB; // DRM BOOL m_3fDRMLicenseFailure; // 3 state logic (unitialized, true, and false) #ifdef BUILD_WITH_DRM CDRMLite m_cDRMLite; BYTE* m_pszKID; // only used to see if it changed and need to ReBind LONG m_cbKID; CComPtr m_spDRMSecureChannel; // authenticator... #endif HRESULT CheckIfSecureServer(IFilterGraph *pGraph=NULL); // return S_OK only if trust the server registered in the graph service provider HRESULT InitializeAsSecureClient(); #ifdef FILTERS_CAN_CREATE_THEIR_OWN_TRUST HRESULT RegisterSecureServer(IFilterGraph *pGraph=NULL); // return S_OK only if trust the server registered in the graph service provider HRESULT CheckIfSecureClient(IUnknown *pUnk); // prototype for VidControl method to see if it trusts the filter #endif // Restarting the upstream delivery HRESULT OnRestartDelivery(IMediaSample *pSample); // Rate Segment enum {kMaxRateSegments = 32}; enum {kSecsPurgeThreshold = 5 }; CTTimestampRate m_PTSRate ; // stopping and flushing HRESULT DoEndOfStreamDuringDrop(); BOOL m_fCompleteNotified; // DropQueue (circular buffer) HRESULT CreateDropQueueThread(); HRESULT KillDropQueueThread(); DWORD m_dwDropQueueThreadId; // Thread used to queue up/process dropped packets HANDLE m_hDropQueueThread; // Thread used to queue up/process dropped packets HANDLE m_hDropQueueThreadAliveEvent; // Signal from thread that its ready HANDLE m_hDropQueueThreadDieEvent; // Signal from thread that its ready HANDLE m_hDropQueueEmptySemaphore; // Waited on in DropQueue, inits to zero, goes when non-zero HANDLE m_hDropQueueFullSemaphore; // Waited on in Main Thread, inits to N, stops when goes to zero HANDLE m_hDropQueueAdviseTimeEvent; // Wait until some time passes DWORD m_dwDropQueueEventCookie; // cookie for the TimeEvent // and a new sample HRESULT AddSampleToDropQueue(IMediaSample *pSample); // add the top sample void AddMaxSampleToDropQueue(IMediaSample *pSample); // remove the bottom sample void DropMinSampleFromDropQueue(); // return the oldest version IMediaSample * GetMinDropQueueSample(); // flush all samples (when pause or stop) HRESULT FlushDropQueue(); // drop samples from drop queue static void DropQueueThreadProc (CDTFilter *pcontext); HRESULT DropQueueThreadBody(); enum {kMaxQueuePackets = 10}; // maximum number of packets to queue up IMediaSample * m_rgMedSampDropQueue[kMaxQueuePackets]; int m_cDropQueueMin; // first sample filled int m_cDropQueueMax; // next sample we will fill // minimal stats void InitStats() { CAutoLock cLock(m_pLock); m_cPackets = 0; m_clBytesTotal = 0; m_cSampsDropped = 0; m_cSampsDroppedOverflowed = 0; m_cBlockedWhileDroppingASample = 0; m_cRestarts++; } LONG m_cPackets; // total stamples processed LONG64 m_clBytesTotal; // total number of bytes processed LONG m_cSampsDropped; // total dropped LONG m_cBlockedWhileDroppingASample; // total times paused due to DropQueue thread being full LONG m_cSampsDroppedOverflowed; // total dropped and didn't time out (should be zero) LONG m_cRestarts; // total number of reinits Timeit m_tiAuthenticate; // time in authentication methods Timeit m_tiProcess; // total ::process time Timeit m_tiProcessIn; // total ::process time minus the final 'SendSample' Timeit m_tiProcessDRM; // :process time of just the DRM code Timeit m_tiRun; // total run time Timeit m_tiStartup; // creating the license and similar startup Timeit m_tiTeardown; // closing things down } ; #endif // __EncDec__DTFilter_h