mmserv/voipaudioservices/JitterBufferUtility/src/JitterBuffer.cpp
changeset 0 71ca22bcf22a
child 3 4f62049db6ac
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:  JitterBuffer component capable to audioframe buffering.
       
    15 *
       
    16 */
       
    17 
       
    18 
       
    19 // INCLUDE FILES
       
    20 #include <e32base.h>
       
    21 #include <mmcccodecinformation.h> //FourCC codes
       
    22 #include "debugtracemacros.h"
       
    23 #include "InternalDef.h"
       
    24 #include "JitterBufferObserver.h"
       
    25 #include "JitterBufferImpl.h"
       
    26 #include "JitterBuffer.h"
       
    27 
       
    28 
       
    29 // -----------------------------------------------------------------------------
       
    30 // CVoIPJitterBuffer::CVoIPJitterBuffer
       
    31 // C++ default constructor can NOT contain any code, that
       
    32 // might leave.
       
    33 // -----------------------------------------------------------------------------
       
    34 //
       
    35 CVoIPJitterBuffer::CVoIPJitterBuffer(MJitterBufferObserver* aObserver) :
       
    36     CActive(EPriorityNormal)
       
    37     {
       
    38     iObserver = aObserver;
       
    39     iState = EJBufStopped;
       
    40     iTmCurrentEmptyBuffer = TTime(0);
       
    41     iTmPreviousEmptyBuffer = TTime(0);
       
    42     }
       
    43 
       
    44 // -----------------------------------------------------------------------------
       
    45 // CVoIPDownlinkThread::NewL
       
    46 // Static constructor.
       
    47 // -----------------------------------------------------------------------------
       
    48 //
       
    49 EXPORT_C CVoIPJitterBuffer* CVoIPJitterBuffer::NewL(
       
    50                                                MJitterBufferObserver* aObserver)
       
    51     {
       
    52     CVoIPJitterBuffer* self = new (ELeave) CVoIPJitterBuffer(aObserver);
       
    53     CleanupStack::PushL(self);
       
    54     self->ConstructL();
       
    55     CleanupStack::Pop(self);
       
    56     return self;
       
    57     }
       
    58 
       
    59 // -----------------------------------------------------------------------------
       
    60 // CVoIPJitterBuffer::ConstructL
       
    61 // Symbian two-phase constructor
       
    62 // -----------------------------------------------------------------------------
       
    63 //
       
    64 void CVoIPJitterBuffer::ConstructL()
       
    65     {
       
    66     CActiveScheduler::Add(this);
       
    67     iTimer.CreateLocal();
       
    68     }
       
    69 
       
    70 // -----------------------------------------------------------------------------
       
    71 // CVoIPJitterBuffer::~CVoIPJitterBuffer
       
    72 // Destructor deallocate memory.
       
    73 // -----------------------------------------------------------------------------
       
    74 //
       
    75 CVoIPJitterBuffer::~CVoIPJitterBuffer()
       
    76     {
       
    77     TRACE_PRN_FN_ENT;
       
    78 
       
    79     if (IsActive())
       
    80         {
       
    81         Cancel();
       
    82         }
       
    83 
       
    84     delete iJitterBufferImpl;
       
    85     iTimer.Close();
       
    86 
       
    87     TRACE_PRN_FN_EXT;
       
    88     }
       
    89 
       
    90 // -----------------------------------------------------------------------------
       
    91 // CVoIPJitterBuffer::SetupL
       
    92 // Setup Jitterbuffer
       
    93 // -----------------------------------------------------------------------------
       
    94 //
       
    95 EXPORT_C void CVoIPJitterBuffer::SetupL(const TFourCC aCodec,
       
    96                                         const TVoIPJBConfig& aJBConfig)
       
    97     {
       
    98     TRACE_PRN_FN_ENT;
       
    99 
       
   100     iCodec = aCodec;
       
   101 
       
   102     if (!iJitterBufferImpl)
       
   103         {
       
   104         iJitterBufferImpl = CVoIPJitterBufferImpl::NewL(iObserver);
       
   105         }
       
   106 
       
   107     if (iJitterBufferImpl)
       
   108         {
       
   109         iJitterBufferImpl->SetupL(aCodec, aJBConfig);
       
   110         iSampleInterval =
       
   111                 aJBConfig.iSampleInterval * KJBMillisecondsToMicroseconds;
       
   112 
       
   113         // Cannot use with G711 as it asks buffers in uncontrolled manner
       
   114         // TODO: change the logic so that it inspects what happens in long
       
   115         // run and if it fails, send error and pause itself.
       
   116         if (iCodec != KMccFourCCIdG711)
       
   117             {
       
   118             // Not too strict with delaying, threshold cannot be bigger than
       
   119             // frame time
       
   120             iEmptyBufferDelayThreshold = iSampleInterval / KJBEmptyBufferDelay;
       
   121             }
       
   122 
       
   123         TRACE_PRN_N1(_L("JB-> DelayThreshold [%d]"),iEmptyBufferDelayThreshold);
       
   124         }
       
   125 
       
   126     TRACE_PRN_FN_EXT;
       
   127     }
       
   128 
       
   129 // -----------------------------------------------------------------------------
       
   130 // CVoIPJitterBuffer::ResetBuffer
       
   131 // Reset Jitterbuffer
       
   132 // -----------------------------------------------------------------------------
       
   133 //
       
   134 EXPORT_C void CVoIPJitterBuffer::ResetBuffer(TBool aPlayTone)
       
   135     {
       
   136     TRACE_PRN_FN_ENT;
       
   137 
       
   138     if (iJitterBufferImpl)
       
   139         {
       
   140         iJitterBufferImpl->ResetBuffer(aPlayTone);
       
   141         }
       
   142 
       
   143     TRACE_PRN_FN_EXT;
       
   144     }
       
   145 
       
   146 // -----------------------------------------------------------------------------
       
   147 // CVoIPJitterBuffer::DelayDownL
       
   148 // Delay Down
       
   149 // -----------------------------------------------------------------------------
       
   150 //
       
   151 EXPORT_C void CVoIPJitterBuffer::DelayDown()
       
   152     {
       
   153     if (iJitterBufferImpl)
       
   154         {
       
   155         TRAPD(err, iJitterBufferImpl->DelayDownL());
       
   156         if (err != KErrNone)
       
   157             {
       
   158             TRACE_PRN_IF_ERR(err);
       
   159             iObserver->EventJB(MJitterBufferObserver::EGeneralError, err);
       
   160             }
       
   161         }
       
   162     }
       
   163 
       
   164 // -----------------------------------------------------------------------------
       
   165 // CVoIPJitterBuffer::DelayUpL
       
   166 // Delay Up
       
   167 // -----------------------------------------------------------------------------
       
   168 //
       
   169 EXPORT_C void CVoIPJitterBuffer::DelayUp()
       
   170     {
       
   171     if (iJitterBufferImpl)
       
   172         {
       
   173         TRAPD(err, iJitterBufferImpl->DelayUpL());
       
   174         if (err != KErrNone)
       
   175             {
       
   176             TRACE_PRN_IF_ERR(err);
       
   177             iObserver->EventJB(MJitterBufferObserver::EGeneralError, err);
       
   178             }
       
   179         }
       
   180     }
       
   181 
       
   182 // -----------------------------------------------------------------------------
       
   183 // CVoIPJitterBuffer::Play
       
   184 //
       
   185 // -----------------------------------------------------------------------------
       
   186 //
       
   187 EXPORT_C void CVoIPJitterBuffer::Play()
       
   188     {
       
   189     TRACE_PRN_FN_ENT;
       
   190 
       
   191     iState = EJBufPlaying;
       
   192     iRequestSize = 0;
       
   193 
       
   194     TRACE_PRN_FN_EXT;
       
   195     }
       
   196 
       
   197 // -----------------------------------------------------------------------------
       
   198 // CVoIPJitterBuffer::Pause
       
   199 //
       
   200 // -----------------------------------------------------------------------------
       
   201 //
       
   202 EXPORT_C void CVoIPJitterBuffer::Pause()
       
   203     {
       
   204     iState = EJBufPaused;
       
   205     ResetBuffer();
       
   206     Cancel();
       
   207     }
       
   208 
       
   209 // -----------------------------------------------------------------------------
       
   210 // CVoIPJitterBuffer::Stop
       
   211 //
       
   212 // -----------------------------------------------------------------------------
       
   213 //
       
   214 EXPORT_C void CVoIPJitterBuffer::Stop()
       
   215     {
       
   216     iState = EJBufStopped;
       
   217     ResetBuffer();
       
   218     Cancel();
       
   219     }
       
   220 
       
   221 // -----------------------------------------------------------------------------
       
   222 // CVoIPJitterBuffer::FillBufferL
       
   223 //
       
   224 // -----------------------------------------------------------------------------
       
   225 //
       
   226 EXPORT_C TInt CVoIPJitterBuffer::FillBuffer(CMMFBuffer* aBuffer)
       
   227     {
       
   228 //    TRACE_PRN_FN_ENT;
       
   229 
       
   230     TInt err = KErrNone;
       
   231 
       
   232     if (iJitterBufferImpl && iJitterBufferImpl->BufferLength())
       
   233         {
       
   234         TRACE_PRN_N(_L("CVoIPJitterBuffer::FillBufferL NORMAL"));
       
   235 
       
   236         TUint32 emptyBufferDelay = 0;
       
   237         
       
   238         if (iCodec != KMccFourCCIdG729)
       
   239             {
       
   240             // This can cause JB overflow on G729 (it does in the loopback)
       
   241             DetermineEmptyBufferDelay();
       
   242             }
       
   243 
       
   244         iPlayBuffer = aBuffer;
       
   245         iJitterBufferImpl->GetDataFrame(iPlayBuffer);
       
   246         TransitionState(EEmptyData, emptyBufferDelay);
       
   247         }
       
   248     else
       
   249         {
       
   250         err = KErrNotReady;
       
   251         TRACE_PRN_IF_ERR(err);
       
   252         iObserver->EventJB(MJitterBufferObserver::EGeneralError, err);
       
   253         }
       
   254 
       
   255 //    TRACE_PRN_FN_EXT;
       
   256     return err;
       
   257     }
       
   258 
       
   259 // -----------------------------------------------------------------------------
       
   260 // CVoIPJitterBuffer::EmptyBuffer
       
   261 // Buffer with data comes in and is passed to JB queue.
       
   262 //
       
   263 // It was callback based; now DNL-THR->BufferFilled will call it directly
       
   264 // upon data receiving. The supplier is now the DNL thread.
       
   265 //
       
   266 // -----------------------------------------------------------------------------
       
   267 //
       
   268 EXPORT_C TInt CVoIPJitterBuffer::EmptyBuffer(CMMFBuffer* aBuffer)
       
   269     {
       
   270 //    TRACE_PRN_FN_ENT;
       
   271     TInt err = KErrNotReady;
       
   272 
       
   273     if (iJitterBufferImpl && (iState == EJBufPlaying))
       
   274         {
       
   275         if (iJitterBufferImpl->BufferLength() == 0)
       
   276             {
       
   277             return err;
       
   278             }
       
   279 
       
   280 //        TRACE_PRN_N1(_L("JB-> BUF Size: [%d]"), aBuffer->BufferSize());
       
   281 //        TRACE_PRN_N1(_L("JB-> REQ Size: [%d]"), aBuffer->RequestSize());
       
   282 
       
   283         // Adaptation control will be done based on played frames
       
   284         err = iJitterBufferImpl->AddDataFrame(aBuffer);
       
   285         }
       
   286 
       
   287     iObserver->EventJB(MJitterBufferObserver::EBufferConsumed);
       
   288 
       
   289     TRACE_PRN_IF_ERR(err);
       
   290 //    TRACE_PRN_FN_EXT;
       
   291     return err;
       
   292     }
       
   293 
       
   294 // -----------------------------------------------------------------------------
       
   295 // CVoIPJitterBuffer::PlayBuffer
       
   296 //
       
   297 // -----------------------------------------------------------------------------
       
   298 //
       
   299 void CVoIPJitterBuffer::PlayBuffer()
       
   300     {
       
   301 //    TRACE_PRN_FN_ENT;
       
   302 
       
   303     // iDataSink has valid data - send for playback
       
   304     iObserver->EventJB(MJitterBufferObserver::EBufferReadyToPlay);
       
   305 
       
   306     // Go to wait state
       
   307 //    TransitionState(EWait);
       
   308 
       
   309 //    TRACE_PRN_FN_EXT;
       
   310     }
       
   311 
       
   312 // -----------------------------------------------------------------------------
       
   313 // CVoIPJitterBuffer::DoCancel
       
   314 // From CActive
       
   315 // -----------------------------------------------------------------------------
       
   316 //
       
   317 void CVoIPJitterBuffer::DoCancel()
       
   318     {
       
   319     iTimer.Cancel();
       
   320     }
       
   321 
       
   322 // -----------------------------------------------------------------------------
       
   323 // CVoIPJitterBuffer::RunL
       
   324 // From CActive
       
   325 // -----------------------------------------------------------------------------
       
   326 //
       
   327 void CVoIPJitterBuffer::RunL()
       
   328     {
       
   329     TRACE_PRN_FN_ENT;
       
   330 
       
   331     switch (iState)
       
   332         {
       
   333         case EJBufStopped:
       
   334             break;
       
   335         case EJBufPaused:
       
   336             break;
       
   337         case EJBufPlaying:
       
   338             {
       
   339             switch (iTransitionState)
       
   340                 {
       
   341                 case EWait:
       
   342                     TRACE_PRN_N(_L("CVoIPJitterBuffer::RunL EWait"));
       
   343                     break;
       
   344                 case EEmptyData:
       
   345                     TRACE_PRN_N(_L("CVoIPJitterBuffer::RunL EEmptyData"));
       
   346                     PlayBuffer();
       
   347                     break;
       
   348                 default:
       
   349                     User::Leave(KErrArgument);
       
   350                     break;
       
   351                 }
       
   352             break;
       
   353             }
       
   354         default:
       
   355             User::Leave(KErrArgument);
       
   356             break;
       
   357         }
       
   358 
       
   359     TRACE_PRN_FN_EXT;
       
   360     }
       
   361 
       
   362 // -----------------------------------------------------------------------------
       
   363 // CVoIPJitterBuffer::RunError
       
   364 //
       
   365 // -----------------------------------------------------------------------------
       
   366 //
       
   367 TInt CVoIPJitterBuffer::RunError(TInt aError)
       
   368     {
       
   369     iObserver->EventJB(MJitterBufferObserver::EGeneralError, aError);
       
   370     return KErrNone;
       
   371     }
       
   372 
       
   373 // -----------------------------------------------------------------------------
       
   374 // CVoIPJitterBuffer::TransitionState
       
   375 //
       
   376 // -----------------------------------------------------------------------------
       
   377 //
       
   378 void CVoIPJitterBuffer::TransitionState(TJBTransitionState aTransitionState,
       
   379                                         TUint32 aStateChangeDelay)
       
   380     {
       
   381     TRequestStatus* stat = &iStatus;
       
   382 
       
   383     iTransitionState = aTransitionState;
       
   384     Cancel();
       
   385 
       
   386     if (aStateChangeDelay)
       
   387         {
       
   388         iTimer.After(iStatus, TTimeIntervalMicroSeconds32(aStateChangeDelay));
       
   389         }
       
   390     else
       
   391         {
       
   392         User::RequestComplete(stat, KErrNone);
       
   393         }
       
   394 
       
   395     SetActive();
       
   396     }
       
   397 
       
   398 // -----------------------------------------------------------------------------
       
   399 // CVoIPJitterBuffer::DetermineEmptyBufferDelay
       
   400 // -----------------------------------------------------------------------------
       
   401 //
       
   402 TUint32 CVoIPJitterBuffer::DetermineEmptyBufferDelay()
       
   403     {
       
   404     TUint32 emptyBufferDelay(0);
       
   405     iTmCurrentEmptyBuffer.HomeTime();
       
   406 
       
   407     if (iTmPreviousEmptyBuffer.Int64())
       
   408         {
       
   409         TTimeIntervalMicroSeconds difference =
       
   410             iTmCurrentEmptyBuffer.MicroSecondsFrom(iTmPreviousEmptyBuffer);
       
   411 
       
   412         if (difference.Int64() < iEmptyBufferDelayThreshold)
       
   413             {
       
   414             emptyBufferDelay = iSampleInterval - difference.Int64();
       
   415             }
       
   416         }
       
   417 
       
   418     iTmPreviousEmptyBuffer = iTmCurrentEmptyBuffer;
       
   419     return emptyBufferDelay;
       
   420     }
       
   421 
       
   422 
       
   423 //  End of File