diff -r 72290a6868df -r bf4e57f9a0ce multimediacommscontroller/mmccrtpsourcesink/src/mccjittercalculator.cpp --- 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( iReportInterval ) <= - ( getTime.Int64() / KConversionFactor ) ) - { - // compare clients jitter level to current level - if ( static_cast( 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( iReportInterval ) <= + ( getTime.Int64() / KConversionFactor ) ) + { + // compare clients jitter level to current level + if ( static_cast( 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( 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( 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