//------------------------------------------------------------------------------ // // 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: tsstats.h Abstract: This module contains the struct and shared memory information that the demux uses for writing transport stream statistics Revision History: 07-Oct-1999 created 19-Apr-2000 added push clock stats Notes: These stats are more counters than statistics, but the goal is to make the counter available so other apps can manipulate the figures and obtain the data that they need. For example, there's no bitrate counter but an app can easily implement such a stat by computing the packet delta between successive reads and dividing by the time delta. How to obtain stats The design goal here to is to provide a way for 3rd parties to write stat apps that would not be intrusive to the operation of the demux. Providing stats via a callback interface leaves the operation of the demux at the mercy of the callback code. Instead, we create/open a shared memory mapping that is available cross-process. The structures that the demux writes to are made available, along with the memory map name, and any 3rd party app can read the data, reset it, manipulate it as they need. More than 1 such app can operate on a single host because the memory mapped file is available to any process that opens it. Dropped Packets There's a slight discrepency in the dropped packets. What the demux code does not accomodate for is the count of dropped packets in aborted media samples. So if 10 packets have been accumulated in a media sample and the 11th is found to be discontinuous, and the media sample is aborted, those 10 will not be counted in the cummulative total. When implementing the stats, I made them as unintrusive as possible. Instead, there's an aborted media sample counter, which implies more dropped packets. And I added an aborted bytes counter that counts the lost bytes due to aborted media samples. Statistics Types There are 2 varieties of stats: (1) global, (2) global and per PID. The difference between them is size of the mapped memory. Performance wise, there should be little difference, aside from the memory access times. --*/ #ifndef __mp2demux_tsstats_h #define __mp2demux_tsstats_h // ---------------------------------------------------------------------------- // ---------------------------------------------------------------------------- // statistics apps need this information BEGIN // ---------------------------------------------------------------------------- // version #define MPEG2_STATS_VERSION_MAJOR 1 #define MPEG2_STATS_VERSION_MINOR 2 #define MPEG2_STATS_VERSION(major,minor) ((((ULONGLONG) (major)) << 32) | (minor)) #define MPEG2_STATS_GET_MAJOR_VERSION(ull) ((DWORD) ((ull) >> 32)) #define MPEG2_STATS_GET_MINOR_VERSION(ull) ((DWORD) (ull)) // version history // 1.0 dx8 release // 1.1 added versioning information // ---------------------------------------------------------------------------- // names of the file mapping object #define MPEG2_TRANSPORT_STATS_NAME TEXT ("MPEG2_DEMULTIPLEXER_STATS_TRANSPORT") #define MPEG2_PROGRAM_STATS_NAME TEXT ("MPEG2_DEMULTIPLEXER_STATS_PROGRAM") // ---------------------------------------------------------------------------- // global /*++ fDemuxIsIRefClock TRUE if the demux is the graph clock dPerPCRObservedSlope each time we process a PCR we compute the PCR/QPC slope; this is that value dIRefClockUsedSlope this value should slowly converge on the above llUpwardAdjustments number of upward adjustments made as dIRefClockUsedSlope converges on dPerPCRObservedSlope; triggered when dIRefClockUsedSlope is > dPerPCRObservedSlope + allowable error llDownwardAdjustments number of downward adjustments made as dIRefClockUsedSlope converges on dPerPCRObservedSlope; triggered when dIRefClockUsedSlope is < dPerPCRObservedSlope - allowable error llAllowableErrorDegradations number of times no correction was made and the allowable error was degraded --*/ struct MPEG2_CLOCK_SUBORDINATE_STATS { ULONGLONG cQueuedAdvises : 24, cSignaledAdvises : 24, cStaleAdvises : 16 ; ULONGLONG cInboundsBrackets : 16, cOutofBoundsBrackets: 16, cQueueLength : 8, fSubordinating : 1, Reserved1 : 15 ; REFERENCE_TIME rtTargetShift ; REFERENCE_TIME rtCurShift ; double dScalingVal ; double dLastBracketScalingVal ; // old members are listed below; we keep the struct the same size so // the other counters all still work /* BOOL fDemuxIsIRefClock ; // TRUE: demux is the graph clock double dPerPCRObservedSlope ; // per PCR measured PCR/QPC slope double dIRefClockUsedSlope ; // PCR/QPC slope that is being used to generate the clock double dCarry ; // ::GetTime () carry value LONGLONG llUpwardAdjustments ; // upward adjustments LONGLONG llDownwardAdjustments ; // downward adjustments LONGLONG llAllowableErrorDegradations ; // no correction results in a degradation */ } ; /*++ llLastPCR last PCR processed llAudioPESPTS last audio PES PTS llVideoPESPTS last video PES PTS llBasePCR baseline PCR cPTS_PCROutOfBoundsDelta number of PTSs that were out of tolerance with the current PCR stream --*/ struct MPEG2_TIMESTAMP_STATS { ULONGLONG BufferingMillis : 48, cBufferAdjustments : 16 ; LONGLONG llBasePCR ; // base PCR -- timeline origin; stats value not scaled LONGLONG llLastPCR ; // last PCR (used) ULONGLONG cPCR ; // PCR count REFERENCE_TIME rtAudioStreamPTSBase ; // baseline time for audio LONGLONG llAudioPESPTS ; // last audio PES PTS (90khz) ULONGLONG cAudioPESPTS ; // audio PES PTS count LONGLONG llAudioPESPTS_PCR_Delta ; // PES_PTS - PCR (90khz) REFERENCE_TIME rtVideoStreamPTSBase ; // baseline time for video LONGLONG llVideoPESPTS ; // last video PES PTS (90khz) ULONGLONG cVideoPESPTS ; // video PES PTS count LONGLONG llVideoPESPTS_PCR_Delta ; // PES_PTS - PCR (90khz) ULONGLONG cPTS_PCROutOfBoundsDelta ; // count of PTS-PCR delta too big } ; /*++ cTimeDiscontinuities incremented whenever a time stamp or PCR value, carried in a mapped PID, exceeds the previously received value by more than is allowable in the h.222.0 specification; this counter is incremented by the objects that ensure timestamp streams increase monotonically --*/ struct MPEG2_TIME_STATS { ULONGLONG cTimeDiscontinuities ; // # of out-of-tolerance clock values MPEG2_CLOCK_SUBORDINATE_STATS ClockSubordinate ; MPEG2_TIMESTAMP_STATS TimeStamp ; } ; /*++ --*/ struct MPEG2_TRANSPORT_PSI_STATS { ULONGLONG cNewPATSectionsProcessed ; ULONGLONG cNewPMTSectionsProcessed ; ULONGLONG cPrograms ; } ; /*++ how each counter should be tallied: cGlobalPackets incremented for all packets, regardless of PID, existence of mapping, errors, etc... call this category [1] cGlobalMPEG2Errors incremented for all category [1] packets that have the transport_error_indicator bit set cGlobalNewPayloads incremented for all category [1] packets that have the payload_unit_start_indicator bit set cGlobalDiscontinuities incremented for all category [1] packets that have discontinuities cGlobalMappedPackets incremented for all packets that are mapped; should be <= cGlobalPackets; call this category [2] cGlobalDroppedPackets incremented whenever a category [2] packet is dropped for whatever reason - errors, waiting for a payload_unit_start_indicator bit, etc...; NOTE: this number is not incremented when a media sample containing a partially reassembled payload, is aborted cGlobalPSIPackets incremented whenever a category [2] packet is processed (not dropped) that is mapped to be carrying PSI cGlobalPESPackets incremented whenever a category [2] packet is processed (not dropped) that is mapped to be carrying PES cGlobalAbortedMediaSamples incremented whenever a media sample with >= 1 collected packets is aborted due to a content error cGlobalAbortedBytes incremented by the number of bytes carried in each aborted media sample; this counter was added so the number of transport packets dropped by this type of error could be estimated; such packets are not counted in the cGlobalDroppedPackets cGlobalInputMediaSamples incremented whenever a media sample is received by the input pin cGlobalOutputMediaSamples incremented whenever a media sample is queued for transmission downstream --*/ struct MPEG2_STATS_GLOBAL { ULONGLONG ullVersion ; // ull for alignment // high DWORD: major // low DWORD: minor // ------------------------------------------------------------------------ ULONGLONG cGlobalPackets ; // packets processed ULONGLONG cGlobalPESPackets ; // mapped packets that carry PES ULONGLONG cGlobalMPEG2Errors ; // packet errors ULONGLONG cGlobalNewPayloads ; // payloads ULONGLONG cGlobalDiscontinuities ; // packet discontinuities ULONGLONG cGlobalSyncPoints ; // sync points ULONGLONG cGlobalMappedPackets ; // mapped packets processed ULONGLONG cGlobalDroppedPackets ; // mapped packets dropped ULONGLONG cGlobalAbortedMediaSamples ; // media samples aborted due to errors ULONGLONG cGlobalAbortedBytes ; // bytes of aborted media sample payloads ULONGLONG cGlobalInputMediaSamples ; // media samples received ULONGLONG cGlobalOutputMediaSamples ; // media samples queued for transmission MPEG2_TIME_STATS TimeStats ; // all clock and timestamp stats } ; // ---------------------------------------------------------------------------- // transport specific /*++ how each per-PID counter should be tallied: cPIDPackets incremented whenever a packet of the specified PID is received; call this category [3] cPIDMPEG2Errors incremented for each category [3] packet with the transport_error_indicator bit set cPIDNewPayloads incremented for each category [3] packet that has the payload_unit_start_indicator bit set cPIDDiscontinuities incremented for each category [3] packet that has a discontinuity cPIDMappedPackets incremented for each packet of the specified PID, for which a mapping exists; call this category [4]; increment for _each_ mapping of the PID cPIDDroppedPackets incremented whenever a category [4] packet is dropped for whatever reason - errors, waiting for a payload_unit_start_indicator bit, etc...; increment for _each_ mapping of the PID, so if a PID is mapped to 2 pins, this will increment by 2 --*/ struct MPEG2_TRANSPORT_PID_STATS { ULONGLONG cPIDPackets ; // transport packets seen ULONGLONG cPIDMPEG2Errors ; // transport_error_indicator errors seen ULONGLONG cPIDNewPayloads ; // payload_unit_start_indicator bit set ULONGLONG cPIDDiscontinuities ; // per PID discontinuities ULONGLONG cPIDMappedPackets ; // mapped transport packets processed ULONGLONG cPIDDroppedPackets ; // mapped packets dropped due to errors } ; struct MPEG2_TRANSPORT_STATS { MPEG2_STATS_GLOBAL GlobalStats ; ULONGLONG cPSIPackets ; // mapped packets that carry PSI ULONGLONG cSyncByteSeeks ; // sync_byte seeks - means packets are not packed ULONGLONG cSpannedPacket ; // number of packets we've found that span MPEG2_TRANSPORT_PSI_STATS PSIStats ; MPEG2_TRANSPORT_PID_STATS PID [DISTINCT_PID_COUNT] ; } ; // ---------------------------------------------------------------------------- // program specific struct MPEG2_PER_STREAM_PROGRAM_STATS { ULONGLONG cStreamIdPackets ; ULONGLONG cStreamIdMapped ; ULONGLONG cStreamIdDropped ; ULONGLONG cBytesProcessed ; } ; struct MPEG2_PROGRAM_STATS { MPEG2_STATS_GLOBAL GlobalStats ; ULONGLONG cPackHeaders ; // pack headers seen ULONGLONG cSystemHeaders ; // system headers seen ULONGLONG cProgramStreamMaps ; // PS PMTs seen ULONGLONG cDirectoryPESPackets ; // PS Directories seen ULONGLONG cBytesProcessed ; // total bytes processed MPEG2_PER_STREAM_PROGRAM_STATS StreamId [DISTINCT_STREAM_ID_COUNT] ; } ; // statistics apps need this information END // --------------------------------------------------------------------------- // shared memory object class CMpeg2SharedMem { BYTE * m_pbShared ; DWORD m_dwSize ; HANDLE m_hMapping ; void Free_ ( ) ; HRESULT Create_ ( IN TCHAR * szName, IN DWORD dwSize ) ; public : CMpeg2SharedMem ( IN TCHAR * szName, IN DWORD dwSize, OUT HRESULT * phr ) ; virtual ~CMpeg2SharedMem ( ) ; BYTE * GetSharedMem () { return m_pbShared ; } DWORD GetSharedSize () { return m_dwSize ; } } ; // COM object that implements the transport stream stats interface class CMpeg2TransportStatsCOM : public IMpeg2TransportStatsRaw, private CMpeg2SharedMem { IUnknown * m_punkOwning ; public : CMpeg2TransportStatsCOM ( IN IUnknown * punkOwning, OUT HRESULT * phr ) : m_punkOwning (punkOwning), CMpeg2SharedMem (MPEG2_TRANSPORT_STATS_NAME, sizeof MPEG2_TRANSPORT_STATS, phr ) { ASSERT (m_punkOwning) ; } STDMETHODIMP_ (ULONG) AddRef () { return m_punkOwning -> AddRef () ; } STDMETHODIMP_ (ULONG) Release () { return m_punkOwning -> Release () ; } STDMETHODIMP QueryInterface (REFIID riid, void ** ppv) { return m_punkOwning -> QueryInterface (riid, ppv) ; } DECLARE_IPMEG2TRANSPORTSTATSRAW () ; } ; // COM object that implements the program stream stats interface class CMpeg2ProgramStatsCOM : public IMpeg2ProgramStatsRaw, private CMpeg2SharedMem { IUnknown * m_punkOwning ; public : CMpeg2ProgramStatsCOM ( IN IUnknown * punkOwning, OUT HRESULT * phr ) : m_punkOwning (punkOwning), CMpeg2SharedMem (MPEG2_PROGRAM_STATS_NAME, sizeof MPEG2_PROGRAM_STATS, phr ) { ASSERT (m_punkOwning) ; } STDMETHODIMP_ (ULONG) AddRef () { return m_punkOwning -> AddRef () ; } STDMETHODIMP_ (ULONG) Release () { return m_punkOwning -> Release () ; } STDMETHODIMP QueryInterface (REFIID riid, void ** ppv) { return m_punkOwning -> QueryInterface (riid, ppv) ; } DECLARE_IPMEG2PROGRAMSTATSRAW () ; } ; // COM-based host for the stream specific COM interfaces class CMpeg2StatsCOM : public CUnknown { CMpeg2TransportStatsCOM * m_pTransportStatsCOM ; CMpeg2ProgramStatsCOM * m_pProgramStatsCOM ; public : CMpeg2StatsCOM ( IN IUnknown * pIUnknown ) ; ~CMpeg2StatsCOM ( ) ; DECLARE_IUNKNOWN ; STDMETHODIMP NonDelegatingQueryInterface ( IN REFIID riid, OUT void ** ppv ) ; // class factory static CUnknown * WINAPI CreateInstance ( IN IUnknown * pIUnknown, IN HRESULT * pHr ) ; } ; class CMpeg2Stats /*++ refcounted stats class - used throughout the demux by various other refcounted objects, so we need to have it live/die by refcounts. --*/ { MPEG2_STATS_GLOBAL * m_pStats ; MPEG2_TRANSPORT_STATS * m_pTransportStats ; MPEG2_PROGRAM_STATS * m_pProgramStats ; DWORD m_Mpeg2StreamType ; DWORD m_dwSize ; LONG m_cRef ; HANDLE m_hMapping ; BYTE m_ExpectedContinuityCounter [DISTINCT_PID_COUNT] ; CMpeg2SharedMem * m_pSharedMem ; // ======================================================================== // ** transport specific ** // // per PID counters __inline void PID_Packet_ (DWORD PID) { ASSERT (m_pTransportStats) ; m_pTransportStats -> PID [PID].cPIDPackets++ ; } __inline void PID_MPEG2Error_ (DWORD PID) { ASSERT (m_pTransportStats) ; m_pTransportStats -> PID [PID].cPIDMPEG2Errors++ ; } __inline void PID_NewPayload_ (DWORD PID) { ASSERT (m_pTransportStats) ; m_pTransportStats -> PID [PID].cPIDNewPayloads++ ; } __inline void PID_Discontinuity_ (DWORD PID) { ASSERT (m_pTransportStats) ; m_pTransportStats -> PID [PID].cPIDDiscontinuities++;} __inline void PID_MappedPacket_ (DWORD PID) { ASSERT (m_pTransportStats) ; m_pTransportStats -> PID [PID].cPIDMappedPackets++ ; } __inline void PID_DroppedPacket_ (DWORD PID) { ASSERT (m_pTransportStats) ; m_pTransportStats -> PID [PID].cPIDDroppedPackets++ ;} // ======================================================================== // ** program specific ** // // per-start code counters __inline void StartCode_Packet_ (DWORD sc, int iLen) { ASSERT (m_pProgramStats) ; m_pProgramStats -> StreamId [sc].cStreamIdPackets++ ; m_pProgramStats -> StreamId [sc].cBytesProcessed += iLen ; switch (sc) { case MPEG2_PACK_START_CODE : m_pProgramStats -> cPackHeaders++ ; break ; case MPEG2_SYSTEM_HEADER_START_CODE : m_pProgramStats -> cSystemHeaders++ ; break ; case PS_PMT_START_CODE : m_pProgramStats -> cProgramStreamMaps++ ; break ; case PS_DIRECTORY_START_CODE : m_pProgramStats -> cDirectoryPESPackets++ ; break ; } ; } __inline void StartCode_MappedPacket_ (DWORD sc) { ASSERT (m_pProgramStats) ; m_pProgramStats -> StreamId [sc].cStreamIdMapped++ ; } __inline void StartCode_DroppedPacket_ (DWORD sc) { ASSERT (m_pProgramStats) ; m_pProgramStats -> StreamId [sc].cStreamIdDropped++ ;} public : CMpeg2Stats ( ) ; ~CMpeg2Stats ( ) ; // defaults to no stats if the parameter value is not exactly one of // the presets HRESULT Initialize ( IN BOOL fEnable, IN DWORD Mpeg2StreamType ) ; void Free ( ) ; void Clear ( ) ; // refcounting ULONG AddRef ( ) { return InterlockedIncrement (& m_cRef) ; } ULONG Release ( ) { if (InterlockedDecrement (& m_cRef) == 0) { delete this ; return 0 ; } return m_cRef ; } // ==================================================================== // global counters (stream agnostic) // ==================================================================== // -------------------------------------------------------------------- // global counters // r parameter: override reporting __inline void Global_Packet (BOOL r = TRUE) { if (m_pStats && r) m_pStats -> cGlobalPackets++ ; } // f is the bit value of interest __inline void Global_MPEG2Error (BOOL f, BOOL r = TRUE) { if (m_pStats && f && r) m_pStats -> cGlobalMPEG2Errors++ ; } __inline void Global_NewPayload (BOOL f, BOOL r = TRUE) { if (m_pStats && f && r) m_pStats -> cGlobalNewPayloads++ ; } __inline void Global_Discontinuity (BOOL r = TRUE) { if (m_pStats && r) m_pStats -> cGlobalDiscontinuities++ ; } __inline void Global_SyncPoint (BOOL f, BOOL r = TRUE) { if (m_pStats && r && f) m_pStats -> cGlobalSyncPoints++ ; } __inline void Global_MappedPacket (BOOL r = TRUE) { if (m_pStats && r) m_pStats -> cGlobalMappedPackets++ ; } __inline void Global_MappedPacketDropped (BOOL r = TRUE) { if (m_pStats && r) m_pStats -> cGlobalDroppedPackets++ ; } __inline void Global_MediaSampleIn (BOOL r = TRUE) { if (m_pStats && r) m_pStats -> cGlobalInputMediaSamples++ ; } __inline void Global_MediaSampleOut (BOOL r = TRUE) { if (m_pStats && r) m_pStats -> cGlobalOutputMediaSamples++ ; } __inline void Global_MediaSampleAbort (BOOL r = TRUE) { if (m_pStats && r) m_pStats -> cGlobalAbortedMediaSamples++ ; } __inline void Global_BytesAborted (DWORD c, BOOL r = TRUE) { if (m_pStats && r) m_pStats -> cGlobalAbortedBytes += c ; } __inline void Global_MappedPacketPES (BOOL r = TRUE) { if (m_pStats && r) m_pStats -> cGlobalPESPackets++ ; } // -------------------------------------------------------------------- // timer counters __inline void TimeDiscontinuity () { if (m_pStats) m_pStats -> TimeStats.cTimeDiscontinuities++ ; } __inline void AudioPTSBase (REFERENCE_TIME * prt, REFERENCE_TIME * prts) { if (m_pStats) m_pStats -> TimeStats.TimeStamp.rtAudioStreamPTSBase = (* prt) + (* prts) ; } __inline void AudioPTSBase_Clear () { if (m_pStats) m_pStats -> TimeStats.TimeStamp.rtAudioStreamPTSBase = -1 ; } __inline void VideoPTSBase (REFERENCE_TIME * prt, REFERENCE_TIME * prts) { if (m_pStats) m_pStats -> TimeStats.TimeStamp.rtVideoStreamPTSBase = (* prt) + (* prts) ; } __inline void VideoPTSBase_Clear () { if (m_pStats) m_pStats -> TimeStats.TimeStamp.rtVideoStreamPTSBase = -1 ; } __inline void Buffering (REFERENCE_TIME * prt) { if (m_pStats) m_pStats -> TimeStats.TimeStamp.BufferingMillis = ::DShowToMillis (* prt) ; } __inline void BufferAdjustment () { if (m_pStats) m_pStats -> TimeStats.TimeStamp.cBufferAdjustments++ ; } __inline void NewTimeline () { PCR (UNDEFINED) ; BasePCR (UNDEFINED) ; AudioPTSBase_Clear () ; VideoPTSBase_Clear () ; } __inline void PCR (LONGLONG pcr) { if (m_pStats) { m_pStats -> TimeStats.TimeStamp.llLastPCR = pcr ; m_pStats -> TimeStats.TimeStamp.cPCR++ ; } } __inline void AudioPTSOut () { if (m_pStats) { m_pStats -> TimeStats.TimeStamp.cAudioPESPTS++ ; }} __inline void AudioPESPTS (LONGLONG * pll) { if (m_pStats) { m_pStats -> TimeStats.TimeStamp.llAudioPESPTS = (* pll) ; m_pStats -> TimeStats.TimeStamp.llAudioPESPTS_PCR_Delta = m_pStats -> TimeStats.TimeStamp.llAudioPESPTS - PCRToPTS (m_pStats -> TimeStats.TimeStamp.llLastPCR) ; } } __inline void VideoPTSOut () { if (m_pStats) { m_pStats -> TimeStats.TimeStamp.cVideoPESPTS++ ; }} __inline void VideoPESPTS (LONGLONG * pll) { if (m_pStats) { m_pStats -> TimeStats.TimeStamp.llVideoPESPTS = (* pll) ; m_pStats -> TimeStats.TimeStamp.llVideoPESPTS_PCR_Delta = m_pStats -> TimeStats.TimeStamp.llVideoPESPTS - PCRToPTS (m_pStats -> TimeStats.TimeStamp.llLastPCR) ; } } __inline void BasePCR (LONGLONG ll) { if (m_pStats) m_pStats -> TimeStats.TimeStamp.llBasePCR = ll ; } __inline void OutOfBoundsPTS (LONGLONG pts) { if (m_pStats) m_pStats -> TimeStats.TimeStamp.cPTS_PCROutOfBoundsDelta++ ; } __inline void QueuedAdvise () { if (m_pStats) m_pStats -> TimeStats.ClockSubordinate.cQueuedAdvises++ ; } __inline void Advise () { if (m_pStats) m_pStats -> TimeStats.ClockSubordinate.cSignaledAdvises++ ; } __inline void StaleAdvise () { if (m_pStats) m_pStats -> TimeStats.ClockSubordinate.cStaleAdvises++ ; } __inline void SubordinateState (BOOL f) { if (m_pStats) m_pStats -> TimeStats.ClockSubordinate.fSubordinating = f ; } __inline void InboundsBracket (double Ratio) { if (m_pStats) { m_pStats -> TimeStats.ClockSubordinate.cInboundsBrackets++ ; m_pStats -> TimeStats.ClockSubordinate.dLastBracketScalingVal = Ratio ; }} __inline void OutOfBoundsBracket(double Ratio) { if (m_pStats) { m_pStats -> TimeStats.ClockSubordinate.cOutofBoundsBrackets++ ; m_pStats -> TimeStats.ClockSubordinate.dLastBracketScalingVal = Ratio ; }} __inline void QueueLength (DWORD len) { if (m_pStats) m_pStats -> TimeStats.ClockSubordinate.cQueueLength = len ; } __inline void ScalingVal (double dVal) { if (m_pStats) m_pStats -> TimeStats.ClockSubordinate.dScalingVal = dVal ; } __inline void RefclockShift (CTSmoothingFilter * psf) { if (m_pStats) { m_pStats -> TimeStats.ClockSubordinate.rtTargetShift = psf -> TargetVal () ; m_pStats -> TimeStats.ClockSubordinate.rtCurShift = psf -> CurVal () ; } } // called for ALL packets processed, regardless of the existence of a mapping or not // defined in tsmapper.cpp __inline void NewPacketStats ( IN MPEG2_SYS_BUFFER * pSysBuffer, IN DWORD dw = 0 // ignored for transport; program: stream_id ) ; // called by a parser when a mapped packet is dropped; defined in plparse.h __inline void DroppedPacket ( IN MPEG2_SYS_BUFFER * pSysBuffer, IN BOOL fReportStat ) ; // called by a parser when a mapped packet is received; defined in plparse.h __inline void MappedPacket ( IN MPEG2_SYS_BUFFER * pSysBuffer, IN BOOL fReportStat ) ; // ==================================================================== // transport-specific // ==================================================================== __inline void MappedPacketPSI (BOOL r = TRUE) { if (m_pTransportStats && r) m_pTransportStats -> cPSIPackets++ ; } __inline void SyncByteSeek () { if (m_pTransportStats) m_pTransportStats -> cSyncByteSeeks++ ; } __inline void SpannedPacket () { if (m_pTransportStats) m_pTransportStats -> cSpannedPacket++ ; } } ; #endif // __mp2demux_tsstats_h