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