multimediacommscontroller/mmccrtpsourcesink/src/mccjittercalculator.cpp
changeset 0 1bce908db942
child 32 f2ed1fc4c163
equal deleted inserted replaced
-1:000000000000 0:1bce908db942
       
     1 /*
       
     2 * Copyright (c) 2005-2006 Nokia Corporation and/or its subsidiary(-ies).
       
     3 * All rights reserved.
       
     4 * This component and the accompanying materials are made available
       
     5 * under the terms of "Eclipse Public License v1.0"
       
     6 * which accompanies this distribution, and is available
       
     7 * at the URL "http://www.eclipse.org/legal/epl-v10.html".
       
     8 *
       
     9 * Initial Contributors:
       
    10 * Nokia Corporation - initial contribution.
       
    11 *
       
    12 * Contributors:
       
    13 *
       
    14 * Description:    MccJitterCalculator calculates jitter level and compares given
       
    15 *                triggers.
       
    16 *
       
    17 */
       
    18 
       
    19 
       
    20 
       
    21 
       
    22 // INCLUDE FILES
       
    23 #include "mccinternaldef.h"
       
    24 #include "mccrtpdatasource.h"
       
    25 #include "mccjittercalculator.h"
       
    26 #include "mccinternalevents.h"
       
    27 
       
    28 #ifdef VOIP_TRACE_ENABLED
       
    29 #include <voip_trace.h>
       
    30 #endif
       
    31 
       
    32 #ifdef _DEBUG
       
    33 #define TRACE_JITCALC
       
    34 #include <e32svr.h>
       
    35 #endif
       
    36 
       
    37 // CONSTANTS
       
    38 
       
    39 // Packet interval for jitter/jitterbuffer stat reports
       
    40 const TUint KJitterReportInterval = 16;
       
    41 // Conversion factor from uSecs to mSecs
       
    42 const TInt KConversionFactor = 1000;
       
    43 // Samplerate in kHz, currently only 8kHz supported
       
    44 const TUint KSampleRate = 8;
       
    45 
       
    46 const TInt KNum4( 4 );
       
    47 const TInt KNum8( 8 );
       
    48 const TInt KNumZero( 0 );
       
    49 
       
    50 // ============================ MEMBER FUNCTIONS ===============================
       
    51 
       
    52 // -----------------------------------------------------------------------------
       
    53 // CMccJitterCalculator::CMccJitterCalculator
       
    54 // C++ default constructor can NOT contain any code, that
       
    55 // might leave.
       
    56 // -----------------------------------------------------------------------------
       
    57 //
       
    58 CMccJitterCalculator::CMccJitterCalculator( MRtpJitterObserver& aObserver ) : 
       
    59     iObserver( &aObserver )
       
    60     {
       
    61     }
       
    62 
       
    63 // -----------------------------------------------------------------------------
       
    64 // CMccJitterCalculator::ConstructL
       
    65 // Symbian 2nd phase constructor can leave.
       
    66 // -----------------------------------------------------------------------------
       
    67 //
       
    68 #ifdef FTD_ENABLED
       
    69 void CMccJitterCalculator::ConstructL()
       
    70     {
       
    71     TInt err = iStreamStatsQueue.OpenGlobal( KMccStreamStats, EOwnerProcess );
       
    72     if ( KErrNone != err )
       
    73         {
       
    74         User::Leave( err );
       
    75         }
       
    76     
       
    77     err = iJBufStatsQueue.OpenGlobal( KMccJBufferStats, EOwnerProcess );
       
    78     if ( KErrNone != err )
       
    79         {
       
    80         iStreamStatsQueue.Close();
       
    81         User::Leave( err );
       
    82         }
       
    83     }
       
    84 #endif
       
    85 
       
    86 // -----------------------------------------------------------------------------
       
    87 // CMccJitterCalculator::NewL
       
    88 // Static constructor.
       
    89 // -----------------------------------------------------------------------------
       
    90 //
       
    91 CMccJitterCalculator* CMccJitterCalculator::NewL( MRtpJitterObserver& aObserver )
       
    92     {
       
    93     CMccJitterCalculator* self = 
       
    94             new ( ELeave ) CMccJitterCalculator( aObserver );
       
    95     
       
    96     #ifdef FTD_ENABLED
       
    97     CleanupStack::PushL ( self );
       
    98     self->ConstructL ();
       
    99     CleanupStack::Pop( self );
       
   100     #endif
       
   101     
       
   102     return self;
       
   103     }
       
   104 
       
   105 
       
   106 // -----------------------------------------------------------------------------
       
   107 // CMccJitterCalculator::~CMccJitterCalculator
       
   108 // Destructor.
       
   109 // -----------------------------------------------------------------------------
       
   110 //
       
   111 CMccJitterCalculator::~CMccJitterCalculator()
       
   112     {
       
   113     #ifdef TRACE_JITCALC
       
   114         RDebug::Print( _L("CMccJitterCalculator::~CMccJitterCalculator IN") );
       
   115     #endif
       
   116     
       
   117     if ( IsObserving() )
       
   118     	{
       
   119         CancelObserving();               
       
   120         }
       
   121 
       
   122     iObserver = NULL;
       
   123     
       
   124     #ifdef FTD_ENABLED
       
   125     iStreamStatsQueue.Close();
       
   126     iJBufStatsQueue.Close();
       
   127     #endif
       
   128     
       
   129     #ifdef TRACE_JITCALC
       
   130         RDebug::Print( _L("CMccJitterCalculator::~CMccJitterCalculator OUT") );
       
   131     #endif
       
   132     }
       
   133 
       
   134 // -----------------------------------------------------------------------------
       
   135 // CMccJitterCalculator::RtpPacketReceived
       
   136 // Calculates jitter values
       
   137 // -----------------------------------------------------------------------------
       
   138 //
       
   139 void CMccJitterCalculator::RtpPacketReceived( const TUint32 aTimeStamp, 
       
   140     TBool aMarker )
       
   141     {
       
   142     #ifdef TRACE_JITCALC
       
   143         RDebug::Print( _L("CMccJitterCalculator::RtpPacketReceived IN") );
       
   144     #endif
       
   145     
       
   146     #ifdef VOIP_RECEIVED_RTP_PACKET_INFO_ENABLED
       
   147         VoipTrace("%x %x %d %d %d", MCC_TRACE, MCC_RECEIVED_RTP_PACKET_INFO,
       
   148         aHeaderInfo.iSeqNum, aHeaderInfo.iTimestamp, iPacketsReceived );
       
   149     #endif
       
   150     
       
   151     // Jitter calculating based on RFC3550 Appendix A.8, see www.ietf.org
       
   152     if ( aMarker || !iPacketsReceived )
       
   153         {
       
   154         // A new talkspurt, redo calculations Marker bit is set after silent
       
   155         // period and indicates that new speech data is received
       
   156         iPrevPacketArrival.HomeTime();
       
   157         TInt64 pcktTrans = iPrevPacketArrival.Int64() / TInt64( KConversionFactor );
       
   158         
       
   159         // Convert timestamp to milliseconds and calculate transit time   
       
   160         iPrevPacketTransit = 
       
   161                 pcktTrans - static_cast<TInt64>( ( aTimeStamp / KSampleRate ) );
       
   162         
       
   163         // Reset jitter and packet counter for new talkspurt
       
   164         iCurJitter = KNumZero;
       
   165         iPacketsReceived = KNumZero;
       
   166         }
       
   167     else
       
   168         {
       
   169         // Just another packet in the talkspurt
       
   170         TTime newPacket;
       
   171         newPacket.HomeTime();
       
   172         
       
   173         // Time of Arrival in milliseconds
       
   174         TInt64 curPacketTOA = ( newPacket.Int64() / TInt64( KConversionFactor ) );
       
   175         
       
   176         // Convert timestamp to milliseconds and calculate transit time
       
   177         TInt64 curPacketTransit 
       
   178             = curPacketTOA - static_cast<TInt64>( ( aTimeStamp / KSampleRate ) );
       
   179         
       
   180         TInt64 diff = curPacketTransit - iPrevPacketTransit;
       
   181         iPrevPacketTransit = curPacketTransit;
       
   182         diff = Abs( diff );
       
   183 
       
   184         // Jitter is floating mean value over 16 packets last received
       
   185         iCurJitter +=  diff - ( ( iCurJitter + KNum8 ) >> KNum4 );
       
   186         
       
   187         #ifdef TRACE_JITCALC
       
   188             RDebug::Print( _L("CMccJitterCalculator::RtpPacketReceived CUR_TOA: %Ld"), curPacketTOA );
       
   189             RDebug::Print( _L("CMccJitterCalculator::RtpPacketReceived CUR_TRANS: %Ld"), curPacketTransit );
       
   190             RDebug::Print( _L("CMccJitterCalculator::RtpPacketReceived CUR_DIFF: %Ld"), diff );
       
   191             RDebug::Print( _L("CMccJitterCalculator::RtpPacketReceived CUR_JITT: %Lu"), iCurJitter );
       
   192             RDebug::Print( _L("CMccJitterCalculator::RtpPacketReceived SC_CUR_JITT: %Lu"), ( iCurJitter >> KNum4 ) );
       
   193         #endif
       
   194         }
       
   195     
       
   196     iPacketsReceived++;
       
   197     iCurTime.HomeTime();
       
   198     
       
   199     #ifdef TRACE_JITCALC
       
   200         RDebug::Print ( _L("CMccJitterCalculator::RtpPacketReceived newPacket = %Ld"), iCurTime.Int64() );
       
   201     #endif
       
   202     
       
   203     #ifdef FTD_ENABLED
       
   204     TMccStreamStats stats;
       
   205     stats.iPacketsReceived = iPacketsReceived;
       
   206     stats.SetFieldUpdatedFlag( EPacketsReceived );
       
   207     iStreamStatsQueue.Send( stats );
       
   208     
       
   209     TMccJBufferStats jStats;
       
   210     jStats.iJitterEstimate = iCurJitter;
       
   211     iJBufStatsQueue.Send( jStats );
       
   212     #endif 
       
   213     
       
   214     // Report jitter if we have enough received packets and jitter
       
   215     if ( !( iPacketsReceived % KJitterReportInterval ) && iCurJitter )
       
   216         {
       
   217         #ifdef TRACE_JITCALC
       
   218             RDebug::Print( _L("CMccJitterCalculator::RtpPacketReceived SENDING RCV: %d"), iPacketsReceived );
       
   219         #endif
       
   220         
       
   221         TMccRtpEventData event( ( iCurJitter >> KNum4 ), 
       
   222                                 iPacketsReceived, 
       
   223                                 iPrevPacketTransit,
       
   224                                 KNumZero );
       
   225         
       
   226         iObserver->SendJitterEvent( event, KErrNone );
       
   227         }
       
   228     
       
   229     JitterObserving();
       
   230     }
       
   231 
       
   232 // ---------------------------------------------------------------------------
       
   233 // CMccJitterCalculator::StartObserving
       
   234 // Switch to deside report type
       
   235 // ---------------------------------------------------------------------------
       
   236 //  
       
   237 TInt CMccJitterCalculator::StartObserving()
       
   238     {
       
   239     #ifdef TRACE_JITCALC
       
   240         RDebug::Print( _L("CMccJitterCalculator::StartObserving IN") );
       
   241     #endif
       
   242     
       
   243     TInt err( KErrNone );
       
   244     iHomeTime.HomeTime();
       
   245     
       
   246     #ifdef TRACE_JITCALC
       
   247         RDebug::Print ( _L("CMccJitterCalculator::StartObserving HomeTime = %Ld"), iHomeTime.Int64()  );
       
   248         RDebug::Print( _L("CMccJitterCalculator::StartObserving iReportType: %d"), iReportType );
       
   249     #endif
       
   250 
       
   251     switch( iReportType )
       
   252         {
       
   253         case EMccJitterReport:
       
   254             #ifdef TRACE_JITCALC
       
   255                 RDebug::Print( _L("CMccJitterCalculator::StartObserving  iReportType selected EMccJitterReport"));
       
   256             #endif
       
   257             iJitterObsOn = ETrue;                
       
   258             iMediaQualityObservingStarted = ETrue;                
       
   259             break;
       
   260             
       
   261         case EMccPacketLossReport:
       
   262             #ifdef TRACE_JITCALC
       
   263                 RDebug::Print( _L("CMccJitterCalculator::StartObserving  iReportType selected EMccPacketLossReport"));
       
   264             #endif
       
   265             iFrameLossObsOn = ETrue;
       
   266             iMediaQualityObservingStarted = ETrue;
       
   267             break;
       
   268             
       
   269         case EMccQualityReportAll:
       
   270             #ifdef TRACE_JITCALC
       
   271                 RDebug::Print( _L("CMccJitterCalculator::StartObserving  iReportType selected EMccQualityReportAll"));
       
   272             #endif
       
   273             iJitterObsOn = ETrue;
       
   274             iFrameLossObsOn = ETrue;
       
   275             iMediaQualityObservingStarted = ETrue;
       
   276             break;
       
   277 
       
   278         default:
       
   279             // if report type is not set
       
   280             #ifdef TRACE_JITCALC
       
   281                 RDebug::Print( _L("CMccJitterCalculator::StartObserving  iReportType selected default"));
       
   282             #endif
       
   283             
       
   284             err = KErrArgument;
       
   285             break;
       
   286         }
       
   287     
       
   288     return err;
       
   289     }
       
   290 
       
   291 // ---------------------------------------------------------------------------
       
   292 // CMccJitterCalculator::CancelObserving
       
   293 // Cancel is called by client
       
   294 // ---------------------------------------------------------------------------
       
   295 //  
       
   296 void CMccJitterCalculator::CancelObserving()
       
   297     {
       
   298     #ifdef TRACE_JITCALC
       
   299         RDebug::Print( _L("CMccJitterCalculator::CancelObserving IN") );
       
   300     #endif
       
   301     
       
   302     iJitterObsOn = EFalse;
       
   303     iFrameLossObsOn = EFalse;
       
   304     iMediaQualityObservingStarted = EFalse;
       
   305     }
       
   306 
       
   307 // ---------------------------------------------------------------------------
       
   308 // CMccJitterCalculator::SetMediaConfigsL
       
   309 // Open aMessage and read media configs
       
   310 // ---------------------------------------------------------------------------
       
   311 //     
       
   312 void CMccJitterCalculator::SetMediaConfigsL( const TMMFMessage& aMessage )
       
   313     {
       
   314     #ifdef TRACE_JITCALC
       
   315         RDebug::Print( _L("CMccJitterCalculator::SetMediaConfigs IN") );
       
   316     #endif
       
   317     
       
   318     TMMFMessage* tmp = new ( ELeave ) TMMFMessage( aMessage );
       
   319     CleanupStack::PushL( tmp );
       
   320     
       
   321     TMccMediaQualConfBuf configPckg;
       
   322     tmp->ReadData1FromClientL( configPckg );
       
   323 
       
   324     iMediaConf = configPckg();
       
   325         
       
   326     // Read data from client
       
   327     iJitterLevelFromClient = iMediaConf.iJitterLevel;
       
   328     iPacketLossFromClient = iMediaConf.iPacketLoss;
       
   329     iReportType = iMediaConf.iReportType;
       
   330     iReportIntervalType = iMediaConf.iReportIntervalType;
       
   331     iReportInterval = iMediaConf.iReportInterval;
       
   332         
       
   333     #ifdef TRACE_JITCALC
       
   334         RDebug::Print( _L("CMccJitterCalculator::SetMediaConfigsL SESSION %d"), iMediaConf.iSessionId );
       
   335         RDebug::Print( _L("CMccJitterCalculator::SetMediaConfigsL JITTER LEVEL %d"), iMediaConf.iJitterLevel );
       
   336         RDebug::Print( _L("CMccJitterCalculator::SetMediaConfigsL PACKET LOSS %d"), iMediaConf.iPacketLoss ); 
       
   337         RDebug::Print( _L("CMccJitterCalculator::SetMediaConfigsL REPORT TYPE %d"), iMediaConf.iReportType );
       
   338         RDebug::Print( _L("CMccJitterCalculator::SetMediaConfigsL REPORT INTERVAL TYPE %d"), iMediaConf.iReportIntervalType );
       
   339         RDebug::Print( _L("CMccJitterCalculator::SetMediaConfigsL REPORT INTERVAL %d"), iMediaConf.iReportInterval );
       
   340     #endif
       
   341         
       
   342     CleanupStack::PopAndDestroy( tmp );
       
   343     }
       
   344 
       
   345 // -----------------------------------------------------------------------------
       
   346 // CMccJitterCalculator::ResetCounters
       
   347 // Set counters ready to receive packets
       
   348 // -----------------------------------------------------------------------------
       
   349 //
       
   350 void CMccJitterCalculator::ResetCounters()
       
   351     {
       
   352     #ifdef TRACE_JITCALC
       
   353         RDebug::Print( _L("CMccJitterCalculator::ResetCounters()") );
       
   354     #endif
       
   355         
       
   356     iPacketsReceived = KNumZero;
       
   357     iCurJitter = KNumZero;
       
   358     iPrevPacketTransit = KNumZero;
       
   359     }
       
   360 
       
   361 // -----------------------------------------------------------------------------
       
   362 // CMccJitterCalculator::JitterObserving
       
   363 // Trigger controller. Compares calculated and defined values.
       
   364 // private method
       
   365 // -----------------------------------------------------------------------------
       
   366 //  
       
   367 void CMccJitterCalculator::JitterObserving()
       
   368     {
       
   369     if ( iJitterObsOn )
       
   370         {
       
   371         #ifdef TRACE_JITCALC
       
   372             RDebug::Print( _L("CMccJitterCalculator::JitterObserving Jitter level observing ON") );
       
   373             RDebug::Print( _L("CMccJitterCalculator::JitterObserving jitterlevel %u ms compared to jitter estimate %Lu ms"), 
       
   374                 iJitterLevelFromClient, ( iCurJitter / KConversionFactor ) );
       
   375         #endif
       
   376         
       
   377         // Normalize iCurJitter
       
   378         TUint64 modJitter = iCurJitter >> KNum4;
       
   379             
       
   380         if ( EMccQualityTimeBased == iReportIntervalType )
       
   381             {
       
   382             // change microsecs to millisecs
       
   383             TTimeIntervalMicroSeconds getTime = 
       
   384                 iCurTime.MicroSecondsFrom( iHomeTime );
       
   385             
       
   386             #ifdef TRACE_JITCALC
       
   387                 RDebug::Print( _L("CMccJitterCalculator::JitterObserving getTime = %Ld"), getTime.Int64() );
       
   388             #endif
       
   389             
       
   390             if ( static_cast<TInt64>( iReportInterval ) <= 
       
   391                ( getTime.Int64() / KConversionFactor ) )
       
   392                 {
       
   393                 // compare clients jitter level to current level
       
   394                 if ( static_cast<TUint64>( iJitterLevelFromClient ) < 
       
   395                     modJitter )
       
   396                     {
       
   397                     #ifdef TRACE_JITCALC
       
   398                         RDebug::Print ( _L("CMccJitterCalculator::JitterObserving jitterlevel %u ms compared to jitter estimate %Lu ms"), 
       
   399                             iJitterLevelFromClient, modJitter );
       
   400                     #endif
       
   401                     
       
   402                     TMccRtpEventData event( ( iCurJitter >> KNum4 ), 
       
   403                                             iPacketsReceived, 
       
   404                                             iPrevPacketTransit,
       
   405                                             modJitter );
       
   406                     
       
   407                     // Informs client via event and cancels jitter observing
       
   408                     iObserver->SendJitterEvent( event, KErrNone );
       
   409                     CancelObserving();
       
   410                     }
       
   411                 
       
   412                 // Initialize hometime again
       
   413                 iHomeTime.HomeTime();
       
   414                 
       
   415                 #ifdef TRACE_JITCALC       
       
   416                     RDebug::Print ( _L("CMccJitterCalculator::JitterObserving Initialize iHomeTime = %Ld"), iHomeTime.Int64() );
       
   417                 #endif
       
   418             
       
   419                 }           
       
   420             }
       
   421         else if ( EMccQualityPacketBased == iReportIntervalType )
       
   422             {
       
   423             iReceivedPacketCounter++;
       
   424             
       
   425             #ifdef TRACE_JITCALC
       
   426                 RDebug::Print( _L("CMccJitterCalculator::JitterObserving iReceivedPacketCounter: %u"), iReceivedPacketCounter );
       
   427             #endif
       
   428             
       
   429             if ( iReportInterval == iReceivedPacketCounter )
       
   430                 {
       
   431                 // compare clients jitter level to current level
       
   432                 if ( iJitterLevelFromClient < modJitter )
       
   433                     {
       
   434                     #ifdef TRACE_JITCALC
       
   435                         RDebug::Print( _L("CMccJitterCalculator::JitterObserving jitterlevel %u ms compared to jitter estimate %Lu ms"), 
       
   436                             iJitterLevelFromClient, modJitter );
       
   437                     #endif
       
   438                     
       
   439                     TMccRtpEventData event( ( iCurJitter >> KNum4 ), 
       
   440                                             iPacketsReceived, 
       
   441                                             iPrevPacketTransit,
       
   442                                             modJitter );
       
   443                     
       
   444                     // Informs client via event and cancels jitter observing
       
   445                     iObserver->SendJitterEvent( event, KErrNone );
       
   446                     CancelObserving();
       
   447                     }
       
   448                   
       
   449                 iReceivedPacketCounter = KNumZero;
       
   450                 }
       
   451             }
       
   452          else
       
   453             {
       
   454             #ifdef TRACE_JITCALC
       
   455                 RDebug::Print( _L("CMccJitterCalculator::JitterObserving Report type is not valid!") );
       
   456             #endif
       
   457             
       
   458             TMccRtpEventData event( ( iCurJitter >> KNum4 ), 
       
   459                                       iPacketsReceived, 
       
   460                                       iPrevPacketTransit,
       
   461                                       KNumZero );
       
   462             
       
   463             iObserver->SendJitterEvent( event, KErrArgument );
       
   464             CancelObserving();
       
   465             }
       
   466         }
       
   467     }
       
   468 
       
   469 // ---------------------------------------------------------------------------
       
   470 // CMccJitterCalculator::IsObserving
       
   471 // To check if observing is ON
       
   472 // ---------------------------------------------------------------------------
       
   473 //      
       
   474 TBool CMccJitterCalculator::IsObserving() const
       
   475     {
       
   476     return iMediaQualityObservingStarted;
       
   477     }
       
   478     
       
   479 //  End of File