multimediacommscontroller/mmccvideosourcesink/src/mccvideojitterbuffer.cpp
changeset 0 1bce908db942
equal deleted inserted replaced
-1:000000000000 0:1bce908db942
       
     1 /*
       
     2 * Copyright (c) 2003 Nokia Corporation and/or its subsidiary(-ies).
       
     3 * All rights reserved.
       
     4 * This component and the accompanying materials are made available
       
     5 * under the terms of "Eclipse Public License v1.0"
       
     6 * which accompanies this distribution, and is available
       
     7 * at the URL "http://www.eclipse.org/legal/epl-v10.html".
       
     8 *
       
     9 * Initial Contributors:
       
    10 * Nokia Corporation - initial contribution.
       
    11 *
       
    12 * Contributors:
       
    13 *
       
    14 * Description:    
       
    15 *
       
    16 */
       
    17 
       
    18 
       
    19 
       
    20 
       
    21 // INCLUDES FILES
       
    22 #include "mccvideojitterbuffer.h"
       
    23 #include "mccvideosourcesinklogs.h"
       
    24 #include "mccdef.h"
       
    25 #include <CXPSPacketSink.h>
       
    26 
       
    27 // CONSTANTS
       
    28 const TUint KMccMilliSecondInMicroSecs = 1000;
       
    29 const TUint KMccMinInactivityTimeoutInMicroSecs = 1000000; // 1 sec
       
    30 
       
    31 #define MCC_CONVERT_TO_90KHZ_CLOCK( valInMicroSecs ) ( valInMicroSecs / 100 * 9 )
       
    32 
       
    33 // ---------------------------------------------------------------------------
       
    34 // CMccVideoPacket::NewLC
       
    35 // ---------------------------------------------------------------------------
       
    36 //
       
    37 CMccVideoJitterBuffer::CMccVideoPacket* CMccVideoJitterBuffer::CMccVideoPacket::NewLC( 
       
    38     TUint aStreamId, 
       
    39     const TRtpRecvHeader& aHeaderInfo, 
       
    40     const TDesC8& aPayloadData,
       
    41     TBool aImportantData )
       
    42     {
       
    43     CMccVideoPacket* self = 
       
    44         new ( ELeave ) CMccVideoPacket( aStreamId, aHeaderInfo, aImportantData );
       
    45     CleanupStack::PushL( self );
       
    46     self->ConstructL( aPayloadData );
       
    47     return self;
       
    48     }
       
    49 
       
    50 // ---------------------------------------------------------------------------
       
    51 // CMccVideoPacket::~CMccVideoPacket
       
    52 // ---------------------------------------------------------------------------
       
    53 //
       
    54 CMccVideoJitterBuffer::CMccVideoPacket::~CMccVideoPacket()
       
    55     {
       
    56     delete iPayloadData;
       
    57     }
       
    58 
       
    59 // ---------------------------------------------------------------------------
       
    60 // CMccVideoPacket::StreamId
       
    61 // ---------------------------------------------------------------------------
       
    62 //
       
    63 TUint CMccVideoJitterBuffer::CMccVideoPacket::StreamId()
       
    64     {
       
    65     return iStreamId;
       
    66     }
       
    67 
       
    68 // ---------------------------------------------------------------------------
       
    69 // CMccVideoPacket::HeaderInfo
       
    70 // ---------------------------------------------------------------------------
       
    71 //
       
    72 TRtpRecvHeader& CMccVideoJitterBuffer::CMccVideoPacket::HeaderInfo()
       
    73     {
       
    74     return iHeaderInfo;
       
    75     }
       
    76 
       
    77 // ---------------------------------------------------------------------------
       
    78 // CMccVideoPacket::PayloadData
       
    79 // ---------------------------------------------------------------------------
       
    80 //    
       
    81 const TDesC8& CMccVideoJitterBuffer::CMccVideoPacket::PayloadData()
       
    82     {
       
    83     return *iPayloadData;
       
    84     }
       
    85 
       
    86 // ---------------------------------------------------------------------------
       
    87 // CMccVideoPacket::CMccVideoPacket
       
    88 // ---------------------------------------------------------------------------
       
    89 //    
       
    90 CMccVideoJitterBuffer::CMccVideoPacket::CMccVideoPacket( 
       
    91     TUint aStreamId, 
       
    92     const TRtpRecvHeader& aHeaderInfo,
       
    93     TBool aImportantData ) :
       
    94     iStreamId( aStreamId ),
       
    95     iHeaderInfo( aHeaderInfo ),
       
    96     iImportantData( aImportantData )
       
    97     {
       
    98     }
       
    99  
       
   100 // ---------------------------------------------------------------------------
       
   101 // CMccVideoPacket::ConstructL
       
   102 // ---------------------------------------------------------------------------
       
   103 //           
       
   104 void CMccVideoJitterBuffer::CMccVideoPacket::ConstructL( const TDesC8& aPayloadData )
       
   105     {
       
   106     iPayloadData = aPayloadData.AllocL();
       
   107     }
       
   108 
       
   109 
       
   110 // ---------------------------------------------------------------------------
       
   111 // CMccVideoJitterBuffer::InsertInSeqNumOrder
       
   112 // ---------------------------------------------------------------------------
       
   113 //
       
   114 TInt CMccVideoJitterBuffer::CMccVideoPacket::InsertInSeqNumOrder( 
       
   115     const CMccVideoPacket& aPacket1, const CMccVideoPacket& aPacket2 )
       
   116     {
       
   117     if ( aPacket1.iHeaderInfo.iSeqNum == aPacket2.iHeaderInfo.iSeqNum )
       
   118         {
       
   119         return 0;
       
   120         }
       
   121     return ( aPacket1.iHeaderInfo.iSeqNum < aPacket2.iHeaderInfo.iSeqNum ) ? -1 : 1;
       
   122     }
       
   123 
       
   124 // ---------------------------------------------------------------------------
       
   125 // CMccVideoJitterBuffer::DroppingAllowed
       
   126 // ---------------------------------------------------------------------------
       
   127 //    
       
   128 TBool CMccVideoJitterBuffer::CMccVideoPacket::DroppingAllowed() const
       
   129     {
       
   130     return ( !iImportantData );
       
   131     }
       
   132     
       
   133 // ---------------------------------------------------------------------------
       
   134 // CMccVideoJitterBuffer::CMccVideoJitterBuffer
       
   135 // C++ default constructor can NOT contain any code, that might leave.
       
   136 // ---------------------------------------------------------------------------
       
   137 //
       
   138 CMccVideoJitterBuffer::CMccVideoJitterBuffer( 
       
   139     MMccVideoJitterBufferObserver& aObserver, 
       
   140     CXPSPacketSink& aPacketSink,
       
   141     TUint aInactivityTimeoutInMs ) :
       
   142     CTimer( CActive::EPriorityStandard ),
       
   143     iObserver( aObserver ),
       
   144     iPacketSink( aPacketSink ),
       
   145     iInactivityTimeoutInMicroSecs( aInactivityTimeoutInMs * KMccMilliSecondInMicroSecs ),
       
   146     iPreviousTime( 0 )
       
   147     {
       
   148     CActiveScheduler::Add( this );
       
   149     
       
   150     iInactivityTimeoutInMicroSecs = aInactivityTimeoutInMs * KMccMilliSecondInMicroSecs;
       
   151     
       
   152     __V_SOURCESINK_CONTROLL_INT1( 
       
   153         "CMccVideoJitterBuffer::CMccVideoJitterBuffer, inactivity timeout:",
       
   154         iInactivityTimeoutInMicroSecs ) 
       
   155     
       
   156     if ( iInactivityTimeoutInMicroSecs < KMccMinInactivityTimeoutInMicroSecs )
       
   157         {
       
   158         iInactivityTimeoutInMicroSecs = KMccMinInactivityTimeoutInMicroSecs;
       
   159         __V_SOURCESINK_CONTROLL_INT1( 
       
   160         "CMccVideoJitterBuffer::CMccVideoJitterBuffer, inactivity timeout adjusted:",
       
   161         iInactivityTimeoutInMicroSecs ) 
       
   162         }
       
   163     }
       
   164 
       
   165 
       
   166 // ---------------------------------------------------------------------------
       
   167 // CMccVideoJitterBuffer::ConstructL
       
   168 // Symbian 2nd phase constructor can leave.
       
   169 // ---------------------------------------------------------------------------
       
   170 //
       
   171 void CMccVideoJitterBuffer::ConstructL()
       
   172     {
       
   173     __V_SOURCESINK_CONTROLL( "CMccVideoJitterBuffer::ConstructL" ) 
       
   174     
       
   175     CTimer::ConstructL();
       
   176     
       
   177     ConfigureL( KMccJitterBufferDefaultLowLimit, 
       
   178                 KMccJitterBufferDefaultHighLimit, 
       
   179                 KMccJitterBufferDefaultPlayThreshold,
       
   180                 KMccJitterBufferDefaultMaxSize,
       
   181                 KMccDefaultVideoFrameRate );
       
   182     
       
   183     __V_SOURCESINK_CONTROLL( "CMccVideoJitterBuffer::ConstructL, exit" ) 
       
   184     }
       
   185 
       
   186 
       
   187 // ---------------------------------------------------------------------------
       
   188 // CMccVideoJitterBuffer::NewL
       
   189 // Two-phased constructor.
       
   190 // ---------------------------------------------------------------------------
       
   191 //
       
   192 CMccVideoJitterBuffer* CMccVideoJitterBuffer::NewL( 
       
   193     MMccVideoJitterBufferObserver& aObserver, 
       
   194     CXPSPacketSink& aPacketSink,
       
   195     TUint aInactivityTimeoutInMs )
       
   196     {
       
   197     CMccVideoJitterBuffer* self = CMccVideoJitterBuffer::NewLC( 
       
   198         aObserver, aPacketSink, aInactivityTimeoutInMs );
       
   199     CleanupStack::Pop( self );
       
   200     return self;
       
   201     }
       
   202 
       
   203 
       
   204 // ---------------------------------------------------------------------------
       
   205 // CMccVideoJitterBuffer::NewLC
       
   206 // Two-phased constructor.
       
   207 // ---------------------------------------------------------------------------
       
   208 //
       
   209 CMccVideoJitterBuffer* CMccVideoJitterBuffer::NewLC( 
       
   210     MMccVideoJitterBufferObserver& aObserver, 
       
   211     CXPSPacketSink& aPacketSink,
       
   212     TUint aInactivityTimeoutInMs )
       
   213     {
       
   214     CMccVideoJitterBuffer* self = new( ELeave ) CMccVideoJitterBuffer( 
       
   215         aObserver, aPacketSink, aInactivityTimeoutInMs );
       
   216     CleanupStack::PushL( self );
       
   217     self->ConstructL();
       
   218     return self;
       
   219     }
       
   220 
       
   221 
       
   222 // ---------------------------------------------------------------------------
       
   223 // CMccVideoJitterBuffer::~CMccVideoJitterBuffer
       
   224 // Destructor.
       
   225 // ---------------------------------------------------------------------------
       
   226 //
       
   227 CMccVideoJitterBuffer::~CMccVideoJitterBuffer()
       
   228     {
       
   229     __V_SOURCESINK_CONTROLL( "CMccVideoJitterBuffer::~CMccVideoJitterBuffer" ) 
       
   230     
       
   231     iQueue.ResetAndDestroy();
       
   232     
       
   233     __V_SOURCESINK_CONTROLL( "CMccVideoJitterBuffer::~CMccVideoJitterBuffer, exit" ) 
       
   234     }
       
   235 
       
   236 
       
   237 // ---------------------------------------------------------------------------
       
   238 // CMccVideoJitterBuffer::ConfigureL
       
   239 // Jitterbuffer gathers data until defined play threshold is exceeded.
       
   240 // After that, packets are posted with certain interval towards Helix. In case
       
   241 // buffer is close to running out of data (low limit reached), posting interval
       
   242 // is increased in order to increase data amount in buffer. Ideal situation
       
   243 // is that buffer has all the time some data so that playback can be kept
       
   244 // smooth. If high limit is reached, posting interval is tightened to avoid
       
   245 // max limit reach. If max limit is anyhow reached, jitterbuffer makes room
       
   246 // by just pushing some amount of oldest data towards Helix. 
       
   247 //
       
   248 // ---------------------------------------------------------------------------
       
   249 //
       
   250 void CMccVideoJitterBuffer::ConfigureL( 
       
   251     TUint aLowLimitMs, 
       
   252     TUint aHighLimitMs, 
       
   253     TUint aPlayThresholdMs, 
       
   254     TUint aMaxSizeMs, 
       
   255     TUint aFrameRateFps )
       
   256     {
       
   257     __V_SOURCESINK_CONTROLL_INT1( 
       
   258         "CMccVideoJitterBuffer::ConfigureL, framerate:", aFrameRateFps ) 
       
   259     __V_SOURCESINK_CONTROLL_INT1( "low limit:", aLowLimitMs )  
       
   260     __V_SOURCESINK_CONTROLL_INT1( "high limit:", aHighLimitMs ) 
       
   261     __V_SOURCESINK_CONTROLL_INT1( "play threshold:", aPlayThresholdMs ) 
       
   262     __V_SOURCESINK_CONTROLL_INT1( "max size:", aMaxSizeMs ) 
       
   263     
       
   264     __ASSERT_ALWAYS( aFrameRateFps > 0, User::Leave( KErrArgument ) );
       
   265     __ASSERT_ALWAYS( aLowLimitMs < aPlayThresholdMs, User::Leave( KErrArgument ) );
       
   266     __ASSERT_ALWAYS( aPlayThresholdMs < aHighLimitMs, User::Leave( KErrArgument ) );
       
   267     __ASSERT_ALWAYS( aHighLimitMs < aMaxSizeMs, User::Leave( KErrArgument ) );
       
   268          
       
   269     iLowLimitMicroSecs = aLowLimitMs * KMccMilliSecondInMicroSecs;
       
   270     iHighLimitMicroSecs = aHighLimitMs * KMccMilliSecondInMicroSecs;
       
   271     iPlayThresholdMicroSecs = aPlayThresholdMs * KMccMilliSecondInMicroSecs;
       
   272     iMaxSizeMicroSecs = aMaxSizeMs * KMccMilliSecondInMicroSecs;
       
   273     iFrameRate = aFrameRateFps;
       
   274     
       
   275     const TInt KMccSecondInMicroSecs = 1000000;
       
   276     
       
   277     const TReal KMccLowLimitInterval = 1.4;
       
   278     const TReal KMccHighLimitInterval = 0.7;
       
   279     iNormalInterval = KMccSecondInMicroSecs / iFrameRate;
       
   280     iLowLimitInterval = (TInt)( iNormalInterval.Int() * KMccLowLimitInterval );
       
   281     iHighLimitInterval = (TInt)( iNormalInterval.Int() * KMccHighLimitInterval );
       
   282     
       
   283     iCurrentInterval = iNormalInterval;
       
   284     
       
   285     __V_SOURCESINK_CONTROLL_INT1( "normal interval:", iNormalInterval.Int() )  
       
   286     __V_SOURCESINK_CONTROLL_INT1( "low limit interval:", iLowLimitInterval.Int() ) 
       
   287     __V_SOURCESINK_CONTROLL_INT1( "high limit interval:", iHighLimitInterval.Int() ) 
       
   288     }
       
   289     
       
   290 // ---------------------------------------------------------------------------
       
   291 // CMccVideoJitterBuffer::EnqueueL
       
   292 // Packets are posted towards Helix in receiving order, queuing could be
       
   293 // seq num based but out of order packets are rare.
       
   294 // ---------------------------------------------------------------------------
       
   295 //
       
   296 CMccVideoJitterBuffer::TMccPacketBufferingStatus CMccVideoJitterBuffer::EnqueueL( 
       
   297     TUint aStreamId, 
       
   298     const TRtpRecvHeader& aHeaderInfo, 
       
   299     const TDesC8& aPayloadData,
       
   300     TBool aImportantData )
       
   301     { 
       
   302     CMccVideoPacket* packet = 
       
   303         CMccVideoPacket::NewLC( aStreamId, aHeaderInfo, aPayloadData, aImportantData );
       
   304     TLinearOrder<CMccVideoPacket> ordering( CMccVideoPacket::InsertInSeqNumOrder );
       
   305     iQueue.InsertInOrderAllowRepeatsL( packet, ordering );
       
   306     CleanupStack::Pop( packet );
       
   307     
       
   308     UpdateFrameCount( *packet, ETrue );
       
   309     
       
   310     if ( PlayThresholdExceeded() )
       
   311         {
       
   312         if ( MaxSizeExceeded() )
       
   313             {
       
   314             MakeRoom();
       
   315             }
       
   316 
       
   317         Start();
       
   318         }
       
   319         
       
   320     return PlayingStatus();
       
   321     }
       
   322 
       
   323 // ---------------------------------------------------------------------------
       
   324 // CMccVideoJitterBuffer::Play
       
   325 // ---------------------------------------------------------------------------
       
   326 //
       
   327 void CMccVideoJitterBuffer::Play()
       
   328     {
       
   329     if ( PlayThresholdExceeded() )
       
   330         {
       
   331         Start();
       
   332         }
       
   333     }
       
   334 
       
   335 // ---------------------------------------------------------------------------
       
   336 // CMccVideoJitterBuffer::Pause
       
   337 // ---------------------------------------------------------------------------
       
   338 //    
       
   339 void CMccVideoJitterBuffer::Pause()
       
   340     {
       
   341     Cancel();
       
   342     }
       
   343 
       
   344 // ---------------------------------------------------------------------------
       
   345 // CMccVideoJitterBuffer::PlayThresholdInMs
       
   346 // ---------------------------------------------------------------------------
       
   347 //
       
   348 TInt CMccVideoJitterBuffer::PlayThresholdInMs()
       
   349     {
       
   350     const TInt KMccMilliSecondInMicroSecs = 1000;
       
   351     return ( iPlayThresholdMicroSecs / KMccMilliSecondInMicroSecs );
       
   352     }
       
   353     
       
   354 // ---------------------------------------------------------------------------
       
   355 // CMccVideoJitterBuffer::Start
       
   356 // ---------------------------------------------------------------------------
       
   357 //
       
   358 void CMccVideoJitterBuffer::Start()
       
   359     {
       
   360     TTimeIntervalMicroSeconds32 newCurrentInterval = CheckCurrentInterval();
       
   361     if ( newCurrentInterval != iCurrentInterval )
       
   362         {
       
   363         __V_SOURCESINK_CONTROLL_INT1( 
       
   364         "CMccVideoJitterBuffer::Start, new interval", newCurrentInterval.Int() ) 
       
   365         
       
   366         Cancel();
       
   367         }
       
   368             
       
   369     if ( !IsActive() )
       
   370         {
       
   371         iCurrentInterval = newCurrentInterval;
       
   372 	    CTimer::HighRes( iCurrentInterval );
       
   373         }
       
   374     }
       
   375 
       
   376 
       
   377 // ---------------------------------------------------------------------------
       
   378 // From class CActive.
       
   379 // ---------------------------------------------------------------------------
       
   380 //
       
   381 void CMccVideoJitterBuffer::RunL()
       
   382     {
       
   383     __V_SOURCESINK_CONTROLL( "CMccVideoJitterBuffer::RunL" ) 
       
   384     
       
   385     if ( PostFirstFrame() )
       
   386         {
       
   387         Start();
       
   388         }
       
   389         
       
   390     __V_SOURCESINK_CONTROLL( "CMccVideoJitterBuffer::RunL, exit" ) 
       
   391     }
       
   392 
       
   393 // ---------------------------------------------------------------------------
       
   394 // CMccVideoJitterBuffer::PlayThresholdExceeded
       
   395 // ---------------------------------------------------------------------------
       
   396 //    
       
   397 TBool CMccVideoJitterBuffer::PlayThresholdExceeded()
       
   398     {
       
   399     if ( !iPlayThresholdExeeced && 
       
   400        ( iFrameCount * iNormalInterval.Int() >= iPlayThresholdMicroSecs ) )
       
   401         {
       
   402         iPlayThresholdExeeced = ETrue;
       
   403         }
       
   404     return iPlayThresholdExeeced;
       
   405     }
       
   406 
       
   407 // ---------------------------------------------------------------------------
       
   408 // CMccVideoJitterBuffer::CheckCurrentInterval
       
   409 // ---------------------------------------------------------------------------
       
   410 // 
       
   411 TTimeIntervalMicroSeconds32 CMccVideoJitterBuffer::CheckCurrentInterval()
       
   412     {
       
   413     TTimeIntervalMicroSeconds32 interval( iNormalInterval );
       
   414     TUint32 dataAmountInMicroSecs( iFrameCount * iNormalInterval.Int() );
       
   415     if ( iQueue.Count() == 0 || dataAmountInMicroSecs < iLowLimitMicroSecs )
       
   416         {
       
   417         interval = iLowLimitInterval;
       
   418         }
       
   419     else if ( dataAmountInMicroSecs > iHighLimitMicroSecs )
       
   420         {
       
   421         interval = iHighLimitInterval;
       
   422         }
       
   423     else if ( iCurrentInterval == iLowLimitInterval && 
       
   424               dataAmountInMicroSecs < iPlayThresholdMicroSecs )
       
   425         {
       
   426         // If on low interval, normalize only once at normal level, otherwise
       
   427         // low limit might be reached shortly again.
       
   428         interval = iLowLimitInterval;
       
   429         }
       
   430     else
       
   431         {
       
   432         }
       
   433     return interval;
       
   434     }
       
   435 
       
   436 // ---------------------------------------------------------------------------
       
   437 // CMccVideoJitterBuffer::UpdateFrameCount
       
   438 // ---------------------------------------------------------------------------
       
   439 //
       
   440 void CMccVideoJitterBuffer::UpdateFrameCount( CMccVideoPacket& aPacket, TBool aIsAdded )
       
   441     {
       
   442     if ( aPacket.HeaderInfo().iMarker != 0 )
       
   443         {
       
   444         if ( aIsAdded )
       
   445             {
       
   446             iFrameCount++;
       
   447             }
       
   448         else if ( iFrameCount > 0 )
       
   449             {
       
   450             iFrameCount--;
       
   451             }
       
   452         else
       
   453             {
       
   454             // NOP
       
   455             }
       
   456             
       
   457         __V_SOURCESINK_CONTROLL_INT1( 
       
   458             "CMccVideoJitterBuffer::UpdateFrameCount, count", iFrameCount ) 
       
   459         }
       
   460     }
       
   461 
       
   462 // ---------------------------------------------------------------------------
       
   463 // CMccVideoJitterBuffer::PostFirstFrame
       
   464 // ---------------------------------------------------------------------------
       
   465 //
       
   466 TBool CMccVideoJitterBuffer::PostFirstFrame()
       
   467     {
       
   468     TBool posted( EFalse );
       
   469     TInt frameEndIndex( KErrNotFound );
       
   470     TUint32 frameTimeStamp( 0 );
       
   471     for ( TInt i = 0; i < iQueue.Count() && !posted; i++ )
       
   472         {
       
   473         CMccVideoPacket* packet = iQueue[ i ]; 
       
   474         
       
   475         if ( frameEndIndex != KErrNotFound )
       
   476             {
       
   477             TRtpRecvHeader& recvHeader = packet->HeaderInfo();
       
   478             if ( recvHeader.iTimestamp != frameTimeStamp && packet->DroppingAllowed() )
       
   479                 {
       
   480                 // Timestamp mismatch, packet does not actually belong
       
   481                 // to this frame, drop it silently
       
   482                 __V_SOURCESINK_CONTROLL( 
       
   483                 "CMccVideoJitterBuffer::PostBuffer, packet dropped due incorrect ts" ) 
       
   484                 }
       
   485             else
       
   486                 {
       
   487                 // Always modify timestamp to zero which causes that Helix
       
   488                 // lets packet go straight away to decoder.
       
   489                 DoRtpHeaderModify( recvHeader );
       
   490          
       
   491                 TInt ret = iPacketSink.Enqueue( 
       
   492                     packet->StreamId(), recvHeader, packet->PayloadData() );
       
   493                 
       
   494                 if ( ret != KErrNone )
       
   495                     {
       
   496                     iObserver.ErrorOccured( ret );
       
   497                     }
       
   498                 else
       
   499                     {
       
   500                     posted = ( frameEndIndex == i );
       
   501                     }
       
   502                 }
       
   503             }
       
   504         else if ( packet->HeaderInfo().iMarker != 0 )
       
   505             {
       
   506             // Full frame in queue, post all packets belonging to the frame
       
   507             frameEndIndex = i;
       
   508             frameTimeStamp = packet->HeaderInfo().iTimestamp;
       
   509             i = -1; // Start again from beginning
       
   510             }
       
   511         else
       
   512             {
       
   513             }
       
   514         }
       
   515     
       
   516     // Delete all posted packets
       
   517     for ( TInt j = frameEndIndex; j >= 0; j-- )
       
   518         {
       
   519         CMccVideoPacket* packet = iQueue[ j ]; 
       
   520         UpdateFrameCount( *packet, EFalse );
       
   521         delete packet;
       
   522         iQueue.Remove( j );
       
   523         }
       
   524         
       
   525     return posted;
       
   526     }
       
   527 
       
   528 // ---------------------------------------------------------------------------
       
   529 // CMccVideoJitterBuffer::MakeRoom
       
   530 // ---------------------------------------------------------------------------
       
   531 //
       
   532 void CMccVideoJitterBuffer::MakeRoom()
       
   533     {
       
   534     __V_SOURCESINK_CONTROLL( "CMccVideoJitterBuffer::MakeRoom" ) 
       
   535     
       
   536     // Make room by pushing some amount from beginning of the queue
       
   537     // towards helix.
       
   538     TBool post = PostFirstFrame();
       
   539     while ( post )
       
   540         {
       
   541         __V_SOURCESINK_CONTROLL( "CMccVideoJitterBuffer::MakeRoom, post" ) 
       
   542         
       
   543         TTimeIntervalMicroSeconds32 interval = CheckCurrentInterval();
       
   544         if ( interval <= iHighLimitInterval )
       
   545             {
       
   546             // Data amount still exceeds high limit
       
   547             post = PostFirstFrame(); 
       
   548             }
       
   549         else
       
   550             {
       
   551             post = EFalse;
       
   552             }
       
   553         }
       
   554         
       
   555     __V_SOURCESINK_CONTROLL( "CMccVideoJitterBuffer::MakeRoom, exit" ) 
       
   556     }
       
   557 
       
   558 // ---------------------------------------------------------------------------
       
   559 // CMccVideoJitterBuffer::MaxSizeExceeded
       
   560 // ---------------------------------------------------------------------------
       
   561 //
       
   562 TBool CMccVideoJitterBuffer::MaxSizeExceeded()
       
   563     {
       
   564     TUint32 dataAmountInMicroSecs( iFrameCount * iNormalInterval.Int() );
       
   565     return ( dataAmountInMicroSecs >= iMaxSizeMicroSecs );
       
   566     }
       
   567 
       
   568 // ---------------------------------------------------------------------------
       
   569 // CMccVideoJitterBuffer::CheckPostingInactivity
       
   570 // ---------------------------------------------------------------------------
       
   571 //
       
   572 void CMccVideoJitterBuffer::CheckPostingInactivity( 
       
   573     TInt64 aTimeFromPreviousFrame )
       
   574     {
       
   575     if ( aTimeFromPreviousFrame > (TInt64)iInactivityTimeoutInMicroSecs )
       
   576         {
       
   577         // If frames haven't been posted within inactivity time, next packet
       
   578         // will cause again "playing started" status report
       
   579         iPlaybackStarted = EFalse;
       
   580         }
       
   581     }
       
   582 
       
   583 // ---------------------------------------------------------------------------
       
   584 // CMccVideoJitterBuffer::PlayingStatus
       
   585 // ---------------------------------------------------------------------------
       
   586 //
       
   587 CMccVideoJitterBuffer::TMccPacketBufferingStatus CMccVideoJitterBuffer::PlayingStatus()
       
   588     {
       
   589     TMccPacketBufferingStatus bufferingStatus( EBuffering );
       
   590     if ( PlayThresholdExceeded() )
       
   591         {
       
   592         if ( iPlaybackStarted )
       
   593             {
       
   594             bufferingStatus = EPlaying;
       
   595             }
       
   596         else
       
   597             {
       
   598             bufferingStatus = EPlayingStarted;
       
   599             iPlaybackStarted = ETrue;
       
   600             }
       
   601         }
       
   602     return bufferingStatus;
       
   603     }
       
   604 
       
   605 // ---------------------------------------------------------------------------
       
   606 // CMccVideoJitterBuffer::DoRtpHeaderModify
       
   607 // Always overwrite timestamps by using own real time clock. There's some 
       
   608 // implementations which do not use RTP timestamps correctly so this
       
   609 // approach is for better interoperability. Also hide seqnum gaps from Helix. 
       
   610 // ---------------------------------------------------------------------------
       
   611 //
       
   612 void CMccVideoJitterBuffer::DoRtpHeaderModify( TRtpRecvHeader& aRecvHeader )
       
   613     {
       
   614     if ( iPreviousTime.Int64() == 0 )
       
   615         {
       
   616         iPreviousTime.HomeTime();
       
   617         iCurrentRealtimeTimestamp = aRecvHeader.iTimestamp;
       
   618         }
       
   619     else if ( aRecvHeader.iTimestamp != iPreviousReceivedTimestamp )
       
   620         {
       
   621         TTime currentTime;
       
   622         currentTime.HomeTime();
       
   623         TTimeIntervalMicroSeconds timeFromPreviousFrame = 
       
   624             currentTime.MicroSecondsFrom( iPreviousTime );
       
   625         iCurrentRealtimeTimestamp += 
       
   626             MCC_CONVERT_TO_90KHZ_CLOCK( timeFromPreviousFrame.Int64() );
       
   627         
       
   628         CheckPostingInactivity( timeFromPreviousFrame.Int64() );
       
   629         
       
   630         iPreviousTime = currentTime;
       
   631         }
       
   632     else
       
   633         {
       
   634         // NOP
       
   635         }
       
   636     
       
   637     __V_SOURCESINK_CONTROLL_INT2( 
       
   638         "Timestamp mod, orig:", aRecvHeader.iTimestamp, " mod:", iCurrentRealtimeTimestamp ) 
       
   639         
       
   640     iPreviousReceivedTimestamp = aRecvHeader.iTimestamp;    
       
   641     aRecvHeader.iTimestamp = iCurrentRealtimeTimestamp;
       
   642     
       
   643     if ( !iSeqNum )
       
   644         {
       
   645         iSeqNum = aRecvHeader.iSeqNum;
       
   646         }
       
   647     else
       
   648         {
       
   649         aRecvHeader.iSeqNum = ++iSeqNum;
       
   650         }
       
   651     }
       
   652                         
       
   653 // End of file
       
   654