multimediacommsengine/mmceshared/src/mcecomavccodec.cpp
changeset 0 1bce908db942
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/multimediacommsengine/mmceshared/src/mcecomavccodec.cpp	Tue Feb 02 01:04:58 2010 +0200
@@ -0,0 +1,708 @@
+/*
+* Copyright (c) 2006 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:    
+*
+*/
+
+
+
+
+#include "mcecomavccodec.h"
+
+#ifdef MCE_COMMON_SERVER_SIDE
+
+#include <mmcccodecinformationfactory.h>
+#include <mmcccodecinformation.h>
+
+#include "mcecommediastream.h"
+
+#endif
+
+
+// CONSTANTS
+_LIT8( KMceAvcProfileLevelIdFmtp, "profile-level-id=" );
+_LIT8( KMceAvcProfileLevel1, "42800A" );
+const TInt KMceAvcProfileLevelIdValLen = 6;
+
+_LIT8( KMceAvcPacketizationModeFmtp, "packetization-mode=" );
+_LIT8( KMceAvcPacketizationModeSingleNal, "0" );
+const TInt KMceAvcPacketizationModeValLen = 1;
+
+#ifdef MCE_COMMON_SERVER_SIDE
+
+_LIT8( KMceAvcProfileLevelOnly1, "0A" );
+const TInt KMceAvcProfileLevelValLen = 2;
+const TInt KMceAvcProfileLevelValOffset = 4;
+
+_LIT8( KMceAvcProfileIopDefault, "80" );
+const TInt KMceAvcProfileIopValLen = 2;
+const TInt KMceAvcProfileIopValOffset = 2;
+
+_LIT8( KMceAvcSpropParameterSetsFmtp, "sprop-parameter-sets=");
+const TChar KMceAvcFmtpParameterSeparator = ';';
+const TChar KMceAvcFtmpParameterSpace = ' ';
+
+#endif
+
+// ============================ MEMBER FUNCTIONS ===============================
+
+
+// -----------------------------------------------------------------------------
+// CMceComAvcCodec::NewL
+// -----------------------------------------------------------------------------
+//
+CMceComAvcCodec* CMceComAvcCodec::NewL( TBuf8<KMceMaxSdpNameLength> aSdpName )
+    {
+    CMceComAvcCodec* self = NewLC( aSdpName );
+    CleanupStack::Pop( self );
+    return self;
+    
+    }
+
+// -----------------------------------------------------------------------------
+// CMceComAvcCodec::NewLC
+// -----------------------------------------------------------------------------
+//
+CMceComAvcCodec* CMceComAvcCodec::NewLC( TBuf8<KMceMaxSdpNameLength> aSdpName )
+    {
+    CMceComAvcCodec* self = new (ELeave) CMceComAvcCodec();
+    CleanupStack::PushL( self );
+    self->ConstructL( aSdpName );
+    return self;
+    }
+
+
+// -----------------------------------------------------------------------------
+// CMceComAvcCodec::~CMceComAvcCodec
+// -----------------------------------------------------------------------------
+//
+CMceComAvcCodec::~CMceComAvcCodec()
+    {
+    }
+    
+
+// -----------------------------------------------------------------------------
+// CMceComAvcCodec::CMceComAvcCodec
+// -----------------------------------------------------------------------------
+//
+CMceComAvcCodec::CMceComAvcCodec()
+    :CMceComVideoCodec()
+    {
+    iCodecMode = KMceAvcModeSingleNal;
+    iClockRate = KMceAvcDefaultFrameRate;
+    iFrameRate = KMceAvcDefaultFrameRate;
+    iResolutionWidth = KMceAvcDefaultFrameWidth;
+    iResolutionHeight = KMceAvcDefaultFrameHeight;
+    iBitrate = KMceAvcLevel1BitrateBps;
+	iMaxBitRate = KMceAvcLevel1BitrateBps;
+	iAllowedBitrates = KMceAvcDefaultAllowedBitrate;
+    iFrameSize = KMceAvcDefaultFrameSize;
+    // Defaults should be defined in MCE API
+    const TUint8 KMceDefaultAvcPayloadType = 98;
+	iPayloadType = KMceDefaultAvcPayloadType;
+    
+    iReceiveFrameRate = KMceAvcDefaultFrameRate;
+    }
+
+
+// -----------------------------------------------------------------------------
+// CMceComAvcCodec::ConstructL
+// -----------------------------------------------------------------------------
+//
+CMceComVideoCodec* CMceComAvcCodec::CloneL()
+    {
+    CMceComAvcCodec* copy = new (ELeave) CMceComAvcCodec();
+    CleanupStack::PushL( copy );
+    copy->ConstructL( *this );
+    CleanupStack::Pop( copy );
+    return copy;
+    
+    }
+
+
+// -----------------------------------------------------------------------------
+// CMceComAvcCodec::ConstructL
+// -----------------------------------------------------------------------------
+//
+void CMceComAvcCodec::ConstructL( TBuf8<KMceMaxSdpNameLength> aSdpName )
+    {
+    CMceComVideoCodec::ConstructL( aSdpName );
+    
+    }
+
+
+// -----------------------------------------------------------------------------
+// CMceComAvcCodec::ConstructL
+// -----------------------------------------------------------------------------
+//
+void CMceComAvcCodec::ConstructL( CMceComAvcCodec& aCodec )
+    {
+    CMceComVideoCodec::ConstructL( aCodec );
+    }
+    
+// -----------------------------------------------------------------------------
+// CMceComAvcCodec::SetBitrate
+// -----------------------------------------------------------------------------
+//
+TInt CMceComAvcCodec::SetBitrate( TUint aBitrate )
+    {
+	return CMceComCodec::SetBitrate( aBitrate );
+    }
+    
+// -----------------------------------------------------------------------------
+// CMceComAvcCodec::SetAllowedBitrates
+// -----------------------------------------------------------------------------
+//
+TInt CMceComAvcCodec::SetAllowedBitrates( TUint aBitrates )
+    {
+    TInt error = KErrNone;
+    
+    //Confirm that the bitrate mask is valid
+    //I.e. after all the valid bitrates are set to zero the value should be zero
+    if ( !aBitrates || 
+        ( aBitrates >> 16 ) > 0 ) 
+        {
+        error = KErrArgument;
+        }
+    else
+        {
+        const TUint KMceOtherInfoMask = 0xFF00;
+        
+        if ( aBitrates == KMceAllowedAvcBitrateAll )
+            {
+            // Start using recommended high bitrate
+            aBitrates = KMceAvcAllowedBitrateRecommendedHigh;
+            }
+            
+        CMceComCodec::SetAllowedBitrates( KMceAllowedAvcBitrateAll );
+        iAllowedBitrates &= aBitrates;
+        TUint maxBitrate = GetMaxBitRate();
+        CMceComVideoCodec::SetMaxBitrate( maxBitrate );
+        if ( iBitrate > maxBitrate )
+            {
+            error = CMceComCodec::SetBitrate( maxBitrate );
+            } 
+            
+        // Update also other avc codec information stored inside
+        // allowed bitrates mask
+        iAllowedBitrates |= ( aBitrates & KMceOtherInfoMask );
+        }
+    
+    return error;
+    }
+
+
+
+// -----------------------------------------------------------------------------
+// CMceComAvcCodec::GetMaxBitRate
+// -----------------------------------------------------------------------------
+//
+TUint CMceComAvcCodec::GetMaxBitRate()
+    {
+    TUint maxBitrate( 0 );
+    if( iAllowedBitrates & KMceAvcBitrateLevel1 )
+        {
+        maxBitrate = KMceAvcLevel1BitrateBps;
+        }
+    else if( iAllowedBitrates & KMceAvcBitrateLevel1b )
+        {
+        maxBitrate = KMceAvcLevel1bBitrateBps;
+        }
+    else if( iAllowedBitrates & KMceAvcBitrateLevel1_1 )
+        {
+        maxBitrate = KMceAvcLevel11BitrateBps;
+        }
+    else if( iAllowedBitrates & KMceAvcBitrateLevel1_2 )
+        {
+        maxBitrate = KMceAvcLevel12BitrateBps;
+        }
+    else if( iAllowedBitrates & KMceAvcBitrateLevel1_3 )
+        {
+        maxBitrate = KMceAvcLevel13BitrateBps;
+        }
+    else if( iAllowedBitrates & KMceAvcBitrateLevel2 )
+        {
+        maxBitrate = KMceAvcLevel2BitrateBps;
+        }
+    else
+        {
+        // NOP
+        }
+        
+    return maxBitrate;
+    }
+
+// -----------------------------------------------------------------------------
+// CMceComAvcCodec::SetMaxBitrate
+// -----------------------------------------------------------------------------
+//
+TInt CMceComAvcCodec::SetMaxBitrate( TUint aMaxBitrate )
+    {
+    TInt status = KErrNone;
+	switch( aMaxBitrate )
+	    {
+	    case KMceAvcLevel1BitrateBps:
+	        {
+	        status = SetAllowedBitrates( KMceAvcCodecProfileIdBaseline |
+	                                     KMceAvcCodecProfileIopConstraintSet | 
+	                                     KMceAvcBitrateLevel1 );
+	        break;
+	        }
+	    case KMceAvcLevel1bBitrateBps:
+	        {
+	        status = SetAllowedBitrates( KMceAvcCodecProfileIdBaseline |
+	                                     KMceAvcCodecProfileIopConstraintSet | 
+	                                     KMceAvcBitrateLevel1b );
+	        break;
+	        }
+	    case KMceAvcLevel11BitrateBps:
+	        {
+	        status = SetAllowedBitrates( KMceAvcCodecProfileIdBaseline |
+	                                     KMceAvcCodecProfileIopConstraintSet | 
+	                                     KMceAvcBitrateLevel1_1 );
+	        break;
+	        }
+	    case KMceAvcLevel12BitrateBps:
+	        {
+	        status = SetAllowedBitrates( KMceAvcCodecProfileIdBaseline |
+	                                     KMceAvcCodecProfileIopConstraintSet | 
+	                                     KMceAvcBitrateLevel1_2 );
+	        break;
+	        }
+	    case KMceAvcLevel13BitrateBps:
+	        {
+	        status = SetAllowedBitrates( KMceAvcCodecProfileIdBaseline |
+	                                     KMceAvcCodecProfileIopConstraintSet | 
+	                                     KMceAvcBitrateLevel1_3 );
+	        break;
+	        }
+	    case KMceAvcLevel2BitrateBps:
+	        {
+	        status = SetAllowedBitrates( KMceAvcCodecProfileIdBaseline |
+	                                     KMceAvcCodecProfileIopConstraintSet | 
+	                                     KMceAvcBitrateLevel2 );
+	        break;
+	        }
+        default:
+            {
+            status = KErrNotSupported;
+            break;
+            }
+	    }
+
+    return status;
+    
+    }
+
+// -----------------------------------------------------------------------------
+// CMceComAvcCodec::ResolveAllowedBitrates
+// -----------------------------------------------------------------------------
+//
+TInt CMceComAvcCodec::ResolveAllowedBitrates( 
+    TUint aBitrate, TUint& aAllowedBitrates )
+    {
+    TInt retVal( KErrNone );
+    
+    if ( aBitrate <= KMceAvcLevel1BitrateBps )
+        {
+        aAllowedBitrates =  KMceAvcCodecProfileIdBaseline | 
+	                        KMceAvcCodecProfileIopConstraintSet | 
+	                        KMceAvcBitrateLevel1;
+        }
+    else if ( aBitrate <= KMceAvcLevel1bBitrateBps )
+        {
+        aAllowedBitrates =  KMceAvcCodecProfileIdBaseline | 
+	                        KMceAvcCodecProfileIopConstraintSet | 
+	                        KMceAvcBitrateLevel1b;
+        }
+    else if ( aBitrate <= KMceAvcLevel11BitrateBps )
+        {
+        aAllowedBitrates =  KMceAvcCodecProfileIdBaseline | 
+	                        KMceAvcCodecProfileIopConstraintSet | 
+	                        KMceAvcBitrateLevel1_1;
+        }
+    else if ( aBitrate <= KMceAvcLevel12BitrateBps )
+        {
+        aAllowedBitrates =  KMceAvcCodecProfileIdBaseline | 
+	                        KMceAvcCodecProfileIopConstraintSet | 
+	                        KMceAvcBitrateLevel1_2;
+        }
+    else if ( aBitrate <= KMceAvcLevel13BitrateBps )
+        {
+        aAllowedBitrates =  KMceAvcCodecProfileIdBaseline | 
+	                        KMceAvcCodecProfileIopConstraintSet | 
+	                        KMceAvcBitrateLevel1_3;
+        }
+    else if ( aBitrate <= KMceAvcLevel2BitrateBps )
+        {
+        aAllowedBitrates =  KMceAvcCodecProfileIdBaseline | 
+	                        KMceAvcCodecProfileIopConstraintSet | 
+	                        KMceAvcBitrateLevel2;
+        }    
+    else 
+        {
+        retVal = KErrNotSupported;
+        }
+        
+    return retVal;
+    }
+
+// -----------------------------------------------------------------------------
+// CMceComAvcCodec::Decodes
+// For AVC, fmtp value contains profile level and packetization mode 
+// information which need to be taken in count (same codec cannot be
+// used for different levels or packetization modes). If less strict matching
+// is used, profile level is ignored but packetization mode is still checked
+// -----------------------------------------------------------------------------
+//
+TBool CMceComAvcCodec::Decodes( 
+    const TDesC8& aRtpmapValue, 
+    const TDesC8& aFmtpValue,
+    TBool aIsStrictMatch )
+    {
+    TBool decodes = CMceComCodec::Decodes( aRtpmapValue, aFmtpValue, aIsStrictMatch );
+    if ( decodes )
+        {
+        TPtrC8 existingFmtpVal = FmtpAttr();
+        
+        TPtrC8 packetizationMode = ParsePacketizationMode( aFmtpValue );
+        TPtrC8 existingPacketizationMode = ParsePacketizationMode( existingFmtpVal );
+        decodes = ( packetizationMode.CompareF( existingPacketizationMode ) == 0 );
+
+        if ( decodes && aIsStrictMatch )
+            {
+            TPtrC8 profileLevelId = ParseProfileLevelId( aFmtpValue );
+                
+            TPtrC8 existingProfileLevelId = ParseProfileLevelId( existingFmtpVal );
+            decodes = ( profileLevelId.CompareF( existingProfileLevelId ) == 0 );
+            }
+        }
+    return decodes;
+    }
+
+// -----------------------------------------------------------------------------
+// CMceComAvcCodec::ParseProfileLevelId
+// -----------------------------------------------------------------------------
+//
+TPtrC8 CMceComAvcCodec::ParseProfileLevelId( const TDesC8& aFmtpValue )
+    {
+    // Non-existing profile-level-id means level 1  
+    TPtrC8 profileLevelIdVal = 
+        GetFmtpAttributeValuePart( aFmtpValue, 
+                                   KMceAvcProfileLevelIdFmtp(), 
+                                   KMceAvcProfileLevelIdValLen, 
+                                   KMceAvcProfileLevel1 );
+                               
+    return profileLevelIdVal;
+    }
+
+// -----------------------------------------------------------------------------
+// CMceComAvcCodec::ParseProfileLevelIdValPart
+// -----------------------------------------------------------------------------
+//
+TPtrC8 CMceComAvcCodec::ParseProfileLevelIdValPart( 
+    const TDesC8& aFmtpValue,
+    TInt aValPartOffset,
+    TInt aValPartLen,
+    const TDesC8& aDefaultVal )
+    {
+    TPtrC8 profileLevelVal( aDefaultVal );
+    
+    TPtrC8 profileLevelIdVal = ParseProfileLevelId( aFmtpValue );
+    if ( profileLevelIdVal.Length() >= aValPartOffset + aValPartLen )
+        {
+        // Take just value part
+        profileLevelVal.Set( profileLevelIdVal.Mid( aValPartOffset, aValPartLen ) );
+        }
+
+    return profileLevelVal;
+    }
+
+// -----------------------------------------------------------------------------
+// CMceComAvcCodec::ReplaceProfileLevelIdValuePart
+// -----------------------------------------------------------------------------
+//
+TInt CMceComAvcCodec::ReplaceProfileLevelIdValuePart( 
+    TDes8& aModifiedFmtp, 
+    const TDesC8& aReplacement,
+    TInt aValPartOffset )
+    {
+    TInt err( KErrArgument );
+    
+    TInt startIndex = aModifiedFmtp.FindF( KMceAvcProfileLevelIdFmtp() );
+    startIndex = ( startIndex != KErrNotFound ) ? 
+        ( startIndex + KMceAvcProfileLevelIdFmtp().Length() ) : startIndex;
+    if ( startIndex != KErrNotFound && 
+       ( startIndex + aValPartOffset + aReplacement.Length() ) <= aModifiedFmtp.Length() )
+        {
+        aModifiedFmtp.Replace( 
+            startIndex + aValPartOffset, 
+            aReplacement.Length(), 
+            aReplacement );
+        err = KErrNone;
+        }
+    return err;
+    }
+    
+// -----------------------------------------------------------------------------
+// CMceComAvcCodec::ParsePacketizationMode
+// -----------------------------------------------------------------------------
+//
+TPtrC8 CMceComAvcCodec::ParsePacketizationMode( const TDesC8& aFmtpValue )
+    {
+    // Non-existing packetization mode means single nal mode
+    TPtrC8 packetizationModeVal =
+        GetFmtpAttributeValuePart( aFmtpValue, 
+                                   KMceAvcPacketizationModeFmtp(), 
+                                   KMceAvcPacketizationModeValLen, 
+                                   KMceAvcPacketizationModeSingleNal );
+   
+    return packetizationModeVal;
+    }
+
+// -----------------------------------------------------------------------------
+// CMceComAvcCodec::GetFmtpAttributeValuePart
+// -----------------------------------------------------------------------------
+//
+TPtrC8 CMceComAvcCodec::GetFmtpAttributeValuePart( 
+    const TDesC8& aFmtpValue,
+    const TDesC8& aFmtpAttributeName, 
+    TInt aValLen, 
+    const TDesC8& aDefaultVal )
+    {
+    TPtrC8 outputValuePart( aDefaultVal );
+    
+    TInt valPos = aFmtpValue.FindF( aFmtpAttributeName );
+    valPos = ( valPos != KErrNotFound ) ? 
+                ( valPos + aFmtpAttributeName.Length() ) : valPos;
+    if ( valPos != KErrNotFound && 
+       ( valPos + aValLen ) <= aFmtpValue.Length() )
+        {
+        outputValuePart.Set( aFmtpValue.Mid( valPos, aValLen ) );
+        }
+    return outputValuePart;
+    }
+    
+#ifdef MCE_COMMON_SERVER_SIDE
+
+// -----------------------------------------------------------------------------
+// CMceComAvcCodec::SetFmtpProposalL
+// -----------------------------------------------------------------------------
+//
+TBool CMceComAvcCodec::SetFmtpProposalL( const TDesC8& aFmtpProposal )
+    {
+    HBufC8* proposal = aFmtpProposal.AllocL();
+    delete iFmtpProposal;
+    iFmtpProposal = proposal;
+    
+    CMccCodecInformationFactory* factory = CMccCodecInformationFactory::NewL();
+    CleanupStack::PushL( factory );
+    CMccCodecInformation* codec = 
+        factory->CreateCodecInformationL( iSdpName );
+    CleanupStack::PushL( codec );
+    
+    TRAPD( err, codec->SetFmtpAttrL( *iFmtpProposal ) );
+    if ( err == KErrNoMemory )
+        {
+        User::Leave( err );
+        }
+    
+    CleanupStack::PopAndDestroy( codec );
+    CleanupStack::PopAndDestroy( factory );
+    
+    return ( err == KErrNone );
+    }
+
+// -----------------------------------------------------------------------------
+// CMceComAvcCodec::SetFmtpFromIncomingSdpL
+// -----------------------------------------------------------------------------
+//
+void CMceComAvcCodec::SetFmtpFromIncomingSdpL( 
+    const TDesC8& aFmtpAttribute, 
+    TBool aRoleAnswerer,
+    TBool aReset )
+    {
+    HBufC8* fmtp = aFmtpAttribute.AllocLC();
+    TPtr8 ptrFmtp( fmtp->Des() );
+    
+    if ( !aRoleAnswerer )
+        {
+        // If no strict match, we are accepting fmtp even it is against specs.
+        // In that case, replace level value with existing level
+        TBool decodes = Decodes( iSdpName, aFmtpAttribute );
+        if ( !decodes )
+            {
+            TPtrC8 existingLevel = 
+                ParseProfileLevelIdValPart( FmtpAttr(), 
+                                            KMceAvcProfileLevelValOffset, 
+                                            KMceAvcProfileLevelValLen, 
+                                            KMceAvcProfileLevelOnly1 );
+            ReplaceProfileLevelIdValuePart( 
+                    ptrFmtp, existingLevel, KMceAvcProfileLevelValOffset );
+            }
+            
+        // In offerer side, tolerate also incorrect iop part usage
+        // by using existing iop val
+        TPtrC8 existingIop = 
+            ParseProfileLevelIdValPart( FmtpAttr(), 
+                                        KMceAvcProfileIopValOffset, 
+                                        KMceAvcProfileIopValLen, 
+                                        KMceAvcProfileIopDefault );
+        ReplaceProfileLevelIdValuePart( 
+                    ptrFmtp, existingIop, KMceAvcProfileIopValOffset );
+        }
+     
+    if ( iStream && iStream->BoundStream() )
+        {
+        // In case of two-way video streams, sprop-parameter-set (configkey)
+        // from incoming sdp is put to receive stream and it will not override
+        // existing key in sendstream
+        if ( IS_SENDSTREAM( iStream ) && IS_RECEIVESTREAM( &iStream->BoundStreamL() ) )
+            {
+            CMceComVideoCodec* boundCodec = 
+                static_cast<CMceComVideoCodec*>(
+                    iStream->BoundStreamL().FindCodecL( *this ) );
+
+            HBufC8* spropParameterSetsVal = 
+                StripFmtpParameterL( ptrFmtp, KMceAvcSpropParameterSetsFmtp() );
+            CleanupStack::PushL( spropParameterSetsVal );
+            if ( boundCodec && 
+                 CMceComVideoCodec::IsConfigKeyValid( spropParameterSetsVal ) )
+                {
+                boundCodec->SetConfigKeyL( spropParameterSetsVal );
+                }
+            CleanupStack::PopAndDestroy( spropParameterSetsVal );    
+            }
+        }
+    
+    SetFmtpAttributeL( ptrFmtp, aReset );
+        
+    CleanupStack::PopAndDestroy( fmtp );
+    }
+
+// -----------------------------------------------------------------------------
+// CMceComAvcCodec::FtmpForOutgoingSdpLC
+// -----------------------------------------------------------------------------
+//    
+HBufC8* CMceComAvcCodec::FtmpForOutgoingSdpLC()
+    {
+    HBufC8* fmtp = CMceComCodec::FtmpForOutgoingSdpLC();
+    if ( iStream && iStream->BoundStream() )
+        {
+        // In case of two-way video streams, sprop-parameter-set (configkey)
+        // for outgoing sdp is taken from send stream
+        if ( IS_RECEIVESTREAM( iStream ) && IS_SENDSTREAM( &iStream->BoundStreamL() ) )
+            {
+            TPtr8 ptrFmtp( fmtp->Des() );
+            
+            CMceComVideoCodec* boundCodec = 
+                static_cast<CMceComVideoCodec*>( 
+                    iStream->BoundStreamL().FindCodecL( *this ) );
+            if ( boundCodec && boundCodec->IsConfigKeyValid() )
+                {
+                HBufC8* spropParameterSetsVal = 
+                    StripFmtpParameterL( ptrFmtp, KMceAvcSpropParameterSetsFmtp() );
+                delete spropParameterSetsVal;
+                
+                HBufC8* newFmtp = AddFmtpParameterL( ptrFmtp,  
+                                                     KMceAvcSpropParameterSetsFmtp(), 
+                                                     *boundCodec->iConfigKey );
+                CleanupStack::PopAndDestroy( fmtp );
+                fmtp = newFmtp;
+                CleanupStack::PushL( fmtp );
+                }
+                
+            }
+        }
+    return fmtp;
+    }
+
+// -----------------------------------------------------------------------------
+// CMceComAvcCodec::StripFmtpParameterL
+// -----------------------------------------------------------------------------
+//
+HBufC8* CMceComAvcCodec::StripFmtpParameterL( 
+    TPtr8& aInputFmtp, 
+    const TDesC8& aStrippedParameter )
+    {
+    HBufC8* strippedParameter = NULL;
+    TInt startIndex = aInputFmtp.FindF( aStrippedParameter );
+    if ( startIndex != KErrNotFound )
+        {
+        TPtrC8 parameterVal = aInputFmtp.Mid( startIndex + aStrippedParameter.Length() );
+        TInt endIndex = parameterVal.Locate( KMceAvcFmtpParameterSeparator );
+        if ( endIndex == KErrNotFound )
+            {
+            endIndex = parameterVal.Length();
+            }    
+        
+        if ( endIndex > 0 )
+            {
+            strippedParameter = parameterVal.Mid( 0, endIndex ).AllocLC();
+            
+            // Remove stripped part from input fmtp
+            TInt deleteLen( endIndex + aStrippedParameter.Length() + 1 );
+            
+            aInputFmtp.Delete( startIndex, deleteLen );
+            aInputFmtp.Trim();
+            
+            CleanupStack::Pop( strippedParameter );
+            }
+        }
+    return strippedParameter;
+    }
+
+// -----------------------------------------------------------------------------
+// CMceComAvcCodec::AddFmtpParameterL
+// -----------------------------------------------------------------------------
+//
+HBufC8* CMceComAvcCodec::AddFmtpParameterL( 
+    const TDesC8& aInputFmtp, 
+    const TDesC8& aAddedParameter, 
+    const TDesC8& aAddedParameterVal )
+    {
+    const TInt KMceAvcAdditionalLen = 2;
+    HBufC8* outputFmtp = HBufC8::NewL( aInputFmtp.Length() + 
+                                       aAddedParameter.Length() + 
+                                       aAddedParameterVal.Length() + 
+                                       KMceAvcAdditionalLen );
+    TPtr8 ptrOutputFmtp( outputFmtp->Des() );
+    
+    // Add original param
+    ptrOutputFmtp.Append( aInputFmtp );
+    
+    // Add separators if needed
+    TInt lastSeparatorIndex = aInputFmtp.LocateReverse( KMceAvcFmtpParameterSeparator );
+    if ( aInputFmtp.Length() > 0 && lastSeparatorIndex < ( aInputFmtp.Length() - 2 ) )
+        {
+        ptrOutputFmtp.Append( KMceAvcFmtpParameterSeparator );
+        }
+    TInt lastSpaceIndex = aInputFmtp.LocateReverse( KMceAvcFtmpParameterSpace );
+    if ( aInputFmtp.Length() > 0 && lastSpaceIndex < ( aInputFmtp.Length() - 1 ) )
+        {
+        ptrOutputFmtp.Append( KMceAvcFtmpParameterSpace );
+        }
+        
+    // Add new parameter
+    ptrOutputFmtp.Append( aAddedParameter );
+    ptrOutputFmtp.Append( aAddedParameterVal );
+    
+    return outputFmtp;
+    }
+    
+#endif
+        
+// End of File
+
+