mmserv/voipaudioservices/JitterBufferUtility/src/JitterBufferImpl.cpp
changeset 0 71ca22bcf22a
child 53 eabc8c503852
equal deleted inserted replaced
-1:000000000000 0:71ca22bcf22a
       
     1 /*
       
     2 * Copyright (c) 2008 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 // INCLUDE FILES
       
    20 #include <e32base.h>
       
    21 #include <mmcccodecinformation.h> //codec FourCC declarations
       
    22 #include "debugtracemacros.h"
       
    23 #include "CngGenerator.h"
       
    24 #include "InternalDef.h"
       
    25 #include "JitterBufferObserver.h"
       
    26 #include "JitterBufferImpl.h"
       
    27 
       
    28 
       
    29 // -----------------------------------------------------------------------------
       
    30 // TJitterBufferElement::CompareSeqNum
       
    31 // Compare SequenceNumber
       
    32 // -----------------------------------------------------------------------------
       
    33 //
       
    34 TInt TJitterBufferElement::CompareSeqNum(const TJitterBufferElement& aElem1,
       
    35                                          const TJitterBufferElement& aElem2)
       
    36     {
       
    37     if (aElem1.iSequenceNumber > aElem2.iSequenceNumber)
       
    38         {
       
    39         return (-1);
       
    40         }
       
    41     else if (aElem1.iSequenceNumber < aElem2.iSequenceNumber)
       
    42         {
       
    43         return (1);
       
    44         }
       
    45     else
       
    46         {
       
    47         return (0);
       
    48         }
       
    49     }
       
    50 
       
    51 // -----------------------------------------------------------------------------
       
    52 // TJitterBufferElement::CompareStamp
       
    53 // Compare Stamp
       
    54 // -----------------------------------------------------------------------------
       
    55 //
       
    56 TInt TJitterBufferElement::CompareStamp(const TJitterBufferElement& aElem1,
       
    57                                         const TJitterBufferElement& aElem2)
       
    58     {
       
    59     if (aElem1.iTimeStamp > aElem2.iTimeStamp)
       
    60         {
       
    61         return (-1);
       
    62         }
       
    63     else if (aElem1.iTimeStamp < aElem2.iTimeStamp)
       
    64         {
       
    65         return (1);
       
    66         }
       
    67     else
       
    68         {
       
    69         return (0);
       
    70         }
       
    71     }
       
    72 
       
    73 // -----------------------------------------------------------------------------
       
    74 // CVoIPJitterBufferImpl::CVoIPJitterBufferImpl
       
    75 // C++ default constructor can NOT contain any code, that might leave.
       
    76 // -----------------------------------------------------------------------------
       
    77 //
       
    78 CVoIPJitterBufferImpl::CVoIPJitterBufferImpl(MJitterBufferObserver* aObserver) :
       
    79     iBufStampSorter(TLinearOrder<TJitterBufferElement>(
       
    80                     TJitterBufferElement::CompareStamp)),
       
    81     iBufSequenceSorter(TLinearOrder<TJitterBufferElement>(
       
    82                     TJitterBufferElement::CompareSeqNum))
       
    83     {
       
    84     iObserver = aObserver;
       
    85     iTonePlayTime.UniversalTime();
       
    86     iSampleRate = KDefaultSampleRateInkHz;
       
    87     iPlay = EFalse;
       
    88     iLastPlayedSeqNum = -1;
       
    89     }
       
    90 
       
    91 // -----------------------------------------------------------------------------
       
    92 // CVoIPJitterBufferImpl::NewL
       
    93 // Static constructor.
       
    94 // -----------------------------------------------------------------------------
       
    95 //
       
    96 CVoIPJitterBufferImpl* CVoIPJitterBufferImpl::NewL(
       
    97                                               MJitterBufferObserver* aObserver)
       
    98     {
       
    99     CVoIPJitterBufferImpl* self = new(ELeave) CVoIPJitterBufferImpl(aObserver);
       
   100     CleanupStack::PushL(self);
       
   101     self->ConstructL();
       
   102     CleanupStack::Pop(self);
       
   103     return self;
       
   104     }
       
   105 
       
   106 // -----------------------------------------------------------------------------
       
   107 // CVoIPJitterBufferImpl::ConstructL
       
   108 // Symbian 2nd phase constructor can leave.
       
   109 // -----------------------------------------------------------------------------
       
   110 //
       
   111 void CVoIPJitterBufferImpl::ConstructL()
       
   112     {
       
   113     }
       
   114 
       
   115 // -----------------------------------------------------------------------------
       
   116 // CVoIPJitterBufferImpl::~CVoIPJitterBufferImpl
       
   117 // Destructor deallocate memory.
       
   118 // -----------------------------------------------------------------------------
       
   119 //
       
   120 CVoIPJitterBufferImpl::~CVoIPJitterBufferImpl()
       
   121     {
       
   122     TRACE_PRN_FN_ENT;
       
   123 
       
   124     delete iCNGenerator;
       
   125 
       
   126     // Deallocate payload memory of jitter buffer elements.
       
   127     TInt count = iBuffer.Count();
       
   128 
       
   129     for (TInt i = 0; i < count; i++)
       
   130         {
       
   131         if (iBuffer[i].iDataFrame)
       
   132             {
       
   133             delete iBuffer[i].iDataFrame;
       
   134             }
       
   135         }
       
   136 
       
   137     iBuffer.Close();
       
   138 
       
   139     TRACE_PRN_FN_EXT;
       
   140     }
       
   141 
       
   142 // -----------------------------------------------------------------------------
       
   143 // CVoIPJitterBufferImpl::SetupL
       
   144 // Setup Jitter buffer
       
   145 // -----------------------------------------------------------------------------
       
   146 //
       
   147 void CVoIPJitterBufferImpl::SetupL(const TFourCC aCodec,
       
   148                                    const TVoIPJBConfig& aJBConfig)
       
   149     {
       
   150     TRACE_PRN_FN_ENT;
       
   151 
       
   152     __ASSERT_ALWAYS(aJBConfig.iJitterLatency, User::Leave(KErrArgument));
       
   153     __ASSERT_ALWAYS(aJBConfig.iJBBufferLength, User::Leave(KErrArgument));
       
   154     __ASSERT_ALWAYS(aJBConfig.iSampleInterval, User::Leave(KErrArgument));
       
   155 
       
   156     // Save the original HW frame time because we may need it in case of
       
   157     // dynamic G.711 adjustment.
       
   158     const TUint8 origHwtime = iJBConfig.iSampleInterval;
       
   159     iJBConfig = aJBConfig;
       
   160 
       
   161     if (iJBConfig.iJBInactivityTimeOut)
       
   162         {
       
   163         if ((iJBConfig.iJBPlayToneFrequency > 0) &&
       
   164             (iJBConfig.iJBPlayToneDuration > 0))
       
   165             {
       
   166             iPlayToneInterval = iJBConfig.iJBPlayToneTimeout;
       
   167             iPlay = ETrue;
       
   168             }
       
   169         }
       
   170 
       
   171     TInt bufLenMultiplier = 1;
       
   172 
       
   173     if (aCodec == KMMFFourCCCodeAMR)
       
   174         {
       
   175         iFrameSize = KAMRNBFrameSize;
       
   176         iSampleInterval = KAMRNBFrameTime;
       
   177         }
       
   178     else if (aCodec == KMccFourCCIdG711)
       
   179         {
       
   180         // G.711 is configured dynamically. Take voip headerlength also into
       
   181         // account. G.711 hwframetime is in milliseconds, so need to multiply.
       
   182         iFrameSize = (iJBConfig.iSampleInterval * KDefaultSampleRateInkHz) +
       
   183                      KVoIPHeaderLength;
       
   184         iSampleInterval = 0;
       
   185 
       
   186         // In case of G.711 codec dynamic configuration, we may need to double
       
   187         // the jitter buffer length if HW frame time is changed from 20ms to
       
   188         // 10ms.
       
   189         if (origHwtime)
       
   190             {
       
   191             bufLenMultiplier = origHwtime / iJBConfig.iSampleInterval;
       
   192 
       
   193             if (!bufLenMultiplier)
       
   194                 {
       
   195                 bufLenMultiplier = 1;
       
   196                 }
       
   197             }
       
   198         }
       
   199     else if (aCodec == KMccFourCCIdILBC)
       
   200         {
       
   201         iFrameSize = KILBCFrameSize;
       
   202         iSampleInterval = 0;
       
   203         }
       
   204     else if (aCodec == KMccFourCCIdG729)
       
   205         {
       
   206         iFrameSize = KG729FrameSize;
       
   207         iSampleInterval = 0;
       
   208         // Multiply G.729 also by two...
       
   209         bufLenMultiplier = 2;
       
   210         }
       
   211     else
       
   212         {
       
   213         TRACE_PRN_N(_L("JB-> Codec Not Supported"));
       
   214         User::Leave(KErrNotSupported);
       
   215         }
       
   216 
       
   217     // Delete and reset old buffer
       
   218     const TInt elems = iBuffer.Count();
       
   219 
       
   220     for (TInt i = 0; i < elems; i++)
       
   221         {
       
   222         if ((iBuffer[i].iDataFrame))
       
   223             {
       
   224             delete iBuffer[i].iDataFrame;
       
   225             iBuffer[i].iDataFrame = NULL;
       
   226             }
       
   227         }
       
   228 
       
   229     iBuffer.Reset();
       
   230 
       
   231     // Calculate needed elements
       
   232     iBufferLength = iJBConfig.iJBBufferLength * bufLenMultiplier;
       
   233     
       
   234     if (iJBConfig.iJBThreshold >= iBufferLength)
       
   235     	{
       
   236     	// adjust threshold size (no need to leave here)
       
   237     	iJBConfig.iJBThreshold = iBufferLength / 2;
       
   238     	}
       
   239 
       
   240     // If the difference between buffer length and threshold is less than 10
       
   241     // increase buffer length, so the differences is 10. This helps handle
       
   242     // buffer overflow more easily.
       
   243     CheckThresholdBufferLength(iBufferLength, iJBConfig.iJBThreshold);
       
   244     iCurrentPlayThreshold = iJBConfig.iJBThreshold;
       
   245     iOriginalPlayThreshold = iJBConfig.iJBThreshold;
       
   246 
       
   247     if (iCNGenerator)
       
   248         {
       
   249         delete iCNGenerator;
       
   250         iCNGenerator = NULL;
       
   251         }
       
   252 
       
   253     iCNGenerator = CVoIPCNGenerator::NewL(iObserver, aCodec);
       
   254 
       
   255     // Create the elements in the Buffer
       
   256     for (TInt k = 0; k < iBufferLength; k++)
       
   257         {
       
   258         CMMFDataBuffer* buf = CMMFDataBuffer::NewL(iFrameSize);
       
   259         CleanupStack::PushL(buf);
       
   260         TJitterBufferElement newElement;
       
   261         newElement.iDataFrame = buf;
       
   262         newElement.iSequenceNumber = -1;
       
   263         newElement.iTimeStamp = -1;
       
   264         iBuffer.AppendL(newElement);
       
   265         CleanupStack::Pop(buf);
       
   266         }
       
   267 
       
   268     // Reset statistics
       
   269     iFramesLost = 0;
       
   270     iFramesReceived = 0;
       
   271     iNumOfLateFrames = 0;
       
   272     iFramesRemoved = 0;
       
   273     iFramesPlayed = 0;
       
   274     iPacketsInBuffer = 0;
       
   275 
       
   276     // Calculate the sequence number increment
       
   277     iSeqNumIncrement = iSampleRate * iJBConfig.iSampleInterval;
       
   278 
       
   279     TRACE_PRN_FN_EXT;
       
   280     }
       
   281 
       
   282 // -----------------------------------------------------------------------------
       
   283 // CVoIPJitterBufferImpl::ResetBufferL
       
   284 // Reset Jitter Buffer
       
   285 // -----------------------------------------------------------------------------
       
   286 //
       
   287 
       
   288 void CVoIPJitterBufferImpl::ResetBuffer(TBool aPlayTone)
       
   289     {
       
   290     TRACE_PRN_FN_ENT;
       
   291 
       
   292     for (TInt i = 0; i < iBufferLength; i++)
       
   293         {
       
   294         iBuffer[i].iSequenceNumber = -1;
       
   295         iBuffer[i].iTimeStamp = -1;
       
   296         }
       
   297 
       
   298     iLastPlayedSeqNum = -1;
       
   299     iCurrentPlayThreshold = iOriginalPlayThreshold;
       
   300     iPacketsInBuffer = 0;
       
   301     iPlay = aPlayTone;
       
   302 
       
   303     TRACE_PRN_FN_EXT;
       
   304     }
       
   305 
       
   306 // -----------------------------------------------------------------------------
       
   307 // CVoIPJitterBufferImpl::DelayUpL
       
   308 // Adds a buffer element into the jitter buffer
       
   309 // -----------------------------------------------------------------------------
       
   310 //
       
   311 void CVoIPJitterBufferImpl::DelayUpL()
       
   312     {
       
   313     TRACE_PRN_FN_ENT;
       
   314 
       
   315     CMMFDataBuffer* buf = CMMFDataBuffer::NewL(iFrameSize);
       
   316     CleanupStack::PushL(buf);
       
   317     TJitterBufferElement newElement;
       
   318     newElement.iDataFrame = buf;
       
   319     newElement.iSequenceNumber = -1;
       
   320     newElement.iTimeStamp = -1;
       
   321     iBuffer.AppendL(newElement);
       
   322     CleanupStack::Pop(buf);
       
   323     
       
   324     iBufferLength++;
       
   325 
       
   326     // Insert one NO_DATA frame into the audio stream, so the jitterbuffer has
       
   327     // the possibility to grow at least one frame from the current size. If
       
   328     // the current playout threshold is zero, then there is ongoing playback or
       
   329     // a DTX period. This means that we should buffer at least one frame before
       
   330     // starting playback.
       
   331     if (iCurrentPlayThreshold == 0)
       
   332         {
       
   333         TRACE_PRN_N(_L("JB-> Adjusting Playback Threshold"));
       
   334         iCurrentPlayThreshold = iPacketsInBuffer + 1;
       
   335         }
       
   336 
       
   337     TRACE_PRN_N1(_L("JB-DelayUpL-> BUF_LEN [%d]"), iBufferLength);
       
   338     TRACE_PRN_N1(_L("JB-DelayUpL-> CUR_FRAMES [%d]"), iPacketsInBuffer);
       
   339     TRACE_PRN_N1(_L("JB-DelayUpL-> PLAY_TH [%d]"), iCurrentPlayThreshold);
       
   340 
       
   341     TRACE_PRN_FN_EXT;
       
   342     }
       
   343 
       
   344 // -----------------------------------------------------------------------------
       
   345 // CVoIPJitterBufferImpl::DelayDownL
       
   346 // Removes an buffer element from the jitter buffer
       
   347 // -----------------------------------------------------------------------------
       
   348 //
       
   349 void CVoIPJitterBufferImpl::DelayDownL()
       
   350     {
       
   351     TRACE_PRN_FN_ENT;
       
   352 
       
   353     // We need to remove one frame from the jitterbuffer. If currently we are
       
   354     // in a DTX period, we're in luck as we do not affect voice quality at all.
       
   355 
       
   356     // DURING DTX:
       
   357     // During DTX periods the jitterbuffer can be empty, so we cannot remove
       
   358     // anything from nothing. Then we basically can remove one element from the
       
   359     // buffer so it is shorter.
       
   360 
       
   361     // DURING SPEECH:
       
   362     // We'll need to remove one audio frame and mark the one preceding the
       
   363     // removed frame as bad. Then we'll continue as usual.
       
   364     TRACE_PRN_N1(_L("JB-DelayDownL-> BUF_LEN [%d]"), iBufferLength);
       
   365     TRACE_PRN_N1(_L("JB-DelayDownL-> CUR_FRAMES [%d]"), iPacketsInBuffer);
       
   366 
       
   367     if (IsEmpty())
       
   368         {
       
   369         // Cannot do anything for empty buffer
       
   370         if (KLowBufferLimit < iBufferLength)
       
   371             {
       
   372             TRACE_PRN_N(_L("JB-DelayDownL-> Empty buffer"));
       
   373 
       
   374             delete iBuffer[iBufferLength - 1].iDataFrame;
       
   375             iBuffer.Remove(iBufferLength - 1);
       
   376             iBufferLength--;
       
   377             }
       
   378         else if (iCurrentPlayThreshold > 0)
       
   379             {
       
   380             TRACE_PRN_N(_L("JB-DelayDownL-> Play threshold modification"));
       
   381 
       
   382             iCurrentPlayThreshold--;
       
   383             }
       
   384         else
       
   385             {
       
   386             // Cannot do anything currently
       
   387             TRACE_PRN_N(_L("JB-DelayDownL-> Buffer empty - Do nothing"));
       
   388             return;
       
   389             }
       
   390         }
       
   391     else if (IsFull())
       
   392         {
       
   393         // If there is sufficiently data in the buffer, then remove one
       
   394         // frame and mark the one preceding it bad
       
   395         if (KLowBufferLimit < iPacketsInBuffer)
       
   396             {
       
   397             TRACE_PRN_N(_L("JB-DelayDownL-> Buffer full - Removing"));
       
   398 
       
   399             // Remove the 2nd oldest frame and mark the oldest as bad
       
   400             delete iBuffer[1].iDataFrame;
       
   401             iBuffer.Remove(1);
       
   402 
       
   403             // MARK THE FIRST AS BAD FRAME!!!
       
   404 
       
   405             iBufferLength--;
       
   406             iPacketsInBuffer--;
       
   407             iFramesRemoved++;
       
   408             }
       
   409         else
       
   410             {
       
   411             // Cant do removing, see if playthreshold can be adjusted
       
   412             if (iCurrentPlayThreshold > 0)
       
   413                 {
       
   414                 TRACE_PRN_N(_L("JB-DelayDownL-> Buffer full - Do nothing"));
       
   415 
       
   416                 iCurrentPlayThreshold--;
       
   417                 }
       
   418             }
       
   419         }
       
   420     else
       
   421         {
       
   422         if (KLowBufferLimit < iBufferLength)
       
   423             {
       
   424             TRACE_PRN_N(_L("JB-DelayDownL-> Adjusting frame length"));
       
   425 
       
   426             // Adjust the length of the buffer
       
   427             delete iBuffer[iBufferLength - 1].iDataFrame;
       
   428             iBuffer.Remove(iBufferLength - 1);
       
   429             iBufferLength--;
       
   430             }
       
   431         else
       
   432             {
       
   433             TRACE_PRN_N(_L("JB-DelayDownL-> Buffer too small"));
       
   434             }
       
   435         }
       
   436 
       
   437     TRACE_PRN_FN_EXT;
       
   438     }
       
   439 
       
   440 // -----------------------------------------------------------------------------
       
   441 // CVoIPJitterBufferImpl::CalculateDelay
       
   442 // Calculates the current jitter buffer playback
       
   443 // -----------------------------------------------------------------------------
       
   444 //
       
   445 TTimeIntervalMicroSeconds32 CVoIPJitterBufferImpl::CalculateDelay() const
       
   446     {
       
   447     TTimeIntervalMicroSeconds32 delay =
       
   448                                 iJBConfig.iJitterLatency * iPacketsInBuffer;
       
   449 
       
   450 //    TRACE_PRN_N1(_L("JB-CalculateDelay-> Delay [%d]"), delay);
       
   451 
       
   452     return delay;
       
   453     }
       
   454 
       
   455 // -----------------------------------------------------------------------------
       
   456 // CVoIPJitterBufferImpl::AddDataFrame
       
   457 // Adds audio frame into the jitter buffer
       
   458 // -----------------------------------------------------------------------------
       
   459 //
       
   460 TInt CVoIPJitterBufferImpl::AddDataFrame(CMMFBuffer* aDataBuffer)
       
   461     {
       
   462     if (aDataBuffer == NULL)
       
   463         {
       
   464         return KErrNotReady;
       
   465         }
       
   466 
       
   467     iCurrentSeqNum = aDataBuffer->FrameNumber();
       
   468     iFramesReceived++;
       
   469 
       
   470     // TODO: && TBD: Playout threshold update & re-buffering when starting
       
   471     // a new talk-burst.
       
   472     //
       
   473     // 1. If sender does not use inbaund DTX signalling.
       
   474     //  1.1 We may start re-buffering and sender goes into DTX mode again
       
   475     //      => We may not reach the playout threshold if the talkspurt is short
       
   476     //      => Also some random babble noise may activate the sender temporarily
       
   477     //      => The babble noise frame never gets played or some of these frames
       
   478     //         never get played.
       
   479     //
       
   480     // 2. If sender does use inband DTX signalling
       
   481     //  2.1 We can see the start of the DTX period which is cheked in
       
   482     //      GetDataFrameL()
       
   483     //  2.2 During DTX period we may detect the end of the DTX period &
       
   484     //      updates during the DTX period.
       
   485     //
       
   486     // 3. Packet loss may affect in the DTX detection.
       
   487     //  3.1 DTX start packet may be lost
       
   488     //  3.2 DTX UPDATE packet may be lost (if used)
       
   489     //
       
   490 
       
   491     TUint index = FindLargestSeqNum();
       
   492         
       
   493     if (iLastPlayedSeqNum < KMaxSeqNumber - iSeqNumIncrement)
       
   494         {
       
   495         iIsWrappedAround = IsSeqNumWrappedAround(iLargestSeqNum,
       
   496                                                  iCurrentSeqNum);    
       
   497         }
       
   498     else
       
   499         {
       
   500         // If the last played frame was larger than the current largest
       
   501         // in JB we are most likely running in the wrap-around mode.
       
   502         iIsWrappedAround = IsSeqNumWrappedAround(iLastPlayedSeqNum,
       
   503                                                  iLargestSeqNum);
       
   504         }
       
   505 
       
   506     if (iIsWrappedAround)
       
   507         {
       
   508         iLastPlayedSeqNum = -1;
       
   509         }
       
   510 
       
   511     TRACE_PRN_N1(_L("JB-> [ADD] LARGEST IN  [%d]"), TInt32(iLargestSeqNum));
       
   512     TRACE_PRN_N1(_L("JB-> [ADD] THIS FRAME  [%d]"), TInt32(iCurrentSeqNum));
       
   513     TRACE_PRN_N1(_L("JB-> [ADD] LAST PLAYED [%d]"), TInt32(iLastPlayedSeqNum));
       
   514     TRACE_PRN_N1(_L("JB-> [ADD] PACKETS [%d]"), iPacketsInBuffer);
       
   515 
       
   516     iDataBuffer = static_cast<CMMFDataBuffer*>(aDataBuffer);
       
   517 
       
   518     if (iCurrentSeqNum > iLastPlayedSeqNum)
       
   519         {
       
   520         if (IsFull())
       
   521             {
       
   522             TRACE_PRN_N(_L("JB-> [ADD] BUFFER OVERFLOW"));
       
   523 
       
   524             // Remove the oldest frame from the buffer
       
   525             iLastPlayedSeqNum = iBuffer[iPacketsInBuffer - 1].iSequenceNumber;
       
   526             iBuffer[iPacketsInBuffer - 1].iSequenceNumber = -1;
       
   527             iBuffer[iPacketsInBuffer - 1].iTimeStamp = -1;
       
   528             iPacketsInBuffer--;
       
   529 
       
   530             InsertBufferElement(iDataBuffer->Data(), index);
       
   531             iDataBuffer = NULL;
       
   532             iFramesRemoved++;
       
   533             iOverflowCounter++;
       
   534 
       
   535             TRACE_PRN_N1(_L("JB-> [ADD] OverflowCount[%d]"), iOverflowCounter);
       
   536 
       
   537             // Report overflow only after KOverflowAlarmLimit
       
   538             if (iObserver && iOverflowCounter > KOverflowAlarmLimit)
       
   539                 {
       
   540                 iObserver->EventJB(MJitterBufferObserver::EBufferOverflow);
       
   541                 ResetBuffer(ETrue);
       
   542                 iOverflowCounter = 0;
       
   543                 }
       
   544             }
       
   545         else if (IsEmpty())
       
   546             {
       
   547             TTimeIntervalSeconds interval;
       
   548             TTime currentTime;
       
   549             currentTime.UniversalTime();
       
   550             currentTime.SecondsFrom(iTonePlayTime, interval);
       
   551 
       
   552             if (iPlay && interval.Int() >= iPlayToneInterval)
       
   553                 {
       
   554                 TRACE_PRN_N(_L("JB-> [ADD] BUFFER EMPTY - Tone to be played"));
       
   555                 iTonePlayTime.UniversalTime();
       
   556                 iPlay = EFalse;
       
   557                 }
       
   558             else
       
   559                 {
       
   560                 TRACE_PRN_N(_L("JB-> [ADD] BUFFER EMPTY - Tone NOT played"));
       
   561                 TRACE_PRN_N1(_L("JB-> [ADD] Interval Tm [%d]"), interval.Int());
       
   562                 }
       
   563 
       
   564             // No point to run at 0 threshold; restore the original 
       
   565             // settings and rebuffer. 
       
   566             iCurrentPlayThreshold = iOriginalPlayThreshold;
       
   567 
       
   568             const TInt64 nextGetSeqNum(iLastPlayedSeqNum + iSeqNumIncrement);
       
   569             const TInt64 frameSeq(iDataBuffer->FrameNumber());
       
   570 
       
   571             if (frameSeq > nextGetSeqNum)
       
   572                 {
       
   573                 // We are empty and there are frames missing between last
       
   574                 // received frame and frame sequence number. This might be
       
   575                 // because of DTX period, so we need to adjust accordingly.
       
   576                 iLastPlayedSeqNum = frameSeq - iSeqNumIncrement;
       
   577                 InsertBufferElement(iDataBuffer->Data(), index);
       
   578 
       
   579                 TRACE_PRN_N(_L("JB-> [ADD] MISSING & EMPTY"));
       
   580                 }
       
   581             else
       
   582                 {
       
   583                 InsertBufferElement(iDataBuffer->Data(), index);
       
   584                 }
       
   585             }
       
   586         else
       
   587             {
       
   588             TRACE_PRN_N(_L("JB-> [ADD] NORMAL"));
       
   589             iOverflowCounter = 0;
       
   590             InsertBufferElement(iDataBuffer->Data(), index);
       
   591             }
       
   592         }
       
   593     else
       
   594         {
       
   595         iNumOfLateFrames++;
       
   596         aDataBuffer->SetStatus(EAvailable);
       
   597         TRACE_PRN_N(_L("JB-> [ADD] TOO LATE"));
       
   598         }
       
   599     
       
   600     return KErrNone;
       
   601     }
       
   602 
       
   603 // -----------------------------------------------------------------------------
       
   604 // CVoIPJitterBufferImpl::GetDataFrame
       
   605 // Get DataFrame
       
   606 // -----------------------------------------------------------------------------
       
   607 //
       
   608 TInt CVoIPJitterBufferImpl::GetDataFrame(CMMFBuffer* aBuffer)
       
   609     {
       
   610     if (aBuffer == NULL)
       
   611         {
       
   612         return KErrNotReady;
       
   613         }
       
   614 
       
   615     iDataBuffer = static_cast<CMMFDataBuffer*>(aBuffer);
       
   616     TDes8& playBuffer(iDataBuffer->Data());
       
   617     iFramesPlayed++;
       
   618 
       
   619     if (IsEmpty())
       
   620         {
       
   621         // Buffer is empty, so we need to generate CN frames. During DTX period
       
   622         // this is where we'll end up. If we are empty because of DTX period,
       
   623         // the CN generator will do the error concealment.
       
   624         TRACE_PRN_N(_L("JB-> [GET] BUFFER EMPTY"));
       
   625 
       
   626         iCNGenerator->GenerateSidPacket(playBuffer, iDataBuffer->RequestSize());
       
   627         
       
   628         // Used for talkburst; when talk-burst is over, reset buffer
       
   629         // and sequence number
       
   630         if (iJBConfig.iJBInactivityTimeOut > 0 && iInactivityTime >= 0)
       
   631             {
       
   632             // Currently it is only used for AMR codec.
       
   633             iInactivityTime += iSampleInterval;
       
   634 
       
   635             if (iInactivityTime >= iJBConfig.iJBInactivityTimeOut)
       
   636                 {
       
   637                 TRACE_PRN_N1(_L("JB-> [GET] Inactivity Time Detected [%d]"),
       
   638                              iInactivityTime);
       
   639                 iInactivityTime = -1;
       
   640                 ResetBuffer();
       
   641                 }
       
   642             }
       
   643         }
       
   644     else
       
   645         {
       
   646         // Check if threshold is met. If not, continue buffering.
       
   647         if (iPacketsInBuffer < iCurrentPlayThreshold)
       
   648             {
       
   649             // Give comfort noise when we are buffering before playback starts
       
   650             TRACE_PRN_N(_L("JB-> [GET] THRESHOLD NOT REACHED"));
       
   651             iCNGenerator->GenerateSidPacket(playBuffer,
       
   652                                             iDataBuffer->RequestSize());
       
   653             }
       
   654         else
       
   655             {
       
   656             // Reset threshold, so we can  play current talk-spurt till the
       
   657             // end without affecting speech quality. This means that we will
       
   658             // play the buffer until it is empty. After that, it is either
       
   659             // DTX period or packet loss.
       
   660             iCurrentPlayThreshold = 0;
       
   661 
       
   662             // The actual sequence number which is in the buffer
       
   663 //            const TInt64 frameToPlay(
       
   664 //                         iBuffer[iPacketsInBuffer - 1].iSequenceNumber);
       
   665 
       
   666             TRACE_PRN_N1(_L("JB-> [GET] FRAME TO PLAY [%d]"),
       
   667                          TInt32(iBuffer[iPacketsInBuffer - 1].iSequenceNumber));
       
   668             TRACE_PRN_N1(_L("JB-> [GET] LAST PLAYED   [%d]"),
       
   669                          TInt32(iLastPlayedSeqNum));
       
   670             TRACE_PRN_N1(_L("JB-> [GET] PACKETS [%d]"), iPacketsInBuffer);
       
   671 
       
   672             // Get next in order frame to play
       
   673             TJitterBufferElement& jbElement = iBuffer[iPacketsInBuffer - 1];
       
   674 
       
   675             if (playBuffer.MaxLength() >= jbElement.iDataFrame->Data().Length())
       
   676                 {
       
   677                 playBuffer.Copy(jbElement.iDataFrame->Data());
       
   678                 }
       
   679             else
       
   680                 {
       
   681                 TRACE_PRN_N1(_L("JB-> [GET] ERROR: BUFFER TOO SMALL [%d]"),
       
   682                              playBuffer.MaxLength());
       
   683 
       
   684                 iCNGenerator->GenerateSidPacket(playBuffer,
       
   685                                                 iDataBuffer->RequestSize());
       
   686                 }
       
   687 
       
   688             iLastPlayedSeqNum = jbElement.iSequenceNumber;
       
   689             jbElement.iSequenceNumber = -1;
       
   690             jbElement.iTimeStamp = -1;
       
   691             iPacketsInBuffer--;
       
   692 
       
   693             // Reset inactivity timeout timer
       
   694             iInactivityTime = 0;
       
   695 
       
   696             // Try to lead new buffer to DTX period
       
   697             iCNGenerator->DoDtxDecision(playBuffer);
       
   698             }
       
   699         }
       
   700     
       
   701     return KErrNone;
       
   702     }
       
   703 
       
   704 // -----------------------------------------------------------------------------
       
   705 // CVoIPJitterBufferImpl::FindLargestSeqNum
       
   706 // Find Largest SequenceNumber
       
   707 // -----------------------------------------------------------------------------
       
   708 //
       
   709 TUint CVoIPJitterBufferImpl::FindLargestSeqNum()
       
   710     {
       
   711     TUint pos = 0;
       
   712     const TInt len = BufferLength();
       
   713     iLargestSeqNum = 0;
       
   714 
       
   715     for (TUint i = 0; i < len; i++)
       
   716         {
       
   717         // 99% of the time element 0 will hold the largest sequence num,
       
   718         // so, it won't have to search through the entire array.
       
   719         if (iBuffer[i].iSequenceNumber > iLargestSeqNum)
       
   720             {
       
   721             iLargestSeqNum = iBuffer[i].iSequenceNumber;
       
   722             pos = i;
       
   723             }
       
   724         }
       
   725 
       
   726     return pos;
       
   727     }
       
   728 
       
   729 // -----------------------------------------------------------------------------
       
   730 // CVoIPJitterBufferImpl::InsertBufferElement
       
   731 // Insert Buffer Element
       
   732 // -----------------------------------------------------------------------------
       
   733 //
       
   734 void CVoIPJitterBufferImpl::InsertBufferElement(const TDesC8& aBuffer,
       
   735                                                 TInt64 aLargestSeqNum)
       
   736     {
       
   737 //    TRACE_PRN_FN_ENT;
       
   738 
       
   739 /*    if (aBuffer.Length() == 0 || aBuffer.Length() > iFrameSize)
       
   740         {
       
   741         TRACE_PRN_N(_L("JB->INVALID DATA, IGNORING"));
       
   742         return;
       
   743         }*/
       
   744 
       
   745     const TInt len(BufferLength());
       
   746 
       
   747     if (iIsWrappedAround)
       
   748         {
       
   749         iBuffer[len-1].iDataFrame->Data().Copy(aBuffer);
       
   750         iBuffer[len-1].iSequenceNumber = iCurrentSeqNum;
       
   751 
       
   752         for (TInt i = 0; i < len; i++)
       
   753             {
       
   754             if (iBuffer[i].iTimeStamp > aLargestSeqNum)
       
   755                 {
       
   756                 aLargestSeqNum = iBuffer[i].iTimeStamp;
       
   757                 }
       
   758             }
       
   759 
       
   760         iBuffer[len-1].iTimeStamp = aLargestSeqNum + 1;
       
   761         iBuffer.Sort(iBufStampSorter);
       
   762         iLastPlayedSeqNum = -1;
       
   763         }
       
   764     else
       
   765         {
       
   766         iBuffer[len-1].iDataFrame->Data().Copy(aBuffer);
       
   767         iBuffer[len-1].iSequenceNumber = iCurrentSeqNum;
       
   768         iBuffer[len-1].iTimeStamp = iCurrentSeqNum - BufferLength();
       
   769         iBuffer.Sort(iBufSequenceSorter);
       
   770         }
       
   771 
       
   772     iPacketsInBuffer++;
       
   773 
       
   774 //    TRACE_PRN_FN_EXT;
       
   775     }
       
   776 
       
   777 // -----------------------------------------------------------------------------
       
   778 // CVoIPJitterBufferImpl::BufferLength()
       
   779 // Return buffer length.
       
   780 // -----------------------------------------------------------------------------
       
   781 //
       
   782 TInt CVoIPJitterBufferImpl::BufferLength() const
       
   783     {
       
   784     return iBufferLength;
       
   785     }
       
   786 
       
   787 // -----------------------------------------------------------------------------
       
   788 // CVoIPJitterBufferImpl::PacketCount()
       
   789 // Return number of packets that are currently in the buffer.
       
   790 // -----------------------------------------------------------------------------
       
   791 //
       
   792 TInt CVoIPJitterBufferImpl::PacketCount() const
       
   793     {
       
   794     return iPacketsInBuffer;
       
   795     }
       
   796 
       
   797 // -----------------------------------------------------------------------------
       
   798 // CVoIPJitterBufferImpl::IsFull()
       
   799 // Return:    True if full
       
   800 //            False if not full
       
   801 // -----------------------------------------------------------------------------
       
   802 //
       
   803 TBool CVoIPJitterBufferImpl::IsFull() const
       
   804     {
       
   805     return (iPacketsInBuffer == iBufferLength);
       
   806     }
       
   807 
       
   808 // -----------------------------------------------------------------------------
       
   809 // CVoIPJitterBufferImpl::IsEmpty()
       
   810 // Return:    True if empty
       
   811 //            False if not empty
       
   812 // -----------------------------------------------------------------------------
       
   813 //
       
   814 TBool CVoIPJitterBufferImpl::IsEmpty() const
       
   815     {
       
   816     return (iPacketsInBuffer == 0);
       
   817     }
       
   818 
       
   819 // -----------------------------------------------------------------------------
       
   820 // CVoIPJitterBufferImpl::IsSeqNumWrappedAround
       
   821 // Checks if sequence number is wrapped around between aSeqNum1 and aSeqNum2.
       
   822 // The sequence number wrap-around condition cannot be reliably detected by
       
   823 // checking for exact numbers (e.g. aSeqNum1==KMaxSeqNumber and aSeqNum2==0).
       
   824 // This is because of network packet loss, where there might be gaps between
       
   825 // frame sequence numbers.
       
   826 // -----------------------------------------------------------------------------
       
   827 //
       
   828 TBool CVoIPJitterBufferImpl::IsSeqNumWrappedAround(TInt64 aSeqNum1,
       
   829                                                    TInt64 aSeqNum2) const
       
   830     {
       
   831     TBool status = EFalse;
       
   832 
       
   833     if (aSeqNum1 >= (KMaxSeqNumber - iSeqNumIncrement) &&
       
   834         aSeqNum2 <= (iBufferLength * iSeqNumIncrement))
       
   835         {
       
   836         TRACE_PRN_N(_L("JB-> SEQUENCE WRAPPED-AROUND"));
       
   837         status = ETrue;
       
   838         }
       
   839 
       
   840     return status;
       
   841     }
       
   842 
       
   843 // -----------------------------------------------------------------------------
       
   844 // CVoIPJitterBufferImpl::GenerateStatistics
       
   845 // Generates the statistics from the jitterbuffer
       
   846 // -----------------------------------------------------------------------------
       
   847 //
       
   848 void CVoIPJitterBufferImpl::GenerateStatistics(/*TJBStats& aStats*/) const
       
   849     {/*
       
   850     aStats.iFramesReceived = iFramesReceived;
       
   851     aStats.iBufferLength = iBufferLength;
       
   852     aStats.iFramesInBuffer = iPacketsInBuffer;
       
   853     aStats.iFrameLoss = iFramesLost;
       
   854     aStats.iLateFrames = iNumOfLateFrames;
       
   855     aStats.iFramesRemoved = iFramesRemoved;
       
   856     aStats.iFramesPlayed = iFramesPlayed;*/
       
   857     }
       
   858 
       
   859 // -----------------------------------------------------------------------------
       
   860 // CVoIPJitterBufferImpl::CheckThresholdBufferLength
       
   861 // -----------------------------------------------------------------------------
       
   862 //
       
   863 void CVoIPJitterBufferImpl::CheckThresholdBufferLength(TInt& aBufferLength,
       
   864                                                        TInt aTreshhold) const
       
   865     {
       
   866     const TInt numTen = 10;
       
   867 
       
   868     if ((aBufferLength - aTreshhold) < numTen)
       
   869         {
       
   870         aBufferLength = aTreshhold + numTen;
       
   871         }
       
   872     }
       
   873 
       
   874 
       
   875 //  End of File
       
   876