--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/multimediacommscontroller/mmccrtpsourcesink/src/mccjittercalculator.cpp Tue Feb 02 01:04:58 2010 +0200
@@ -0,0 +1,479 @@
+/*
+* Copyright (c) 2005-2006 Nokia Corporation and/or its subsidiary(-ies).
+* All rights reserved.
+* This component and the accompanying materials are made available
+* under the terms of "Eclipse Public License v1.0"
+* which accompanies this distribution, and is available
+* at the URL "http://www.eclipse.org/legal/epl-v10.html".
+*
+* Initial Contributors:
+* Nokia Corporation - initial contribution.
+*
+* Contributors:
+*
+* Description: MccJitterCalculator calculates jitter level and compares given
+* triggers.
+*
+*/
+
+
+
+
+// INCLUDE FILES
+#include "mccinternaldef.h"
+#include "mccrtpdatasource.h"
+#include "mccjittercalculator.h"
+#include "mccinternalevents.h"
+
+#ifdef VOIP_TRACE_ENABLED
+#include <voip_trace.h>
+#endif
+
+#ifdef _DEBUG
+#define TRACE_JITCALC
+#include <e32svr.h>
+#endif
+
+// CONSTANTS
+
+// Packet interval for jitter/jitterbuffer stat reports
+const TUint KJitterReportInterval = 16;
+// Conversion factor from uSecs to mSecs
+const TInt KConversionFactor = 1000;
+// Samplerate in kHz, currently only 8kHz supported
+const TUint KSampleRate = 8;
+
+const TInt KNum4( 4 );
+const TInt KNum8( 8 );
+const TInt KNumZero( 0 );
+
+// ============================ MEMBER FUNCTIONS ===============================
+
+// -----------------------------------------------------------------------------
+// CMccJitterCalculator::CMccJitterCalculator
+// C++ default constructor can NOT contain any code, that
+// might leave.
+// -----------------------------------------------------------------------------
+//
+CMccJitterCalculator::CMccJitterCalculator( MRtpJitterObserver& aObserver ) :
+ iObserver( &aObserver )
+ {
+ }
+
+// -----------------------------------------------------------------------------
+// CMccJitterCalculator::ConstructL
+// Symbian 2nd phase constructor can leave.
+// -----------------------------------------------------------------------------
+//
+#ifdef FTD_ENABLED
+void CMccJitterCalculator::ConstructL()
+ {
+ TInt err = iStreamStatsQueue.OpenGlobal( KMccStreamStats, EOwnerProcess );
+ if ( KErrNone != err )
+ {
+ User::Leave( err );
+ }
+
+ err = iJBufStatsQueue.OpenGlobal( KMccJBufferStats, EOwnerProcess );
+ if ( KErrNone != err )
+ {
+ iStreamStatsQueue.Close();
+ User::Leave( err );
+ }
+ }
+#endif
+
+// -----------------------------------------------------------------------------
+// CMccJitterCalculator::NewL
+// Static constructor.
+// -----------------------------------------------------------------------------
+//
+CMccJitterCalculator* CMccJitterCalculator::NewL( MRtpJitterObserver& aObserver )
+ {
+ CMccJitterCalculator* self =
+ new ( ELeave ) CMccJitterCalculator( aObserver );
+
+ #ifdef FTD_ENABLED
+ CleanupStack::PushL ( self );
+ self->ConstructL ();
+ CleanupStack::Pop( self );
+ #endif
+
+ return self;
+ }
+
+
+// -----------------------------------------------------------------------------
+// CMccJitterCalculator::~CMccJitterCalculator
+// Destructor.
+// -----------------------------------------------------------------------------
+//
+CMccJitterCalculator::~CMccJitterCalculator()
+ {
+ #ifdef TRACE_JITCALC
+ RDebug::Print( _L("CMccJitterCalculator::~CMccJitterCalculator IN") );
+ #endif
+
+ if ( IsObserving() )
+ {
+ CancelObserving();
+ }
+
+ iObserver = NULL;
+
+ #ifdef FTD_ENABLED
+ iStreamStatsQueue.Close();
+ iJBufStatsQueue.Close();
+ #endif
+
+ #ifdef TRACE_JITCALC
+ RDebug::Print( _L("CMccJitterCalculator::~CMccJitterCalculator OUT") );
+ #endif
+ }
+
+// -----------------------------------------------------------------------------
+// CMccJitterCalculator::RtpPacketReceived
+// Calculates jitter values
+// -----------------------------------------------------------------------------
+//
+void CMccJitterCalculator::RtpPacketReceived( const TUint32 aTimeStamp,
+ TBool aMarker )
+ {
+ #ifdef TRACE_JITCALC
+ RDebug::Print( _L("CMccJitterCalculator::RtpPacketReceived IN") );
+ #endif
+
+ #ifdef VOIP_RECEIVED_RTP_PACKET_INFO_ENABLED
+ VoipTrace("%x %x %d %d %d", MCC_TRACE, MCC_RECEIVED_RTP_PACKET_INFO,
+ aHeaderInfo.iSeqNum, aHeaderInfo.iTimestamp, iPacketsReceived );
+ #endif
+
+ // Jitter calculating based on RFC3550 Appendix A.8, see www.ietf.org
+ if ( aMarker || !iPacketsReceived )
+ {
+ // A new talkspurt, redo calculations Marker bit is set after silent
+ // period and indicates that new speech data is received
+ iPrevPacketArrival.HomeTime();
+ TInt64 pcktTrans = iPrevPacketArrival.Int64() / TInt64( KConversionFactor );
+
+ // Convert timestamp to milliseconds and calculate transit time
+ iPrevPacketTransit =
+ pcktTrans - static_cast<TInt64>( ( aTimeStamp / KSampleRate ) );
+
+ // Reset jitter and packet counter for new talkspurt
+ iCurJitter = KNumZero;
+ iPacketsReceived = KNumZero;
+ }
+ else
+ {
+ // Just another packet in the talkspurt
+ TTime newPacket;
+ newPacket.HomeTime();
+
+ // Time of Arrival in milliseconds
+ TInt64 curPacketTOA = ( newPacket.Int64() / TInt64( KConversionFactor ) );
+
+ // Convert timestamp to milliseconds and calculate transit time
+ TInt64 curPacketTransit
+ = curPacketTOA - static_cast<TInt64>( ( aTimeStamp / KSampleRate ) );
+
+ TInt64 diff = curPacketTransit - iPrevPacketTransit;
+ iPrevPacketTransit = curPacketTransit;
+ diff = Abs( diff );
+
+ // Jitter is floating mean value over 16 packets last received
+ iCurJitter += diff - ( ( iCurJitter + KNum8 ) >> KNum4 );
+
+ #ifdef TRACE_JITCALC
+ RDebug::Print( _L("CMccJitterCalculator::RtpPacketReceived CUR_TOA: %Ld"), curPacketTOA );
+ RDebug::Print( _L("CMccJitterCalculator::RtpPacketReceived CUR_TRANS: %Ld"), curPacketTransit );
+ RDebug::Print( _L("CMccJitterCalculator::RtpPacketReceived CUR_DIFF: %Ld"), diff );
+ RDebug::Print( _L("CMccJitterCalculator::RtpPacketReceived CUR_JITT: %Lu"), iCurJitter );
+ RDebug::Print( _L("CMccJitterCalculator::RtpPacketReceived SC_CUR_JITT: %Lu"), ( iCurJitter >> KNum4 ) );
+ #endif
+ }
+
+ iPacketsReceived++;
+ iCurTime.HomeTime();
+
+ #ifdef TRACE_JITCALC
+ RDebug::Print ( _L("CMccJitterCalculator::RtpPacketReceived newPacket = %Ld"), iCurTime.Int64() );
+ #endif
+
+ #ifdef FTD_ENABLED
+ TMccStreamStats stats;
+ stats.iPacketsReceived = iPacketsReceived;
+ stats.SetFieldUpdatedFlag( EPacketsReceived );
+ iStreamStatsQueue.Send( stats );
+
+ TMccJBufferStats jStats;
+ jStats.iJitterEstimate = iCurJitter;
+ iJBufStatsQueue.Send( jStats );
+ #endif
+
+ // Report jitter if we have enough received packets and jitter
+ if ( !( iPacketsReceived % KJitterReportInterval ) && iCurJitter )
+ {
+ #ifdef TRACE_JITCALC
+ RDebug::Print( _L("CMccJitterCalculator::RtpPacketReceived SENDING RCV: %d"), iPacketsReceived );
+ #endif
+
+ TMccRtpEventData event( ( iCurJitter >> KNum4 ),
+ iPacketsReceived,
+ iPrevPacketTransit,
+ KNumZero );
+
+ iObserver->SendJitterEvent( event, KErrNone );
+ }
+
+ JitterObserving();
+ }
+
+// ---------------------------------------------------------------------------
+// CMccJitterCalculator::StartObserving
+// Switch to deside report type
+// ---------------------------------------------------------------------------
+//
+TInt CMccJitterCalculator::StartObserving()
+ {
+ #ifdef TRACE_JITCALC
+ RDebug::Print( _L("CMccJitterCalculator::StartObserving IN") );
+ #endif
+
+ TInt err( KErrNone );
+ iHomeTime.HomeTime();
+
+ #ifdef TRACE_JITCALC
+ RDebug::Print ( _L("CMccJitterCalculator::StartObserving HomeTime = %Ld"), iHomeTime.Int64() );
+ RDebug::Print( _L("CMccJitterCalculator::StartObserving iReportType: %d"), iReportType );
+ #endif
+
+ switch( iReportType )
+ {
+ case EMccJitterReport:
+ #ifdef TRACE_JITCALC
+ RDebug::Print( _L("CMccJitterCalculator::StartObserving iReportType selected EMccJitterReport"));
+ #endif
+ iJitterObsOn = ETrue;
+ iMediaQualityObservingStarted = ETrue;
+ break;
+
+ case EMccPacketLossReport:
+ #ifdef TRACE_JITCALC
+ RDebug::Print( _L("CMccJitterCalculator::StartObserving iReportType selected EMccPacketLossReport"));
+ #endif
+ iFrameLossObsOn = ETrue;
+ iMediaQualityObservingStarted = ETrue;
+ break;
+
+ case EMccQualityReportAll:
+ #ifdef TRACE_JITCALC
+ RDebug::Print( _L("CMccJitterCalculator::StartObserving iReportType selected EMccQualityReportAll"));
+ #endif
+ iJitterObsOn = ETrue;
+ iFrameLossObsOn = ETrue;
+ iMediaQualityObservingStarted = ETrue;
+ break;
+
+ default:
+ // if report type is not set
+ #ifdef TRACE_JITCALC
+ RDebug::Print( _L("CMccJitterCalculator::StartObserving iReportType selected default"));
+ #endif
+
+ err = KErrArgument;
+ break;
+ }
+
+ return err;
+ }
+
+// ---------------------------------------------------------------------------
+// CMccJitterCalculator::CancelObserving
+// Cancel is called by client
+// ---------------------------------------------------------------------------
+//
+void CMccJitterCalculator::CancelObserving()
+ {
+ #ifdef TRACE_JITCALC
+ RDebug::Print( _L("CMccJitterCalculator::CancelObserving IN") );
+ #endif
+
+ iJitterObsOn = EFalse;
+ iFrameLossObsOn = EFalse;
+ iMediaQualityObservingStarted = EFalse;
+ }
+
+// ---------------------------------------------------------------------------
+// CMccJitterCalculator::SetMediaConfigsL
+// Open aMessage and read media configs
+// ---------------------------------------------------------------------------
+//
+void CMccJitterCalculator::SetMediaConfigsL( const TMMFMessage& aMessage )
+ {
+ #ifdef TRACE_JITCALC
+ RDebug::Print( _L("CMccJitterCalculator::SetMediaConfigs IN") );
+ #endif
+
+ TMMFMessage* tmp = new ( ELeave ) TMMFMessage( aMessage );
+ CleanupStack::PushL( tmp );
+
+ TMccMediaQualConfBuf configPckg;
+ tmp->ReadData1FromClientL( configPckg );
+
+ iMediaConf = configPckg();
+
+ // Read data from client
+ iJitterLevelFromClient = iMediaConf.iJitterLevel;
+ iPacketLossFromClient = iMediaConf.iPacketLoss;
+ iReportType = iMediaConf.iReportType;
+ iReportIntervalType = iMediaConf.iReportIntervalType;
+ iReportInterval = iMediaConf.iReportInterval;
+
+ #ifdef TRACE_JITCALC
+ RDebug::Print( _L("CMccJitterCalculator::SetMediaConfigsL SESSION %d"), iMediaConf.iSessionId );
+ RDebug::Print( _L("CMccJitterCalculator::SetMediaConfigsL JITTER LEVEL %d"), iMediaConf.iJitterLevel );
+ RDebug::Print( _L("CMccJitterCalculator::SetMediaConfigsL PACKET LOSS %d"), iMediaConf.iPacketLoss );
+ RDebug::Print( _L("CMccJitterCalculator::SetMediaConfigsL REPORT TYPE %d"), iMediaConf.iReportType );
+ RDebug::Print( _L("CMccJitterCalculator::SetMediaConfigsL REPORT INTERVAL TYPE %d"), iMediaConf.iReportIntervalType );
+ RDebug::Print( _L("CMccJitterCalculator::SetMediaConfigsL REPORT INTERVAL %d"), iMediaConf.iReportInterval );
+ #endif
+
+ CleanupStack::PopAndDestroy( tmp );
+ }
+
+// -----------------------------------------------------------------------------
+// CMccJitterCalculator::ResetCounters
+// Set counters ready to receive packets
+// -----------------------------------------------------------------------------
+//
+void CMccJitterCalculator::ResetCounters()
+ {
+ #ifdef TRACE_JITCALC
+ RDebug::Print( _L("CMccJitterCalculator::ResetCounters()") );
+ #endif
+
+ iPacketsReceived = KNumZero;
+ iCurJitter = KNumZero;
+ iPrevPacketTransit = KNumZero;
+ }
+
+// -----------------------------------------------------------------------------
+// CMccJitterCalculator::JitterObserving
+// Trigger controller. Compares calculated and defined values.
+// private method
+// -----------------------------------------------------------------------------
+//
+void CMccJitterCalculator::JitterObserving()
+ {
+ if ( iJitterObsOn )
+ {
+ #ifdef TRACE_JITCALC
+ RDebug::Print( _L("CMccJitterCalculator::JitterObserving Jitter level observing ON") );
+ RDebug::Print( _L("CMccJitterCalculator::JitterObserving jitterlevel %u ms compared to jitter estimate %Lu ms"),
+ 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();
+ }
+ }
+ }
+
+// ---------------------------------------------------------------------------
+// CMccJitterCalculator::IsObserving
+// To check if observing is ON
+// ---------------------------------------------------------------------------
+//
+TBool CMccJitterCalculator::IsObserving() const
+ {
+ return iMediaQualityObservingStarted;
+ }
+
+// End of File