--- a/multimediacommscontroller/mmccrtpsourcesink/src/mccjittercalculator.cpp Tue Jul 06 14:42:02 2010 +0300
+++ b/multimediacommscontroller/mmccrtpsourcesink/src/mccjittercalculator.cpp Wed Aug 18 10:09:50 2010 +0300
@@ -11,7 +11,7 @@
*
* Contributors:
*
-* Description: MccJitterCalculator calculates jitter level and compares given
+* Description: MccJitterCalculator calculates jitter level and compares given
* triggers.
*
*/
@@ -46,6 +46,13 @@
const TInt KNum4( 4 );
const TInt KNum8( 8 );
const TInt KNumZero( 0 );
+const TInt KNumHundred( 100 );
+
+const TUint32 KRtpFractationAccuracy = 5000;
+// Specified period of the moving average
+const TUint32 KDivider = 250;
+// Specified the max calculate count of package loss
+const TUint32 KMaxCalCount = 200;
// ============================ MEMBER FUNCTIONS ===============================
@@ -137,7 +144,7 @@
// -----------------------------------------------------------------------------
//
void CMccJitterCalculator::RtpPacketReceived( const TUint32 aTimeStamp,
- TBool aMarker )
+ TBool aMarker, TUint16 aSeqNum )
{
#ifdef TRACE_JITCALC
RDebug::Print( _L("CMccJitterCalculator::RtpPacketReceived IN") );
@@ -147,6 +154,33 @@
VoipTrace("%x %x %d %d %d", MCC_TRACE, MCC_RECEIVED_RTP_PACKET_INFO,
aHeaderInfo.iSeqNum, aHeaderInfo.iTimestamp, iPacketsReceived );
#endif
+
+ TBool calculatePkgLoss = ETrue;
+ if ( EMccQualityPacketBased == iReportIntervalType || iFrameLossObsOn )
+ {
+ // Save current packet sequence number
+ // The SeqNum come from RTP package. It maybe start from a random number between
+ // 0 to 65535. iStartingSeqNum should be reset
+ // while iCurrentSeqNum was reset (by remote packages)
+ iCurrentSeqNum = aSeqNum;
+ if( iStartingSeqNum == KNumZero ||
+ iStartingSeqNum > iCurrentSeqNum )
+ {
+ iStartingSeqNum = aSeqNum;
+ if ( iStartingSeqNum > 0 )
+ {
+ iStartingSeqNum--;
+ }
+ else
+ {
+ #ifdef TRACE_JITCALC
+ RDebug::Print( _L("Received SeqNum is 0, don't calculate lost package") );
+ #endif
+ calculatePkgLoss = EFalse;
+ }
+ }
+ iReceivedPacketCounter++;
+ }
// Jitter calculating based on RFC3550 Appendix A.8, see www.ietf.org
if ( aMarker || !iPacketsReceived )
@@ -218,15 +252,20 @@
RDebug::Print( _L("CMccJitterCalculator::RtpPacketReceived SENDING RCV: %d"), iPacketsReceived );
#endif
- TMccRtpEventData event( ( iCurJitter >> KNum4 ),
+ TMccRtpEventDataExtended event( ( iCurJitter >> KNum4 ),
iPacketsReceived,
iPrevPacketTransit,
+ KNumZero,
+ KNumZero,
KNumZero );
iObserver->SendJitterEvent( event, KErrNone );
}
- JitterObserving();
+ if ( calculatePkgLoss )
+ {
+ JitterObserving();
+ }
}
// ---------------------------------------------------------------------------
@@ -302,6 +341,7 @@
iJitterObsOn = EFalse;
iFrameLossObsOn = EFalse;
iMediaQualityObservingStarted = EFalse;
+ iStartingSeqNum = KNumZero;
}
// ---------------------------------------------------------------------------
@@ -356,6 +396,9 @@
iPacketsReceived = KNumZero;
iCurJitter = KNumZero;
iPrevPacketTransit = KNumZero;
+ iCurrentSeqNum = KNumZero;
+ iStartingSeqNum = KNumZero;
+ iReceivedPacketCounter = KNumZero;
}
// -----------------------------------------------------------------------------
@@ -366,6 +409,13 @@
//
void CMccJitterCalculator::JitterObserving()
{
+ #ifdef TRACE_JITCALC
+ RDebug::Print( _L("CMccJitterCalculator::JitterObserving IN") );
+ #endif
+
+ TBool resetValuesForNextReport = EFalse;
+ TBool cancelObs = EFalse;
+
if ( iJitterObsOn )
{
#ifdef TRACE_JITCALC
@@ -374,98 +424,32 @@
iJitterLevelFromClient, ( iCurJitter / KConversionFactor ) );
#endif
- // Normalize iCurJitter
- TUint64 modJitter = iCurJitter >> KNum4;
-
- if ( EMccQualityTimeBased == iReportIntervalType )
- {
- // change microsecs to millisecs
- TTimeIntervalMicroSeconds getTime =
- iCurTime.MicroSecondsFrom( iHomeTime );
-
- #ifdef TRACE_JITCALC
- RDebug::Print( _L("CMccJitterCalculator::JitterObserving getTime = %Ld"), getTime.Int64() );
- #endif
-
- if ( static_cast<TInt64>( iReportInterval ) <=
- ( getTime.Int64() / KConversionFactor ) )
- {
- // compare clients jitter level to current level
- if ( static_cast<TUint64>( iJitterLevelFromClient ) <
- modJitter )
- {
- #ifdef TRACE_JITCALC
- RDebug::Print ( _L("CMccJitterCalculator::JitterObserving jitterlevel %u ms compared to jitter estimate %Lu ms"),
- iJitterLevelFromClient, modJitter );
- #endif
-
- TMccRtpEventData event( ( iCurJitter >> KNum4 ),
- iPacketsReceived,
- iPrevPacketTransit,
- modJitter );
-
- // Informs client via event and cancels jitter observing
- iObserver->SendJitterEvent( event, KErrNone );
- CancelObserving();
- }
-
- // Initialize hometime again
- iHomeTime.HomeTime();
-
- #ifdef TRACE_JITCALC
- RDebug::Print ( _L("CMccJitterCalculator::JitterObserving Initialize iHomeTime = %Ld"), iHomeTime.Int64() );
- #endif
-
- }
- }
- else if ( EMccQualityPacketBased == iReportIntervalType )
- {
- iReceivedPacketCounter++;
-
- #ifdef TRACE_JITCALC
- RDebug::Print( _L("CMccJitterCalculator::JitterObserving iReceivedPacketCounter: %u"), iReceivedPacketCounter );
- #endif
-
- if ( iReportInterval == iReceivedPacketCounter )
- {
- // compare clients jitter level to current level
- if ( iJitterLevelFromClient < modJitter )
- {
- #ifdef TRACE_JITCALC
- RDebug::Print( _L("CMccJitterCalculator::JitterObserving jitterlevel %u ms compared to jitter estimate %Lu ms"),
- iJitterLevelFromClient, modJitter );
- #endif
-
- TMccRtpEventData event( ( iCurJitter >> KNum4 ),
- iPacketsReceived,
- iPrevPacketTransit,
- modJitter );
-
- // Informs client via event and cancels jitter observing
- iObserver->SendJitterEvent( event, KErrNone );
- CancelObserving();
- }
-
- iReceivedPacketCounter = KNumZero;
- }
- }
- else
- {
- #ifdef TRACE_JITCALC
- RDebug::Print( _L("CMccJitterCalculator::JitterObserving Report type is not valid!") );
- #endif
-
- TMccRtpEventData event( ( iCurJitter >> KNum4 ),
- iPacketsReceived,
- iPrevPacketTransit,
- KNumZero );
-
- iObserver->SendJitterEvent( event, KErrArgument );
- CancelObserving();
- }
+ CheckJitter( resetValuesForNextReport, cancelObs );
+ }
+
+ if ( iFrameLossObsOn )
+ {
+ #ifdef TRACE_JITCALC
+ RDebug::Print( _L("CMccJitterCalculator::JitterObserving Frame Loss observing ON") );
+ #endif
+
+ CheckPacketLoss( resetValuesForNextReport, cancelObs );
}
+
+ if( resetValuesForNextReport )
+ {
+ // Initialize hometime again
+ iHomeTime.HomeTime();
+ #ifdef TRACE_JITCALC
+ RDebug::Print ( _L("CMccJitterCalculator::JitterObserving Initialize iHomeTime = %Ld"), iHomeTime.Int64() );
+ #endif
+ }
+ if( cancelObs )
+ {
+ CancelObserving();
+ }
}
-
+
// ---------------------------------------------------------------------------
// CMccJitterCalculator::IsObserving
// To check if observing is ON
@@ -476,4 +460,288 @@
return iMediaQualityObservingStarted;
}
+// -----------------------------------------------------------------------------
+// CMccJitterCalculator::CountPacketLossPercentage
+// Counts packet loss percentage from iStartingSeqNum, iCurrentSeqNum
+// and iReceivedPacketCounter
+// private method
+// -----------------------------------------------------------------------------
+//
+TInt CMccJitterCalculator::CountPacketLossPercentage()
+ {
+ TUint32 numberOfPacketsExpected( 0 );
+ numberOfPacketsExpected = iCurrentSeqNum - iStartingSeqNum;
+
+ if ( ( iPrevExpectedPackets - iPrevPacketsReceived ) ==
+ ( numberOfPacketsExpected - iReceivedPacketCounter ) )
+ {
+ // no packet lost - inorder
+ iPrevFerValue = CalculateFer( iPrevFerValue, EFalse, ETrue );
+ }
+ else if ( ( iPrevPacketsReceived < iReceivedPacketCounter ) &&
+ ( iPrevExpectedPackets == numberOfPacketsExpected ) )
+ {
+ // no packet lost - late packet - remove FER
+ iPrevFerValue = CalculateFer( iPrevFerValue, ETrue, EFalse );
+ }
+ else if ( numberOfPacketsExpected > iPrevExpectedPackets )
+ {
+
+ // packet lost - add FER by number of packets lost.
+ // expected = 5, prev_expected 3 => diff 2 but loss is ONE thats why - 1
+ TUint32 maxCalcount =
+ numberOfPacketsExpected - iPrevExpectedPackets - 1 < KMaxCalCount ?
+ numberOfPacketsExpected - iPrevExpectedPackets - 1 : KMaxCalCount;
+ for ( TUint32 i = 0; i < maxCalcount; i++ )
+ {
+ iPrevFerValue = CalculateFer( iPrevFerValue, ETrue, ETrue );
+ }
+ }
+
+ iPrevExpectedPackets = numberOfPacketsExpected;
+ iPrevPacketsReceived = iReceivedPacketCounter;
+
+ TInt percentage( iPrevFerValue / KRtpFractationAccuracy );
+ return percentage;
+ }
+
+// -----------------------------------------------------------------------------
+// CMccJitterCalculator::CheckJitter
+// Checks if current jitter level exceeds the jitter level given by the client,
+// and if exceeded, sends the report to client
+// private method
+// -----------------------------------------------------------------------------
+//
+void CMccJitterCalculator::CheckJitter( TBool& aReportIntervalReached,
+ TBool& aReportSent )
+ {
+ #ifdef TRACE_JITCALC
+ RDebug::Print( _L("CMccJitterCalculator::CheckJitter IN") );
+ #endif
+
+ // Normalize iCurJitter
+ TUint64 modJitter = iCurJitter >> KNum4;
+
+ if ( EMccQualityTimeBased == iReportIntervalType )
+ {
+ // change microsecs to millisecs
+ TTimeIntervalMicroSeconds getTime =
+ iCurTime.MicroSecondsFrom( iHomeTime );
+
+ #ifdef TRACE_JITCALC
+ RDebug::Print( _L("CMccJitterCalculator::CheckJitter getTime = %Ld"), getTime.Int64() );
+ #endif
+
+ if ( static_cast<TInt64>( iReportInterval ) <=
+ ( getTime.Int64() / KConversionFactor ) )
+ {
+ // compare clients jitter level to current level
+ if ( static_cast<TUint64>( iJitterLevelFromClient ) <
+ modJitter )
+ {
+ #ifdef TRACE_JITCALC
+ RDebug::Print ( _L("CMccJitterCalculator::CheckJitter jitterlevel %u ms compared to jitter estimate %Lu ms"),
+ iJitterLevelFromClient, modJitter );
+ #endif
+
+ TMccRtpEventDataExtended event( ( iCurJitter >> KNum4 ),
+ iPacketsReceived,
+ iPrevPacketTransit,
+ modJitter,
+ KNumZero,
+ KNumZero );
+
+ // Informs client via event and cancels jitter observing
+ iObserver->SendJitterEvent( event, KErrNone );
+ aReportSent = ETrue;
+ }
+ aReportIntervalReached = ETrue;
+ }
+ }
+ else if ( EMccQualityPacketBased == iReportIntervalType )
+ {
+ #ifdef TRACE_JITCALC
+ RDebug::Print( _L("CMccJitterCalculator::CheckJitter iReceivedPacketCounter: %u"), iReceivedPacketCounter );
+ #endif
+
+ if ( iReportInterval == iReceivedPacketCounter )
+ {
+ // compare clients jitter level to current level
+ if ( iJitterLevelFromClient < modJitter )
+ {
+ #ifdef TRACE_JITCALC
+ RDebug::Print( _L("CMccJitterCalculator::CheckJitter jitterlevel %u ms compared to jitter estimate %Lu ms"),
+ iJitterLevelFromClient, modJitter );
+ #endif
+
+ TMccRtpEventDataExtended event( ( iCurJitter >> KNum4 ),
+ iPacketsReceived,
+ iPrevPacketTransit,
+ modJitter,
+ KNumZero,
+ KNumZero );
+
+ // Informs client via event and cancels jitter observing
+ iObserver->SendJitterEvent( event, KErrNone );
+ aReportSent = ETrue;
+ }
+ aReportIntervalReached = ETrue;
+ }
+ }
+ else
+ {
+ #ifdef TRACE_JITCALC
+ RDebug::Print( _L("CMccJitterCalculator::CheckJitter Report type is not valid!") );
+ #endif
+
+ TMccRtpEventDataExtended event( ( iCurJitter >> KNum4 ),
+ iPacketsReceived,
+ iPrevPacketTransit,
+ KNumZero,
+ KNumZero,
+ KNumZero );
+
+ iObserver->SendJitterEvent( event, KErrArgument );
+ aReportSent = ETrue;
+ }
+
+ }
+
+// -----------------------------------------------------------------------------
+// CMccJitterCalculator::CheckPacketLoss
+// Checks if current packet loss level exceeds the packet loss level
+// given by the client, and if exceeded, sends the report to client
+// private method
+// -----------------------------------------------------------------------------
+//
+void CMccJitterCalculator::CheckPacketLoss( TBool& aReportIntervalReached,
+ TBool& aReportSent )
+ {
+ #ifdef TRACE_JITCALC
+ RDebug::Print( _L("CMccJitterCalculator::CheckPacketLoss IN") );
+ #endif
+
+ TInt packetLossPercentage = CountPacketLossPercentage();
+
+ if ( EMccQualityTimeBased == iReportIntervalType )
+ {
+ // change microsecs to millisecs
+ TTimeIntervalMicroSeconds getTime =
+ iCurTime.MicroSecondsFrom( iHomeTime );
+
+ #ifdef TRACE_JITCALC
+ RDebug::Print( _L("CMccJitterCalculator::CheckPacketLoss getTime = %Ld"), getTime.Int64() );
+ #endif
+
+ if ( static_cast<TInt64>( iReportInterval ) <=
+ ( getTime.Int64() / KConversionFactor ) )
+ {
+ // If the packet loss percentage was exceeded
+ if( iPacketLossFromClient < packetLossPercentage )
+ {
+ #ifdef TRACE_JITCALC
+ RDebug::Print( _L("CMccJitterCalculator::CheckPacketLoss Packet Loss From Client %u compared to Current Packet Loss %u "),
+ iPacketLossFromClient, packetLossPercentage );
+ #endif
+
+ TMccRtpEventDataExtended event( ( iCurJitter >> KNum4 ),
+ iPacketsReceived,
+ iPrevPacketTransit,
+ KNumZero,
+ packetLossPercentage,
+ packetLossPercentage );
+
+ // Informs client via event and cancels jitter observing
+ iObserver->SendJitterEvent( event, KErrNone );
+ aReportSent = ETrue;
+ }
+ aReportIntervalReached = ETrue;
+ }
+ }
+ else if ( EMccQualityPacketBased == iReportIntervalType )
+ {
+
+ #ifdef TRACE_JITCALC
+ RDebug::Print( _L("CMccJitterCalculator::CheckPacketLoss EMccQualityPacketBased == iReportIntervalType") );
+ RDebug::Print( _L("CMccJitterCalculator::CheckPacketLoss iReceivedPacketCounter: %u"), iReceivedPacketCounter );
+ #endif
+
+ if ( iReportInterval == iReceivedPacketCounter )
+ {
+ // If the packet loss percentage was exceeded
+ if( iPacketLossFromClient < packetLossPercentage )
+ {
+ #ifdef TRACE_JITCALC
+ RDebug::Print( _L("CMccJitterCalculator::CheckPacketLoss Packet Loss From Client %u compared to Current Packet Loss %u "),
+ iPacketLossFromClient, packetLossPercentage );
+ #endif
+
+ TMccRtpEventDataExtended event( ( iCurJitter >> KNum4 ),
+ iPacketsReceived,
+ iPrevPacketTransit,
+ KNumZero,
+ packetLossPercentage,
+ packetLossPercentage );
+
+ // Informs client via event and cancels jitter observing
+ iObserver->SendJitterEvent( event, KErrNone );
+ aReportSent = ETrue;
+ }
+ aReportIntervalReached = ETrue;
+ }
+ }
+ else
+ {
+ #ifdef TRACE_JITCALC
+ RDebug::Print( _L("CMccJitterCalculator::CheckPacketLoss Report type is not valid!") );
+ #endif
+
+ TMccRtpEventDataExtended event( ( iCurJitter >> KNum4 ),
+ iPacketsReceived,
+ iPrevPacketTransit,
+ KNumZero,
+ KNumZero,
+ KNumZero );
+
+ iObserver->SendJitterEvent( event, KErrArgument );
+ aReportSent = ETrue;
+ }
+ }
+
+// -----------------------------------------------------------------------------
+// CMccJitterCalculator::CalculateFer
+// Calculates a new FER value
+// -----------------------------------------------------------------------------
+//
+TUint32 CMccJitterCalculator::CalculateFer( TUint32 aPrevValue,
+ TBool aAdd, TBool aFlag )
+ {
+ TUint32 ret = 0;
+ TInt64 temp_add = 0;
+
+ temp_add = aAdd * KNumHundred * KRtpFractationAccuracy;
+
+ TInt64 diff = temp_add - (TInt64)aPrevValue;
+ TInt32 tempValue = static_cast<TInt32>( diff / KDivider );
+
+ if ( aFlag )
+ {
+ ret = TUint32( aPrevValue + tempValue );
+ }
+ else
+ {
+ if ( aPrevValue > tempValue )
+ {
+ ret = TUint32( aPrevValue - tempValue );
+ }
+ else
+ {
+ // removed FER would have gone over thus zero
+ ret = 0;
+ }
+ }
+
+ return ret;
+ }
+
// End of File