multimediacommscontroller/mmccjitterbuffer/src/mccjitterbufferimpl.cpp
changeset 0 1bce908db942
child 18 817c922b90eb
equal deleted inserted replaced
-1:000000000000 0:1bce908db942
       
     1 /*
       
     2 * Copyright (c) 2004-2007 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:    Implementation of Mcc Jitterbuffer
       
    15 *
       
    16 */
       
    17 
       
    18 
       
    19 
       
    20 
       
    21 // INCLUDE FILES
       
    22 #include "mmcccodecinformation.h"
       
    23 #include "mccjitterbufferimpl.h"
       
    24 #include "mcccngenerator.h"
       
    25 #include "mccinternalevents.h"
       
    26 #include "mccinternaldef.h"
       
    27 #include "mccjitterbufferlogs.h"
       
    28 #include "mccjitterbufferobserver.h"
       
    29 
       
    30 // LOCAL CONSTANTS
       
    31 const TInt KDefaultSampleRateInkHz = 8;
       
    32 const TInt KWbSampleRateInkHz = 16;
       
    33 const TInt KLowBufferLimit = 2;
       
    34 const TInt KOverflowAlarmLimit = 20;
       
    35 const TInt KSequentialLateFramesLimit = 20;
       
    36 
       
    37 // Codec frame sizes
       
    38 const TInt KAMRNBFrameSize = 32;
       
    39 const TInt KAMRWBFrameSize = 64;
       
    40 const TInt KILBCFrameSize = 52;
       
    41 const TInt KG729FrameSize = 24; // 10 octets + 2 for header
       
    42 
       
    43 // Maximum possible sequence number of RTP packet with standard RTP header.
       
    44 const TInt KMaxSeqNumber = 65535;        // 16-bit value
       
    45 
       
    46 // Codec frame times
       
    47 const TInt KAMRNBFrameTime = 20;
       
    48 
       
    49 // ============================= LOCAL FUNCTIONS ===============================
       
    50 
       
    51 // -----------------------------------------------------------------------------
       
    52 // TJitterBufferElement::CompareSeqNum
       
    53 // Compare SequenceNumber
       
    54 // -----------------------------------------------------------------------------    
       
    55 //
       
    56 TInt TJitterBufferElement::CompareSeqNum( const TJitterBufferElement& aElem1, 
       
    57         const TJitterBufferElement& aElem2 )
       
    58     {
       
    59     if ( aElem1.iSequenceNumber > aElem2.iSequenceNumber )
       
    60         {
       
    61         return (-1);
       
    62         }
       
    63     else if ( aElem1.iSequenceNumber < aElem2.iSequenceNumber )
       
    64         {
       
    65         return (1);
       
    66         }
       
    67     else
       
    68         {
       
    69         return (0);
       
    70         }
       
    71     }
       
    72 
       
    73 // -----------------------------------------------------------------------------
       
    74 // TJitterBufferElement::CompareStamp
       
    75 // Compare Stamp
       
    76 // -----------------------------------------------------------------------------        
       
    77 //
       
    78 TInt TJitterBufferElement::CompareStamp( const TJitterBufferElement& aElem1, 
       
    79         const TJitterBufferElement& aElem2 )
       
    80     {
       
    81     if ( aElem1.iStamp > aElem2.iStamp )
       
    82         {
       
    83         return (-1);
       
    84         }
       
    85     else if ( aElem1.iStamp < aElem2.iStamp )
       
    86         {
       
    87         return (1);
       
    88         }
       
    89     else
       
    90         {
       
    91         return (0);
       
    92         }
       
    93     }
       
    94 
       
    95 // ============================ MEMBER FUNCTIONS ===============================
       
    96 
       
    97 // -----------------------------------------------------------------------------
       
    98 // CMccJitterBufferImpl::CMccJitterBufferImpl
       
    99 // C++ default constructor can NOT contain any code, that
       
   100 // might leave.
       
   101 // -----------------------------------------------------------------------------
       
   102 //
       
   103 CMccJitterBufferImpl::CMccJitterBufferImpl( MJitterBufferObserver* aObserver): 
       
   104 		iPacketsInBuffer( 0 ), 
       
   105         iLastGetSeqNum( -1 ), 
       
   106         iBufStampSorter( 
       
   107             TLinearOrder<TJitterBufferElement>( TJitterBufferElement::CompareStamp ) 
       
   108             ),
       
   109         iBufSequenceSorter( 
       
   110             TLinearOrder<TJitterBufferElement>( TJitterBufferElement::CompareSeqNum ) 
       
   111             ),
       
   112         iSeqNumIncrement( 0 ),
       
   113         iPlay( EFalse ),
       
   114         iObserver( aObserver ),
       
   115         iOverflowCounter( 0 ),
       
   116         iPlayToneInterval( 0 ),
       
   117         iNotifyUser( ETrue ),
       
   118         iLatestNotifiedEvent( KMccEventNone ),
       
   119         iSampleRate( KDefaultSampleRateInkHz )
       
   120     {
       
   121     iTonePlayTime.UniversalTime();
       
   122     }
       
   123 
       
   124 // -----------------------------------------------------------------------------
       
   125 // CMccJitterBufferImpl::NewL
       
   126 // Static constructor.
       
   127 // -----------------------------------------------------------------------------
       
   128 //
       
   129 CMccJitterBufferImpl* CMccJitterBufferImpl::NewL( MJitterBufferObserver* aObserver )
       
   130     {
       
   131     __JITTER_BUFFER( "CMccJitterBufferImpl::NewL 64bit version" )
       
   132 
       
   133     CMccJitterBufferImpl* self = new( ELeave ) CMccJitterBufferImpl( aObserver );
       
   134     CleanupStack::PushL( self );
       
   135     self->ConstructL();
       
   136     CleanupStack::Pop( self );
       
   137 
       
   138     return self;
       
   139     }
       
   140 
       
   141 // -----------------------------------------------------------------------------
       
   142 // CMccJitterBufferImpl::ConstructL
       
   143 // Symbian 2nd phase constructor can leave.
       
   144 // -----------------------------------------------------------------------------
       
   145 //
       
   146 void CMccJitterBufferImpl::ConstructL()
       
   147     {
       
   148     SetBufferState( EIdle );
       
   149     SendStreamEventToClient( KMccStreamIdle, ETrue );
       
   150     }
       
   151 
       
   152 // -----------------------------------------------------------------------------
       
   153 // CMccJitterBufferImpl::~CMccJitterBufferImpl
       
   154 // Destructor deallocate memory.
       
   155 // -----------------------------------------------------------------------------
       
   156 //
       
   157 CMccJitterBufferImpl::~CMccJitterBufferImpl()
       
   158     {
       
   159     __JITTER_BUFFER( "CMccJitterBufferImpl::~CMccJitterBufferImpl entry" )
       
   160 
       
   161     delete iCnGenerator;    
       
   162         
       
   163     // Deallocate payload memory of jitter buffer elements.
       
   164     const TInt count = iBuffer.Count();
       
   165     for ( TInt i = 0; i < count; i++ )
       
   166         {
       
   167         delete iBuffer[i].iDataFrame;
       
   168         } 
       
   169 
       
   170     iBuffer.Close();
       
   171     iObserver = NULL;
       
   172     
       
   173     __JITTER_BUFFER( "CMccJitterBufferImpl::~CMccJitterBufferImpl exit" )
       
   174     }
       
   175     
       
   176 // -----------------------------------------------------------------------------
       
   177 // CMccJitterBufferImpl::SetupL
       
   178 // Setup Jitterbuffer
       
   179 // -----------------------------------------------------------------------------
       
   180 //
       
   181 void CMccJitterBufferImpl::SetupL( 
       
   182     TInt aPlayoutThreshold, 
       
   183     const TMccCodecInfo& aCInfo, 
       
   184     CMMFDevSound& aDevSound, 
       
   185     MAsyncEventHandler* aEventHandler,
       
   186     TUint32 aEndpointId )
       
   187     {
       
   188     __JITTER_BUFFER_INT1( "CMccJitterBufferImpl::SetupL aCInfo.iJitterBufBufferLength:",
       
   189                           aCInfo.iJitterBufBufferLength )
       
   190     __JITTER_BUFFER_INT1( "CMccJitterBufferImpl::SetupL aPlayoutThreshold:",
       
   191                           aPlayoutThreshold )
       
   192     __JITTER_BUFFER_INT1( "CMccJitterBufferImpl::SetupL aCInfo.iJitterBufInactivityTimeOut:",
       
   193                           aCInfo.iJitterBufInactivityTimeOut )
       
   194     __JITTER_BUFFER_INT1( "CMccJitterBufferImpl::SetupL aCInfo.iJitterBufPlayToneTimeout:",
       
   195                           aCInfo.iJitterBufPlayToneTimeout )
       
   196     __JITTER_BUFFER_INT1( "CMccJitterBufferImpl::SetupL aCInfo.iJitterBufPlayToneFrequency:",
       
   197                           aCInfo.iJitterBufPlayToneFrequency )
       
   198     __JITTER_BUFFER_INT1( "CMccJitterBufferImpl::SetupL aCInfo.iJitterBufPlayToneDuration:",
       
   199                           aCInfo.iJitterBufPlayToneDuration )
       
   200     __JITTER_BUFFER_INT1( "CMccJitterBufferImpl::SetupL aCInfo.iHwFrameTime:",
       
   201                           aCInfo.iHwFrameTime )
       
   202     __JITTER_BUFFER_INT1( "CMccJitterBufferImpl::SetupL aCInfo.iPtime:",
       
   203                           aCInfo.iPtime )
       
   204     
       
   205     // Changed if-statement to asserts. Added also check agains 0 hwframetime
       
   206     __ASSERT_ALWAYS( aCInfo.iPtime, User::Leave( KErrArgument ) );
       
   207     __ASSERT_ALWAYS( aCInfo.iJitterBufBufferLength, User::Leave( KErrArgument ) );
       
   208     __ASSERT_ALWAYS( aCInfo.iHwFrameTime, User::Leave( KErrArgument ) );
       
   209     
       
   210     // Save the original HW frame time because we may need it in case of
       
   211     // dynamic G.711 adjustment.
       
   212     const TUint8 origHwtime = iCInfo.iHwFrameTime;
       
   213     iCInfo = aCInfo;
       
   214     iEventHandler = aEventHandler;
       
   215     iEndpointId = aEndpointId;
       
   216     
       
   217     __JITTER_BUFFER_INT1( "CMccJitterBufferImpl::SetupL origHwtime:", origHwtime )
       
   218     
       
   219     if( iCInfo.iJitterBufInactivityTimeOut )
       
   220         {
       
   221         if( ( iCInfo.iJitterBufPlayToneFrequency > 0 ) && 
       
   222             ( iCInfo.iJitterBufPlayToneDuration > 0 ) )
       
   223             {
       
   224             iPlayToneInterval = iCInfo.iJitterBufPlayToneTimeout;            
       
   225             iPlay = ETrue;
       
   226             }
       
   227         }
       
   228         
       
   229     TInt bufLenMultiplier = 1;
       
   230     if ( iCInfo.iFourCC == KMMFFourCCCodeAMR )
       
   231         {
       
   232         iFrameSize = KAMRNBFrameSize;
       
   233         iFrameTime = KAMRNBFrameTime;
       
   234         }
       
   235     else if ( iCInfo.iFourCC == KMMFFourCCCodeAWB )
       
   236         {   
       
   237         iFrameSize = KAMRWBFrameSize;
       
   238         iFrameTime = KAMRNBFrameTime;
       
   239         iSampleRate = KWbSampleRateInkHz;
       
   240         }
       
   241     else if( iCInfo.iFourCC == KMccFourCCIdG711 )
       
   242         {
       
   243         // G.711 is configured dynamically. Take voip headerlength also in to
       
   244         // account. G.711 hwframetime is in milliseconds, so need to multiply.
       
   245         iFrameSize = ( iCInfo.iHwFrameTime * KDefaultSampleRateInkHz )
       
   246             + KVoIPHeaderLength;
       
   247         iFrameTime = 0;
       
   248         
       
   249         // In case of G.711 codec dynamic configuration, we may need to double
       
   250         // the jitterbuffer length if HW frame time is changed from 20ms to
       
   251         // 10ms. 
       
   252         if ( origHwtime )
       
   253             {
       
   254             bufLenMultiplier = origHwtime / iCInfo.iHwFrameTime;
       
   255             if ( !bufLenMultiplier )
       
   256                 {
       
   257                 bufLenMultiplier = 1;
       
   258                 }
       
   259             }
       
   260         }
       
   261     else if( iCInfo.iFourCC == KMccFourCCIdILBC )
       
   262         {
       
   263         iFrameSize = KILBCFrameSize;
       
   264         iFrameTime = 0;
       
   265         }
       
   266     else if( iCInfo.iFourCC == KMccFourCCIdG729 )
       
   267         {
       
   268         iFrameSize = KG729FrameSize;
       
   269         iFrameTime = 0;
       
   270         // Multiply G.729 also by two...
       
   271         bufLenMultiplier = 2;
       
   272         }
       
   273     else
       
   274         {
       
   275         __JITTER_BUFFER( "CMccJitterBufferImpl::SetupL KErrNotSupported" )
       
   276         
       
   277         User::Leave( KErrNotSupported );
       
   278         }
       
   279             
       
   280     // Delete old buffer & reset it
       
   281     const TInt elems = iBuffer.Count();
       
   282     for( TInt i = 0; i < elems; i++ )
       
   283         {
       
   284         delete iBuffer[i].iDataFrame;
       
   285         iBuffer[i].iDataFrame = NULL;
       
   286         }
       
   287     
       
   288     iBuffer.Reset();
       
   289     
       
   290     // Calculate needed elements
       
   291     TInt bufLen = iCInfo.iJitterBufBufferLength * bufLenMultiplier;
       
   292     
       
   293     __JITTER_BUFFER_INT1( "CMccJitterBufferImpl::SetupL G.711 bufLenMultiplier ",
       
   294         bufLenMultiplier )
       
   295     __JITTER_BUFFER_INT1( "CMccJitterBufferImpl::SetupL iBufferLength: ",
       
   296         bufLen )
       
   297     
       
   298     __ASSERT_ALWAYS( aPlayoutThreshold < bufLen, User::Leave( KErrTooBig ) );
       
   299     
       
   300     // if differences between bufferlength and treshold set by client
       
   301     // is less than 10, increase bufferlength so the differences is 10
       
   302     // this is to help buffer goes to overflow easily.
       
   303     // Also possible G.711/729 multiplier needs to be taken care of.
       
   304     CheckThresholdBufferLength( bufLen, aPlayoutThreshold );
       
   305     iCurrentPlayThreshold = aPlayoutThreshold * bufLenMultiplier;
       
   306     iOriginalPlayThreshold = aPlayoutThreshold * bufLenMultiplier;
       
   307     
       
   308     if( iCnGenerator )
       
   309         {
       
   310         delete iCnGenerator;
       
   311         iCnGenerator = NULL;
       
   312         }
       
   313 
       
   314     iCnGenerator = CMccCnGenerator::NewL( iCInfo.iFourCC, aDevSound );
       
   315     
       
   316     // Create the elements in the Buffer
       
   317     for( TInt k = 0; k < bufLen; k++ )
       
   318         {
       
   319         CMMFDataBuffer* buf = CMMFDataBuffer::NewL( iFrameSize );
       
   320         CleanupStack::PushL( buf );
       
   321         TJitterBufferElement newElement;
       
   322         newElement.iDataFrame = buf;
       
   323         newElement.iSequenceNumber = -1;
       
   324         newElement.iStamp = -1;
       
   325         iBuffer.AppendL( newElement );
       
   326         CleanupStack::Pop( buf );
       
   327         }
       
   328     
       
   329     // Zero the statistic members
       
   330     iFramesLost = 0;
       
   331     iFramesReceived = 0;
       
   332     iNumOfLateFrames = 0;
       
   333     iFramesRemoved = 0;
       
   334     iFramesPlayed = 0;
       
   335     iPacketsInBuffer = 0;
       
   336     
       
   337     // Calculate the sequence number increment
       
   338     iSeqNumIncrement = iSampleRate * iCInfo.iHwFrameTime;
       
   339     } 
       
   340         
       
   341 // -----------------------------------------------------------------------------
       
   342 // CMccJitterBufferImpl::ResetBufferL
       
   343 // Reset Jitterbuffer
       
   344 // -----------------------------------------------------------------------------
       
   345 //
       
   346 
       
   347 void CMccJitterBufferImpl::ResetBuffer( TBool aPlayTone, TBool aNotifyUser )
       
   348     {
       
   349     const TInt bufLen = BufferLength();
       
   350     __JITTER_BUFFER_INT1( "CMccJitterBufferImpl::ResetBuffer bufLen: ", bufLen )
       
   351     __JITTER_BUFFER_INT1( "CMccJitterBufferImpl::ResetBuffer pktsIn: ", iPacketsInBuffer )
       
   352     
       
   353     for( TInt i = 0; i < bufLen; i++ )
       
   354         {
       
   355         iBuffer[i].iSequenceNumber = -1;
       
   356         iBuffer[i].iStamp = -1;
       
   357         }
       
   358     
       
   359     iLastGetSeqNum = -1;
       
   360     iCurrentPlayThreshold = iOriginalPlayThreshold;
       
   361     iPacketsInBuffer = 0; 
       
   362     iPlay = aPlayTone; 
       
   363     
       
   364     if ( BufferState() != EIdle && 
       
   365          aNotifyUser && 
       
   366          iLatestNotifiedEvent != KMccStreamIdle )
       
   367         {
       
   368         SendStreamEventToClient( KMccStreamIdle, ETrue );
       
   369         }
       
   370     
       
   371     SetBufferState( EIdle );
       
   372     iDropNextFrame = EFalse;
       
   373     }
       
   374 
       
   375 // -----------------------------------------------------------------------------
       
   376 // CMccJitterBufferImpl::CurrentCodec
       
   377 // Return current codec.
       
   378 // -----------------------------------------------------------------------------
       
   379 //
       
   380 TFourCC CMccJitterBufferImpl::CurrentCodec() const
       
   381     {
       
   382     return iCInfo.iFourCC;
       
   383     }
       
   384     
       
   385 // -----------------------------------------------------------------------------
       
   386 // CMccJitterBufferImpl::DelayUpL
       
   387 // Adds a buffer element into the jitter buffer
       
   388 // -----------------------------------------------------------------------------
       
   389 //
       
   390 void CMccJitterBufferImpl::DelayUpL()
       
   391     {
       
   392     CMMFDataBuffer* buf = CMMFDataBuffer::NewL( iFrameSize );
       
   393     CleanupStack::PushL( buf );
       
   394     TJitterBufferElement newElement;
       
   395     newElement.iDataFrame = buf;
       
   396     newElement.iSequenceNumber = -1;
       
   397     newElement.iStamp = -1;
       
   398     iBuffer.AppendL( newElement );
       
   399     CleanupStack::Pop( buf );
       
   400     
       
   401     // Insert one NO_DATA frame into the audio stream, so the jitterbuffer has
       
   402     // the possibility to grow at least one frame from the current status. 
       
   403     // If the current playout threshold is zero, then there is playout ongoing or
       
   404     // a DTX period. This means that we should buffer at least one frame before
       
   405     // starting playout.
       
   406     if( 0 == iCurrentPlayThreshold )
       
   407         {
       
   408         __JITTER_BUFFER( "CMccJitterBufferImpl::DelayUpL Adjusting Playout Threshold" )
       
   409         
       
   410         iCurrentPlayThreshold = iPacketsInBuffer + 1;
       
   411         }
       
   412     
       
   413     __JITTER_BUFFER_INT1( "CMccJitterBufferImpl::DelayUpL BUF_LEN:", BufferLength() )
       
   414     __JITTER_BUFFER_INT1( "CMccJitterBufferImpl::DelayUpL CUR_FRAMES:", iPacketsInBuffer )
       
   415     __JITTER_BUFFER_INT1( "CMccJitterBufferImpl::DelayUpL PLAY_TH:", iCurrentPlayThreshold )
       
   416     }
       
   417     
       
   418 // -----------------------------------------------------------------------------
       
   419 // CMccJitterBufferImpl::DelayDownL
       
   420 // Removes an buffer element from the jitter buffer
       
   421 // -----------------------------------------------------------------------------
       
   422 //
       
   423 void CMccJitterBufferImpl::DelayDownL()
       
   424     {
       
   425     // We need to remove one frame from the jitterbuffer. If currently we are
       
   426     // in a DTX period, we're in luck as we do not affect voice quality at all.
       
   427     
       
   428     // DURING DTX:
       
   429     // During DTX periods the jitterbuffer can be empty, so we cannot remove
       
   430     // anything from nothing. Then we basically can remove one element from the
       
   431     // buffer so it is shorter.
       
   432     
       
   433     // DURING SPEECH:
       
   434     // We'll need to remove one audio frame and mark the one preceding the 
       
   435     // removed frame as bad. Then we'll continue as usual.
       
   436     const TInt bufLen = BufferLength();
       
   437     __JITTER_BUFFER_INT1( "CMccJitterBufferImpl::DelayDownL BUF_LEN:", bufLen )
       
   438     __JITTER_BUFFER_INT1("CMccJitterBufferImpl::DelayDownL CUR_FRAMES:", iPacketsInBuffer )
       
   439     
       
   440     if( this->IsEmpty() )
       
   441         {
       
   442         // Cannot do anything for empty buffer
       
   443         if( KLowBufferLimit < bufLen )
       
   444             {
       
   445             __JITTER_BUFFER( "CMccJitterBufferImpl::DelayDownL Empty buffer" )
       
   446             
       
   447             delete iBuffer[bufLen - 1].iDataFrame;
       
   448             iBuffer.Remove( bufLen - 1 );
       
   449             }
       
   450         else if( 0 < iCurrentPlayThreshold )
       
   451             {
       
   452             __JITTER_BUFFER( "CMccJitterBufferImpl::DelayDownL Playthreshold modification" )
       
   453                         
       
   454             iCurrentPlayThreshold--;
       
   455             }
       
   456         else
       
   457             {
       
   458             __JITTER_BUFFER( "CMccJitterBufferImpl::DelayDownL Buffer empty, cant do anything" )
       
   459             // Cannot do anything currently
       
   460             return;
       
   461             }
       
   462         }
       
   463     else if( this->IsFull() )
       
   464         {
       
   465         // If there is sufficiently data in the buffer, then remove one
       
   466         // frame and mark the one preceding it bad
       
   467         if( KLowBufferLimit < iPacketsInBuffer )
       
   468             {
       
   469             __JITTER_BUFFER( "CMccJitterBufferImpl::DelayDownL Buffer full, doing removal" )
       
   470             
       
   471             // Remove the 2nd oldest frame and mark the oldest as bad
       
   472             delete iBuffer[1].iDataFrame;
       
   473             iBuffer.Remove( 1 );
       
   474             
       
   475             // MARK THE FIRST AS BAD FRAME!!!
       
   476             iPacketsInBuffer--;
       
   477             iFramesRemoved++;
       
   478             }
       
   479         else
       
   480             {
       
   481             // Cant do removing, see if playthreshold can be adjusted
       
   482             if( 0 < iCurrentPlayThreshold )
       
   483                 {
       
   484                 __JITTER_BUFFER( "CMccJitterBufferImpl::DelayDownL Buffer full, cant do anything" )
       
   485                 
       
   486                 iCurrentPlayThreshold--;
       
   487                 }
       
   488             }
       
   489         }
       
   490     else
       
   491         {
       
   492         if( KLowBufferLimit < bufLen )
       
   493             {
       
   494             __JITTER_BUFFER( "CMccJitterBufferImpl::DelayDownL Some frames, adjusting length" )
       
   495             
       
   496             // Adjust the length of the buffer
       
   497             delete iBuffer[bufLen - 1].iDataFrame;
       
   498             iBuffer.Remove( bufLen - 1 );
       
   499             }
       
   500         else
       
   501             {
       
   502             __JITTER_BUFFER( "CMccJitterBufferImpl::DelayDownL Some frames, too small buffer" )
       
   503             }
       
   504         }
       
   505     }
       
   506     
       
   507 // -----------------------------------------------------------------------------
       
   508 // CMccJitterBufferImpl::CalculateDelay
       
   509 // Calculates the current delay that jitterbuffer has in the playback
       
   510 // -----------------------------------------------------------------------------
       
   511 //
       
   512 TTimeIntervalMicroSeconds32 CMccJitterBufferImpl::CalculateDelay() const
       
   513     {
       
   514     __JITTER_BUFFER_INT1( "CMccJitterBufferImpl::CalculateDelay:", iCInfo.iPtime * iPacketsInBuffer )
       
   515 
       
   516     return iCInfo.iPtime * iPacketsInBuffer;
       
   517     }        
       
   518         
       
   519 // -----------------------------------------------------------------------------
       
   520 // CMccJitterBufferImpl::AddDataFrameL
       
   521 // Adds a audio frame into the jitterbuffer passed in the aDataBuffer
       
   522 // -----------------------------------------------------------------------------
       
   523 //
       
   524 void CMccJitterBufferImpl::AddDataFrameL( CMMFBuffer* aDataBuffer )
       
   525     {
       
   526     User::LeaveIfNull( aDataBuffer );
       
   527     const TInt64 seqNum = aDataBuffer->FrameNumber();
       
   528     iFramesReceived++;
       
   529     
       
   530     const TInt num( FindLargestSeqNum() );
       
   531     
       
   532     __JITTER_BUFFER_INT1( "CMccJitterBufferImpl::AddDataFrameL FRAM_SEQNUM:", seqNum )
       
   533     __JITTER_BUFFER_INT1( "CMccJitterBufferImpl::AddDataFrameL LAST_SEQNUM:", iLastGetSeqNum )
       
   534     __JITTER_BUFFER_INT1( "CMccJitterBufferImpl::AddDataFrameL PACKETS:", iPacketsInBuffer )
       
   535     
       
   536     const CMMFDataBuffer* dataBuffer( static_cast<CMMFDataBuffer*>( aDataBuffer ) );
       
   537     
       
   538     if( seqNum > iLastGetSeqNum )
       
   539         {
       
   540         iNumOfSequentialLateFrames = 0;
       
   541         if( IsFull() )
       
   542             {
       
   543             __JITTER_BUFFER_INT1( "CMccJitterBufferImpl::AddDataFrameL OFLOW dropnext: ",
       
   544                 iDropNextFrame );
       
   545             
       
   546             iFramesRemoved++;
       
   547 			iOverflowCounter++;
       
   548 			if ( iObserver && iOverflowCounter > KOverflowAlarmLimit )
       
   549                 {
       
   550 	            __JITTER_BUFFER( "CMccJitterBufferImpl::AddDataFrameL OFLOW reported" )
       
   551 	            
       
   552                 iOverflowCounter = 0;
       
   553                 iObserver->JitterBufferError( MJitterBufferObserver::EBufferOverflow );
       
   554                 ResetBuffer( ETrue, EFalse );
       
   555                 
       
   556                 // Do not inform resource unavailability several times. Once playback
       
   557                 // is ok again, resource unavailability can be informed if it occurs.
       
   558                 SendStreamEventToClient( KMccResourceNotAvailable, ETrue );
       
   559                 iNotifyUser = EFalse;
       
   560                 }
       
   561             
       
   562             // Check that we actually have packets to remove from the buffer.
       
   563             if ( !iDropNextFrame && iPacketsInBuffer )
       
   564                 {
       
   565                 // Remove the newest frame in the buffer
       
   566                 (void) iBuffer[ iPacketsInBuffer - 1 ].iSequenceNumber;
       
   567                 iBuffer[ iPacketsInBuffer - 1 ].iSequenceNumber = -1;
       
   568                 iBuffer[ iPacketsInBuffer - 1 ].iStamp = -1;
       
   569                 iPacketsInBuffer--;
       
   570                 
       
   571                 iDropNextFrame = ETrue;
       
   572                 }
       
   573             else
       
   574                 {
       
   575                 iDropNextFrame = EFalse;
       
   576                 }
       
   577             
       
   578             // If we dropped this frame, then return from here.
       
   579             if ( !iDropNextFrame )
       
   580                 {
       
   581                 return;
       
   582                 }
       
   583             }
       
   584         else if( IsEmpty() )
       
   585             {
       
   586             // Buffering
       
   587             HandleNotifications( ETrue );
       
   588             
       
   589     		TTimeIntervalSeconds interval;
       
   590     		TTime currentTime;
       
   591     		currentTime.UniversalTime();
       
   592             currentTime.SecondsFrom( iTonePlayTime, interval );
       
   593             
       
   594             if( iPlay && interval.Int() >= iPlayToneInterval )
       
   595                 {    
       
   596                 __JITTER_BUFFER( "CMccJitterBufferImpl::AddDataFrameL tone to be played" )                
       
   597     			iTonePlayTime.UniversalTime();
       
   598                 iPlay = EFalse;
       
   599                 }
       
   600             
       
   601             const TInt64 nextGetSeqNum( iLastGetSeqNum + iSeqNumIncrement );
       
   602             if( seqNum > nextGetSeqNum )
       
   603                 {
       
   604                 // We are empty and there is frames missing between last get frame
       
   605                 // and frame sequence number. This might be because of DTX period
       
   606                 // so we need to adjust to the situation
       
   607                 iLastGetSeqNum = seqNum - iSeqNumIncrement;
       
   608                 
       
   609                 __JITTER_BUFFER( "CMccJitterBufferImpl::AddDataFrameL MISSING & EMPTY" )
       
   610                 __JITTER_BUFFER_INT2( "CMccJitterBufferImpl::AddDataFrameL ADJ_LAST:", iLastGetSeqNum,
       
   611                                       " FRM_SEQ:", seqNum )
       
   612                 }
       
   613             }
       
   614         else
       
   615             {
       
   616             __JITTER_BUFFER( "CMccJitterBufferImpl::AddDataFrameL NORMAL" )
       
   617             
       
   618 			iOverflowCounter = 0;
       
   619             }
       
   620         
       
   621         // Reset inactivity timing. NB. all branches need to reset inactivity
       
   622         // and insert the new element.
       
   623         iInactivityTime = 0;
       
   624         InsertBufferElement( dataBuffer->Data(), num, seqNum );
       
   625         }
       
   626     else
       
   627         {
       
   628         iNumOfLateFrames++;
       
   629         if(++iNumOfSequentialLateFrames > KSequentialLateFramesLimit )
       
   630              iLastGetSeqNum = -1;
       
   631         
       
   632         __JITTER_BUFFER( "CMccJitterBufferImpl::AddDataFrameL TOO LATE" )
       
   633         }
       
   634     }
       
   635     
       
   636 // -----------------------------------------------------------------------------
       
   637 // CMccJitterBufferImpl::GetDataFrameL
       
   638 // Get DataFrame
       
   639 // -----------------------------------------------------------------------------
       
   640 //
       
   641 void CMccJitterBufferImpl::GetDataFrameL( CMMFBuffer* aBuffer )
       
   642     {
       
   643     User::LeaveIfNull( aBuffer );
       
   644     CMMFDataBuffer& dataBuffer = static_cast<CMMFDataBuffer&>( *aBuffer );
       
   645     TDes8& playBuffer( dataBuffer.Data() );
       
   646     iFramesPlayed++;
       
   647     
       
   648     __JITTER_BUFFER_INT1( "CMccJitterBufferImpl::GetDataFrameL PACKETS:", iPacketsInBuffer )
       
   649     
       
   650     if( IsEmpty() )
       
   651         {
       
   652         // Buffer is empty, so we need to generate CN frames. During DTX period
       
   653         // this is where we'll end up. If we are empty because of DTX period,
       
   654         // the CN generator will do the error concealment.
       
   655         iCnGenerator->GenerateSidPacket( playBuffer, dataBuffer.RequestSize() );
       
   656         iCurrentPlayThreshold = iOriginalPlayThreshold;
       
   657         
       
   658         // Used for talkburst, if talkburst over, reset buffer and sequence numbers
       
   659         if( iCInfo.iJitterBufInactivityTimeOut > 0 && iInactivityTime >= 0 )
       
   660             {
       
   661             iInactivityTime = iInactivityTime + iFrameTime;
       
   662             if( iInactivityTime >= (TInt) iCInfo.iJitterBufInactivityTimeOut )
       
   663                 {
       
   664                 __JITTER_BUFFER_INT2("CMccJitterBufferImpl::Inactivity timeout:",
       
   665                                      iCInfo.iJitterBufInactivityTimeOut,
       
   666                                      " time:", iInactivityTime )
       
   667                 
       
   668                 iInactivityTime = -1;
       
   669                 ResetBuffer();
       
   670                 }
       
   671             }
       
   672         }
       
   673     else 
       
   674         {
       
   675         // This is where we buffer some data before starting the playout so we can
       
   676         // take some jitter by nature without adaptation.
       
   677         if( iPacketsInBuffer < iCurrentPlayThreshold )
       
   678             {
       
   679             // Give comfort noise when we are buffering for playback start
       
   680             __JITTER_BUFFER( "CMccJitterBufferImpl::GetDataFrameL THRESHOLD NOT REACHED" )
       
   681             __JITTER_BUFFER_INT1( "CMccJitterBufferImpl::GetDataFrameL iCurrentPlayThreshold",
       
   682                 iCurrentPlayThreshold )
       
   683             
       
   684             iCnGenerator->GenerateSidPacket(
       
   685                 playBuffer, dataBuffer.RequestSize() );
       
   686             }
       
   687         else
       
   688             {
       
   689             // Not buffering
       
   690             HandleNotifications( EFalse );
       
   691             
       
   692             // Set the playout threshold to zero so we play the current talkspurt to the
       
   693             // end and do not affect the speech quality. This means that we will play the
       
   694             // buffer until it is empty. After that it is either DTX period or it is packet
       
   695             // loss.
       
   696             iCurrentPlayThreshold = 0;
       
   697             
       
   698             // Next sequence number that should be in the buffer
       
   699             TInt64 nextSeqNum = iLastGetSeqNum + iSeqNumIncrement;
       
   700             if( -1 == iLastGetSeqNum )
       
   701                 {
       
   702                 // Last get sequence number was -1, so add one
       
   703                 __JITTER_BUFFER( "CMccJitterBufferImpl::GetDataFrameL LAST WAS -1 ADJUSTING" )
       
   704 
       
   705                 nextSeqNum += 1;
       
   706                 }
       
   707                 
       
   708             // The actual sequence number which is in the buffer
       
   709             const TInt64 nextFrameSeqNum(
       
   710                 iBuffer[ iPacketsInBuffer - 1 ].iSequenceNumber );
       
   711             
       
   712             __JITTER_BUFFER_INT1( "CMccJitterBufferImpl::GetDataFrameL NEXT_GET_SEQ_NUM:", nextSeqNum )
       
   713             __JITTER_BUFFER_INT1( "CMccJitterBufferImpl::GetDataFrameL FRAME_SEQ_NUM:", nextFrameSeqNum )
       
   714             __JITTER_BUFFER_INT1( "CMccJitterBufferImpl::GetDataFrameL PACKETS:", iPacketsInBuffer )
       
   715             __JITTER_BUFFER_INT1( "CMccJitterBufferImpl::GetDataFrameL LAST_GET_SEQ_NUM:", iLastGetSeqNum )
       
   716             
       
   717             // Check if the next sequence number is smaller than the frame number of the next
       
   718             // frame to be played out. This will mean that a frame was lost and we need to do
       
   719             // error concealment. 
       
   720             // Also we need to take account the start of the playout when iLastGetSeqNum == -1 
       
   721             // so we play the first frame in the buffer regardless of it's sequence number.
       
   722             // This should also take the sequence number wrap around situation.
       
   723             
       
   724             // As if(0) is intentional, PC-lint warning disabled:
       
   725             /*lint -e506 */
       
   726             //if ( nextSeqNum < nextFrameSeqNum )
       
   727             if ( 0 )
       
   728                 {
       
   729                 __JITTER_BUFFER( "CMccJitterBufferImpl::GetDataFrameL LOST FRAME" )
       
   730 
       
   731                 iFramesLost++;
       
   732                 iLastGetSeqNum = iLastGetSeqNum + iSeqNumIncrement;
       
   733                 
       
   734                 __JITTER_BUFFER_INT1( "CMccJitterBufferImpl::GetDataFrameL 1. LAST_GET_SEQ_NUM IS NOW:", iLastGetSeqNum )
       
   735                 
       
   736                 iCnGenerator->GenerateSidPacket( playBuffer,
       
   737                     dataBuffer.RequestSize() );
       
   738                 }
       
   739             else
       
   740                 {
       
   741                 __JITTER_BUFFER( "CMccJitterBufferImpl::GetDataFrameL NORMAL" )
       
   742                 
       
   743                 TJitterBufferElement& bufferElement = iBuffer[ iPacketsInBuffer - 1 ];
       
   744                 if ( playBuffer.MaxLength() >= bufferElement.iDataFrame->Data().Length() )
       
   745                     {
       
   746                     playBuffer.Copy( bufferElement.iDataFrame->Data() );
       
   747                     }
       
   748                 else
       
   749                     {
       
   750                     __JITTER_BUFFER_INT1( "CMccJitterBufferImpl::GetDataFrameL ERROR - output buffer too small, maxlen:", 
       
   751                                           playBuffer.MaxLength() )
       
   752 
       
   753                     iCnGenerator->GenerateSidPacket( playBuffer, dataBuffer.RequestSize() );
       
   754                     }
       
   755                 
       
   756                 iLastGetSeqNum = bufferElement.iSequenceNumber;
       
   757                 bufferElement.iSequenceNumber = -1;
       
   758                 bufferElement.iStamp = -1;
       
   759                 iPacketsInBuffer--;
       
   760                 iInactivityTime = -1;
       
   761                 
       
   762                 // Lets see if the new buffer will lead into a DTX period
       
   763                 iCnGenerator->DoDtxDecision( playBuffer );
       
   764                 }
       
   765             }
       
   766         }
       
   767     }
       
   768 
       
   769 // -----------------------------------------------------------------------------
       
   770 // CMccJitterBufferImpl::FindLargestSeqNum
       
   771 // Find Largest SequenceNumber
       
   772 // -----------------------------------------------------------------------------
       
   773 //
       
   774 TInt CMccJitterBufferImpl::FindLargestSeqNum() const
       
   775     {
       
   776     TInt64 num = 0;
       
   777     TInt pos = 0;
       
   778     const TInt len( BufferLength() );
       
   779     
       
   780     for( TInt i = 0; i < len; i++ )
       
   781         {
       
   782         if( iBuffer[i].iSequenceNumber > num ) 
       
   783             {
       
   784             num = iBuffer[i].iSequenceNumber;
       
   785             pos = i;
       
   786             }
       
   787         }
       
   788 
       
   789     return pos;
       
   790     }
       
   791     
       
   792 // -----------------------------------------------------------------------------
       
   793 // CMccJitterBufferImpl::InsertBufferElement
       
   794 // Insert Buffer Element
       
   795 // -----------------------------------------------------------------------------
       
   796 //
       
   797 void CMccJitterBufferImpl::InsertBufferElement( const TDesC8& aBuffer, 
       
   798     TInt64 aLargestSeqNum, TInt64 aFrameNumber )
       
   799     {
       
   800     __JITTER_BUFFER_INT1( "CMccJitterBufferImpl::InsertBufferElement aFrameNumber:",
       
   801         aFrameNumber )
       
   802     
       
   803     if ( !aBuffer.Length() || aBuffer.Length() > iFrameSize )
       
   804         {
       
   805         __JITTER_BUFFER( "CMccJitterBufferImpl::InsertBufferElement INVALID DATA, IGNORING" )
       
   806         return;
       
   807         }
       
   808     
       
   809     const TInt len( this->BufferLength() );
       
   810     iBuffer[len-1].iDataFrame->Data().Copy( aBuffer );
       
   811     iBuffer[len-1].iSequenceNumber = aFrameNumber;
       
   812     
       
   813     if ( IsSeqNumWrappedAround( iBuffer[aLargestSeqNum].iSequenceNumber, aFrameNumber ) )
       
   814         {
       
   815         for ( TInt i = 0; i < len; i++ )
       
   816             {
       
   817             if( iBuffer[i].iStamp > aLargestSeqNum ) 
       
   818                 {
       
   819                 aLargestSeqNum = iBuffer[i].iStamp;
       
   820                 }
       
   821             }
       
   822         
       
   823         iBuffer[len-1].iStamp = aLargestSeqNum + 1;
       
   824         iBuffer.Sort( iBufStampSorter );
       
   825         iLastGetSeqNum = -1;
       
   826         }
       
   827     else 
       
   828         {
       
   829         iBuffer[len-1].iStamp = aFrameNumber - BufferLength();
       
   830         iBuffer.Sort( iBufSequenceSorter );
       
   831         }
       
   832     
       
   833     iPacketsInBuffer++;
       
   834     }
       
   835 
       
   836 // -----------------------------------------------------------------------------
       
   837 // CMccJitterBufferImpl::BufferLength()
       
   838 // Return bufferlength.
       
   839 // -----------------------------------------------------------------------------
       
   840 //
       
   841 TInt CMccJitterBufferImpl::BufferLength() const
       
   842     {
       
   843     return iBuffer.Count();
       
   844     }
       
   845 
       
   846 // -----------------------------------------------------------------------------
       
   847 // CMccJitterBufferImpl::IsFull()
       
   848 // Return:    True if full
       
   849 //            False if not full
       
   850 // -----------------------------------------------------------------------------
       
   851 //
       
   852 TBool CMccJitterBufferImpl::IsFull() const
       
   853     {
       
   854     return ( iPacketsInBuffer == BufferLength() );
       
   855     }
       
   856 
       
   857 // -----------------------------------------------------------------------------
       
   858 // CMccJitterBufferImpl::IsEmpty()
       
   859 // Return:    True if empty
       
   860 //            False if not empty
       
   861 // -----------------------------------------------------------------------------
       
   862 //
       
   863 TBool CMccJitterBufferImpl::IsEmpty() const
       
   864     {
       
   865     return ( iPacketsInBuffer == 0 );    
       
   866     }
       
   867 
       
   868 // -----------------------------------------------------------------------------
       
   869 // CMccJitterBufferImpl::IsSeqNumWrappedAround
       
   870 // Checks if sequence number wrapped around from aSeqNum1 to aSeqNum2
       
   871 // The sequence number wrap-around condition cannot be reliably detected by 
       
   872 // checking for exact numbers, i.e., aSeqNum1==KMaxSeqNumber and aSeqNum2==0, 
       
   873 // because, due to packet losses in network, sequence numbers may have gaps 
       
   874 // between them.
       
   875 // -----------------------------------------------------------------------------
       
   876 //
       
   877 TBool CMccJitterBufferImpl::IsSeqNumWrappedAround( TInt64 aSeqNum1, 
       
   878     TInt64 aSeqNum2 ) const
       
   879     {
       
   880     __JITTER_BUFFER_INT1( "CMccJitterBufferImpl::IsSeqNumWrappedAround aSeqNum1:", aSeqNum1 )
       
   881     __JITTER_BUFFER_INT1( "CMccJitterBufferImpl::IsSeqNumWrappedAround aSeqNum2:", aSeqNum2 )
       
   882     
       
   883     if ( aSeqNum1 > ( KMaxSeqNumber - BufferLength() ) && 
       
   884          aSeqNum2 < BufferLength() )
       
   885         {
       
   886         __JITTER_BUFFER( "CMccJitterBufferImpl::IsSeqNumWrappedAround ETrue" )
       
   887         return ETrue;
       
   888         }
       
   889     else
       
   890         {
       
   891         __JITTER_BUFFER( "CMccJitterBufferImpl::IsSeqNumWrappedAround EFalse" )
       
   892         return EFalse;
       
   893         }
       
   894     }
       
   895 
       
   896 // -----------------------------------------------------------------------------
       
   897 // CMccJitterBufferImpl::GenerateStatistics
       
   898 // Generates the statistics from the jitterbuffer
       
   899 // -----------------------------------------------------------------------------
       
   900 //
       
   901 void CMccJitterBufferImpl::GenerateStatistics( TMccJitterBufferEventData& aEvent ) const
       
   902     {
       
   903     aEvent.iFramesReceived = iFramesReceived;
       
   904     aEvent.iBufferLength = BufferLength();
       
   905     aEvent.iFramesInBuffer = iPacketsInBuffer;
       
   906     aEvent.iFrameLoss = iFramesLost;
       
   907     aEvent.iLateFrames = iNumOfLateFrames;
       
   908     aEvent.iFramesRemoved = iFramesRemoved;
       
   909     aEvent.iFramesPlayed = iFramesPlayed;
       
   910     }
       
   911 
       
   912 // -----------------------------------------------------------------------------
       
   913 // CMccJitterBufferImpl::HandleNotifications
       
   914 // -----------------------------------------------------------------------------
       
   915 //
       
   916 void CMccJitterBufferImpl::HandleNotifications( TBool aBuffering )
       
   917     {
       
   918     if ( aBuffering )
       
   919         {
       
   920         if ( BufferState() < EPlaying )
       
   921             {
       
   922             __JITTER_BUFFER( "CMccJitterBufferImpl::HandleNotifications, to buffering state" )
       
   923             
       
   924             SetBufferState( EBuffering );
       
   925             SendStreamEventToClient( KMccStreamBuffering, ETrue );
       
   926             }
       
   927         }
       
   928     else
       
   929         {
       
   930         if ( BufferState() >= EBuffering )
       
   931             {
       
   932             // Do not notify about streaming until we know that speaker
       
   933             // is really playing provided data. This cannot be known when
       
   934             // first buffer is sent to speaker.
       
   935             if ( BufferState() == EDetermining )
       
   936                 {
       
   937                 __JITTER_BUFFER( "CMccJitterBufferImpl::HandleNotifications, to playing state" )
       
   938 
       
   939                 SetBufferState( EPlaying );
       
   940                 iNotifyUser = ETrue;
       
   941                 
       
   942                 // As we are hiding buffer state changes when doing several
       
   943                 // speaker starting attempts in row:
       
   944                 // idle->buffering->streaming->idle->noresources->(buffering)->
       
   945                 // (streaming)->(idle)->(noresources)->(buffering)-> etc.
       
   946                 // We have to "fake" the buffering event when we are
       
   947                 // sure that playback is fine.
       
   948                 if ( KMccStreamBuffering != iLatestNotifiedEvent )
       
   949                     {
       
   950                     SendStreamEventToClient( KMccStreamBuffering, ETrue );
       
   951                     }
       
   952                 
       
   953                 SendStreamEventToClient( KMccStreamPlaying, ETrue );
       
   954                 }
       
   955             else
       
   956                 {
       
   957                 SetBufferState( EDetermining );
       
   958                 }
       
   959             }
       
   960         }
       
   961     }
       
   962   
       
   963 // -----------------------------------------------------------------------------
       
   964 // CMccJitterBufferImpl::CheckThresholdBufferLength
       
   965 // -----------------------------------------------------------------------------
       
   966 //  
       
   967 void CMccJitterBufferImpl::CheckThresholdBufferLength(
       
   968     TInt& aBufferLength, TInt aTreshhold ) const
       
   969     {
       
   970     const TInt numTen = 10;
       
   971     if ( ( aBufferLength - aTreshhold ) < numTen )  
       
   972         {
       
   973         aBufferLength = aTreshhold + numTen;
       
   974         }
       
   975     }
       
   976 
       
   977 // -----------------------------------------------------------------------------
       
   978 // CMccJitterBufferImpl::SendStreamEventToClient
       
   979 // -----------------------------------------------------------------------------
       
   980 //	
       
   981 void CMccJitterBufferImpl::SendStreamEventToClient( 
       
   982     TMccEventType aEventType,
       
   983     TBool aAllEndpoints )
       
   984     {
       
   985     __JITTER_BUFFER( "CMccJitterBufferImpl::SendStreamEventToClient" )
       
   986     
       
   987     if ( iEventHandler && iNotifyUser )
       
   988 	    {
       
   989 	    const TUint32 endpointId = aAllEndpoints ? 0 : iEndpointId;
       
   990 	    // Clear old event
       
   991 	    { 
       
   992 	    iMccEvent = TMccEvent();
       
   993 	    }
       
   994 	    
       
   995 	    iMccEvent.iEndpointId = endpointId;
       
   996 	    iMccEvent.iEventCategory = KMccEventCategoryStream;
       
   997 	    iMccEvent.iEventType = aEventType;
       
   998 
       
   999 		TMccInternalEvent internalEvent( KMccJitterBufferUid, 
       
  1000 		                                 EMccInternalEventNone,
       
  1001 		                                 iMccEvent );
       
  1002 		                         
       
  1003 		iEventHandler->SendEventToClient( internalEvent );
       
  1004 		iLatestNotifiedEvent = aEventType;
       
  1005 	    }
       
  1006 	else
       
  1007 		{
       
  1008 		__JITTER_BUFFER( "CMccJitterBufferImpl::SendStreamEventToClient, sending ignored" )
       
  1009 		}
       
  1010     }
       
  1011 
       
  1012 // -----------------------------------------------------------------------------
       
  1013 // CMccJitterBufferImpl::SetBufferState
       
  1014 // -----------------------------------------------------------------------------
       
  1015 //		
       
  1016 void CMccJitterBufferImpl::SetBufferState( TMccJitterBufferImplState aState )
       
  1017     {
       
  1018     iBufferState = aState;
       
  1019     }
       
  1020 
       
  1021 // -----------------------------------------------------------------------------
       
  1022 // CMccJitterBufferImpl::BufferState
       
  1023 // -----------------------------------------------------------------------------
       
  1024 //   
       
  1025 CMccJitterBufferImpl::TMccJitterBufferImplState 
       
  1026     CMccJitterBufferImpl::BufferState() const
       
  1027     {
       
  1028     return iBufferState;
       
  1029     }
       
  1030         
       
  1031 // ========================== OTHER EXPORTED FUNCTIONS =========================
       
  1032 
       
  1033 //  End of File 
       
  1034