|         |      1 /* | 
|         |      2 * Copyright (c) 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:     | 
|         |     15 * | 
|         |     16 */ | 
|         |     17  | 
|         |     18  | 
|         |     19  | 
|         |     20 // INCLUDE FILES | 
|         |     21 #include "mccqoscontroller.h" | 
|         |     22 #include "mccrateadaptationobserver.h" | 
|         |     23 #include "mmccevents.h" | 
|         |     24 #include "mccresources.h" | 
|         |     25 #include "mccdatasource.h" | 
|         |     26 #include "mccdatasink.h" | 
|         |     27 #include "QosControllerLog.h" | 
|         |     28 #include "mccinternalevents.h" | 
|         |     29  | 
|         |     30 // EXTERNAL DATA STRUCTURES | 
|         |     31  | 
|         |     32 // EXTERNAL FUNCTION PROTOTYPES   | 
|         |     33  | 
|         |     34 // CONSTANTS | 
|         |     35 const TInt KPluginMicroSecInSec = 1; | 
|         |     36 // MACROS | 
|         |     37  | 
|         |     38 // LOCAL CONSTANTS AND MACROS | 
|         |     39  | 
|         |     40 // MODULE DATA STRUCTURES | 
|         |     41  | 
|         |     42 // LOCAL FUNCTION PROTOTYPES | 
|         |     43  | 
|         |     44 // FORWARD DECLARATIONS | 
|         |     45  | 
|         |     46 // ============================= LOCAL FUNCTIONS =============================== | 
|         |     47  | 
|         |     48 // ============================ MEMBER FUNCTIONS =============================== | 
|         |     49  | 
|         |     50 // ----------------------------------------------------------------------------- | 
|         |     51 // CMccQosController::NewL | 
|         |     52 // ----------------------------------------------------------------------------- | 
|         |     53 // | 
|         |     54 EXPORT_C CMccQosController* CMccQosController::NewL(  | 
|         |     55     MMccRateAdaptationObserver& aObserver, | 
|         |     56     MMccResources& aResources ) | 
|         |     57     { | 
|         |     58     __TRACE_MCC_QOS_CONTROLLER1("CMccQosController::NewL"); | 
|         |     59     CMccQosController* self =  | 
|         |     60         new ( ELeave ) CMccQosController( aObserver, aResources ); | 
|         |     61     CleanupStack::PushL( self ); | 
|         |     62     self->ConstructL(); | 
|         |     63     CleanupStack::Pop( self ); | 
|         |     64     return self; | 
|         |     65     } | 
|         |     66  | 
|         |     67 // ----------------------------------------------------------------------------- | 
|         |     68 // CMccQosController::~CMccQosController | 
|         |     69 // ----------------------------------------------------------------------------- | 
|         |     70 //         | 
|         |     71 EXPORT_C CMccQosController::~CMccQosController() | 
|         |     72     { | 
|         |     73     __TRACE_MCC_QOS_CONTROLLER1("CMccQosController::~CMccQosController"); | 
|         |     74     if ( iDeltaTimer ) | 
|         |     75         { | 
|         |     76         iDeltaTimer->Remove( iDeltaTimerEntry ); | 
|         |     77         } | 
|         |     78     delete iDeltaTimer; | 
|         |     79      | 
|         |     80     iIcmpErrors.Reset(); | 
|         |     81     iIcmpErrors.Close(); | 
|         |     82      | 
|         |     83     __TRACE_MCC_QOS_CONTROLLER1("CMccQosController::~CMccQosController end"); | 
|         |     84     } | 
|         |     85  | 
|         |     86 // ----------------------------------------------------------------------------- | 
|         |     87 // CMccQosController::EventReceived | 
|         |     88 // ----------------------------------------------------------------------------- | 
|         |     89 // | 
|         |     90 EXPORT_C TBool CMccQosController::EventReceived( const TMccEvent& aEvent ) | 
|         |     91     { | 
|         |     92     __TRACE_MCC_QOS_CONTROLLER1("CMccQosController::EventReceived"); | 
|         |     93      | 
|         |     94     // Check if interesting event and then do calculations. | 
|         |     95     // If adaptation is needed, make async brake and continue with it once | 
|         |     96     // dummy async completes. QosController has also responsibility of | 
|         |     97     // icmp error handling (random errors are filtered etc.). | 
|         |     98      | 
|         |     99     TBool ignoreEvent( EFalse ); | 
|         |    100      | 
|         |    101     if ( aEvent.iEventCategory == KMccEventCategoryRtcp ) | 
|         |    102     	{ | 
|         |    103 		__TRACE_MCC_QOS_CONTROLLER3( | 
|         |    104 		    "CMccQosController::EventReceived TMccEvent:iSessionId=",  | 
|         |    105 		    aEvent.iSessionId); | 
|         |    106 		__TRACE_MCC_QOS_CONTROLLER3( | 
|         |    107 		    "CMccQosController::EventReceived TMccEvent:iLinkId=",  | 
|         |    108 		    aEvent.iLinkId); | 
|         |    109 		__TRACE_MCC_QOS_CONTROLLER3( | 
|         |    110 		    "CMccQosController::EventReceived TMccEvent:iStreamId=",  | 
|         |    111 		    aEvent.iStreamId); | 
|         |    112 		__TRACE_MCC_QOS_CONTROLLER3( | 
|         |    113 		    "CMccQosController::EventReceived TMccEvent:iEndpointId=",  | 
|         |    114 		    aEvent.iEndpointId); | 
|         |    115 		__TRACE_MCC_QOS_CONTROLLER3( | 
|         |    116 		    "CMccQosController::EventReceived TMccEvent:iErrorCode=",  | 
|         |    117 		    aEvent.iErrorCode); | 
|         |    118  | 
|         |    119 		const TMccRtcpEventData& eventdata =  | 
|         |    120     		(*reinterpret_cast<const TMccRtcpEventDataPackage*>(  | 
|         |    121                 &aEvent.iEventData ))();  | 
|         |    122                        | 
|         |    123     	if ( eventdata.iRtcpPacketType == KRtcpRrPacket ) | 
|         |    124             { | 
|         |    125             // RR received | 
|         |    126      | 
|         |    127             iStreamStat = eventdata.iStats; | 
|         |    128 			__TRACE_MCC_QOS_CONTROLLER3( | 
|         |    129 			    "CMccQosController::EventReceived TRtpPeerStat:iNumPacketsSent=",  | 
|         |    130 			    iStreamStat.iNumPacketsSent); | 
|         |    131 			__TRACE_MCC_QOS_CONTROLLER3( | 
|         |    132 			    "CMccQosController::EventReceived TRtpPeerStat:iCumNumOctetsSent=",  | 
|         |    133 			    iStreamStat.iCumNumOctetsSent); | 
|         |    134 			__TRACE_MCC_QOS_CONTROLLER3( | 
|         |    135 			    "CMccQosController::EventReceived TRtpPeerStat:RoundTripDelay=",  | 
|         |    136 			    iStreamStat.iRoundTripDelay); | 
|         |    137   			__TRACE_MCC_QOS_CONTROLLER3( | 
|         |    138   			    "CMccQosController::EventReceived TRtpPeerStat:iTxBandwidth=",  | 
|         |    139   			    iStreamStat.iTxBandwidth); | 
|         |    140  			__TRACE_MCC_QOS_CONTROLLER3( | 
|         |    141  			    "CMccQosController::EventReceived TRtpPeerStat:iCumNumPacketsLost=",  | 
|         |    142  			    iStreamStat.iCumNumPacketsLost); | 
|         |    143  			__TRACE_MCC_QOS_CONTROLLER3( | 
|         |    144  			    "CMccQosController::EventReceived TRtpPeerStat:iFractionLost=",  | 
|         |    145  			    iStreamStat.iFractionLost); | 
|         |    146  			__TRACE_MCC_QOS_CONTROLLER3( | 
|         |    147  			    "CMccQosController::EventReceived TRtpPeerStat:iArrivalJitter=",  | 
|         |    148  			    iStreamStat.iArrivalJitter); | 
|         |    149   			__TRACE_MCC_QOS_CONTROLLER3( | 
|         |    150   			    "CMccQosController::EventReceived TRtpPeerStat:iRxBandwidth=",  | 
|         |    151   			    iStreamStat.iRxBandwidth); | 
|         |    152    			__TRACE_MCC_QOS_CONTROLLER3( | 
|         |    153    			    "CMccQosController::EventReceived TRtpPeerStat:iChannelBufferSize=",  | 
|         |    154    			    iStreamStat.iChannelBufferSize); | 
|         |    155   			__TRACE_MCC_QOS_CONTROLLER3( | 
|         |    156   			    "CMccQosController::EventReceived TRtpPeerStat:iNTPTimeStampSec=",  | 
|         |    157   			    iStreamStat.iNTPTimeStampSec);   			 | 
|         |    158   			__TRACE_MCC_QOS_CONTROLLER3( | 
|         |    159   			    "CMccQosController::EventReceived TRtpPeerStat:iNTPTimeStampFrac=",  | 
|         |    160   			    iStreamStat.iNTPTimeStampFrac); | 
|         |    161   			 | 
|         |    162             DoAdaptationCalculations(); | 
|         |    163             } | 
|         |    164         } | 
|         |    165     else if ( aEvent.iEventCategory == KMccEventCategoryRtp &&  | 
|         |    166               aEvent.iEventType == KMccStreamError && | 
|         |    167               aEvent.iErrorCode == KErrHostUnreach ) | 
|         |    168         { | 
|         |    169         ignoreEvent = HandleIcmpError( aEvent ); | 
|         |    170         } | 
|         |    171     else | 
|         |    172         { | 
|         |    173         // NOP | 
|         |    174         } | 
|         |    175      | 
|         |    176     __TRACE_MCC_QOS_CONTROLLER1("CMccQosController::EventReceived end");    | 
|         |    177       | 
|         |    178     return ignoreEvent; | 
|         |    179     } | 
|         |    180      | 
|         |    181 //----------------------------------------------------------------------------- | 
|         |    182 // CMccQosController::DoAdaptationCalculations   | 
|         |    183 // ----------------------------------------------------------------------------- | 
|         |    184 //   | 
|         |    185 void CMccQosController::DoAdaptationCalculations() | 
|         |    186 	{ | 
|         |    187 	__TRACE_MCC_QOS_CONTROLLER1("CMccQosController::DoAdaptationCalculations"); | 
|         |    188  | 
|         |    189 	#ifdef RATECONTROL | 
|         |    190 	 | 
|         |    191 	ClearRateEventData(); | 
|         |    192 	 | 
|         |    193 	__TRACE_MCC_QOS_CONTROLLER3("CMccQosController::RoundTripTime",  | 
|         |    194 	                            iRoundTripTime ); | 
|         |    195 	__TRACE_MCC_QOS_CONTROLLER3("CMccQosController::RoundTripDelay",  | 
|         |    196 	                            iStreamStat.iRoundTripDelay ); | 
|         |    197 		 | 
|         |    198 	if ( iRoundTripTime ) | 
|         |    199 		{ | 
|         |    200 		// Temporary change will not affect immediately so much (kind of mean value) | 
|         |    201 		const TReal q = 0.9; | 
|         |    202 		iRoundTripTime =  | 
|         |    203 		    TInt ( q * iRoundTripTime + (1.0 - q) * iStreamStat.iRoundTripDelay ); | 
|         |    204 		__TRACE_MCC_QOS_CONTROLLER3("CMccQosController::New RoundTripTime=",  | 
|         |    205 		                            iRoundTripTime ); | 
|         |    206 		} | 
|         |    207 	else | 
|         |    208 		{ | 
|         |    209 		iRoundTripTime = iStreamStat.iRoundTripDelay;  | 
|         |    210 		} | 
|         |    211 	 | 
|         |    212 	// Store some amount of previous round trip delay values in order to | 
|         |    213 	// calculate average value of certain period	 | 
|         |    214     iRoundTripDelays[ iEventCounter % KMccShortTermCalculation ] = iStreamStat.iRoundTripDelay; | 
|         |    215      | 
|         |    216     iEventCounter++; | 
|         |    217      | 
|         |    218     TBool adaptedAtThisRound( EFalse ); | 
|         |    219 	 | 
|         |    220 	if ( iStreamStat.iFractionLost > iThresholdValues.iFractionLostHigh ) | 
|         |    221 	    { | 
|         |    222 	    // Immediately drop bitrate if significant number of packets got lost | 
|         |    223 	    __TRACE_MCC_QOS_CONTROLLER1( | 
|         |    224 	        "CMccQosController::DoAdaptationCalculations, fractions lost, decrease"); | 
|         |    225 	    iRateEventData.iRateAdaptationAdvice = ( 1.0 - KAdaptation ); | 
|         |    226 	    DoAdaptation(); | 
|         |    227 	    adaptedAtThisRound = ETrue; | 
|         |    228 	    }	  | 
|         |    229      | 
|         |    230     if ( !( iEventCounter % KMccShortTermCalculation ) ) | 
|         |    231         { | 
|         |    232         // If long term calculation resulted in change, we are interested  | 
|         |    233         // how it affected to average round trip delay | 
|         |    234         __TRACE_MCC_QOS_CONTROLLER1( | 
|         |    235             "CMccQosController::DoAdaptationCalculations, short term"); | 
|         |    236              | 
|         |    237         TInt roundTripDelayOfThisPeriod = CalculateDelayOfShortTermPeriod(); | 
|         |    238          | 
|         |    239         __TRACE_MCC_QOS_CONTROLLER3( | 
|         |    240             "CMccQosController::DoAdaptationCalculations, avg delay of this period",  | 
|         |    241             roundTripDelayOfThisPeriod ); | 
|         |    242          | 
|         |    243         if ( !adaptedAtThisRound ) | 
|         |    244             { | 
|         |    245             TInt comparisonDelay = GetShortTermComparisonDelay(); | 
|         |    246              | 
|         |    247             __TRACE_MCC_QOS_CONTROLLER3( | 
|         |    248                 "CMccQosController::DoAdaptationCalculations, comparison delay",  | 
|         |    249                 comparisonDelay ); | 
|         |    250              | 
|         |    251             if ( roundTripDelayOfThisPeriod - comparisonDelay > KRoundTripTimeLimit ) | 
|         |    252                 { | 
|         |    253                 __TRACE_MCC_QOS_CONTROLLER1( | 
|         |    254                     "CMccQosController::DoAdaptationCalculations, decrease"); | 
|         |    255                 iRateEventData.iRateAdaptationAdvice = 1.0 - KAdaptation; | 
|         |    256                 DoAdaptation(); | 
|         |    257                 adaptedAtThisRound = ETrue; | 
|         |    258                 } | 
|         |    259             else if ( comparisonDelay - roundTripDelayOfThisPeriod > KRoundTripTimeLimit ) | 
|         |    260                 { | 
|         |    261                 __TRACE_MCC_QOS_CONTROLLER1( | 
|         |    262                     "CMccQosController::DoAdaptationCalculations, increase"); | 
|         |    263                 iRateEventData.iRateAdaptationAdvice = 1.0 + KAdaptation; | 
|         |    264                 DoAdaptation(); | 
|         |    265                 adaptedAtThisRound = ETrue; | 
|         |    266                 } | 
|         |    267             else | 
|         |    268                 { | 
|         |    269                 } | 
|         |    270             } | 
|         |    271              | 
|         |    272         iRoundTripDelayOfPreviousShortPeriod = roundTripDelayOfThisPeriod; | 
|         |    273         } | 
|         |    274 	 | 
|         |    275 	if ( !( iEventCounter % KMccLongTermCalculation ) ) | 
|         |    276 	    { | 
|         |    277 	    __TRACE_MCC_QOS_CONTROLLER1( | 
|         |    278 	        "CMccQosController::DoAdaptationCalculations, long term"); | 
|         |    279 	     | 
|         |    280 	    if ( !adaptedAtThisRound && !iAdapted ) | 
|         |    281 	        { | 
|         |    282 	        // If adaptation wasn't needed within previous long term period, try to | 
|         |    283 	        // increase bitrate. Remember round trip time of this period so that | 
|         |    284 	        // we can see what kind of impact the increasing of bitrate has.  | 
|         |    285 	        __TRACE_MCC_QOS_CONTROLLER1( | 
|         |    286 	            "CMccQosController::DoAdaptationCalculations, try to increase"); | 
|         |    287 	        iRateEventData.iRateAdaptationAdvice = ( 1.0 + KAdaptationMore ); | 
|         |    288 	        DoAdaptation(); | 
|         |    289 	        adaptedAtThisRound = ETrue; | 
|         |    290 	        } | 
|         |    291 	         | 
|         |    292 	    iAdapted = EFalse; | 
|         |    293 	    } | 
|         |    294 			 | 
|         |    295 	#endif //RATECONTROL	 | 
|         |    296 	__TRACE_MCC_QOS_CONTROLLER1("CMccQosController::DoAdaptationCalculations end"); | 
|         |    297     } | 
|         |    298      | 
|         |    299 // ----------------------------------------------------------------------------- | 
|         |    300 // CMccQosController::FillRateAdaptationEventL | 
|         |    301 // ----------------------------------------------------------------------------- | 
|         |    302 //       | 
|         |    303 void CMccQosController::FillRateAdaptationEvent() | 
|         |    304 	{ | 
|         |    305 	__TRACE_MCC_QOS_CONTROLLER1("CMccQosController::FillRateAdaptationEvent"); | 
|         |    306 	iEvent = TMccEvent(); | 
|         |    307 	TMccRateAdaptationEventDataPackage temp(iRateEventData); | 
|         |    308 	iEvent.iEventData.Copy( temp );	  | 
|         |    309 	__TRACE_MCC_QOS_CONTROLLER1("CMccQosController::FillRateAdaptationEvent end"); | 
|         |    310 	} | 
|         |    311 	 | 
|         |    312 // ----------------------------------------------------------------------------- | 
|         |    313 // CMccQosController::ClearRateEventData | 
|         |    314 // ----------------------------------------------------------------------------- | 
|         |    315 //       | 
|         |    316 void CMccQosController::ClearRateEventData() | 
|         |    317 	{ | 
|         |    318 	__TRACE_MCC_QOS_CONTROLLER1("CMccQosController::ClearRateEventData");	 | 
|         |    319 	iRateEventData = TMccRateAdaptationEventData(); | 
|         |    320 	__TRACE_MCC_QOS_CONTROLLER1("CMccQosController::ClearRateEventData end");	 | 
|         |    321 	} | 
|         |    322 	 | 
|         |    323 // ----------------------------------------------------------------------------- | 
|         |    324 // CMccQosController::StartTimerForAsync | 
|         |    325 // ----------------------------------------------------------------------------- | 
|         |    326 // | 
|         |    327 void CMccQosController::StartTimerForAsync () | 
|         |    328 	{ | 
|         |    329 	__TRACE_MCC_QOS_CONTROLLER1("CMccQosController::StartTimerForAsync"); | 
|         |    330 	iDeltaTimer->Remove(iDeltaTimerEntry); | 
|         |    331 	TTimeIntervalMicroSeconds32 interval(KPluginMicroSecInSec); | 
|         |    332 	iDeltaTimer->Queue(interval, iDeltaTimerEntry); | 
|         |    333 	__TRACE_MCC_QOS_CONTROLLER1("CMccQosController::StartTimerForAsync end");	 | 
|         |    334 	}	 | 
|         |    335   | 
|         |    336 // ----------------------------------------------------------------------------- | 
|         |    337 // CMccQosController::AsyncTimerExpired | 
|         |    338 // ----------------------------------------------------------------------------- | 
|         |    339 // | 
|         |    340 TInt CMccQosController::AsyncTimerExpired(TAny* aPtr) | 
|         |    341 	{ | 
|         |    342 	__TRACE_MCC_QOS_CONTROLLER1("CMccQosController::AsyncTimerExpired"); | 
|         |    343  | 
|         |    344 	CMccQosController* self = reinterpret_cast<CMccQosController*>(aPtr); | 
|         |    345 	self ->GetSinkSources(); | 
|         |    346 	 | 
|         |    347 	__TRACE_MCC_QOS_CONTROLLER1("CMccQosController::AsyncTimerExpired end"); | 
|         |    348   	return ETrue; | 
|         |    349 	}  | 
|         |    350      | 
|         |    351 // ----------------------------------------------------------------------------- | 
|         |    352 // CMccQosController::GetSinkSources | 
|         |    353 // ----------------------------------------------------------------------------- | 
|         |    354 // | 
|         |    355 void CMccQosController::GetSinkSources() | 
|         |    356 	{ | 
|         |    357 	__TRACE_MCC_QOS_CONTROLLER1("CMccQosController::GetSinkSources"); | 
|         |    358     iBitRateChanged = EFalse; | 
|         |    359     const RPointerArray<MDataSource>& tempSources = iResources.Sources( ETrue ); | 
|         |    360   	FillRateAdaptationEvent(); | 
|         |    361   	TInt result = 0; | 
|         |    362   	for ( TInt i = 0; i < tempSources.Count(); i++ ) | 
|         |    363         { | 
|         |    364         iResultEvent = TMccEvent(); | 
|         |    365 		__TRACE_MCC_QOS_CONTROLLER3("CMccQosController::GetSinkSources Sources", i); | 
|         |    366  | 
|         |    367         CMccDataSource* item = static_cast<CMccDataSource*> (tempSources[ i ]);  | 
|         |    368         iResultEvent = TMccEvent(); 	 | 
|         |    369         result = item->RateAdaptationRequest( iEvent, iResultEvent ); | 
|         |    370         CheckRateChangeResult( result ); | 
|         |    371         } | 
|         |    372   	const RPointerArray<MDataSink>& tempSinks = iResources.Sinks( ETrue ); | 
|         |    373   	for ( TInt j = 0; j < tempSinks.Count(); j++ ) | 
|         |    374         { | 
|         |    375         iResultEvent = TMccEvent(); | 
|         |    376 		__TRACE_MCC_QOS_CONTROLLER3("CMccQosController::GetSinkSources Sinks", j);         | 
|         |    377         CMccDataSink* item = static_cast<CMccDataSink*> (tempSinks[ j ]); | 
|         |    378         result = item->RateAdaptationRequest( iEvent, iResultEvent ); | 
|         |    379         CheckRateChangeResult( result ); | 
|         |    380         } | 
|         |    381     if ( !iBitRateChanged ) | 
|         |    382     	{ | 
|         |    383     	iMainObserver.RateAdaptationAlert( iEvent, | 
|         |    384     				 MMccRateAdaptationObserver::ERateAdaptationNotPossible ); | 
|         |    385     	} | 
|         |    386 	__TRACE_MCC_QOS_CONTROLLER1("CMccQosController::GetSinkSources END");  | 
|         |    387 	}     | 
|         |    388      | 
|         |    389 // ----------------------------------------------------------------------------- | 
|         |    390 // CMccQosController::CheckRateChangeResult | 
|         |    391 // ----------------------------------------------------------------------------- | 
|         |    392 //  | 
|         |    393 void CMccQosController::CheckRateChangeResult( TInt aValue ) | 
|         |    394     { | 
|         |    395 	__TRACE_MCC_QOS_CONTROLLER1("CMccQosController::CheckRateChangeResult");     | 
|         |    396     if ( aValue == KErrNone ) | 
|         |    397     	{ | 
|         |    398 		TMccRateAdaptationEventDataPackage resultdatapkg; | 
|         |    399 		resultdatapkg.Copy(iResultEvent.iEventData); | 
|         |    400 		TMccRateAdaptationEventData resultdata = resultdatapkg(); | 
|         |    401         if ( resultdata.iBitrateOriginal != resultdata.iBitrateModified ) | 
|         |    402         	{ | 
|         |    403         	__TRACE_MCC_QOS_CONTROLLER1("CMccQosController::BitRateChanged ETRUE"); | 
|         |    404         	iBitRateChanged = ETrue; | 
|         |    405         	} | 
|         |    406     	} | 
|         |    407 	__TRACE_MCC_QOS_CONTROLLER1("CMccQosController::CheckRateChangeResult end"); | 
|         |    408     } | 
|         |    409  | 
|         |    410 // ----------------------------------------------------------------------------- | 
|         |    411 // CMccQosController::HandleIcmpError | 
|         |    412 // ----------------------------------------------------------------------------- | 
|         |    413 //  | 
|         |    414 TBool CMccQosController::HandleIcmpError( const TMccEvent& aEvent ) | 
|         |    415     { | 
|         |    416     __TRACE_MCC_QOS_CONTROLLER1("CMccQosController::HandleIcmpError");    | 
|         |    417      | 
|         |    418     // By default error is ignored. Only if there has been certain amount | 
|         |    419     // of errors within certain time window, error is reported. | 
|         |    420     // | 
|         |    421     TBool ignoreError( ETrue ); | 
|         |    422      | 
|         |    423     // Do first cleanup of all entries which have exceeded their monitoring | 
|         |    424     // timewindow. | 
|         |    425     TTime currentTime; | 
|         |    426     currentTime.HomeTime(); | 
|         |    427     TMccQosControllerIcmpError cleanupIcmpError; | 
|         |    428     cleanupIcmpError.iErrorTimeWindowBeginning = currentTime; | 
|         |    429     TIdentityRelation<TMccQosControllerIcmpError>  | 
|         |    430         cleanupComparison( IcmpErrorCleanup ); | 
|         |    431     TInt index = iIcmpErrors.Find( cleanupIcmpError, cleanupComparison ); | 
|         |    432     while ( index != KErrNotFound ) | 
|         |    433         { | 
|         |    434         iIcmpErrors.Remove( index ); | 
|         |    435         index = iIcmpErrors.Find( cleanupIcmpError, cleanupComparison ); | 
|         |    436         } | 
|         |    437      | 
|         |    438     __TRACE_MCC_QOS_CONTROLLER1("CMccQosController::HandleIcmpError, cleanup done");   | 
|         |    439      | 
|         |    440     TIdentityRelation<TMccQosControllerIcmpError> comparison( IcmpErrorMatch ); | 
|         |    441     TMccQosControllerIcmpError icmpError; | 
|         |    442     icmpError.iLinkId = aEvent.iLinkId; | 
|         |    443     index = iIcmpErrors.Find( icmpError, comparison ); | 
|         |    444     if ( index != KErrNotFound ) | 
|         |    445         { | 
|         |    446         TMccQosControllerIcmpError& existingIcmpError = iIcmpErrors[ index ]; | 
|         |    447         existingIcmpError.iErrorCount++; | 
|         |    448         if ( existingIcmpError.iErrorCount >= KMccIcmpErrorThreshold ) | 
|         |    449             { | 
|         |    450             // Report the error | 
|         |    451             ignoreError = EFalse; | 
|         |    452             iIcmpErrors.Remove( index ); | 
|         |    453             } | 
|         |    454         } | 
|         |    455     else | 
|         |    456         { | 
|         |    457         icmpError.iErrorCount = KMccFirstIcmpError; | 
|         |    458         icmpError.iErrorTimeWindowBeginning = currentTime; | 
|         |    459          | 
|         |    460         // It does not matter if entry cannot be added because of low memory | 
|         |    461         iIcmpErrors.Append( icmpError ); | 
|         |    462         } | 
|         |    463      | 
|         |    464     __TRACE_MCC_QOS_CONTROLLER3("CMccQosController::HandleIcmpError ignore:",  | 
|         |    465                                 ignoreError );   | 
|         |    466         | 
|         |    467     return ignoreError; | 
|         |    468     } | 
|         |    469  | 
|         |    470 // ----------------------------------------------------------------------------- | 
|         |    471 // CMccQosController::IcmpErrorMatch | 
|         |    472 // ----------------------------------------------------------------------------- | 
|         |    473 //      | 
|         |    474 TBool CMccQosController::IcmpErrorMatch(  | 
|         |    475     const TMccQosControllerIcmpError& aError1,  | 
|         |    476     const TMccQosControllerIcmpError& aError2 ) | 
|         |    477     { | 
|         |    478     // First argument is the search term | 
|         |    479     return ( aError1.iLinkId == aError2.iLinkId ); | 
|         |    480     } | 
|         |    481  | 
|         |    482 // ----------------------------------------------------------------------------- | 
|         |    483 // CMccQosController::IcmpErrorCleanup | 
|         |    484 // ----------------------------------------------------------------------------- | 
|         |    485 //      | 
|         |    486 TBool CMccQosController::IcmpErrorCleanup(  | 
|         |    487     const TMccQosControllerIcmpError& aError1,  | 
|         |    488     const TMccQosControllerIcmpError& aError2 ) | 
|         |    489     { | 
|         |    490     // First argument is the search term | 
|         |    491     TInt64 timeWindow =  | 
|         |    492         aError1.iErrorTimeWindowBeginning.MicroSecondsFrom(  | 
|         |    493             aError2.iErrorTimeWindowBeginning ).Int64(); | 
|         |    494     return ( timeWindow > KMccIcmpErrorTimeWindow ); | 
|         |    495     } | 
|         |    496         | 
|         |    497 // ----------------------------------------------------------------------------- | 
|         |    498 // CMccQosController::CMccQosController | 
|         |    499 // ----------------------------------------------------------------------------- | 
|         |    500 //       | 
|         |    501 CMccQosController::CMccQosController( | 
|         |    502     MMccRateAdaptationObserver& aObserver, | 
|         |    503     MMccResources& aResources ) : | 
|         |    504     iMainObserver( aObserver ), | 
|         |    505     iResources( aResources ), | 
|         |    506     iDeltaTimerCallBack(AsyncTimerExpired, this), | 
|         |    507     iBitRateChanged(EFalse) | 
|         |    508     { | 
|         |    509     __TRACE_MCC_QOS_CONTROLLER1("CMccQosController::CMccQosController"); | 
|         |    510     iDeltaTimerEntry.Set(iDeltaTimerCallBack); | 
|         |    511     } | 
|         |    512  | 
|         |    513 // ----------------------------------------------------------------------------- | 
|         |    514 // CMccQosController::ConstructL | 
|         |    515 // ----------------------------------------------------------------------------- | 
|         |    516 //  | 
|         |    517 void CMccQosController::ConstructL() | 
|         |    518     { | 
|         |    519 	__TRACE_MCC_QOS_CONTROLLER1("CMccQosController::ConstructL");     | 
|         |    520     iDeltaTimer = CDeltaTimer::NewL(CActive::EPriorityStandard); | 
|         |    521     iEventCounter = 0; | 
|         |    522     #ifdef RATECONTROL | 
|         |    523     //rate control threshold values | 
|         |    524  | 
|         |    525     iThresholdValues.iFractionLostHigh = 30; | 
|         |    526     iThresholdValues.iFractionLostLow = 0; | 
|         |    527  | 
|         |    528 	iRoundTripTime = 0; | 
|         |    529 	 | 
|         |    530 	iAdapted = EFalse; | 
|         |    531  | 
|         |    532 	#endif //RATECONTROL | 
|         |    533     } | 
|         |    534  | 
|         |    535 // ----------------------------------------------------------------------------- | 
|         |    536 // CMccQosController::DoAdaptation | 
|         |    537 // ----------------------------------------------------------------------------- | 
|         |    538 //  | 
|         |    539 void CMccQosController::DoAdaptation() | 
|         |    540     { | 
|         |    541     StartTimerForAsync(); | 
|         |    542     iAdapted = ETrue; | 
|         |    543     } | 
|         |    544  | 
|         |    545 // ----------------------------------------------------------------------------- | 
|         |    546 // CMccQosController::GetShortTermComparisonDelay | 
|         |    547 // ----------------------------------------------------------------------------- | 
|         |    548 //  | 
|         |    549 TInt CMccQosController::GetShortTermComparisonDelay() | 
|         |    550     {     | 
|         |    551     if ( iRoundTripDelayOfPreviousShortPeriod ) | 
|         |    552         { | 
|         |    553         return iRoundTripDelayOfPreviousShortPeriod; | 
|         |    554         } | 
|         |    555          | 
|         |    556     return iRoundTripTime; | 
|         |    557     } | 
|         |    558  | 
|         |    559 // ----------------------------------------------------------------------------- | 
|         |    560 // CMccQosController::CalculateDelayOfShortTermPeriod | 
|         |    561 // ----------------------------------------------------------------------------- | 
|         |    562 // | 
|         |    563 TInt CMccQosController::CalculateDelayOfShortTermPeriod() | 
|         |    564     { | 
|         |    565     TInt roundTripDelayOfThisPeriod( 0 ); | 
|         |    566     for ( TInt i = 0; i < KMccShortTermCalculation; i++ ) | 
|         |    567         { | 
|         |    568         roundTripDelayOfThisPeriod += iRoundTripDelays[ i ]; | 
|         |    569         } | 
|         |    570     return ( roundTripDelayOfThisPeriod / KMccShortTermCalculation ); | 
|         |    571     } | 
|         |    572      | 
|         |    573 // End of file | 
|         |    574  |