multimediacommscontroller/mmccvideosourcesink/src/mccvideosinkuser.cpp
changeset 0 1bce908db942
equal deleted inserted replaced
-1:000000000000 0:1bce908db942
       
     1 /*
       
     2 * Copyright (c) 2006 Nokia Corporation and/or its subsidiary(-ies).
       
     3 * All rights reserved.
       
     4 * This component and the accompanying materials are made available
       
     5 * under the terms of "Eclipse Public License v1.0"
       
     6 * which accompanies this distribution, and is available
       
     7 * at the URL "http://www.eclipse.org/legal/epl-v10.html".
       
     8 *
       
     9 * Initial Contributors:
       
    10 * Nokia Corporation - initial contribution.
       
    11 *
       
    12 * Contributors:
       
    13 *
       
    14 * Description:    
       
    15 *
       
    16 */
       
    17 
       
    18 
       
    19 
       
    20 // INCLUDE FILES
       
    21 #include "mccvideosinkuser.h"
       
    22 #include "mccvideosourcesinklogs.h"
       
    23 #include "mccdef.h"
       
    24 #include "mccinternaldef.h"
       
    25 #include <CXPSPacketSink.h>
       
    26 
       
    27 // CONSTANTS
       
    28 const TUint32 KMccModifyMonitoringShortPeriodMicrosecs = 2000000;
       
    29 const TUint32 KMccModifyMonitoringLongPeriodMicrosecs = 10000000;
       
    30 const TUint32 KMccMaxDenyPeriodMicrosecs = 1000000;
       
    31 const TReal KMccMonitoringShortPeriodTimestampIncreaseFactorDown = 0.6;
       
    32 const TReal KMccMonitoringShortPeriodTimestampIncreaseFactorUp = 1.4;
       
    33 const TReal KMccMonitoringLongPeriodTimestampIncreaseFactorDown = 0.8;
       
    34 const TReal KMccMonitoringLongPeriodTimestampIncreaseFactorUp = 1.2;
       
    35 
       
    36 const TInt KMccJitterBufferThresholdPacketTime = 20;
       
    37 
       
    38 // Minimum times for preroll
       
    39 const TInt KMccOneMediaMinPreroll = 1000;
       
    40 const TInt KMccSeveralMediaMinPreroll = 2000;
       
    41 
       
    42 // MACROS
       
    43 #define MCC_CONVERT_TO_90KHZ_CLOCK( valInMicroSecs ) ( valInMicroSecs / 100 * 9 )
       
    44 
       
    45 // ---------------------------------------------------------------------------
       
    46 // TMccTimeStampEntry::TMccTimeStampEntry
       
    47 // ---------------------------------------------------------------------------
       
    48 //
       
    49 TMccTimeStampEntry::TMccTimeStampEntry() : 
       
    50     iTime( 0 ), iSeq( 0 )
       
    51     {
       
    52     }
       
    53 
       
    54 // ---------------------------------------------------------------------------
       
    55 // TMccTimeStampEntry::TMccTimeStampEntry
       
    56 // ---------------------------------------------------------------------------
       
    57 //    
       
    58 TMccTimeStampEntry::TMccTimeStampEntry( TInt64 aTime, TUint16 aSeq ) :
       
    59     iTime( aTime ), iSeq( aSeq )
       
    60     {
       
    61     }
       
    62 
       
    63 // ---------------------------------------------------------------------------
       
    64 // CMccVideoSinkUser::NewL
       
    65 // ---------------------------------------------------------------------------
       
    66 //
       
    67 CMccVideoSinkUser* CMccVideoSinkUser::NewL( 
       
    68     MAsyncEventHandler* aAsyncEventHandler, 
       
    69     TUid aMediaType,
       
    70     TUint aStreamId,
       
    71     TReal aFrameRate,
       
    72     CXPSPacketSink& aPacketSink )
       
    73     {
       
    74     CMccVideoSinkUser* self = 
       
    75         CMccVideoSinkUser::NewLC( aAsyncEventHandler,
       
    76                                   aMediaType,
       
    77                                   aStreamId,
       
    78                                   aFrameRate,
       
    79                                   aPacketSink );
       
    80     CleanupStack::Pop( self );
       
    81     return self;
       
    82     }
       
    83     
       
    84 // ---------------------------------------------------------------------------
       
    85 // CMccVideoSinkUser::NewLC
       
    86 // ---------------------------------------------------------------------------
       
    87 //
       
    88 CMccVideoSinkUser* CMccVideoSinkUser::NewLC( 
       
    89     MAsyncEventHandler* aAsyncEventHandler, 
       
    90     TUid aMediaType,
       
    91     TUint aStreamId,
       
    92     TReal aFrameRate,
       
    93     CXPSPacketSink& aPacketSink )
       
    94     {
       
    95     CMccVideoSinkUser* self = 
       
    96         new ( ELeave ) CMccVideoSinkUser( 
       
    97             aAsyncEventHandler, aMediaType, aStreamId, aFrameRate, aPacketSink );
       
    98     CleanupStack::PushL( self );
       
    99     return self;
       
   100     }
       
   101 
       
   102 // ---------------------------------------------------------------------------
       
   103 // CMccVideoSinkUser::~CMccVideoSinkUser
       
   104 // ---------------------------------------------------------------------------
       
   105 //        
       
   106 CMccVideoSinkUser::~CMccVideoSinkUser()
       
   107     {
       
   108     delete iJitterBuf;
       
   109     }
       
   110         
       
   111 // ---------------------------------------------------------------------------
       
   112 // CMccVideoSinkUser::CMccVideoSinkUser
       
   113 // ---------------------------------------------------------------------------
       
   114 //
       
   115 CMccVideoSinkUser::CMccVideoSinkUser( 
       
   116     MAsyncEventHandler* aAsyncEventHandler, 
       
   117     TUid aMediaType,
       
   118     TUint aStreamId,
       
   119     TReal aFrameRate,
       
   120     CXPSPacketSink& aPacketSink ) :
       
   121     iAsyncEventHandler( aAsyncEventHandler ),
       
   122     iMediaType( aMediaType ),
       
   123     iStreamId( aStreamId ),
       
   124     iStartedOnce( EFalse ),
       
   125     iFrameRate( aFrameRate ),
       
   126     iPacketSink( aPacketSink ),
       
   127     iPacketOverflowState( ENormal ),
       
   128     iNumTimeStamps( 0 ),
       
   129     iAverageTimeStampDifference( 0 ),
       
   130     iResetNeeded( EFalse ),
       
   131     iModifyMode( EModifyInit ),
       
   132     iFirstModifyCheck( 0 ),
       
   133     iFirstModifyCheckTimestamp( 0 ),
       
   134     iFirstTimestamp( 0 ),
       
   135     iAllowFrame( ETrue ),
       
   136     iDenyFramesStarted( 0 ),
       
   137     iMultipleMediaTypes( EFalse ),
       
   138     iPreviousPacketOriginalTimeStamp( KMaxTUint32 ),
       
   139     iPreviousPacketModifiedTimeStamp( 0 ),
       
   140     iPreviousPacketTime( 0 ),
       
   141     iCurrentMonitoringPeriod( KMccModifyMonitoringShortPeriodMicrosecs ),
       
   142     iTimestampIncreaseFactorDown( KMccMonitoringShortPeriodTimestampIncreaseFactorDown ),
       
   143     iTimestampIncreaseFactorUp( KMccMonitoringShortPeriodTimestampIncreaseFactorUp )
       
   144     {
       
   145     } 
       
   146 
       
   147 // ---------------------------------------------------------------------------
       
   148 // CMccVideoSinkUser::EnqueueL
       
   149 // ---------------------------------------------------------------------------
       
   150 //
       
   151 CMccVideoJitterBuffer::TMccPacketBufferingStatus CMccVideoSinkUser::EnqueueL( 
       
   152     const TRtpRecvHeader& aHeaderInfo, const TDesC8& aPayloadData )
       
   153     {
       
   154     CMccVideoJitterBuffer::TMccPacketBufferingStatus 
       
   155         bufferingStatus( CMccVideoJitterBuffer::EPlaying );
       
   156 
       
   157     if ( aPayloadData.Length() > GetPayloadSize() )
       
   158         {
       
   159         // Too big buffer causes playback to stop at Helix, drop the packet
       
   160         // silently
       
   161         __V_SOURCESINK_CONTROLL( 
       
   162             "CMccVideoSinkUser::EnqueueL, Too big packet dropped" ) 
       
   163         }
       
   164     else if ( iJitterBuf )
       
   165         {
       
   166         TBool importantPacket = CodecSpecificDataHandling( aPayloadData );
       
   167         bufferingStatus = iJitterBuf->EnqueueL( iStreamId, 
       
   168                                                 aHeaderInfo, 
       
   169                                                 aPayloadData, 
       
   170                                                 importantPacket );
       
   171         }
       
   172     else
       
   173         {
       
   174         TInt err = iPacketSink.Enqueue( iStreamId, aHeaderInfo, aPayloadData );
       
   175         if ( err )
       
   176             {
       
   177             CheckErrorL( err );
       
   178             }
       
   179         }
       
   180     return bufferingStatus;
       
   181     }
       
   182     
       
   183 // ---------------------------------------------------------------------------
       
   184 // CMccVideoSinkUser::Set
       
   185 // ---------------------------------------------------------------------------
       
   186 //
       
   187 void CMccVideoSinkUser::Set( 
       
   188     MAsyncEventHandler* aAsyncEventHandler, 
       
   189     TUid aMediaType,
       
   190     TUint aStreamId )
       
   191     {
       
   192     iAsyncEventHandler = aAsyncEventHandler;
       
   193     iMediaType = aMediaType;
       
   194     iStreamId = aStreamId;
       
   195     }
       
   196 
       
   197 // ---------------------------------------------------------------------------
       
   198 // CMccVideoSinkUser::SetFrameRateL
       
   199 // ---------------------------------------------------------------------------
       
   200 //    
       
   201 void CMccVideoSinkUser::SetFrameRateL( TReal aFrameRate )
       
   202     {
       
   203     if ( aFrameRate != iFrameRate )
       
   204         {
       
   205         if ( iJitterBuf )
       
   206             {
       
   207             __V_SOURCESINK_CONTROLL( 
       
   208             "CMccVideoSinkUser::SetFrameRateL, configure jitterbuffer" ) 
       
   209             
       
   210             iJitterBuf->ConfigureL( KMccJitterBufferDefaultLowLimit, 
       
   211                                     KMccJitterBufferDefaultHighLimit, 
       
   212                                     KMccJitterBufferDefaultPlayThreshold,
       
   213                                     KMccJitterBufferDefaultMaxSize,
       
   214                                     aFrameRate );
       
   215             }
       
   216         
       
   217         iFrameRate = aFrameRate;
       
   218         }
       
   219     }
       
   220 
       
   221 // ---------------------------------------------------------------------------
       
   222 // CMccVideoSinkUser::GetPreroll
       
   223 // Helix does not restrict min preroll (buffering time) but it is safer to
       
   224 // have some  restriction as otherwise continuous buffering may occur if
       
   225 // Helix side buffering is used. If we are on real time mode, buffering
       
   226 // is handled at MCC side (this is indicated with preroll value zero).
       
   227 // Especially when two or more media types are used, data may not be received
       
   228 // in sync and longer buffering guards against running out of data of certain
       
   229 // media type.
       
   230 // ---------------------------------------------------------------------------
       
   231 //    
       
   232 TInt CMccVideoSinkUser::GetPreroll()
       
   233     {
       
   234     TInt preroll = iCodecInfo.iJitterBufThreshold * KMccJitterBufferThresholdPacketTime;
       
   235     
       
   236     __V_SOURCESINK_CONTROLL_INT1( 
       
   237                 "CMccVideoSinkUser::GetPreroll, preroll before adjust:", preroll )
       
   238                 	
       
   239     if ( iMultipleMediaTypes || preroll > KMccOneMediaMinPreroll )
       
   240         {    
       
   241         TInt minPreroll = iMultipleMediaTypes ? KMccSeveralMediaMinPreroll : 
       
   242                                                 KMccOneMediaMinPreroll;           
       
   243         if ( preroll < minPreroll )
       
   244             {
       
   245             preroll = minPreroll;
       
   246             }
       
   247         }
       
   248     else
       
   249         {
       
   250         // Real time mode enabled as client set jitter buffer threshold
       
   251         // value to small enough and only one media type is used.
       
   252         preroll = 0;
       
   253         }
       
   254         
       
   255     __V_SOURCESINK_CONTROLL_INT1( 
       
   256             "CMccVideoSinkUserImpl::GetPreroll, preroll:", preroll )   
       
   257             
       
   258     return preroll;
       
   259     }
       
   260 
       
   261 // ---------------------------------------------------------------------------
       
   262 // CMccVideoSinkUser::GetActualPreroll
       
   263 // In case of real-time mode, actual preroll value is defined by jitterbuffer
       
   264 // ---------------------------------------------------------------------------
       
   265 // 
       
   266 TInt CMccVideoSinkUser::GetActualPreroll()
       
   267     {      
       
   268     TInt preroll( 0 );
       
   269     if ( iJitterBuf )
       
   270         {
       
   271         preroll = iJitterBuf->PlayThresholdInMs();
       
   272         }
       
   273     else
       
   274         {
       
   275         preroll = GetPreroll();
       
   276         }
       
   277         
       
   278      __V_SOURCESINK_CONTROLL_INT1( "CMccVideoSinkUser::GetActualPreroll, preroll:", 
       
   279                                    preroll )
       
   280                 
       
   281     return preroll;
       
   282     }
       
   283     
       
   284 // ---------------------------------------------------------------------------
       
   285 // CMccVideoSinkUser::Play
       
   286 // ---------------------------------------------------------------------------
       
   287 // 
       
   288 void CMccVideoSinkUser::Play()
       
   289     {
       
   290     if ( iJitterBuf )
       
   291         {
       
   292         iJitterBuf->Play();
       
   293         }
       
   294     }
       
   295 
       
   296 // ---------------------------------------------------------------------------
       
   297 // CMccVideoSinkUser::Pause
       
   298 // ---------------------------------------------------------------------------
       
   299 //         
       
   300 void CMccVideoSinkUser::Pause()
       
   301     {
       
   302     if ( iJitterBuf )
       
   303         {
       
   304         iJitterBuf->Pause();
       
   305         }
       
   306     }
       
   307     
       
   308 // ---------------------------------------------------------------------------
       
   309 // CMccVideoSinkUser::IsQueueSizeDefined
       
   310 // ---------------------------------------------------------------------------
       
   311 //                           
       
   312 TBool CMccVideoSinkUser::IsQueueSizeDefined() const
       
   313     {
       
   314     return ( iCodecInfo.iJitterBufBufferLength > 0 );
       
   315     }
       
   316 
       
   317 // ---------------------------------------------------------------------------
       
   318 // CMccVideoSinkUser::QueueSize
       
   319 // ---------------------------------------------------------------------------
       
   320 //    
       
   321 TUint CMccVideoSinkUser::QueueSize() const
       
   322     {
       
   323     TInt queueSize = 
       
   324         ( iCodecInfo.iJitterBufBufferLength < KMccMinXPSQueueSize ) ?
       
   325             KMccMinXPSQueueSize : iCodecInfo.iJitterBufBufferLength;
       
   326 
       
   327     return queueSize;
       
   328     }
       
   329 
       
   330 // ---------------------------------------------------------------------------
       
   331 // CMccVideoSinkUser::PacketOverflowState
       
   332 // ---------------------------------------------------------------------------
       
   333 //
       
   334 CMccVideoSinkUser::TMccPacketOverflowState 
       
   335     CMccVideoSinkUser::PacketOverflowState() const
       
   336     {
       
   337     return iPacketOverflowState;
       
   338     }
       
   339 
       
   340 // ---------------------------------------------------------------------------
       
   341 // CMccVideoSinkUser::SetPacketOverflow
       
   342 // ---------------------------------------------------------------------------
       
   343 //
       
   344 void CMccVideoSinkUser::SetPacketOverflow( TMccPacketOverflowState aState )
       
   345     {
       
   346     iPacketOverflowState = aState;
       
   347     }
       
   348 
       
   349 // ---------------------------------------------------------------------------
       
   350 // CMccVideoSinkUser::AddTimeStamp
       
   351 // ---------------------------------------------------------------------------
       
   352 //   
       
   353 void CMccVideoSinkUser::AddTimeStamp( TInt64 aTimeStamp, TUint16 aSeq )
       
   354     {
       
   355     if ( iResetNeeded )
       
   356         {
       
   357         return;
       
   358         }
       
   359     
       
   360     UpdateFirstTimestamp( aTimeStamp );
       
   361                 
       
   362     TInt lastTimeStamp = iNumTimeStamps - 1;
       
   363     if ( lastTimeStamp >= 0 && iTimeStamps[ lastTimeStamp ].iTime == aTimeStamp )
       
   364         {
       
   365         // Do not allow subsequent same timestamps, update sequence number
       
   366         iTimeStamps[ lastTimeStamp ].iSeq = aSeq;
       
   367         return;
       
   368         }
       
   369         
       
   370     if ( iNumTimeStamps >= KMccTimeStampArraySize )
       
   371         {
       
   372         RemoveFirstTimeStamp();
       
   373         }
       
   374     
       
   375     iNumTimeStamps++;
       
   376     TInt lastIndex = iNumTimeStamps - 1;
       
   377     iTimeStamps[ lastIndex ].iTime = aTimeStamp;
       
   378     iTimeStamps[ lastIndex ].iSeq = aSeq;
       
   379     }
       
   380 
       
   381 // ---------------------------------------------------------------------------
       
   382 // CMccVideoSinkUser::RemoveFirstTimeStamp
       
   383 // ---------------------------------------------------------------------------
       
   384 //   
       
   385 void CMccVideoSinkUser::RemoveFirstTimeStamp()
       
   386     {
       
   387     for ( TInt i = 1; i < iNumTimeStamps; i++ )
       
   388         {
       
   389         iTimeStamps[ i - 1 ] = iTimeStamps[ i ];
       
   390         }
       
   391     if ( iNumTimeStamps > 0 )
       
   392         {
       
   393         iNumTimeStamps--;
       
   394         }
       
   395     }
       
   396 
       
   397 // ---------------------------------------------------------------------------
       
   398 // CMccVideoSinkUser::RemoveAllTimeStamps
       
   399 // ---------------------------------------------------------------------------
       
   400 //    
       
   401 void CMccVideoSinkUser::RemoveAllTimeStamps()
       
   402     {
       
   403     iNumTimeStamps = 0;
       
   404     }
       
   405 
       
   406 // ---------------------------------------------------------------------------
       
   407 // CMccVideoSinkUser::NumTimeStamps
       
   408 // ---------------------------------------------------------------------------
       
   409 //   
       
   410 TInt CMccVideoSinkUser::NumTimeStamps() const
       
   411     {
       
   412     return iNumTimeStamps;
       
   413     }
       
   414 
       
   415 // ---------------------------------------------------------------------------
       
   416 // CMccVideoSinkUser::Reset
       
   417 // ---------------------------------------------------------------------------
       
   418 //     
       
   419 void CMccVideoSinkUser::Reset( TBool aFullReset )
       
   420     {
       
   421     __V_SOURCESINK_CONTROLL_INT1( 
       
   422         "CMccVideoSinkUser::Reset, fullreset:", aFullReset )
       
   423         
       
   424     if ( aFullReset )
       
   425         {
       
   426         SetPacketOverflow( ENormal );
       
   427         RemoveAllTimeStamps();
       
   428         iAverageTimeStampDifference = 0;
       
   429         iResetNeeded = EFalse;
       
   430     
       
   431         SetModifyingState( EModifyInit );
       
   432         iFirstModifyCheck = 0;
       
   433         iFirstModifyCheckTimestamp = 0;
       
   434         iFirstTimestamp = 0;
       
   435         
       
   436         iAllowFrame = ETrue;
       
   437         iDenyFramesStarted = TTime( 0 );
       
   438         
       
   439         iPreviousPacketOriginalTimeStamp = KMaxTUint32;
       
   440         iPreviousPacketModifiedTimeStamp = 0;
       
   441         iPreviousPacketTime = TTime( 0 );
       
   442         
       
   443         iCurrentMonitoringPeriod = KMccModifyMonitoringShortPeriodMicrosecs;
       
   444         
       
   445         iTimestampIncreaseFactorDown = 
       
   446             KMccMonitoringShortPeriodTimestampIncreaseFactorDown;
       
   447         iTimestampIncreaseFactorUp = 
       
   448             KMccMonitoringShortPeriodTimestampIncreaseFactorUp;
       
   449         }
       
   450     }
       
   451 
       
   452 // ---------------------------------------------------------------------------
       
   453 // CMccVideoSinkUser::CalculateAverageTimeStampDifference
       
   454 // ---------------------------------------------------------------------------
       
   455 //   
       
   456 void CMccVideoSinkUser::CalculateAverageTimeStampDifference()
       
   457     {
       
   458     CheckDenyFramesMaxPeriod();
       
   459     
       
   460     // Calculate difference only if there's enough timestamps and average
       
   461     // difference has not been yet calculated
       
   462     if ( !iResetNeeded &&
       
   463          !iAverageTimeStampDifference &&
       
   464          iNumTimeStamps == KMccTimeStampArraySize )
       
   465         {
       
   466         TInt lastTimeStamp( iNumTimeStamps - 1 );
       
   467         
       
   468         // Calculate first the average timestamp difference between last N packets
       
   469         TInt seqNumDif( 0 );
       
   470         for ( TInt i = lastTimeStamp; i > 0; i-- )
       
   471             {
       
   472             seqNumDif = iTimeStamps[ i ].iSeq - iTimeStamps[ i - 1 ].iSeq;
       
   473             seqNumDif = Abs( seqNumDif );
       
   474             seqNumDif = ( seqNumDif == 0 ) ? 1 : seqNumDif;
       
   475                 
       
   476             iAverageTimeStampDifference += (TUint32)(
       
   477                 ( iTimeStamps[ i ].iTime - iTimeStamps[ i - 1 ].iTime ) / seqNumDif );
       
   478             }
       
   479             
       
   480         iAverageTimeStampDifference = 
       
   481             iAverageTimeStampDifference / ( KMccTimeStampArraySize - 1 ); 
       
   482 
       
   483         __V_SOURCESINK_CONTROLL_INT1( 
       
   484             "CMccVideoSinkUser::CalculateAverageTimeStampDifference, average dif:", 
       
   485             iAverageTimeStampDifference )
       
   486         }
       
   487     }
       
   488 
       
   489 // ---------------------------------------------------------------------------
       
   490 // CMccVideoSinkUser::IsResetNeeded
       
   491 // If there's big gap in timestamps, videoplayer needs to be resetted to
       
   492 // succesfully continue playback. If modifying is in use, gaps are ignored.
       
   493 // ---------------------------------------------------------------------------
       
   494 //    
       
   495 TBool CMccVideoSinkUser::IsResetNeeded( TRtpRecvHeader& aHeaderInfo )
       
   496     {
       
   497     if ( !iResetNeeded )
       
   498         {
       
   499         if ( RealTimeUser() )
       
   500             {
       
   501             iResetNeeded = IsResetNeededRealTimeMode( aHeaderInfo );
       
   502             }
       
   503         else
       
   504             {
       
   505             iResetNeeded = IsResetNeededNormalMode( aHeaderInfo );
       
   506             }
       
   507         }    
       
   508     return iResetNeeded;
       
   509     }
       
   510 
       
   511 // ---------------------------------------------------------------------------
       
   512 // CMccVideoSinkUser::IsResetNeeded
       
   513 // ---------------------------------------------------------------------------
       
   514 // 
       
   515 TBool CMccVideoSinkUser::IsResetNeeded() const
       
   516     {
       
   517     return iResetNeeded;
       
   518     }
       
   519 
       
   520 // ---------------------------------------------------------------------------
       
   521 // CMccVideoSinkUser::IsModifyNeeded
       
   522 // Check if other end is using video timestamps incorrectly and modify
       
   523 // them to be as correct as possible as Helix cannot deal with incorrect
       
   524 // timestamps. Modify check is not used in audio+video scenario as packet
       
   525 // flow is not as stable in that case.
       
   526 // ---------------------------------------------------------------------------
       
   527 //
       
   528 TBool CMccVideoSinkUser::IsModifyNeeded( TRtpRecvHeader& aHeaderInfo )
       
   529     {
       
   530     if ( iMultipleMediaTypes )
       
   531         {
       
   532         return EFalse;
       
   533         }
       
   534     
       
   535     if ( iModifyMode == EModifyInit )
       
   536         {
       
   537         DoModifyCheckInit( aHeaderInfo );
       
   538         }
       
   539     
       
   540     if ( MonitoringModify() )
       
   541         {
       
   542         DoModifyCheckMonitoring( aHeaderInfo );
       
   543         }
       
   544         
       
   545     return DoModify( aHeaderInfo );
       
   546     }
       
   547 
       
   548 // ---------------------------------------------------------------------------
       
   549 // CMccVideoSinkUser::SetAllowFrame
       
   550 // If some other user has resetted XPS because of timestamp skew, this
       
   551 // user cannot pass media until it has also detected timestamp skew. 
       
   552 // However, there's guard "timer" which stops denial if it takes too long
       
   553 // (i.e. timestamp skew didn't occur/was not detected for some reason).
       
   554 // This kind of error situtation can cause medias to go out of sync but
       
   555 // it is anyway better than not being able to continue playback at all.
       
   556 // ---------------------------------------------------------------------------
       
   557 //
       
   558 void CMccVideoSinkUser::SetAllowFrame( TBool aAllowFrame )
       
   559     {
       
   560     __V_SOURCESINK_CONTROLL_INT1( 
       
   561         "CMccVideoSinkUser::SetAllowFrame, allow:", aAllowFrame )
       
   562             
       
   563     iAllowFrame = aAllowFrame;
       
   564     
       
   565     if ( !iAllowFrame )
       
   566         {
       
   567         iDenyFramesStarted.HomeTime();
       
   568         }
       
   569     }
       
   570 
       
   571 // ---------------------------------------------------------------------------
       
   572 // CMccVideoSinkUser::AllowFrame
       
   573 // ---------------------------------------------------------------------------
       
   574 //            
       
   575 TBool CMccVideoSinkUser::AllowFrame() const
       
   576     {
       
   577     return iAllowFrame;
       
   578     }
       
   579 
       
   580 // ---------------------------------------------------------------------------
       
   581 // CMccVideoSinkUser::SetMultipleMediaTypesL
       
   582 // ---------------------------------------------------------------------------
       
   583 // 
       
   584 void CMccVideoSinkUser::SetMultipleMediaTypesL( TBool aMultipleMediaTypes )
       
   585     {
       
   586     iMultipleMediaTypes = aMultipleMediaTypes;
       
   587     if ( RealTimeUser() && !iJitterBuf )
       
   588         {
       
   589         __V_SOURCESINK_CONTROLL( 
       
   590         "CMccVideoSinkUser::SetMultipleMediaTypesL, creating jitterbuffer" )
       
   591         
       
   592         iJitterBuf = CMccVideoJitterBuffer::NewL( 
       
   593             *this, iPacketSink, iCodecInfo.iJitterBufInactivityTimeOut );
       
   594         }
       
   595     }
       
   596 
       
   597 // ---------------------------------------------------------------------------
       
   598 // CMccVideoSinkUser::SetCodecInfoL
       
   599 // ---------------------------------------------------------------------------
       
   600 // 
       
   601 void CMccVideoSinkUser::SetCodecInfoL( const TMccCodecInfo& aCodecInfo )
       
   602     {
       
   603     iCodecInfo = aCodecInfo;
       
   604     }
       
   605 
       
   606 // ---------------------------------------------------------------------------
       
   607 // CMccVideoSinkUser::CodecInfo
       
   608 // ---------------------------------------------------------------------------
       
   609 //         
       
   610 TMccCodecInfo& CMccVideoSinkUser::CodecInfo()
       
   611     {
       
   612     return iCodecInfo;
       
   613     }
       
   614 
       
   615 // ---------------------------------------------------------------------------
       
   616 // CMccVideoSinkUser::GetPayloadSize
       
   617 // ---------------------------------------------------------------------------
       
   618 //
       
   619 TInt CMccVideoSinkUser::GetPayloadSize()
       
   620     {
       
   621     if ( !iPayloadSize )
       
   622         {
       
   623         TInt payloadSize( iCodecInfo.iFrameSize );
       
   624         __V_SOURCESINK_CONTROLL_INT1( 
       
   625             "CMccVideoSinkUser::GetPayloadSize, size:", payloadSize )
       
   626             
       
   627         if ( payloadSize < KMccVideoSinkMinPayloadBufSize )
       
   628             {
       
   629             payloadSize = KMccVideoSinkMinPayloadBufSize;
       
   630             __V_SOURCESINK_CONTROLL_INT1( 
       
   631             "CMccVideoSinkUser::GetPayloadSize, size modified:", payloadSize )
       
   632             }
       
   633         iPayloadSize = payloadSize;
       
   634         }
       
   635     return iPayloadSize;
       
   636     }
       
   637     
       
   638 // ---------------------------------------------------------------------------
       
   639 // CMccVideoSinkUser::ErrorOccured
       
   640 // ---------------------------------------------------------------------------
       
   641 //
       
   642 void CMccVideoSinkUser::ErrorOccured( TInt aError )
       
   643     {
       
   644     TRAP_IGNORE( CheckErrorL( aError ) )
       
   645     }
       
   646     
       
   647 // ---------------------------------------------------------------------------
       
   648 // CMccVideoSinkUser::DoModify
       
   649 // ---------------------------------------------------------------------------
       
   650 // 
       
   651 TBool CMccVideoSinkUser::DoModify( TRtpRecvHeader& aHeaderInfo )
       
   652     {
       
   653     TBool modifyRequired( EFalse );
       
   654     
       
   655     if ( ModifyRequired() )
       
   656         {
       
   657         TUint32 timeStamp = aHeaderInfo.iTimestamp;
       
   658         
       
   659         TTime currentTime;
       
   660         currentTime.HomeTime();
       
   661             
       
   662         if ( timeStamp == iPreviousPacketOriginalTimeStamp )
       
   663             {
       
   664             // Frame is divided into several packets, packet time of
       
   665             // first packet in the frame is used until frame changes.
       
   666             timeStamp = iPreviousPacketModifiedTimeStamp;
       
   667             currentTime = iPreviousPacketTime;
       
   668             }
       
   669         else if ( iPreviousPacketTime.Int64() != 0 )
       
   670             {
       
   671             TTimeIntervalMicroSeconds interval = 
       
   672                 currentTime.MicroSecondsFrom( iPreviousPacketTime );
       
   673             
       
   674             __V_SOURCESINK_CONTROLL_INT1( 
       
   675             "CMccVideoSinkUser diffr:", interval.Int64() )
       
   676             
       
   677             timeStamp = iPreviousPacketModifiedTimeStamp + 
       
   678                 MCC_CONVERT_TO_90KHZ_CLOCK( interval.Int64() );
       
   679             }
       
   680          else
       
   681             {
       
   682             // NOP
       
   683             }
       
   684         
       
   685         __V_SOURCESINK_CONTROLL_INT2( 
       
   686             "CMccVideoSinkUser orig:", aHeaderInfo.iTimestamp, 
       
   687             " new:", timeStamp ) 
       
   688             
       
   689         iPreviousPacketOriginalTimeStamp = aHeaderInfo.iTimestamp;   
       
   690         iPreviousPacketModifiedTimeStamp = timeStamp;
       
   691         aHeaderInfo.iTimestamp = timeStamp; 
       
   692         iPreviousPacketTime = currentTime;
       
   693             
       
   694         modifyRequired = ETrue;        
       
   695         }
       
   696         
       
   697     return modifyRequired;
       
   698     }
       
   699     
       
   700 // ---------------------------------------------------------------------------
       
   701 // CMccVideoSinkUser::SeqNumDifToLastSeqNum
       
   702 // ---------------------------------------------------------------------------
       
   703 // 
       
   704 TInt CMccVideoSinkUser::SeqNumDifToLastSeqNum( TUint16 aSeq )
       
   705     {
       
   706     TInt seqNumDif( 1 );
       
   707     TInt lastTimeStampIndex( iNumTimeStamps - 1 );
       
   708     if ( lastTimeStampIndex >= 0 )
       
   709         {
       
   710         TUint16 lastSeqNum = iTimeStamps[ lastTimeStampIndex ].iSeq;
       
   711         seqNumDif = aSeq - lastSeqNum;
       
   712         }
       
   713     return seqNumDif;
       
   714     }
       
   715 
       
   716 // ---------------------------------------------------------------------------
       
   717 // CMccVideoSinkUser::SetModifyingState
       
   718 // ---------------------------------------------------------------------------
       
   719 //
       
   720 void CMccVideoSinkUser::SetModifyingState( TMccTimeStampModifyMode aModifyMode )
       
   721     {
       
   722     __V_SOURCESINK_CONTROLL_INT1( 
       
   723         "CMccVideoSinkUser::SetModifyingState, state:", aModifyMode )
       
   724     iModifyMode = aModifyMode;
       
   725     }
       
   726 
       
   727 // ---------------------------------------------------------------------------
       
   728 // CMccVideoSinkUser::MonitoringModify
       
   729 // ---------------------------------------------------------------------------
       
   730 //
       
   731 TBool CMccVideoSinkUser::MonitoringModify()
       
   732     {
       
   733     return ( iModifyMode == EModifyRequiredMonitoring ||
       
   734              iModifyMode == EModifyNotRequiredMonitoring );
       
   735     }
       
   736 
       
   737 // ---------------------------------------------------------------------------
       
   738 // CMccVideoSinkUser::ModifyRequired
       
   739 // ---------------------------------------------------------------------------
       
   740 //
       
   741 TBool CMccVideoSinkUser::ModifyRequired()
       
   742     {
       
   743     return ( iModifyMode == EModifyRequired || 
       
   744              iModifyMode == EModifyRequiredMonitoring );
       
   745     }
       
   746 
       
   747 // ---------------------------------------------------------------------------
       
   748 // CMccVideoSinkUser::DoModifyCheckInit
       
   749 // Check if other end does not use timestamps correctly.
       
   750 // ---------------------------------------------------------------------------
       
   751 //
       
   752 void CMccVideoSinkUser::DoModifyCheckInit( 
       
   753     const TRtpRecvHeader& aHeaderInfo )
       
   754     {
       
   755     TUint32 timeStamp = aHeaderInfo.iTimestamp;
       
   756 
       
   757     TUint32 timeStampDifference = GetTimestampDifferenceToPrevious( timeStamp );
       
   758     
       
   759     if ( timeStampDifference > 0 )
       
   760         {
       
   761         const TReal KMccPreferredTimeStampStep = 
       
   762                 TReal( KMccDefaultVideoFrequency / iFrameRate );
       
   763         
       
   764         // If timestamp increased less than half of preferred step,
       
   765         // there is something wrong and timestamps need to be modified       
       
   766         const TInt KMccTimeStampIncreaseMin = KMccPreferredTimeStampStep / 2;
       
   767         
       
   768         if ( timeStampDifference < KMccTimeStampIncreaseMin )
       
   769             {
       
   770             __V_SOURCESINK_CONTROLL_INT1( 
       
   771                 "CMccVideoSinkUser::DoModifyCheckInit, inc, difference:",
       
   772                 timeStampDifference )
       
   773             
       
   774             SetModifyingState( EModifyRequiredMonitoring );
       
   775             }
       
   776         else
       
   777             {
       
   778             SetModifyingState( EModifyNotRequiredMonitoring );
       
   779             }
       
   780         }        
       
   781     }
       
   782 
       
   783 // ---------------------------------------------------------------------------
       
   784 // CMccVideoSinkUser::DoModifyCheckMonitoring
       
   785 // Monitor certain period of time at the beginning of streaming whether
       
   786 // other end is using timestamp incorrectly. Or stop modifying if it looks 
       
   787 // that initial decision to modify timestamps was incorrect (other end is 
       
   788 // after all using them correctly).
       
   789 // ---------------------------------------------------------------------------
       
   790 //
       
   791 void CMccVideoSinkUser::DoModifyCheckMonitoring( 
       
   792     const TRtpRecvHeader& aHeaderInfo )
       
   793     {
       
   794     TUint32 timeStamp = aHeaderInfo.iTimestamp;
       
   795     
       
   796     TTime currentTime;
       
   797     currentTime.HomeTime(); 
       
   798         
       
   799     if ( iFirstModifyCheck == 0 )
       
   800         {
       
   801         iFirstModifyCheck.HomeTime();
       
   802         iFirstModifyCheckTimestamp = timeStamp;
       
   803         return;
       
   804         }
       
   805         
       
   806     TTimeIntervalMicroSeconds timeMonitored = 
       
   807         currentTime.MicroSecondsFrom( iFirstModifyCheck );
       
   808     
       
   809     if ( timeMonitored > iCurrentMonitoringPeriod )
       
   810         {
       
   811         const TInt KMicrosecsToSecs = 1000000;
       
   812 
       
   813         TInt timestampIncreaseWithinMonitoringPeriod = 
       
   814                 timeStamp - iFirstModifyCheckTimestamp;
       
   815                 
       
   816         TReal idealTimestampIncrease = 
       
   817             KMccDefaultVideoFrequency * timeMonitored.Int64() / KMicrosecsToSecs;
       
   818         
       
   819          __V_SOURCESINK_CONTROLL_INT2( 
       
   820                 "CMccVideoSinkUser::DoModifyCheckMonitoring, period:",
       
   821                 timeMonitored.Int64(),
       
   822                 "inc:", timestampIncreaseWithinMonitoringPeriod )
       
   823             
       
   824         __V_SOURCESINK_CONTROLL_REAL( 
       
   825                 "CMccVideoSinkUser::DoModifyCheckMonitoring, ideal inc:", 
       
   826                 idealTimestampIncrease )
       
   827                     
       
   828         if ( timestampIncreaseWithinMonitoringPeriod < 
       
   829                 ( idealTimestampIncrease * iTimestampIncreaseFactorDown ) ||
       
   830              timestampIncreaseWithinMonitoringPeriod >
       
   831                 ( idealTimestampIncrease * iTimestampIncreaseFactorUp ) )
       
   832             {        
       
   833             // Need to calculate average difference again
       
   834             iAverageTimeStampDifference = 0;
       
   835             iNumTimeStamps = 0;
       
   836             
       
   837             DecideMonitoringContinuation( EModifyRequired );
       
   838             }
       
   839         else
       
   840             {
       
   841             DecideMonitoringContinuation( EModifyNotRequired );
       
   842             }
       
   843         }      
       
   844     }
       
   845 
       
   846 // ---------------------------------------------------------------------------
       
   847 // CMccVideoSinkUser::GetTimestampDifferenceToPrevious
       
   848 // ---------------------------------------------------------------------------
       
   849 //
       
   850 TUint32 CMccVideoSinkUser::GetTimestampDifferenceToPrevious( 
       
   851     TUint32 aCurrentTimestamp )
       
   852     {
       
   853     TUint32 timeStampDifference( 0 );
       
   854     TInt lastTimeStampIndex( iNumTimeStamps - 1 ); 
       
   855     if ( lastTimeStampIndex >= 0 && 
       
   856          aCurrentTimestamp != iTimeStamps[ lastTimeStampIndex ].iTime )
       
   857         {
       
   858         TUint32 lastTimeStamp = iTimeStamps[ lastTimeStampIndex ].iTime;
       
   859 
       
   860         timeStampDifference = 
       
   861             aCurrentTimestamp > lastTimeStamp ? 
       
   862                 ( aCurrentTimestamp - lastTimeStamp ) : 
       
   863                 ( lastTimeStamp - aCurrentTimestamp );
       
   864         }
       
   865     return timeStampDifference;
       
   866     }
       
   867 
       
   868 // ---------------------------------------------------------------------------
       
   869 // CMccVideoSinkUser::UpdateFirstTimestamp
       
   870 // ---------------------------------------------------------------------------
       
   871 //
       
   872 void CMccVideoSinkUser::UpdateFirstTimestamp( TUint32 aTimestamp )
       
   873     {      
       
   874     if ( iFirstTimestamp == 0 )
       
   875         {
       
   876         iFirstTimestamp = aTimestamp;
       
   877         
       
   878         __V_SOURCESINK_CONTROLL_INT1( 
       
   879         "CMccVideoSinkUser::UpdateFirstTimestamp, first timestamp:", 
       
   880         iFirstTimestamp )
       
   881         }
       
   882     }
       
   883 
       
   884 // ---------------------------------------------------------------------------
       
   885 // CMccVideoSinkUser::DifferenceThreshold
       
   886 // If there's some gap in sequence numbers which is not anyhow too big, it
       
   887 // might be that some frames are just dropped by network or sender. 
       
   888 // In such case take seq num dif in count for timestamp difference threshold.
       
   889 // With negative seq num, threshold is always more strict.
       
   890 // ---------------------------------------------------------------------------
       
   891 //    
       
   892 TUint32 CMccVideoSinkUser::DifferenceThreshold( TInt aSeqNumDif ) const
       
   893     {
       
   894     if ( aSeqNumDif > KMccSeqNumDifferenceThresholdMin &&
       
   895          aSeqNumDif < KMccSeqNumDifferenceThresholdMax )
       
   896         {
       
   897         return iAverageTimeStampDifference * 
       
   898             ( aSeqNumDif + KMccTimeStampDifferenceTreshold );
       
   899         }
       
   900     return iAverageTimeStampDifference * KMccTimeStampDifferenceTreshold;
       
   901     }
       
   902 
       
   903 // ---------------------------------------------------------------------------
       
   904 // CMccVideoSinkUser::CheckDenyFramesMaxPeriod
       
   905 // ---------------------------------------------------------------------------
       
   906 //    
       
   907 void CMccVideoSinkUser::CheckDenyFramesMaxPeriod()
       
   908     {
       
   909     if ( iDenyFramesStarted.Int64() > 0 )
       
   910         {
       
   911         TTime currentTime;
       
   912         currentTime.HomeTime();
       
   913         
       
   914         TTimeIntervalMicroSeconds denyPeriod = 
       
   915             currentTime.MicroSecondsFrom( iDenyFramesStarted );
       
   916             
       
   917         if ( denyPeriod > KMccMaxDenyPeriodMicrosecs )
       
   918             {
       
   919             __V_SOURCESINK_CONTROLL( 
       
   920                 "CMccVideoSinkUser::CheckDenyFramesMaxPeriod, end denial" )
       
   921         
       
   922             Reset( ETrue );
       
   923             }
       
   924         }
       
   925     }
       
   926 
       
   927 // ---------------------------------------------------------------------------
       
   928 // CMccVideoSinkUser::DecideMonitoringContinuation
       
   929 // ---------------------------------------------------------------------------
       
   930 // 
       
   931 void CMccVideoSinkUser::DecideMonitoringContinuation( 
       
   932     TMccTimeStampModifyMode aNextState )
       
   933     {
       
   934     TMccTimeStampModifyMode decidedNextState( aNextState );
       
   935     if ( iCurrentMonitoringPeriod == KMccModifyMonitoringShortPeriodMicrosecs )
       
   936         {
       
   937         // Monitor still for longer period, after longer period of sampling
       
   938         // more strict rules can be used to detect incorrect behavior
       
   939         iCurrentMonitoringPeriod = KMccModifyMonitoringLongPeriodMicrosecs;
       
   940         iTimestampIncreaseFactorDown = 
       
   941             KMccMonitoringLongPeriodTimestampIncreaseFactorDown;
       
   942         iTimestampIncreaseFactorUp = 
       
   943             KMccMonitoringLongPeriodTimestampIncreaseFactorUp;
       
   944         if ( aNextState == EModifyRequired )
       
   945             {
       
   946             decidedNextState = EModifyRequiredMonitoring;
       
   947             }
       
   948         else if ( aNextState == EModifyNotRequired )
       
   949             {
       
   950             decidedNextState = EModifyNotRequiredMonitoring;
       
   951             }
       
   952         else
       
   953             {
       
   954             }
       
   955         }
       
   956     SetModifyingState( decidedNextState );
       
   957     }
       
   958 
       
   959 // ---------------------------------------------------------------------------
       
   960 // CMccVideoSinkUser::IsResetNeededNormalMode
       
   961 // ---------------------------------------------------------------------------
       
   962 // 
       
   963 TBool CMccVideoSinkUser::IsResetNeededNormalMode( 
       
   964     TRtpRecvHeader& aHeaderInfo )
       
   965     {
       
   966     TBool isResetNeeded( EFalse );
       
   967     TUint32 oldTimeStamp = aHeaderInfo.iTimestamp;
       
   968         
       
   969     if ( !ModifyRequired() && iAverageTimeStampDifference )
       
   970         {
       
   971         TUint32 timeStamp = aHeaderInfo.iTimestamp;
       
   972         
       
   973         // Check if new timestamp is totally off the charts.
       
   974         
       
   975         TInt lastTimeStamp( iNumTimeStamps - 1 );
       
   976         
       
   977         TInt seqNumDif = SeqNumDifToLastSeqNum( aHeaderInfo.iSeqNum );
       
   978 
       
   979         if ( timeStamp > iTimeStamps[ lastTimeStamp ].iTime )
       
   980             {
       
   981             isResetNeeded = ( timeStamp - iTimeStamps[ lastTimeStamp ].iTime ) > 
       
   982                 DifferenceThreshold( seqNumDif );
       
   983             }
       
   984         else
       
   985             {
       
   986             isResetNeeded = ( timeStamp + DifferenceThreshold( seqNumDif ) ) < 
       
   987                     iTimeStamps[ lastTimeStamp ].iTime;
       
   988             }
       
   989         }
       
   990         
       
   991     if ( isResetNeeded )
       
   992         {
       
   993         // Rollback changes if resetted
       
   994         aHeaderInfo.iTimestamp = oldTimeStamp; 
       
   995         }
       
   996     else
       
   997         {
       
   998         // Return value is not interesting
       
   999         IsModifyNeeded( aHeaderInfo );
       
  1000         }
       
  1001         
       
  1002     return isResetNeeded;
       
  1003     }
       
  1004 
       
  1005 // ---------------------------------------------------------------------------
       
  1006 // CMccVideoSinkUser::IsResetNeededRealTimeMode
       
  1007 // ---------------------------------------------------------------------------
       
  1008 // 
       
  1009 TBool CMccVideoSinkUser::IsResetNeededRealTimeMode( 
       
  1010     TRtpRecvHeader& /*aHeaderInfo*/ )
       
  1011     {
       
  1012     // Reset never needed    
       
  1013     return EFalse;
       
  1014     }
       
  1015     
       
  1016 // ---------------------------------------------------------------------------
       
  1017 // CMccVideoSinkUser::RealTimeUser
       
  1018 // ---------------------------------------------------------------------------
       
  1019 // 
       
  1020 TBool CMccVideoSinkUser::RealTimeUser()
       
  1021     {
       
  1022     return ( GetPreroll() == 0 );
       
  1023     }
       
  1024 
       
  1025 // ---------------------------------------------------------------------------
       
  1026 // CMccVideoSinkUser::CheckErrorL
       
  1027 // ---------------------------------------------------------------------------
       
  1028 //
       
  1029 void CMccVideoSinkUser::CheckErrorL( TInt aError )
       
  1030     {
       
  1031     __V_SOURCESINK_CONTROLL_INT1( "CMccVideoSinkUser::CheckErrorL, error", aError )
       
  1032     if ( aError == KErrOverflow )
       
  1033 		{		
       
  1034 	    SetPacketOverflow( CMccVideoSinkUser::EOccured );	
       
  1035 	    
       
  1036 	    // Overflow is not cosidered as a fatal error as it can be recovered
       
  1037 	    aError = KErrNone;	
       
  1038 		}
       
  1039     User::LeaveIfError( aError );
       
  1040     }
       
  1041 
       
  1042 
       
  1043 // ---------------------------------------------------------------------------
       
  1044 // CMccVideoSinkUser::CodecSpecificDataHandling
       
  1045 // ---------------------------------------------------------------------------
       
  1046 //  
       
  1047 TBool CMccVideoSinkUser::CodecSpecificDataHandling( const TDesC8& aPayloadData )
       
  1048     {
       
  1049     TBool importantData( EFalse );
       
  1050     if ( MCC_IS_AVC_USER_ENTRY( this ) )
       
  1051         {
       
  1052         // Avc sprop-parameter-set values are dropped due helix seems to have
       
  1053         // currently some issue with those.
       
  1054         if ( TMccCodecInfo::IsAvcPpsOrSpsData( aPayloadData, ETrue ) )
       
  1055             {
       
  1056             __V_SOURCESINK_CONTROLL_STR8( 
       
  1057             "CMccVideoSinkUser::CodecSpecificDataHandling, data:", aPayloadData )
       
  1058             importantData = ETrue;
       
  1059             }
       
  1060         }
       
  1061     return importantData;
       
  1062     }
       
  1063         
       
  1064 // End of file
       
  1065