diff -r 000000000000 -r 1bce908db942 multimediacommscontroller/mmccsubcontroller/src/mccrtpmediaclock.cpp --- /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 +#include +#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