multimediacommscontroller/mmccsubcontroller/src/mccrtpmediaclock.cpp
changeset 0 1bce908db942
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/multimediacommscontroller/mmccsubcontroller/src/mccrtpmediaclock.cpp	Tue Feb 02 01:04:58 2010 +0200
@@ -0,0 +1,279 @@
+/*
+* Copyright (c) 2006-2008 Nokia Corporation and/or its subsidiary(-ies).
+* All rights reserved.
+* This component and the accompanying materials are made available
+* under the terms of "Eclipse Public License v1.0"
+* which accompanies this distribution, and is available
+* at the URL "http://www.eclipse.org/legal/epl-v10.html".
+*
+* Initial Contributors:
+* Nokia Corporation - initial contribution.
+*
+* Contributors:
+*
+* Description:    rtp media clock
+*
+*/
+
+
+
+
+#include <e32std.h>
+#include <e32math.h>
+#include "mccrtpmediaclock.h"
+#include "mccsubcontrollerlogs.h"
+
+// LOCAL CONSTANTS
+
+// Helper for calculating next timestamp with sampling rate.
+const TUint KKiloHzDivider( 1000 );
+
+// Idle time limit when no timestamps have been asked from media clock. If
+// idle time is larger than this, then next timestamp is calculated from
+// actual time between two timestamp requests.
+const TInt KIdleTimeStampLimitSecs = 1;
+
+// ======== MEMBER FUNCTIONS ========
+
+
+// ---------------------------------------------------------------------------
+// default C++ constructor.
+// ---------------------------------------------------------------------------
+//
+CMccRtpMediaClock::CMccRtpMediaClock() : iSamplingFreq( K8Khz ),
+    iHwFrametime( K20ms )
+    {
+    
+    }
+
+// ---------------------------------------------------------------------------
+// Symbian 2nd phase constructor.
+// ---------------------------------------------------------------------------
+//
+void CMccRtpMediaClock::ConstructL()
+    {
+    // Generate random initial rtp timestamp which will be mapped to initial
+    // time. Then take note of the construction time of mediaclock.
+    iPreviousTimestamp.HomeTime();
+    TInt64 seed = iPreviousTimestamp.Int64();
+    iCurRtpTS = Abs( Math::Rand( seed ) );
+    iPreviousTimestamp.UniversalTime();
+    }
+
+// ---------------------------------------------------------------------------
+// Static constructor.
+// ---------------------------------------------------------------------------
+//
+CMccRtpMediaClock* CMccRtpMediaClock::NewL()
+    {
+    CMccRtpMediaClock* self = new( ELeave ) CMccRtpMediaClock();
+    CleanupStack::PushL( self );
+    self->ConstructL();
+    CleanupStack::Pop( self );
+    
+    return self;
+    }
+
+// ---------------------------------------------------------------------------
+// Destructor
+// ---------------------------------------------------------------------------
+//
+CMccRtpMediaClock::~CMccRtpMediaClock()
+    {
+    iRegister.Close();
+    }
+
+// ---------------------------------------------------------------------------
+// Each media clock client must register themselves once. If sampling rate or
+// frametime of the client is changed, client must register again.
+// ---------------------------------------------------------------------------
+//
+TUint32 CMccRtpMediaClock::RegisterMediaFormat( TUint aSamplingFreq, 
+                                                TInt aHwFrametime )
+    {
+    __SUBCONTROLLER_INT1( "CMccRtpMediaClock::RegisterMediaFormat aSamplingFreq: ", aSamplingFreq )
+    __SUBCONTROLLER_INT1( "CMccRtpMediaClock::RegisterMediaFormat aHwFrametime: ", aHwFrametime )
+    
+    // create unique key for client
+    TUint32 key = Math::Random();
+    
+    // create record of registered clients
+    TMccRegInfo reg_info;
+    reg_info.iKey = key;
+    reg_info.iSamplingFreq = aSamplingFreq;
+    reg_info.iHwFrametime = aHwFrametime;
+    iRegister.Append( reg_info );
+    
+    __SUBCONTROLLER_INT1( "CMccRtpMediaClock::RegisterMediaFormat key created: ", key )
+       
+    return key;
+    }
+
+// ---------------------------------------------------------------------------
+// Get new timestamp for registered media format
+// ---------------------------------------------------------------------------
+//
+TInt CMccRtpMediaClock::GetTimeStamp( TUint32 aKey, TUint32& aTimeStamp )
+    {
+    __SUBCONTROLLER( "CMccRtpMediaClock::GetTimeStamp" );
+    
+    TInt cell( KErrNotFound );
+    
+    if ( aKey != iUsedKey )
+        {
+        __SUBCONTROLLER_INT1( "---CMccRtpMediaClock::GetTimeStamp key changed: ", aKey )
+        
+        TInt err = CheckKey( aKey, cell );
+        if ( err )
+            {
+            // if not registered, -1 is returned
+            return err;
+            }
+        }
+    
+    // increment is done with previous sampling rate and hw time
+    aTimeStamp = TimeStampIncrement();
+    
+    if ( KErrNotFound != cell )
+        {
+        // update current parameters
+        iUsedKey = aKey;
+        iSamplingFreq = iRegister[cell].iSamplingFreq;
+        iHwFrametime = iRegister[cell].iHwFrametime;
+        
+        __SUBCONTROLLER_INT1( "CMccRtpMediaClock::GetTimeStamp cell: ", cell )
+        __SUBCONTROLLER_INT1( "CMccRtpMediaClock::GetTimeStamp iRegister.iKey: ", iRegister[cell].iKey )
+        __SUBCONTROLLER_INT1( "CMccRtpMediaClock::GetTimeStamp iRegister.iSamplingFreq: ", iRegister[cell].iSamplingFreq )
+        __SUBCONTROLLER_INT1( "CMccRtpMediaClock::GetTimeStamp iRegister.iHwFrametime: ", iRegister[cell].iHwFrametime )
+        }
+    
+    return KErrNone;
+    }
+
+// ---------------------------------------------------------------------------
+// Returns the latest used rtp timestamp.
+// For 'initial keep alive' and 'during call keep alive'.
+// ---------------------------------------------------------------------------
+//
+void CMccRtpMediaClock::GetLatestConsumedTS( TUint32& aTimeStamp )
+    {
+    __SUBCONTROLLER_INT1( "CMccRtpMediaClock::GetLatestConsumedTS: ", iCurRtpTS );
+    
+    aTimeStamp = iCurRtpTS;
+    }
+
+// ---------------------------------------------------------------------------
+// Private method
+// Designed to take care of rtp time stamp calculation
+// ---------------------------------------------------------------------------
+//
+TUint32 CMccRtpMediaClock::TimeStampIncrement()
+    {
+    __SUBCONTROLLER ("CMccRtpMediaClock::TimeStampIncrement" )  
+    
+    TTime current;
+    current.UniversalTime();
+    
+    TTimeIntervalSeconds seconds;
+    current.SecondsFrom( iPreviousTimestamp, seconds );
+    
+    __SUBCONTROLLER_INT1( "CMccRtpMediaClock::TimeStampIncrement secs: ", seconds.Int() )
+    
+    // Note: We cannot rely that this function is called with monotonic rate.
+    // Due to the fact that audio adaptation may not work with monotonic rate,
+    // we must not use TTime and other variants to calculate RTP timestamps,
+    // but increment the timestamp each time this function is called.
+    // Thus we rely on the fact that caller knows best if the RTP mediaclock
+    // timestamp should be incremented.
+    // Note that if there is at least two second delay between the calls to
+    // this function, then we take into account the actual time between the
+    // calls. Currently we use two second limit between the calls.
+    const TTimeIntervalSeconds diff( KIdleTimeStampLimitSecs );
+    if ( diff < seconds )
+        {
+        iTimeBasedIncrement = ETrue;
+        
+        iCurRtpTS += TUint( seconds.Int() * iSamplingFreq );
+        
+        __SUBCONTROLLER_INT1( "CMccRtpMediaClock::TimeStampIncrement timebased incr: ",
+            seconds.Int() * iSamplingFreq )
+        }
+    else
+        {
+        iTimeBasedIncrement = EFalse;
+        
+        const TUint khzPart = iSamplingFreq / KKiloHzDivider;
+        iCurRtpTS += TUint( iHwFrametime * khzPart );
+        
+        __SUBCONTROLLER_INT1( "CMccRtpMediaClock::TimeStampIncrement callbased incr: ",
+            iHwFrametime * khzPart )
+        }
+    
+    __SUBCONTROLLER_INT1( "CMccRtpMediaClock::TimeStampIncrement iCurRtpTS: ",
+        iCurRtpTS )
+    
+    // Get the current time to make the calculation when called next.
+    iPreviousTimestamp.UniversalTime();
+    
+    return iCurRtpTS;
+    }
+
+// ---------------------------------------------------------------------------
+// Private method
+// Check used key if it is registered
+// ---------------------------------------------------------------------------
+//
+TInt CMccRtpMediaClock::CheckKey( TUint32 aKey, TInt& aCell )
+    {
+    __SUBCONTROLLER( "CMccRtpMediaClock::CheckKey" )
+    
+    const TInt count( iRegister.Count() );
+    
+    for( TInt i = 0; i < count; i++ )
+        {
+        if( iRegister[i].iKey == aKey )
+            {
+            __SUBCONTROLLER_INT1( "CMccRtpMediaClock::CheckKey return key cell: ", i )
+            
+            aCell = i;
+            return KErrNone;
+            }
+        }
+    
+    __SUBCONTROLLER( "CMccRtpMediaClock::CheckKey return error KErrNotFound" )
+    
+    return KErrNotFound;
+    }
+
+// ---------------------------------------------------------------------------
+// Removes a media format registration if found.
+// ---------------------------------------------------------------------------
+//
+void CMccRtpMediaClock::UnregisterMediaFormat( TUint32 aKey )
+    {
+    __SUBCONTROLLER_INT1( "CMccRtpMediaClock::UnregisterMediaFormat aKey: ", aKey )
+            
+    TInt cell = KErrNotFound;
+    TInt err = CheckKey( aKey, cell );
+    if ( KErrNone == err )
+        {
+        __SUBCONTROLLER_INT1( "CMccRtpMediaClock::UnregisterMediaFormat remove cell: ",
+            cell )
+        
+        iRegister.Remove( cell );
+        }
+    }
+
+// ---------------------------------------------------------------------------
+// Checks whether 'timebased' or 'callback' increment has been used
+// ---------------------------------------------------------------------------
+//
+TBool CMccRtpMediaClock::TimeBasedIncrement() const
+   	{
+   	__SUBCONTROLLER_INT1( "CMccRtpMediaClock::TimeBasedIncrement: ", 
+   	    iTimeBasedIncrement )
+   	return iTimeBasedIncrement;
+   	}
+
+
+// End of file