multimediacommsengine/mmceshared/src/mcecomavccodec.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 
       
    21 #include "mcecomavccodec.h"
       
    22 
       
    23 #ifdef MCE_COMMON_SERVER_SIDE
       
    24 
       
    25 #include <mmcccodecinformationfactory.h>
       
    26 #include <mmcccodecinformation.h>
       
    27 
       
    28 #include "mcecommediastream.h"
       
    29 
       
    30 #endif
       
    31 
       
    32 
       
    33 // CONSTANTS
       
    34 _LIT8( KMceAvcProfileLevelIdFmtp, "profile-level-id=" );
       
    35 _LIT8( KMceAvcProfileLevel1, "42800A" );
       
    36 const TInt KMceAvcProfileLevelIdValLen = 6;
       
    37 
       
    38 _LIT8( KMceAvcPacketizationModeFmtp, "packetization-mode=" );
       
    39 _LIT8( KMceAvcPacketizationModeSingleNal, "0" );
       
    40 const TInt KMceAvcPacketizationModeValLen = 1;
       
    41 
       
    42 #ifdef MCE_COMMON_SERVER_SIDE
       
    43 
       
    44 _LIT8( KMceAvcProfileLevelOnly1, "0A" );
       
    45 const TInt KMceAvcProfileLevelValLen = 2;
       
    46 const TInt KMceAvcProfileLevelValOffset = 4;
       
    47 
       
    48 _LIT8( KMceAvcProfileIopDefault, "80" );
       
    49 const TInt KMceAvcProfileIopValLen = 2;
       
    50 const TInt KMceAvcProfileIopValOffset = 2;
       
    51 
       
    52 _LIT8( KMceAvcSpropParameterSetsFmtp, "sprop-parameter-sets=");
       
    53 const TChar KMceAvcFmtpParameterSeparator = ';';
       
    54 const TChar KMceAvcFtmpParameterSpace = ' ';
       
    55 
       
    56 #endif
       
    57 
       
    58 // ============================ MEMBER FUNCTIONS ===============================
       
    59 
       
    60 
       
    61 // -----------------------------------------------------------------------------
       
    62 // CMceComAvcCodec::NewL
       
    63 // -----------------------------------------------------------------------------
       
    64 //
       
    65 CMceComAvcCodec* CMceComAvcCodec::NewL( TBuf8<KMceMaxSdpNameLength> aSdpName )
       
    66     {
       
    67     CMceComAvcCodec* self = NewLC( aSdpName );
       
    68     CleanupStack::Pop( self );
       
    69     return self;
       
    70     
       
    71     }
       
    72 
       
    73 // -----------------------------------------------------------------------------
       
    74 // CMceComAvcCodec::NewLC
       
    75 // -----------------------------------------------------------------------------
       
    76 //
       
    77 CMceComAvcCodec* CMceComAvcCodec::NewLC( TBuf8<KMceMaxSdpNameLength> aSdpName )
       
    78     {
       
    79     CMceComAvcCodec* self = new (ELeave) CMceComAvcCodec();
       
    80     CleanupStack::PushL( self );
       
    81     self->ConstructL( aSdpName );
       
    82     return self;
       
    83     }
       
    84 
       
    85 
       
    86 // -----------------------------------------------------------------------------
       
    87 // CMceComAvcCodec::~CMceComAvcCodec
       
    88 // -----------------------------------------------------------------------------
       
    89 //
       
    90 CMceComAvcCodec::~CMceComAvcCodec()
       
    91     {
       
    92     }
       
    93     
       
    94 
       
    95 // -----------------------------------------------------------------------------
       
    96 // CMceComAvcCodec::CMceComAvcCodec
       
    97 // -----------------------------------------------------------------------------
       
    98 //
       
    99 CMceComAvcCodec::CMceComAvcCodec()
       
   100     :CMceComVideoCodec()
       
   101     {
       
   102     iCodecMode = KMceAvcModeSingleNal;
       
   103     iClockRate = KMceAvcDefaultFrameRate;
       
   104     iFrameRate = KMceAvcDefaultFrameRate;
       
   105     iResolutionWidth = KMceAvcDefaultFrameWidth;
       
   106     iResolutionHeight = KMceAvcDefaultFrameHeight;
       
   107     iBitrate = KMceAvcLevel1BitrateBps;
       
   108 	iMaxBitRate = KMceAvcLevel1BitrateBps;
       
   109 	iAllowedBitrates = KMceAvcDefaultAllowedBitrate;
       
   110     iFrameSize = KMceAvcDefaultFrameSize;
       
   111     // Defaults should be defined in MCE API
       
   112     const TUint8 KMceDefaultAvcPayloadType = 98;
       
   113 	iPayloadType = KMceDefaultAvcPayloadType;
       
   114     
       
   115     iReceiveFrameRate = KMceAvcDefaultFrameRate;
       
   116     }
       
   117 
       
   118 
       
   119 // -----------------------------------------------------------------------------
       
   120 // CMceComAvcCodec::ConstructL
       
   121 // -----------------------------------------------------------------------------
       
   122 //
       
   123 CMceComVideoCodec* CMceComAvcCodec::CloneL()
       
   124     {
       
   125     CMceComAvcCodec* copy = new (ELeave) CMceComAvcCodec();
       
   126     CleanupStack::PushL( copy );
       
   127     copy->ConstructL( *this );
       
   128     CleanupStack::Pop( copy );
       
   129     return copy;
       
   130     
       
   131     }
       
   132 
       
   133 
       
   134 // -----------------------------------------------------------------------------
       
   135 // CMceComAvcCodec::ConstructL
       
   136 // -----------------------------------------------------------------------------
       
   137 //
       
   138 void CMceComAvcCodec::ConstructL( TBuf8<KMceMaxSdpNameLength> aSdpName )
       
   139     {
       
   140     CMceComVideoCodec::ConstructL( aSdpName );
       
   141     
       
   142     }
       
   143 
       
   144 
       
   145 // -----------------------------------------------------------------------------
       
   146 // CMceComAvcCodec::ConstructL
       
   147 // -----------------------------------------------------------------------------
       
   148 //
       
   149 void CMceComAvcCodec::ConstructL( CMceComAvcCodec& aCodec )
       
   150     {
       
   151     CMceComVideoCodec::ConstructL( aCodec );
       
   152     }
       
   153     
       
   154 // -----------------------------------------------------------------------------
       
   155 // CMceComAvcCodec::SetBitrate
       
   156 // -----------------------------------------------------------------------------
       
   157 //
       
   158 TInt CMceComAvcCodec::SetBitrate( TUint aBitrate )
       
   159     {
       
   160 	return CMceComCodec::SetBitrate( aBitrate );
       
   161     }
       
   162     
       
   163 // -----------------------------------------------------------------------------
       
   164 // CMceComAvcCodec::SetAllowedBitrates
       
   165 // -----------------------------------------------------------------------------
       
   166 //
       
   167 TInt CMceComAvcCodec::SetAllowedBitrates( TUint aBitrates )
       
   168     {
       
   169     TInt error = KErrNone;
       
   170     
       
   171     //Confirm that the bitrate mask is valid
       
   172     //I.e. after all the valid bitrates are set to zero the value should be zero
       
   173     if ( !aBitrates || 
       
   174         ( aBitrates >> 16 ) > 0 ) 
       
   175         {
       
   176         error = KErrArgument;
       
   177         }
       
   178     else
       
   179         {
       
   180         const TUint KMceOtherInfoMask = 0xFF00;
       
   181         
       
   182         if ( aBitrates == KMceAllowedAvcBitrateAll )
       
   183             {
       
   184             // Start using recommended high bitrate
       
   185             aBitrates = KMceAvcAllowedBitrateRecommendedHigh;
       
   186             }
       
   187             
       
   188         CMceComCodec::SetAllowedBitrates( KMceAllowedAvcBitrateAll );
       
   189         iAllowedBitrates &= aBitrates;
       
   190         TUint maxBitrate = GetMaxBitRate();
       
   191         CMceComVideoCodec::SetMaxBitrate( maxBitrate );
       
   192         if ( iBitrate > maxBitrate )
       
   193             {
       
   194             error = CMceComCodec::SetBitrate( maxBitrate );
       
   195             } 
       
   196             
       
   197         // Update also other avc codec information stored inside
       
   198         // allowed bitrates mask
       
   199         iAllowedBitrates |= ( aBitrates & KMceOtherInfoMask );
       
   200         }
       
   201     
       
   202     return error;
       
   203     }
       
   204 
       
   205 
       
   206 
       
   207 // -----------------------------------------------------------------------------
       
   208 // CMceComAvcCodec::GetMaxBitRate
       
   209 // -----------------------------------------------------------------------------
       
   210 //
       
   211 TUint CMceComAvcCodec::GetMaxBitRate()
       
   212     {
       
   213     TUint maxBitrate( 0 );
       
   214     if( iAllowedBitrates & KMceAvcBitrateLevel1 )
       
   215         {
       
   216         maxBitrate = KMceAvcLevel1BitrateBps;
       
   217         }
       
   218     else if( iAllowedBitrates & KMceAvcBitrateLevel1b )
       
   219         {
       
   220         maxBitrate = KMceAvcLevel1bBitrateBps;
       
   221         }
       
   222     else if( iAllowedBitrates & KMceAvcBitrateLevel1_1 )
       
   223         {
       
   224         maxBitrate = KMceAvcLevel11BitrateBps;
       
   225         }
       
   226     else if( iAllowedBitrates & KMceAvcBitrateLevel1_2 )
       
   227         {
       
   228         maxBitrate = KMceAvcLevel12BitrateBps;
       
   229         }
       
   230     else if( iAllowedBitrates & KMceAvcBitrateLevel1_3 )
       
   231         {
       
   232         maxBitrate = KMceAvcLevel13BitrateBps;
       
   233         }
       
   234     else if( iAllowedBitrates & KMceAvcBitrateLevel2 )
       
   235         {
       
   236         maxBitrate = KMceAvcLevel2BitrateBps;
       
   237         }
       
   238     else
       
   239         {
       
   240         // NOP
       
   241         }
       
   242         
       
   243     return maxBitrate;
       
   244     }
       
   245 
       
   246 // -----------------------------------------------------------------------------
       
   247 // CMceComAvcCodec::SetMaxBitrate
       
   248 // -----------------------------------------------------------------------------
       
   249 //
       
   250 TInt CMceComAvcCodec::SetMaxBitrate( TUint aMaxBitrate )
       
   251     {
       
   252     TInt status = KErrNone;
       
   253 	switch( aMaxBitrate )
       
   254 	    {
       
   255 	    case KMceAvcLevel1BitrateBps:
       
   256 	        {
       
   257 	        status = SetAllowedBitrates( KMceAvcCodecProfileIdBaseline |
       
   258 	                                     KMceAvcCodecProfileIopConstraintSet | 
       
   259 	                                     KMceAvcBitrateLevel1 );
       
   260 	        break;
       
   261 	        }
       
   262 	    case KMceAvcLevel1bBitrateBps:
       
   263 	        {
       
   264 	        status = SetAllowedBitrates( KMceAvcCodecProfileIdBaseline |
       
   265 	                                     KMceAvcCodecProfileIopConstraintSet | 
       
   266 	                                     KMceAvcBitrateLevel1b );
       
   267 	        break;
       
   268 	        }
       
   269 	    case KMceAvcLevel11BitrateBps:
       
   270 	        {
       
   271 	        status = SetAllowedBitrates( KMceAvcCodecProfileIdBaseline |
       
   272 	                                     KMceAvcCodecProfileIopConstraintSet | 
       
   273 	                                     KMceAvcBitrateLevel1_1 );
       
   274 	        break;
       
   275 	        }
       
   276 	    case KMceAvcLevel12BitrateBps:
       
   277 	        {
       
   278 	        status = SetAllowedBitrates( KMceAvcCodecProfileIdBaseline |
       
   279 	                                     KMceAvcCodecProfileIopConstraintSet | 
       
   280 	                                     KMceAvcBitrateLevel1_2 );
       
   281 	        break;
       
   282 	        }
       
   283 	    case KMceAvcLevel13BitrateBps:
       
   284 	        {
       
   285 	        status = SetAllowedBitrates( KMceAvcCodecProfileIdBaseline |
       
   286 	                                     KMceAvcCodecProfileIopConstraintSet | 
       
   287 	                                     KMceAvcBitrateLevel1_3 );
       
   288 	        break;
       
   289 	        }
       
   290 	    case KMceAvcLevel2BitrateBps:
       
   291 	        {
       
   292 	        status = SetAllowedBitrates( KMceAvcCodecProfileIdBaseline |
       
   293 	                                     KMceAvcCodecProfileIopConstraintSet | 
       
   294 	                                     KMceAvcBitrateLevel2 );
       
   295 	        break;
       
   296 	        }
       
   297         default:
       
   298             {
       
   299             status = KErrNotSupported;
       
   300             break;
       
   301             }
       
   302 	    }
       
   303 
       
   304     return status;
       
   305     
       
   306     }
       
   307 
       
   308 // -----------------------------------------------------------------------------
       
   309 // CMceComAvcCodec::ResolveAllowedBitrates
       
   310 // -----------------------------------------------------------------------------
       
   311 //
       
   312 TInt CMceComAvcCodec::ResolveAllowedBitrates( 
       
   313     TUint aBitrate, TUint& aAllowedBitrates )
       
   314     {
       
   315     TInt retVal( KErrNone );
       
   316     
       
   317     if ( aBitrate <= KMceAvcLevel1BitrateBps )
       
   318         {
       
   319         aAllowedBitrates =  KMceAvcCodecProfileIdBaseline | 
       
   320 	                        KMceAvcCodecProfileIopConstraintSet | 
       
   321 	                        KMceAvcBitrateLevel1;
       
   322         }
       
   323     else if ( aBitrate <= KMceAvcLevel1bBitrateBps )
       
   324         {
       
   325         aAllowedBitrates =  KMceAvcCodecProfileIdBaseline | 
       
   326 	                        KMceAvcCodecProfileIopConstraintSet | 
       
   327 	                        KMceAvcBitrateLevel1b;
       
   328         }
       
   329     else if ( aBitrate <= KMceAvcLevel11BitrateBps )
       
   330         {
       
   331         aAllowedBitrates =  KMceAvcCodecProfileIdBaseline | 
       
   332 	                        KMceAvcCodecProfileIopConstraintSet | 
       
   333 	                        KMceAvcBitrateLevel1_1;
       
   334         }
       
   335     else if ( aBitrate <= KMceAvcLevel12BitrateBps )
       
   336         {
       
   337         aAllowedBitrates =  KMceAvcCodecProfileIdBaseline | 
       
   338 	                        KMceAvcCodecProfileIopConstraintSet | 
       
   339 	                        KMceAvcBitrateLevel1_2;
       
   340         }
       
   341     else if ( aBitrate <= KMceAvcLevel13BitrateBps )
       
   342         {
       
   343         aAllowedBitrates =  KMceAvcCodecProfileIdBaseline | 
       
   344 	                        KMceAvcCodecProfileIopConstraintSet | 
       
   345 	                        KMceAvcBitrateLevel1_3;
       
   346         }
       
   347     else if ( aBitrate <= KMceAvcLevel2BitrateBps )
       
   348         {
       
   349         aAllowedBitrates =  KMceAvcCodecProfileIdBaseline | 
       
   350 	                        KMceAvcCodecProfileIopConstraintSet | 
       
   351 	                        KMceAvcBitrateLevel2;
       
   352         }    
       
   353     else 
       
   354         {
       
   355         retVal = KErrNotSupported;
       
   356         }
       
   357         
       
   358     return retVal;
       
   359     }
       
   360 
       
   361 // -----------------------------------------------------------------------------
       
   362 // CMceComAvcCodec::Decodes
       
   363 // For AVC, fmtp value contains profile level and packetization mode 
       
   364 // information which need to be taken in count (same codec cannot be
       
   365 // used for different levels or packetization modes). If less strict matching
       
   366 // is used, profile level is ignored but packetization mode is still checked
       
   367 // -----------------------------------------------------------------------------
       
   368 //
       
   369 TBool CMceComAvcCodec::Decodes( 
       
   370     const TDesC8& aRtpmapValue, 
       
   371     const TDesC8& aFmtpValue,
       
   372     TBool aIsStrictMatch )
       
   373     {
       
   374     TBool decodes = CMceComCodec::Decodes( aRtpmapValue, aFmtpValue, aIsStrictMatch );
       
   375     if ( decodes )
       
   376         {
       
   377         TPtrC8 existingFmtpVal = FmtpAttr();
       
   378         
       
   379         TPtrC8 packetizationMode = ParsePacketizationMode( aFmtpValue );
       
   380         TPtrC8 existingPacketizationMode = ParsePacketizationMode( existingFmtpVal );
       
   381         decodes = ( packetizationMode.CompareF( existingPacketizationMode ) == 0 );
       
   382 
       
   383         if ( decodes && aIsStrictMatch )
       
   384             {
       
   385             TPtrC8 profileLevelId = ParseProfileLevelId( aFmtpValue );
       
   386                 
       
   387             TPtrC8 existingProfileLevelId = ParseProfileLevelId( existingFmtpVal );
       
   388             decodes = ( profileLevelId.CompareF( existingProfileLevelId ) == 0 );
       
   389             }
       
   390         }
       
   391     return decodes;
       
   392     }
       
   393 
       
   394 // -----------------------------------------------------------------------------
       
   395 // CMceComAvcCodec::ParseProfileLevelId
       
   396 // -----------------------------------------------------------------------------
       
   397 //
       
   398 TPtrC8 CMceComAvcCodec::ParseProfileLevelId( const TDesC8& aFmtpValue )
       
   399     {
       
   400     // Non-existing profile-level-id means level 1  
       
   401     TPtrC8 profileLevelIdVal = 
       
   402         GetFmtpAttributeValuePart( aFmtpValue, 
       
   403                                    KMceAvcProfileLevelIdFmtp(), 
       
   404                                    KMceAvcProfileLevelIdValLen, 
       
   405                                    KMceAvcProfileLevel1 );
       
   406                                
       
   407     return profileLevelIdVal;
       
   408     }
       
   409 
       
   410 // -----------------------------------------------------------------------------
       
   411 // CMceComAvcCodec::ParseProfileLevelIdValPart
       
   412 // -----------------------------------------------------------------------------
       
   413 //
       
   414 TPtrC8 CMceComAvcCodec::ParseProfileLevelIdValPart( 
       
   415     const TDesC8& aFmtpValue,
       
   416     TInt aValPartOffset,
       
   417     TInt aValPartLen,
       
   418     const TDesC8& aDefaultVal )
       
   419     {
       
   420     TPtrC8 profileLevelVal( aDefaultVal );
       
   421     
       
   422     TPtrC8 profileLevelIdVal = ParseProfileLevelId( aFmtpValue );
       
   423     if ( profileLevelIdVal.Length() >= aValPartOffset + aValPartLen )
       
   424         {
       
   425         // Take just value part
       
   426         profileLevelVal.Set( profileLevelIdVal.Mid( aValPartOffset, aValPartLen ) );
       
   427         }
       
   428 
       
   429     return profileLevelVal;
       
   430     }
       
   431 
       
   432 // -----------------------------------------------------------------------------
       
   433 // CMceComAvcCodec::ReplaceProfileLevelIdValuePart
       
   434 // -----------------------------------------------------------------------------
       
   435 //
       
   436 TInt CMceComAvcCodec::ReplaceProfileLevelIdValuePart( 
       
   437     TDes8& aModifiedFmtp, 
       
   438     const TDesC8& aReplacement,
       
   439     TInt aValPartOffset )
       
   440     {
       
   441     TInt err( KErrArgument );
       
   442     
       
   443     TInt startIndex = aModifiedFmtp.FindF( KMceAvcProfileLevelIdFmtp() );
       
   444     startIndex = ( startIndex != KErrNotFound ) ? 
       
   445         ( startIndex + KMceAvcProfileLevelIdFmtp().Length() ) : startIndex;
       
   446     if ( startIndex != KErrNotFound && 
       
   447        ( startIndex + aValPartOffset + aReplacement.Length() ) <= aModifiedFmtp.Length() )
       
   448         {
       
   449         aModifiedFmtp.Replace( 
       
   450             startIndex + aValPartOffset, 
       
   451             aReplacement.Length(), 
       
   452             aReplacement );
       
   453         err = KErrNone;
       
   454         }
       
   455     return err;
       
   456     }
       
   457     
       
   458 // -----------------------------------------------------------------------------
       
   459 // CMceComAvcCodec::ParsePacketizationMode
       
   460 // -----------------------------------------------------------------------------
       
   461 //
       
   462 TPtrC8 CMceComAvcCodec::ParsePacketizationMode( const TDesC8& aFmtpValue )
       
   463     {
       
   464     // Non-existing packetization mode means single nal mode
       
   465     TPtrC8 packetizationModeVal =
       
   466         GetFmtpAttributeValuePart( aFmtpValue, 
       
   467                                    KMceAvcPacketizationModeFmtp(), 
       
   468                                    KMceAvcPacketizationModeValLen, 
       
   469                                    KMceAvcPacketizationModeSingleNal );
       
   470    
       
   471     return packetizationModeVal;
       
   472     }
       
   473 
       
   474 // -----------------------------------------------------------------------------
       
   475 // CMceComAvcCodec::GetFmtpAttributeValuePart
       
   476 // -----------------------------------------------------------------------------
       
   477 //
       
   478 TPtrC8 CMceComAvcCodec::GetFmtpAttributeValuePart( 
       
   479     const TDesC8& aFmtpValue,
       
   480     const TDesC8& aFmtpAttributeName, 
       
   481     TInt aValLen, 
       
   482     const TDesC8& aDefaultVal )
       
   483     {
       
   484     TPtrC8 outputValuePart( aDefaultVal );
       
   485     
       
   486     TInt valPos = aFmtpValue.FindF( aFmtpAttributeName );
       
   487     valPos = ( valPos != KErrNotFound ) ? 
       
   488                 ( valPos + aFmtpAttributeName.Length() ) : valPos;
       
   489     if ( valPos != KErrNotFound && 
       
   490        ( valPos + aValLen ) <= aFmtpValue.Length() )
       
   491         {
       
   492         outputValuePart.Set( aFmtpValue.Mid( valPos, aValLen ) );
       
   493         }
       
   494     return outputValuePart;
       
   495     }
       
   496     
       
   497 #ifdef MCE_COMMON_SERVER_SIDE
       
   498 
       
   499 // -----------------------------------------------------------------------------
       
   500 // CMceComAvcCodec::SetFmtpProposalL
       
   501 // -----------------------------------------------------------------------------
       
   502 //
       
   503 TBool CMceComAvcCodec::SetFmtpProposalL( const TDesC8& aFmtpProposal )
       
   504     {
       
   505     HBufC8* proposal = aFmtpProposal.AllocL();
       
   506     delete iFmtpProposal;
       
   507     iFmtpProposal = proposal;
       
   508     
       
   509     CMccCodecInformationFactory* factory = CMccCodecInformationFactory::NewL();
       
   510     CleanupStack::PushL( factory );
       
   511     CMccCodecInformation* codec = 
       
   512         factory->CreateCodecInformationL( iSdpName );
       
   513     CleanupStack::PushL( codec );
       
   514     
       
   515     TRAPD( err, codec->SetFmtpAttrL( *iFmtpProposal ) );
       
   516     if ( err == KErrNoMemory )
       
   517         {
       
   518         User::Leave( err );
       
   519         }
       
   520     
       
   521     CleanupStack::PopAndDestroy( codec );
       
   522     CleanupStack::PopAndDestroy( factory );
       
   523     
       
   524     return ( err == KErrNone );
       
   525     }
       
   526 
       
   527 // -----------------------------------------------------------------------------
       
   528 // CMceComAvcCodec::SetFmtpFromIncomingSdpL
       
   529 // -----------------------------------------------------------------------------
       
   530 //
       
   531 void CMceComAvcCodec::SetFmtpFromIncomingSdpL( 
       
   532     const TDesC8& aFmtpAttribute, 
       
   533     TBool aRoleAnswerer,
       
   534     TBool aReset )
       
   535     {
       
   536     HBufC8* fmtp = aFmtpAttribute.AllocLC();
       
   537     TPtr8 ptrFmtp( fmtp->Des() );
       
   538     
       
   539     if ( !aRoleAnswerer )
       
   540         {
       
   541         // If no strict match, we are accepting fmtp even it is against specs.
       
   542         // In that case, replace level value with existing level
       
   543         TBool decodes = Decodes( iSdpName, aFmtpAttribute );
       
   544         if ( !decodes )
       
   545             {
       
   546             TPtrC8 existingLevel = 
       
   547                 ParseProfileLevelIdValPart( FmtpAttr(), 
       
   548                                             KMceAvcProfileLevelValOffset, 
       
   549                                             KMceAvcProfileLevelValLen, 
       
   550                                             KMceAvcProfileLevelOnly1 );
       
   551             ReplaceProfileLevelIdValuePart( 
       
   552                     ptrFmtp, existingLevel, KMceAvcProfileLevelValOffset );
       
   553             }
       
   554             
       
   555         // In offerer side, tolerate also incorrect iop part usage
       
   556         // by using existing iop val
       
   557         TPtrC8 existingIop = 
       
   558             ParseProfileLevelIdValPart( FmtpAttr(), 
       
   559                                         KMceAvcProfileIopValOffset, 
       
   560                                         KMceAvcProfileIopValLen, 
       
   561                                         KMceAvcProfileIopDefault );
       
   562         ReplaceProfileLevelIdValuePart( 
       
   563                     ptrFmtp, existingIop, KMceAvcProfileIopValOffset );
       
   564         }
       
   565      
       
   566     if ( iStream && iStream->BoundStream() )
       
   567         {
       
   568         // In case of two-way video streams, sprop-parameter-set (configkey)
       
   569         // from incoming sdp is put to receive stream and it will not override
       
   570         // existing key in sendstream
       
   571         if ( IS_SENDSTREAM( iStream ) && IS_RECEIVESTREAM( &iStream->BoundStreamL() ) )
       
   572             {
       
   573             CMceComVideoCodec* boundCodec = 
       
   574                 static_cast<CMceComVideoCodec*>(
       
   575                     iStream->BoundStreamL().FindCodecL( *this ) );
       
   576 
       
   577             HBufC8* spropParameterSetsVal = 
       
   578                 StripFmtpParameterL( ptrFmtp, KMceAvcSpropParameterSetsFmtp() );
       
   579             CleanupStack::PushL( spropParameterSetsVal );
       
   580             if ( boundCodec && 
       
   581                  CMceComVideoCodec::IsConfigKeyValid( spropParameterSetsVal ) )
       
   582                 {
       
   583                 boundCodec->SetConfigKeyL( spropParameterSetsVal );
       
   584                 }
       
   585             CleanupStack::PopAndDestroy( spropParameterSetsVal );    
       
   586             }
       
   587         }
       
   588     
       
   589     SetFmtpAttributeL( ptrFmtp, aReset );
       
   590         
       
   591     CleanupStack::PopAndDestroy( fmtp );
       
   592     }
       
   593 
       
   594 // -----------------------------------------------------------------------------
       
   595 // CMceComAvcCodec::FtmpForOutgoingSdpLC
       
   596 // -----------------------------------------------------------------------------
       
   597 //    
       
   598 HBufC8* CMceComAvcCodec::FtmpForOutgoingSdpLC()
       
   599     {
       
   600     HBufC8* fmtp = CMceComCodec::FtmpForOutgoingSdpLC();
       
   601     if ( iStream && iStream->BoundStream() )
       
   602         {
       
   603         // In case of two-way video streams, sprop-parameter-set (configkey)
       
   604         // for outgoing sdp is taken from send stream
       
   605         if ( IS_RECEIVESTREAM( iStream ) && IS_SENDSTREAM( &iStream->BoundStreamL() ) )
       
   606             {
       
   607             TPtr8 ptrFmtp( fmtp->Des() );
       
   608             
       
   609             CMceComVideoCodec* boundCodec = 
       
   610                 static_cast<CMceComVideoCodec*>( 
       
   611                     iStream->BoundStreamL().FindCodecL( *this ) );
       
   612             if ( boundCodec && boundCodec->IsConfigKeyValid() )
       
   613                 {
       
   614                 HBufC8* spropParameterSetsVal = 
       
   615                     StripFmtpParameterL( ptrFmtp, KMceAvcSpropParameterSetsFmtp() );
       
   616                 delete spropParameterSetsVal;
       
   617                 
       
   618                 HBufC8* newFmtp = AddFmtpParameterL( ptrFmtp,  
       
   619                                                      KMceAvcSpropParameterSetsFmtp(), 
       
   620                                                      *boundCodec->iConfigKey );
       
   621                 CleanupStack::PopAndDestroy( fmtp );
       
   622                 fmtp = newFmtp;
       
   623                 CleanupStack::PushL( fmtp );
       
   624                 }
       
   625                 
       
   626             }
       
   627         }
       
   628     return fmtp;
       
   629     }
       
   630 
       
   631 // -----------------------------------------------------------------------------
       
   632 // CMceComAvcCodec::StripFmtpParameterL
       
   633 // -----------------------------------------------------------------------------
       
   634 //
       
   635 HBufC8* CMceComAvcCodec::StripFmtpParameterL( 
       
   636     TPtr8& aInputFmtp, 
       
   637     const TDesC8& aStrippedParameter )
       
   638     {
       
   639     HBufC8* strippedParameter = NULL;
       
   640     TInt startIndex = aInputFmtp.FindF( aStrippedParameter );
       
   641     if ( startIndex != KErrNotFound )
       
   642         {
       
   643         TPtrC8 parameterVal = aInputFmtp.Mid( startIndex + aStrippedParameter.Length() );
       
   644         TInt endIndex = parameterVal.Locate( KMceAvcFmtpParameterSeparator );
       
   645         if ( endIndex == KErrNotFound )
       
   646             {
       
   647             endIndex = parameterVal.Length();
       
   648             }    
       
   649         
       
   650         if ( endIndex > 0 )
       
   651             {
       
   652             strippedParameter = parameterVal.Mid( 0, endIndex ).AllocLC();
       
   653             
       
   654             // Remove stripped part from input fmtp
       
   655             TInt deleteLen( endIndex + aStrippedParameter.Length() + 1 );
       
   656             
       
   657             aInputFmtp.Delete( startIndex, deleteLen );
       
   658             aInputFmtp.Trim();
       
   659             
       
   660             CleanupStack::Pop( strippedParameter );
       
   661             }
       
   662         }
       
   663     return strippedParameter;
       
   664     }
       
   665 
       
   666 // -----------------------------------------------------------------------------
       
   667 // CMceComAvcCodec::AddFmtpParameterL
       
   668 // -----------------------------------------------------------------------------
       
   669 //
       
   670 HBufC8* CMceComAvcCodec::AddFmtpParameterL( 
       
   671     const TDesC8& aInputFmtp, 
       
   672     const TDesC8& aAddedParameter, 
       
   673     const TDesC8& aAddedParameterVal )
       
   674     {
       
   675     const TInt KMceAvcAdditionalLen = 2;
       
   676     HBufC8* outputFmtp = HBufC8::NewL( aInputFmtp.Length() + 
       
   677                                        aAddedParameter.Length() + 
       
   678                                        aAddedParameterVal.Length() + 
       
   679                                        KMceAvcAdditionalLen );
       
   680     TPtr8 ptrOutputFmtp( outputFmtp->Des() );
       
   681     
       
   682     // Add original param
       
   683     ptrOutputFmtp.Append( aInputFmtp );
       
   684     
       
   685     // Add separators if needed
       
   686     TInt lastSeparatorIndex = aInputFmtp.LocateReverse( KMceAvcFmtpParameterSeparator );
       
   687     if ( aInputFmtp.Length() > 0 && lastSeparatorIndex < ( aInputFmtp.Length() - 2 ) )
       
   688         {
       
   689         ptrOutputFmtp.Append( KMceAvcFmtpParameterSeparator );
       
   690         }
       
   691     TInt lastSpaceIndex = aInputFmtp.LocateReverse( KMceAvcFtmpParameterSpace );
       
   692     if ( aInputFmtp.Length() > 0 && lastSpaceIndex < ( aInputFmtp.Length() - 1 ) )
       
   693         {
       
   694         ptrOutputFmtp.Append( KMceAvcFtmpParameterSpace );
       
   695         }
       
   696         
       
   697     // Add new parameter
       
   698     ptrOutputFmtp.Append( aAddedParameter );
       
   699     ptrOutputFmtp.Append( aAddedParameterVal );
       
   700     
       
   701     return outputFmtp;
       
   702     }
       
   703     
       
   704 #endif
       
   705         
       
   706 // End of File
       
   707 
       
   708