diff -r 000000000000 -r 1bce908db942 multimediacommsengine/mmcesrv/mmcemediamanager/src/mcemediasdpcodec.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/multimediacommsengine/mmcesrv/mmcemediamanager/src/mcemediasdpcodec.cpp Tue Feb 02 01:04:58 2010 +0200 @@ -0,0 +1,1615 @@ +/* +* 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 FILES + +#include "mcemediadefs.h" +#include "mcemediasdpcodec.h" +#include "mcecomcodec.h" +#include "mcemmlogs.h" +#include "mcepreconditions.h" +#include "mcesdpsession.h" +#include "mcesip.h" +#include "mcemediamanager.h" +#include "mcenatpluginmanager.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +// ================= MEMBER FUNCTIONS ======================= + +// ----------------------------------------------------------------------------- +// CMceMediaSdpCodec::CMceMediaSdpCodec +// ----------------------------------------------------------------------------- +CMceMediaSdpCodec::CMceMediaSdpCodec( RStringF aMedia ) + : CMceSdpCodec( aMedia ) + { + } + + +// ----------------------------------------------------------------------------- +// CMceMediaSdpCodec::~CMceMediaSdpCodec +// ----------------------------------------------------------------------------- +CMceMediaSdpCodec::~CMceMediaSdpCodec() + { + } + + + +// ----------------------------------------------------------------------------- +// CMceMediaSdpCodec::EncodeMediaOfferL +// ----------------------------------------------------------------------------- +// +void CMceMediaSdpCodec::EncodeMediaOfferL( + CMceComMediaStream& aStream, + CSdpMediaField& aMediaLine, + CSdpDocument& aSdpDocument ) + { + MCEMM_DEBUG("CMceMediaSdpCodec::EncodeMediaOfferL(), Entry ") + + // get all the codecs to be offered for this media stream. + const RPointerArray& allCodecs = CodecsL( aStream ); + + CMceComCodec* codec = NULL; + CMceComCodec::TIterator codecs( allCodecs, CMceComCodec::TIterator::EFilterIsNegotiated ); + + // Set the fmt list containing all supported payload + // types supported by this media + // i.e. all the rtpmap fields in the pointer array + HBufC8* fmtlist = CreateFormatListL( codecs ); + CleanupStack::PushL( fmtlist ); + codecs.Reset(); + + aMediaLine.SetFormatListL( *fmtlist ); + CleanupStack::PopAndDestroy( fmtlist ); + + MCEMM_DEBUG_SVALUE("encoded formatlist", aMediaLine.FormatList() ) + + // For each codec supported by this stream create a rtpmap field + // e.g. a=rtpmap: 97 AMR/8000 + // and ptime and maxptime + // e.g. a=ptime:20 a=maxptime:40 + while( codecs.Next( codec ) ) + { + CSdpFmtAttributeField* rtpmap = EncodeRtpmapAttributeLC( *codec ); + + EncodeMediaAttributesL( *codec, aMediaLine, *rtpmap ); + + aMediaLine.FormatAttributeFields().AppendL( rtpmap ); + CleanupStack::Pop( rtpmap ); + + EncodeFmtpAttributeL( *codec, aMediaLine ); + + } + + //encode direction + EncodeDirectionL( aStream, aMediaLine, aSdpDocument, EMceRoleOfferer ); + + //encode client attributes if any + EncodeClientAttributesL( aStream, aMediaLine ); + + //encode secure session if any + EncodeSecureSessionL( aStream, aMediaLine, EMceRoleOfferer ); + + //encode preconditions if any + EncodePreconditionsL( aStream, aMediaLine, EMceRoleOfferer ); + + //encode rtcp port + EncodelocalRtcpAttrL( aMediaLine, aStream ); + + MCEMM_DEBUG("CMceMediaSdpCodec::EncodeMediaOfferL(), Exit ") + } + + +// ----------------------------------------------------------------------------- +// CMceMediaSdpCodec::DecodeMediaAnswerL +// ----------------------------------------------------------------------------- +// +TMceSipWarningCode CMceMediaSdpCodec::DecodeMediaAnswerL( + CSdpMediaField& aMediaLine, + CMceComMediaStream& aStream, + CSdpDocument& aSdpDocument ) + { + MCEMM_DEBUG("CMceMediaSdpCodec::DecodeMediaAnswerL(), Entry ") + + //should have secure session created + + const RPointerArray& allCodecs = CodecsL( aStream ); + CMceComCodec::TIterator codecs( allCodecs ); + + //decode direction or old school hold if necessary + DecodeDirectionL( aMediaLine, aStream, aSdpDocument, EMceRoleOfferer ); + + __ASSERT_ALWAYS( codecs.Count() > 0, User::Leave( KErrNotReady ) ); + __ASSERT_ALWAYS( aMediaLine.Port() != 0 , User::Leave( KErrNotReady ) ); + + //decode based on rtpmaps + their media attributes + TInt decoded = DecodePayloadsL( aMediaLine, aStream, EMceRoleOfferer ); + + if ( !decoded ) + { + MCEMM_DEBUG("ERROR: No codecs decoded") + User::Leave( KErrNotReady ); + } + + // check if remote RTCP port is set according to RFC 3605 + DecodeRemoteRtcpFieldL( aMediaLine, aStream ); + aStream.SetRemoteMediaPort( aMediaLine.Port() ); + + MCEMM_DEBUG_DVALUE("decoded remote port", aStream.RemoteMediaPort() ) + //decode based on fmtps + DecodeFmtpLinesL( aMediaLine, codecs, EMceRoleOfferer ); + + //decode secure session if any + DecodeSecureSessionL( aMediaLine, aStream, EMceRoleOfferer ); + + //decode preconditions if any + TMceSipWarningCode warnings = + DecodePreconditionsL( aMediaLine, aStream, EMceRoleOfferer ); + + //decode client attributes if any + DecodeClientAttributesL( aMediaLine, aStream ); + + MCEMM_DEBUG("CMceMediaSdpCodec::DecodeMediaAnswerL(), Exit ") + return warnings; + } + +// ----------------------------------------------------------------------------- +// CMceMediaSdpCodec::DecodeMediaOfferL +// ----------------------------------------------------------------------------- +// +TMceSipWarningCode CMceMediaSdpCodec::DecodeMediaOfferL( + CSdpMediaField& aMediaLine, + CMceComMediaStream*& aStream, + CMceComSession& aSession, + CSdpDocument& aSdpDocument ) + { + MCEMM_DEBUG("CMceMediaSdpCodec::DecodeMediaOfferL(), Entry ") + + TMceSipWarningCode warning = ValidateSdpL( aMediaLine, aSdpDocument ); + if ( warning != KErrNone ) + { + return warning; + } + + TInt type = Type( aMediaLine, aSdpDocument.AttributeFields() ); + + // create server stream based on the media direction + // attribute (sendonly, sendrcv, rcvonly) + aStream = CreateStreamLC( type ); + aStream->InitializeL( aSession ); + + //decode direction or old school hold if necessary + DecodeDirectionL( aMediaLine, *aStream, aSdpDocument, EMceRoleAnswerer ); + + const RPointerArray& allCodecs = CodecsL( *aStream ); + CMceComCodec::TIterator codecs( allCodecs ); + + //decode based on rtpmaps + their media attributes + TInt decoded = DecodePayloadsL( aMediaLine, *aStream, EMceRoleAnswerer ); + + if ( decoded ) + { + + // check if remote RTCP port is set according to RFC 3605 + DecodeRemoteRtcpFieldL( aMediaLine, *aStream ); + aStream->SetRemoteMediaPort( aMediaLine.Port() ); + + MCEMM_DEBUG_DVALUE("decoded remote port", aStream->RemoteMediaPort() ) + + //decode based on fmtps + DecodeFmtpLinesL( aMediaLine, codecs, EMceRoleAnswerer ); + + //decode session level media attributes + DecodeSessionMediaAttributesL( *aStream, aSdpDocument ); + + + //decode secure session if any + DecodeSecureSessionL( aMediaLine, *aStream, EMceRoleAnswerer ); + //decode preconditions if any + warning = DecodePreconditionsL( aMediaLine, *aStream, EMceRoleAnswerer ); + + + //Decode client attributes if any + DecodeClientAttributesL( aMediaLine, *aStream ); + + aSession.Streams().AppendL( aStream ); + CleanupStack::Pop( aStream ); + + } + else + { + MCEMM_DEBUG("No acceptable codecs found for current media line ") + + // we did not find any acceptable codecs for this stream, return warning + + CleanupStack::PopAndDestroy( aStream ); + aStream = NULL; + warning = KMceSipWarnIncompatibleMediaFormat; + } + + MCEMM_DEBUG("CMceMediaSdpCodec::DecodeMediaOfferL(), Exit ") + + return warning; + + } + +// ----------------------------------------------------------------------------- +// CMceMediaSdpCodec::DecodeMediaUpdateL +// ----------------------------------------------------------------------------- +// +TMceSipWarningCode CMceMediaSdpCodec::DecodeMediaUpdateL( + CSdpMediaField& aMediaLine, + CMceComMediaStream& aStream, + CSdpDocument& aSdpDocument ) + { + + MCEMM_DEBUG("CMceMediaSdpCodec::DecodeMediaUpdateL(), Entry ") + + TMceSipWarningCode warning = ValidateSdpL( aMediaLine, aSdpDocument ); + if ( warning != KErrNone ) + { + return warning; + } + + const RPointerArray& allCodecs = CodecsL( aStream ); + CMceComCodec::TIterator codecs( allCodecs ); + + aStream.SetRemoteMediaPort( aMediaLine.Port() ); + MCEMM_DEBUG_DVALUE("decoded remote port", aStream.RemoteMediaPort() ) + + //should have secure media session existed + + //decode based on rtpmaps + their media attributes + TInt decoded = DecodePayloadsL( aMediaLine, aStream, EMceRoleAnswerer ); + + if ( decoded ) + { + // check if remote RTCP port is set according to RFC 3605 + DecodeRemoteRtcpFieldL( aMediaLine, aStream ); + + + //decode based on fmtps + DecodeFmtpLinesL( aMediaLine, codecs, EMceRoleAnswerer ); + + //decode direction or old school hold if necessary + UpdateDirectionL( aMediaLine, aStream, aSdpDocument ); + + //decode secure session if any + DecodeSecureSessionL( aMediaLine, aStream, EMceRoleAnswerer, KMceMediaCodecUpdate ); + + + //decode preconditions if any + warning = DecodePreconditionsL( aMediaLine, aStream, EMceRoleAnswerer ); + + //decode client attributes if any + DecodeClientAttributesL( aMediaLine, aStream ); + + } + else + { + MCEMM_DEBUG("ERROR: No codecs decoded") + warning = KMceSipWarnIncompatibleMediaFormat; + } + + MCEMM_DEBUG("CMceMediaSdpCodec::DecodeMediaUpdateL(), Exit ") + return warning; + } + +// ----------------------------------------------------------------------------- +// CMceAudioSdpCodec::EncodeMediaAnswerL +// ----------------------------------------------------------------------------- +// +void CMceMediaSdpCodec::EncodeMediaAnswerL( + CMceComMediaStream& aStream, + CSdpMediaField& aMediaLine, + CSdpDocument& aSdpDocument ) + { + MCEMM_DEBUG("CMceMediaSdpCodec::EncodeMediaAnswerL(), Entry ") + + const RPointerArray& allCodecs = CodecsL( aStream ); + CMceComCodec* codec = NULL; + CMceComCodec::TIterator codecs( allCodecs, CMceComCodec::TIterator::EFilterIsNegotiated ); + + if ( codecs.Count() > 0 ) + { + + // Set the fmt list containing all supported payload + // types supported by this media + // i.e. all the rtpmap fields in the pointer array + HBufC8* fmtlist = CreateFormatListL( codecs ); + CleanupStack::PushL( fmtlist ); + codecs.Reset(); + + aMediaLine.SetFormatListL( *fmtlist ); + CleanupStack::PopAndDestroy( fmtlist ); + + MCEMM_DEBUG_SVALUE("encoded formatlist", aMediaLine.FormatList() ) + + aMediaLine.SetPortL( aStream.iLocalMediaPort ); + MCEMM_DEBUG_DVALUE("encoded local port", aMediaLine.Port() ) + + // add the direction attribute + EncodeDirectionL( aStream, aMediaLine, aSdpDocument, EMceRoleAnswerer ); + + while( codecs.Next( codec ) ) + { + CSdpFmtAttributeField* rtpmap = EncodeRtpmapAttributeLC( *codec ); + + EncodeMediaAttributesL( *codec, aMediaLine, *rtpmap ); + + aMediaLine.FormatAttributeFields().AppendL( rtpmap ); + CleanupStack::Pop( rtpmap ); + + EncodeFmtpAttributeL( *codec, aMediaLine ); + + } + + //encode secure session if any + EncodeSecureSessionL( aStream, aMediaLine, EMceRoleAnswerer ); + + //encode preconditions if any + EncodePreconditionsL( aStream, aMediaLine, EMceRoleAnswerer ); + + } + else + { // there was no selected codec for this stream + MCEMM_DEBUG("ERROR: No selected codec found! Reject ") + aMediaLine.RejectMedia(); + } + + // encode client attributes + EncodeClientAttributesL( aStream, aMediaLine ); + + // encode rtcp attributes + EncodelocalRtcpAttrL( aMediaLine, aStream ); + MCEMM_DEBUG("CMceMediaSdpCodec::EncodeMediaAnswerL(), Exit ") + } + +// ----------------------------------------------------------------------------- +// CMceMediaSdpCodec::TypeL +// ----------------------------------------------------------------------------- +// +TInt CMceMediaSdpCodec::Type( + CSdpMediaField& aMedia, + RPointerArray& aSessionAttributes ) const + { + TInt type = Direction( aMedia, aSessionAttributes ); + type = type == KErrNotFound ? SdpCodecStringConstants::EAttributeSendrecv : type; + return type; + } + +// ----------------------------------------------------------------------------- +// CMceMediaSdpCodec::PrepareForDecodeL +// ----------------------------------------------------------------------------- +// +void CMceMediaSdpCodec::PrepareForDecodeL( + CSdpMediaField& /*aMediaLine*/, + CMceComMediaStream* aStream ) + { + MCEMM_DEBUG("CMceMediaSdpCodec::PrepareForDecodeL(), Entry ") + + if ( aStream ) + { + const RPointerArray& allCodecs = CodecsL( *aStream ); + CMceComCodec* codec = NULL; + CMceComCodec::TIterator codecs( allCodecs ); + while( codecs.Next( codec ) ) + { + codec->iIsNegotiated = EFalse; + } + } + + MCEMM_DEBUG("CMceMediaSdpCodec::PrepareForDecodeL(), Exit ") + } + +// ----------------------------------------------------------------------------- +// CMceMediaSdpCodec::DecodeRtpmapLinesL +// ----------------------------------------------------------------------------- +// +TInt CMceMediaSdpCodec::DecodeRtpmapLinesL( + CSdpMediaField& aMediaLine, + CMceComMediaStream& aStream, + TMceNegotiationRole aRole ) const + { + MCEMM_DEBUG("CMceMediaSdpCodec::DecodeRtpmapLinesL(), Entry ") + TInt decoded = 0; + + const RPointerArray& allCodecs = CodecsL( aStream ); + CMceComCodec* codec = NULL; + CMceComCodec::TIterator codecs( allCodecs ); + + RArray payloadTypesInMediaLine; + CleanupClosePushL( payloadTypesInMediaLine ); + + User::LeaveIfError( DecodeFormatList( aMediaLine, payloadTypesInMediaLine ) ); + + RPointerArray< CSdpFmtAttributeField >& formatLines = + aMediaLine.FormatAttributeFields(); + + for ( TInt i = 0; i < formatLines.Count(); i++ ) + { + CSdpFmtAttributeField* formatLine = formatLines[ i ]; + if ( formatLine->Attribute() == + SDP_STRING( SdpCodecStringConstants::EAttributeRtpmap ) ) + //codec + { + TPtrC8 fmtpVal = GetCorrespondingFmtpLineL( aMediaLine, *formatLine ); + + MCE_ITERATOR_FIND_NEXT( + codecs, codec, + codec->Decodes( formatLine->Value(), fmtpVal ) ); + + codecs.Reset(); + + if ( !codec && aRole == EMceRoleOfferer ) + { + // No exact match, do less strict matching for better interoperability + MCE_ITERATOR_FIND_NEXT( + codecs, codec, + codec->Decodes( formatLine->Value(), fmtpVal, EFalse ) ); + codecs.Reset(); + } + + if ( codec ) + { + MCEMM_DEBUG_SVALUE("decoding codec", codec->iSdpName ) + + const TDesC8& payloadTypeInRtpMap = formatLine->Format(); + TUint rtpMapPT = ConvertDesToUintL( payloadTypeInRtpMap ); + + TInt val = payloadTypesInMediaLine.Find( rtpMapPT ); + if ( val != KErrNotFound ) + { + TUint payload = ConvertDesToUintL( formatLine->Format() ); + if ( !IsPayloadTypeSupported( codec->iSdpName, payload ) ) + { + // not supported payload, ignore this codec + continue; + } + if ( !codec->iIsNegotiated ) + { + codec->iPayloadType = payload; + } + codec->iIsNegotiated = ETrue; + //decode media attributes + DecodeMediaAttributesL( aMediaLine, *codec, *formatLine ); + decoded++; + } + else + { + // Discarding as there was no matching pt in medialine for + // this rtmpmap line + codec->iIsNegotiated = EFalse; + if ( aStream.BoundStream() ) + { + CMceComCodec* sync = NULL; + sync = aStream.BoundStreamL().FindCodecL( *codec ); + if ( sync ) + { + sync->iIsNegotiated = EFalse; + } + } + } + } + else if ( aRole == EMceRoleAnswerer ) + { + if ( DecodeRtpmapLineL( *formatLine, aMediaLine, aStream, fmtpVal ) ) + { + decoded++; + } + } + else + { + // NOP + } + + } + } + + CleanupStack::PopAndDestroy( &payloadTypesInMediaLine ); + + MCEMM_DEBUG_DVALUE("decoded codecs", decoded ) + MCEMM_DEBUG("CMceMediaSdpCodec::DecodeRtpmapLinesL(), Exit ") + return decoded; + } + +// ----------------------------------------------------------------------------- +// CMceMediaSdpCodec::DecodeRtpmapLinesL +// ----------------------------------------------------------------------------- +// +TInt CMceMediaSdpCodec::DecodeRtpmapLinesL( + CSdpMediaField& aMediaLine, + CMceComMediaStream& aStream ) const + { + MCEMM_DEBUG("CMceMediaSdpCodec::DecodeRtpmapLinesL(), Entry ") + TInt decoded = 0; + + // Read format level attributes + RPointerArray< CSdpFmtAttributeField >& formatLines = + aMediaLine.FormatAttributeFields(); + + // For all codec specific lines in the offer + for ( TInt i = 0; i < formatLines.Count(); i++ ) + { + CSdpFmtAttributeField* formatLine = formatLines[i]; + if ( formatLine->Attribute() == SDP_STRING( SdpCodecStringConstants::EAttributeRtpmap ) && + DecodeRtpmapLineL( *formatLine, aMediaLine, aStream ) ) + { + decoded++; + } + } + + MCEMM_DEBUG_DVALUE("decoded codecs", decoded ) + MCEMM_DEBUG("CMceMediaSdpCodec::DecodeRtpmapLinesL(), Exit ") + return decoded; + } + +// ----------------------------------------------------------------------------- +// CMceMediaSdpCodec::DecodeStaticPayloadsL +// ----------------------------------------------------------------------------- +// +TInt CMceMediaSdpCodec::DecodeStaticPayloadsL( + CSdpMediaField& aMediaLine, + CMceComMediaStream& aStream, + RArray& aPayloadTypes, + TMceNegotiationRole aRole ) const + { + MCEMM_DEBUG("CMceMediaSdpCodec::DecodeStaticPayloadsL(), Entry ") + TInt decoded = 0; + + DecodeFormatListL( aMediaLine, aPayloadTypes ); + TInt index = 0; + + while( index < aPayloadTypes.Count() ) + { + TUint payload = aPayloadTypes[ index++ ]; + if ( payload < KMinDynamicPT ) + { + CMceComCodec* codec = FindCodec( payload, aStream ); + if ( aRole == EMceRoleAnswerer ) + { + if ( !codec ) + { + codec = CreateCodecLC( payload, aMediaLine ); + if ( codec ) + { + codec->InitializeL( aStream ); + codec->iIsNegotiated = ETrue; + MCEMM_DEBUG_SVALUE("adding codec", codec->iSdpName ) + aStream.AddCodecL( codec ); + CleanupStack::Pop( codec ); + decoded++; + } + } + else + { + codec->iIsNegotiated = ETrue; + decoded++; + } + } + else if ( codec && aRole == EMceRoleOfferer ) + { + codec->iIsNegotiated = ETrue; + decoded++; + } + } + } + + MCEMM_DEBUG_DVALUE("decoded codecs", decoded ) + MCEMM_DEBUG("CMceMediaSdpCodec::DecodeStaticPayloadsL(), Exit ") + return decoded; + } + +// ----------------------------------------------------------------------------- +// CMceMediaSdpCodec::FindCodec +// ----------------------------------------------------------------------------- +// +CMceComCodec* CMceMediaSdpCodec::FindCodec( + TInt aPayloadType, + CMceComMediaStream& aStream ) const + { + TInt error = KErrNone; + + RPointerArray< CMceComCodec > allCodecs; + + TRAP( error, allCodecs = CodecsL( aStream ) ); + CMceComCodec* codec = NULL; + if( error == KErrNone ) + { + CMceComCodec::TIterator codecs( allCodecs ); + + MCE_ITERATOR_FIND_NEXT( codecs, codec, codec->iPayloadType == aPayloadType ); + } + + return codec; + } + +// ----------------------------------------------------------------------------- +// CMceMediaSdpCodec::DecodeRtpmapLineL +// ----------------------------------------------------------------------------- +// +CMceComCodec* CMceMediaSdpCodec::DecodeRtpmapLineL( + CSdpFmtAttributeField& aRtpMaptLine, + CSdpMediaField& aMediaLine, + CMceComMediaStream& aStream, + const TDesC8& aFmtpValue ) const + { + MCEMM_DEBUG("CMceMediaSdpCodec::DecodeFmtpLineL(), Entry ") + + RArray payloadTypesInMediaLine; + CleanupClosePushL( payloadTypesInMediaLine ); + + User::LeaveIfError( DecodeFormatList( aMediaLine, payloadTypesInMediaLine ) ); + + const TDesC8& payloadTypeInRtpMap = aRtpMaptLine.Format(); + + TUint rtpMapPT = ConvertDesToUintL( payloadTypeInRtpMap ); + CMceComCodec* codec = NULL; + + // Ingoring if there is no matching pt in medialine for this rtmpmap line + if ( payloadTypesInMediaLine.Find( rtpMapPT ) != KErrNotFound ) + { + codec = CreateCodecLC( aRtpMaptLine ); + if ( codec ) + { + codec->InitializeL( aStream ); + if ( !codec->SetFmtpProposalL( aFmtpValue ) ) + { + // Fmtp not valid, ignore codec + CleanupStack::PopAndDestroy( codec ); + codec = NULL; + } + else + { + // check if ptime or maxptime attributes are present + DecodeMediaAttributesL( aMediaLine, *codec, aRtpMaptLine ); + codec->iIsNegotiated = ETrue; + MCEMM_DEBUG_SVALUE("adding codec", codec->iSdpName ) + aStream.AddCodecL( codec ); + CleanupStack::Pop( codec ); + } + } + } + + CleanupStack::PopAndDestroy( &payloadTypesInMediaLine ); + + MCEMM_DEBUG("CMceMediaSdpCodec::DecodeFmtpLineL(), Exit ") + return codec; + } + +// ----------------------------------------------------------------------------- +// CMceMediaSdpCodec::DecodeFmtpLinesL +// ----------------------------------------------------------------------------- +// +void CMceMediaSdpCodec::DecodeFmtpLinesL( + CSdpMediaField& aMediaLine, + CMceComCodec::TIterator& aCodecs, + TMceNegotiationRole aRole ) const + { + MCEMM_DEBUG("CMceMediaSdpCodec::DecodeFmtpLinesL(), Entry ") + + RPointerArray< CSdpFmtAttributeField >& formatLines = + aMediaLine.FormatAttributeFields(); + + CMceComCodec* codec = NULL; + while( aCodecs.Next( codec ) ) + { + TBool first = ETrue; + // for all codec specific lines in the offer + TBool found = EFalse; + for ( TInt j = 0; j < formatLines.Count(); j++ ) + { + CSdpFmtAttributeField* formatLine = formatLines[ j ]; + if ( formatLine->Attribute() == + SDP_STRING( SdpCodecStringConstants::EAttributeFmtp ) ) + { + TUint payloadType = ConvertDesToUintL( formatLine->Format() ); + if ( codec->iPayloadType == payloadType ) + { + MCEMM_DEBUG_SVALUE("decoding format", formatLine->Format() ) + const TDesC8& fmtpValue = formatLine->Value(); + MCEMM_DEBUG_SVALUE("decoding fmtp", fmtpValue ) + found = ETrue; + TBool isAnswerer( aRole == EMceRoleAnswerer ); + if ( first ) + { + codec->SetFmtpFromIncomingSdpL( + fmtpValue, isAnswerer, KMceCodecFmtpReset ); + first = EFalse; + } + else + { + codec->SetFmtpFromIncomingSdpL( + fmtpValue, isAnswerer, KMceCodecFmtpAppend ); + } + } + } + } + if ( !found ) + { + // No fmtp line found, use default values + codec->SetDefaultFmtpAttributeL(); + } + MCEMM_DEBUG_SVALUE("decoded fmtp", *codec->iFmtpAttr ) + } + + MCEMM_DEBUG("CMceMediaSdpCodec::DecodeFmtpLinesL(), Exit ") + } + +// ----------------------------------------------------------------------------- +// CMceMediaSdpCodec::EncodeFmtpAttributeL +// ----------------------------------------------------------------------------- +// +void CMceMediaSdpCodec::EncodeFmtpAttributeL( + CMceComCodec& aCodec, + CSdpMediaField& aMedia ) const + { + MCEMM_DEBUG("CMceMediaSdpCodec::EncodeFmtpAttributeL(), Entry ") + + RStringF attributeFmtp = + SDP_STRING( SdpCodecStringConstants::EAttributeFmtp ); + + if( aCodec.iFmtpAttr && aCodec.iFmtpAttr->Size() != 0 ) + { + MCE_DEFINE_DECSTR( payload, aCodec.iPayloadType ) + + HBufC8* fmtpAttr = aCodec.FtmpForOutgoingSdpLC(); + CSdpFmtAttributeField* fmtpLine = + CSdpFmtAttributeField::NewL( attributeFmtp, payload, *fmtpAttr ); + CleanupStack::PopAndDestroy( fmtpAttr ); + CleanupStack::PushL( fmtpLine ); + aMedia.FormatAttributeFields().AppendL( fmtpLine ); + CleanupStack::Pop( fmtpLine ); + + MCEMM_DEBUG_SVALUE( "encoded fmtp", fmtpLine->Value() ) + } + + MCEMM_DEBUG("CMceMediaSdpCodec::EncodeFmtpAttributeL(), Exit ") + } + +// ----------------------------------------------------------------------------- +// CMceMediaSdpCodec::CreateFormatListL +// Creates fmtlist that can be used as media field fmt list -attribute +// (other items were commented in a header). +// Status : Draft +// ----------------------------------------------------------------------------- +// +HBufC8* CMceMediaSdpCodec::CreateFormatListL( + CMceComCodec::TIterator& aCodecs ) const + { + MCEMM_DEBUG("CMceMediaSdpCodec::CreateFmtListL(), Entry ") + + HBufC8* fmtList = HBufC8::NewLC( KMceSdpFormatListLength ); + TPtr8 fmtListPtr( fmtList->Des() ); + + CMceComCodec* codec = NULL; + for ( TInt count = 0; count <= aCodecs.Count()-1; count++ ) + { + aCodecs.Next( codec ); + MCE_DEFINE_DECSTR( payload, codec->iPayloadType ) + fmtListPtr.Append( payload ); + if ( count != aCodecs.Count()-1) + { + fmtListPtr.Append( KMceSipBlank ); + } + } + + CleanupStack::Pop( fmtList ); + + MCEMM_DEBUG("CMceMediaSdpCodec::CreateFmtListL(), Exit ") + + return fmtList; + } + +// ----------------------------------------------------------------------------- +// CMceMediaSdpCodec::DecodeFormatListL +// ----------------------------------------------------------------------------- +// +void CMceMediaSdpCodec::DecodeFormatListL( + CSdpMediaField& aMedia, + RArray& aPayloadTypes ) const + { + MCEMM_DEBUG("CMceMediaSdpCodec::DecodeFormatListL(), Entry ") + + User::LeaveIfError( DecodeFormatList( aMedia, aPayloadTypes ) ); + + MCEMM_DEBUG("CMceMediaSdpCodec::DecodeFormatListL(), Exit ") + } + +// ----------------------------------------------------------------------------- +// CMceMediaSdpCodec::DecodeFormatList +// ----------------------------------------------------------------------------- +// +TInt CMceMediaSdpCodec::DecodeFormatList( + CSdpMediaField& aMedia, + RArray& aPayloadTypes ) const + { + MCEMM_DEBUG("CMceMediaSdpCodec::DecodeFormatList(), Entry ") + + TInt index = 0; + const TDesC8& payloadlist = aMedia.FormatList(); + MCEMM_DEBUG_SVALUE( "decoded format list", payloadlist ) + TLex8 payloads( payloadlist ); + TInt error = KErrNone; + + while( error == KErrNone && !payloads.Eos() && index < KMceMaxPayloadTypes ) + { + TPtrC8 payload = payloads.NextToken(); + TUint convertedUnit = 0; + TLex8 lexConv( payload ); + TInt err = lexConv.Val( convertedUnit, EDecimal ); + if( err != KErrNone ) + { + error = err; + break; + } + error = aPayloadTypes.Append( convertedUnit ); + index++; + } + + MCEMM_DEBUG("CMceMediaSdpCodec::DecodeFormatList(), Exit ") + + return error; + } + +// ----------------------------------------------------------------------------- +// CMceMediaSdpCodec::DecodeRemoteRtcpFieldL +// +// a=rtcp:53020 IN IP4 126.16.64.4 +// ----------------------------------------------------------------------------- +// +void CMceMediaSdpCodec::DecodeRemoteRtcpFieldL( + CSdpMediaField& aMediaLine, + CMceComMediaStream& aStream ) const + { + MCEMM_DEBUG( "CMceMediaSdpCodec::ParseRemoteRtcpFieldL(), Entry" ) + + RStringF rtcpAttributeName = iStringPool.OpenFStringL( KMceSdpAttrRtcp ); + CleanupClosePushL( rtcpAttributeName ); + _LIT8( KMatchIN,"*IN*" ); + _LIT8( KMatchIp,"*IP*" ); + + RPointerArray& attrfields = + aMediaLine.AttributeFields(); + + for ( TInt i = 0; i < attrfields.Count(); i++ ) + { + CSdpAttributeField* attribute = attrfields[i]; + if ( attribute->Attribute() == rtcpAttributeName ) + { + const TDesC8& value = attribute->Value(); + TUint rtcpPort( 0 ); + + if ( value.Match( KMatchIN ) != KErrNotFound ) + { + // found remote IP4 RTCP address + const TUint8 KAddrOffsetFromNetType = 4; + TInt addr_offset = + value.Match( KMatchIp ) + KAddrOffsetFromNetType; + TPtrC8 remoteRtcpAddr = value.Mid( addr_offset ); + + const TUint8 KPortOffsetFromIP = 1; + TInt port_offset = + value.Match( KMatchIN ) - KPortOffsetFromIP; + TPtrC8 remoteRtcpPort = value.Left( port_offset ); + + TLex8 lexPT( remoteRtcpPort ); + User::LeaveIfError( lexPT.Val( rtcpPort, EDecimal ) ); + // copy the address into correct format + TBuf16 input; + input.Copy( remoteRtcpAddr ); + + MCEMM_DEBUG_SVALUE( "Found RTCP address", input ) + + aStream.SetRemoteRtcpMediaAddrL( input ); + } + else + { + // only port present + TLex8 lexPT( value ); + User::LeaveIfError ( lexPT.Val( rtcpPort, EDecimal ) ); + } + + aStream.SetRemoteRtcpMediaPort( rtcpPort ); + + MCEMM_DEBUG_DVALUE( "RTCP Port", rtcpPort ) + } + } + + CleanupStack::PopAndDestroy( &rtcpAttributeName ); + + MCEMM_DEBUG( "CMceMediaSdpCodec::ParseRemoteRtcpFieldL(), Exit" ) + } + +// ----------------------------------------------------------------------------- +// CMceMediaSdpCodec::EncodelocalRtcpAttrL +// +// a=rtcp:53020 IN IP4 126.16.64.4 +// ----------------------------------------------------------------------------- +// +void CMceMediaSdpCodec::EncodelocalRtcpAttrL( + CSdpMediaField& aMediaLine, + CMceComMediaStream& aStream ) const + { + MCEMM_DEBUG("CMceMediaSdpCodec::EncodelocalRtcpAttrL, Entry ") + if ( aStream.Session() && aStream.Session()->UseRtcp() ) + { + MCEMM_DEBUG("RTCP attribute to be added") + TBuf8 rtcpAttrValue; + rtcpAttrValue.Num( aStream.iLocalMediaPort + 1, EDecimal ); + if ( !aStream.Session()->iLocalIpAddress.IsUnspecified() ) + { + CSdpConnectionField* connectionField = + CSdpConnectionField::NewL( aStream.Session()->iLocalIpAddress ); + CleanupStack::PushL( connectionField ); + rtcpAttrValue.Append( KMceSdpSpace ); + rtcpAttrValue.Append( connectionField->NetType().DesC() ); + rtcpAttrValue.Append( KMceSdpSpace ); + rtcpAttrValue.Append( connectionField->AddressType().DesC() ); + rtcpAttrValue.Append( KMceSdpSpace ); + rtcpAttrValue.Append( connectionField->Address() ); + CleanupStack::PopAndDestroy( connectionField ); + } + RStringF attributeRtcp = + SdpCodecStringPool::StringPoolL().OpenFStringL( KMceSdpAttrRtcp ); + CleanupClosePushL( attributeRtcp ); + + CSdpAttributeField* rtcpLine = + CSdpAttributeField::NewLC( attributeRtcp, rtcpAttrValue ); + + MCEMM_DEBUG_SVALUE("encoded rtcpPort", aStream.iLocalMediaPort + 1 ) + + aMediaLine.AttributeFields().AppendL( rtcpLine ); + + CleanupStack::Pop( rtcpLine ); + CleanupStack::PopAndDestroy( ); //attributeRtcp + } + MCEMM_DEBUG("CMceMediaSdpCodec::EncodelocalRtcpAttrL, Exit ") + } + +// ----------------------------------------------------------------------------- +// CMceMediaSdpCodec::CleanAttributes +// ----------------------------------------------------------------------------- +// +void CMceMediaSdpCodec::CleanAttributes( CSdpMediaField& aMedia ) + { + MCEMM_DEBUG("CMceMediaSdpCodec::CleanAttributes(), Entry ") + + //clean attributes + aMedia.AttributeFields().ResetAndDestroy(); + + //clean format attributes + aMedia.FormatAttributeFields().ResetAndDestroy(); + + aMedia.BandwidthFields().ResetAndDestroy(); + + MCEMM_DEBUG("CMceMediaSdpCodec::CleanAttributes(), Exit ") + } + +// ----------------------------------------------------------------------------- +// CMceMediaSdpCodec::DecodeSecureSessionL +// ----------------------------------------------------------------------------- +// +void CMceMediaSdpCodec::DecodeSecureSessionL( + CSdpMediaField& aMediaLine, + CMceComMediaStream& aStream, + TMceNegotiationRole aRole, + TBool aUpdate ) + { + + CMceSecureMediaSession* secureSession = aStream.Session()->SecureSession(); + + if ( aRole == EMceRoleAnswerer && !aUpdate ) + { + aStream.Session()->SecureSessionL().DecodeSecureDesSdpOfferL( aStream, aMediaLine ); + if ( !aStream.Session()->iIsSecureSession ) + { + aStream.Session()->DeleteSecureSession(); + } + } + else if ( secureSession && aRole == EMceRoleAnswerer && aUpdate ) + { + // for long session + if ( secureSession->iKeyNeedUpdated ) + { + secureSession->DecodeSecureDesSdpUpdateL( aStream, aMediaLine ) ; + } + } + else if ( secureSession && aRole == EMceRoleOfferer ) + { + // for Long Session + //sendonly receive only sendandreceive + secureSession->DecodeSecureDesSdpAnswerL( aStream, aMediaLine ) ; + } + } + +// ----------------------------------------------------------------------------- +// CMceMediaSdpCodec::EncodeSecureSessionL +// ----------------------------------------------------------------------------- +// +void CMceMediaSdpCodec::EncodeSecureSessionL( + CMceComMediaStream& aStream, + CSdpMediaField& aMediaLine, + TMceNegotiationRole aRole ) + { + CMceSecureMediaSession* secureSession = aStream.Session()->SecureSession(); + + if ( secureSession ) + { + if ( aRole == EMceRoleOfferer ) + { + secureSession->EncodeSecureDesSdpOfferL( aStream, aMediaLine ); + } + else + { + secureSession->EncodeSecureDesSdpAnswerL( aStream, aMediaLine ); + } + } + } + +// ----------------------------------------------------------------------------- +// CMceMediaSdpCodec::DecodeDirectionL +// ----------------------------------------------------------------------------- +// +void CMceMediaSdpCodec::DecodeDirectionL( CSdpMediaField& aMediaLine, + CMceComMediaStream& aStream, + CSdpDocument& aSdpDocument, + TMceNegotiationRole aRole ) const + { + MCEMM_DEBUG("CMceMediaSdpCodec::DecodeDirectionL(), Entry ") + + TInt rmt_direction = + Direction( aMediaLine, aSdpDocument.AttributeFields() ); + TInt loc_direction = aStream.Direction(); + + CSdpConnectionField* connectionField = aSdpDocument.ConnectionField(); + + CMceSdpSession& sSession = aStream.Session()->SdpSession(); + + CSdpConnectionField* nullAddress = + CSdpConnectionField::DecodeL( KMceSipNullAddressA ); + + CleanupStack::PushL( nullAddress ); + + TUint oldSchool = sSession.iOOldSchool; + TBool isNullAddress = EFalse; + if ( connectionField ) + { + isNullAddress = (connectionField->Address() == nullAddress->Address()); + } + + CleanupStack::PopAndDestroy( nullAddress ); + + //trying to guess other party direction if have got no direction + if ( rmt_direction == KErrNotFound || + ( rmt_direction == SdpCodecStringConstants::EAttributeSendonly && + loc_direction == SdpCodecStringConstants::EAttributeSendonly ) ) + + { + if ( aRole == EMceRoleOfferer ) + { + // did we try old school hold? + if ( oldSchool ) + { + if ( !isNullAddress ) + { + // ignore that other party didn't understand us + // and full cancel of old school process + sSession.iOOldSchool = 0; + sSession.iOOldSchoolProceeding = 0; + sSession.iOOldSchoolCompleted = 0; + } + + rmt_direction = SdpCodecStringConstants::EAttributeRecvonly; + oldSchool = 0; + } + else // didn't try old school yet + { + if ( isNullAddress ) + { + // assuming that other party wanna put us on hold + rmt_direction = SdpCodecStringConstants::EAttributeSendonly; + } + else if ( loc_direction == + SdpCodecStringConstants::EAttributeSendonly && + aStream.Session()->Modifier( KMceMediaDirection ) == + KMceMediaDirectionWithAddress ) + { + // failed to put other party on hold, trying old school + sSession.iOOldSchool = 1; + User::Leave( KMceErrOldSchool ); + } + else + { + // NOP + } + } + } + else // answerer + { + if ( isNullAddress ) + { + // other party puts us on hold + rmt_direction = SdpCodecStringConstants::EAttributeSendonly; + sSession.iIOldSchool = 1; + oldSchool = sSession.iIOldSchool; + } + else + { + rmt_direction = SdpCodecStringConstants::EAttributeSendrecv; + } + } + } + + sSession.iIOldSchool = oldSchool; + + // if unable to determine other party direction then just ignore that + if ( rmt_direction != KErrNotFound ) + { + // now checking for permitted directions + // inverse direction + TInt inv_dir = rmt_direction; + switch (inv_dir) + { + case SdpCodecStringConstants::EAttributeRecvonly: + { + inv_dir=SdpCodecStringConstants::EAttributeSendonly; + break; + } + case SdpCodecStringConstants::EAttributeSendonly: + { + inv_dir=SdpCodecStringConstants::EAttributeRecvonly; + break; + } + default: + { + break; + } + } + + // all directions are permitted for answerer and + // inactive is always accepted + if ( aRole == EMceRoleOfferer && + rmt_direction != SdpCodecStringConstants::EAttributeInactive ) + { + // other party has incompatible direction. terminate session. + if ( loc_direction != SdpCodecStringConstants::EAttributeSendrecv + && + loc_direction != inv_dir ) + { + User::Leave( KErrArgument ); + } + } + + if ( loc_direction != inv_dir ) + { + aStream.SetDirection( rmt_direction, KMceNoEndpointAdjustment ); + } + } + + MCEMM_DEBUG_SVALUE("decoded direction", + SDP_STRING( aStream.Direction() ).DesC() ) + MCEMM_DEBUG("CMceMediaSdpCodec::DecodeDirectionL(), Exit ") + } + +// ----------------------------------------------------------------------------- +// CMceMediaSdpCodec::UpdateDirectionL +// ----------------------------------------------------------------------------- +// + +void CMceMediaSdpCodec::UpdateDirectionL( + CSdpMediaField& aMediaLine, + CMceComMediaStream& aStream, + CSdpDocument& aSdpDocument ) const + { + TInt direction = Direction( aMediaLine, aSdpDocument.AttributeFields() ); + CSdpConnectionField* connectionField = aSdpDocument.ConnectionField(); + if ( connectionField == NULL ) + { + connectionField = ( aMediaLine.ConnectionFields()[0] ) ; + } + + if ( connectionField->Address() == KMceSipNullAddress ) + { + direction = SdpCodecStringConstants::EAttributeSendonly; + } + UpdateStreamL( aStream, direction ); + aStream.SetDirection( direction, KMceNoEndpointAdjustment ); + } + +// ----------------------------------------------------------------------------- +// CMceMediaSdpCodec::EncodeDirectionL +// ----------------------------------------------------------------------------- +// +void CMceMediaSdpCodec::EncodeDirectionL( + CMceComMediaStream& aStream, + CSdpMediaField& aMedia, + CSdpDocument& aSdpDocument, + TMceNegotiationRole aRole ) const + { + MCEMM_DEBUG("CMceMediaSdpCodec::EncodeDirectionL(), Entry ") + + CMceSdpSession& sSession = aStream.Session()->SdpSession(); + + if ( aRole == EMceRoleOfferer && + sSession.iOOldSchool && + aStream.Direction() != SdpCodecStringConstants::EAttributeSendrecv ) + + { + CSdpConnectionField* connField = + CSdpConnectionField::DecodeL( KMceSipNullAddressA ); + aSdpDocument.SetConnectionField( connField ); + MCEMM_DEBUG("using old school") + } + + else + { + RStringF direction = SDP_STRING( aStream.Direction() ); + + CSdpAttributeField* mediaAttr = + CSdpAttributeField::NewLC( direction, KNullDesC8 ); + + MCEMM_DEBUG_SVALUE("encoded direction", mediaAttr->Attribute().DesC() ) + + aMedia.AttributeFields().AppendL( mediaAttr ); + CleanupStack::Pop( mediaAttr ); + } + + MCEMM_DEBUG("CMceMediaSdpCodec::EncodeDirectionL(), Exit ") + } + +// ----------------------------------------------------------------------------- +// CMceMediaSdpCodec::EncodePreconditionsL +// ----------------------------------------------------------------------------- +// +void CMceMediaSdpCodec::EncodePreconditionsL( + CMceComMediaStream& aStream, + CSdpMediaField& aMediaLine, + TMceNegotiationRole aRole ) const + { + CMceSecureMediaSession* secureSession = aStream.Session()->SecureSession(); + + if ( aStream.Session()->Modifier( KMcePreconditions ) == KMcePreconditionsSupported && + !secureSession) + { + if ( ( aRole == EMceRoleOfferer && + aStream.Session()->iUseLocalPreconditions ) || + ( aRole == EMceRoleAnswerer && + aStream.Session()->iUseRemotePreconditions ) ) + { + TMcePreconditions* precondition = aStream.PreconditionsL( KMcePreconditions ); + if ( precondition ) + { + precondition->EncodeL( aMediaLine ); + } + } + } + if ( aStream.Session()->Modifier( KMceSecPreconditions ) == KMcePreconditionsE2ESupported ) + { + TMcePreconditions* precondition = aStream.PreconditionsL( KMceSecPreconditions ); + if ( precondition ) + { + precondition->EncodeL( aMediaLine ); + } + } + } + +// ----------------------------------------------------------------------------- +// CMceMediaSdpCodec::DecodePreconditionsL +// ----------------------------------------------------------------------------- +// +TMceSipWarningCode CMceMediaSdpCodec::DecodePreconditionsL( + CSdpMediaField& aMediaLine, + CMceComMediaStream& aStream, + TMceNegotiationRole aRole ) const + { + MCEMM_DEBUG("CMceMediaSdpCodec::DecodePreconditionsL EntryL") + TMceSipWarningCode warning = KErrNone; + + if ( aStream.Session()->Modifier( KMcePreconditions ) == KMcePreconditionsSupported ) + { + if ( ( aRole == EMceRoleOfferer && + aStream.Session()->iUseLocalPreconditions ) || + ( aRole == EMceRoleAnswerer && + aStream.Session()->iUseRemotePreconditions ) ) + { + aStream.PreconditionsL( KMcePreconditions )->DecodeL( aMediaLine ); + + } + } + if ((aRole == EMceRoleOfferer && + aStream.Session()->iClientCryptoSuites.Count() + && aStream.Session()->Modifier( KMceSecPreconditions ) + == KMcePreconditionsE2ESupported ) + || ( aRole ==EMceRoleAnswerer && ( + aStream.Session()->iRemoteSecPreconditionsRequired || + aStream.Session()->iClientCryptoSuites.Count() ))) + + { + TMcePreconditions* precondition = + aStream.PreconditionsL( KMceSecPreconditions, &aMediaLine ); + + if ( !precondition ) + { + return KErrNone; + } + if ( warning && aStream.Preconditions().Count() ) + { + //normal segmented precondition cases + aStream.Session()->iRemoteSecPreconditionsRequired = EFalse; + aStream.Session()->Modifier( KMceSecPreconditions ) = + KMcePreconditionsNotUsed; + MCEMM_DEBUG("Secure preconds not used") + MCEMM_DEBUG("CMceMediaSdpCodec::DecodePreconditionsL Exit") + return KErrNone; + } + + if ( !precondition->IsMet() ) + { + MCEMM_DEBUG("Decode Secure Precondition") + warning = precondition->DecodeL( aMediaLine ); + } + warning = warning == KMceSipPreconditionFailure ? + warning : KErrNone; + MCEMM_DEBUG_DVALUE ("Decode Secure Precondition warning", warning ) + } + MCEMM_DEBUG("CMceMediaSdpCodec::DecodePreconditionsL Exit") + return warning; + } + +// ----------------------------------------------------------------------------- +// CMceMediaSdpCodec::EncodeClientAttributesL +// ----------------------------------------------------------------------------- +// +void CMceMediaSdpCodec::EncodeClientAttributesL( + CMceComMediaStream& aStream, + CSdpMediaField& aMediaLine ) const + { + MCEMM_DEBUG("CMceMediaSdpCodec::EncodeClientAttributesL, Entry" ) + + CDesC8Array* clientAttributes = aStream.iLocalMediaSDPLines; + __ASSERT_ALWAYS( clientAttributes, User::Leave( KErrArgument ) ); + + CMceSdpCodec::EncodeClientSdpFieldsL( *clientAttributes, aMediaLine ); + + + MCEMM_DEBUG("CMceMediaSdpCodec::EncodeClientAttributesL, Exit" ) + } + +// ----------------------------------------------------------------------------- +// CMceMediaSdpCodec::DecodeClientAttributesL +// ----------------------------------------------------------------------------- +// +void CMceMediaSdpCodec::DecodeClientAttributesL( + CSdpMediaField& aMediaLine, + CMceComMediaStream& aStream ) const + { + MCEMM_DEBUG("CMceMediaSdpCodec::DecodeClientAttributesL, Entry" ) + CDesC8Array* remoteAttributes = + new (ELeave) CDesC8ArrayFlat( KMceArrayGranularity ); + CleanupStack::PushL( remoteAttributes ); + CBufFlat* encodeBuf = NULL; + + for ( TInt i = 0; i < aMediaLine.AttributeFields().Count(); i++ ) + { + encodeBuf = CBufFlat::NewL( KMceExternalizeBufferExpandSize ); + CleanupStack::PushL( encodeBuf ); + RBufWriteStream writeStream( *encodeBuf, 0 ); + writeStream.PushL(); + + aMediaLine.AttributeFields()[ i ]->EncodeL( writeStream ); + MCEMM_DEBUG_SVALUE( "found attribute", encodeBuf->Ptr( 0 ) ) + remoteAttributes->AppendL( encodeBuf->Ptr( 0 ) ); + + CleanupStack::PopAndDestroy(); // writeStream + CleanupStack::PopAndDestroy( encodeBuf ); // encodeBuf + } + + for ( TInt i = 0; i < aMediaLine.BandwidthFields().Count(); i++ ) + { + + encodeBuf = CBufFlat::NewL( KMceExternalizeBufferExpandSize ); + CleanupStack::PushL( encodeBuf ); + RBufWriteStream writeStream( *encodeBuf, 0 ); + writeStream.PushL(); + + aMediaLine.BandwidthFields()[ i ]->EncodeL( writeStream ); + MCEMM_DEBUG_SVALUE("found attribute", encodeBuf->Ptr( 0 ) ) + remoteAttributes->AppendL( encodeBuf->Ptr( 0 ) ); + + CleanupStack::PopAndDestroy(); // writeStream + CleanupStack::PopAndDestroy( encodeBuf ); // encodeBuf + } + + if ( aStream.BoundStream() ) + { + MCEMM_DEBUG("copy attributes to bound stream" ) + // copy attributes to bound stream + CMceComMediaStream& boundStream = aStream.BoundStreamL(); + CDesC8Array* copyAttributes = + new (ELeave) CDesC8ArrayFlat( KMceArrayGranularity ); + CleanupStack::PushL( copyAttributes ); + for ( TInt i = 0; i < remoteAttributes->MdcaCount(); i++ ) + { + copyAttributes->AppendL( remoteAttributes->MdcaPoint( i ) ); + } + CleanupStack::Pop( copyAttributes ); + MCE_DELETE( boundStream.iRemoteMediaSDPLines ); + boundStream.iRemoteMediaSDPLines = copyAttributes; + } + + CleanupStack::Pop( remoteAttributes ); + MCE_DELETE( aStream.iRemoteMediaSDPLines ); + aStream.iRemoteMediaSDPLines = remoteAttributes; + MCEMM_DEBUG("CMceMediaSdpCodec::DecodeClientAttributesL, Exit" ) + } + +// ----------------------------------------------------------------------------- +// CMceMediaSdpCodec::ValidateSdp +// ----------------------------------------------------------------------------- +// +TMceSipWarningCode CMceMediaSdpCodec::ValidateSdpL( + CSdpMediaField& aMediaLine, + CSdpDocument& /*aSdpDocument*/ ) + { + TMceSipWarningCode warning = KErrNone; + RArray payloadTypes; + TInt error = KErrNone; + RPointerArray< CSdpFmtAttributeField >& formatLines = + aMediaLine.FormatAttributeFields(); + + TInt dynamicPayloadsCount = 0; + TInt rtpmapCount = 0; + + error = DecodeFormatList( aMediaLine, payloadTypes ); + + User::LeaveIfError( error ); + + if ( error == KErrNone ) + { + TInt index = 0; + while( index < payloadTypes.Count() ) + { + dynamicPayloadsCount = payloadTypes[ index++ ] >= KMinDynamicPT ? + dynamicPayloadsCount + 1 : dynamicPayloadsCount; + } + index = 0; + while( index < formatLines.Count() ) + { + rtpmapCount = formatLines[ index++ ]->Attribute() == + SDP_STRING( SdpCodecStringConstants::EAttributeRtpmap ) ? + rtpmapCount + 1 : rtpmapCount; + } + + if ( dynamicPayloadsCount > 0 && rtpmapCount == 0 ) + { + warning = KMceSipBadRequest; + } + } + else + { + warning = KMceSipServerInternalError; + } + + payloadTypes.Close(); + + return warning; + } + +// ----------------------------------------------------------------------------- +// CMceMediaSdpCodec::DecodePayloadsL +// ----------------------------------------------------------------------------- +// +TInt CMceMediaSdpCodec::DecodePayloadsL( + CSdpMediaField& aMediaLine, + CMceComMediaStream& aStream, + TMceNegotiationRole aRole ) const + { + TInt decoded( 0 ); + + RArray payloadTypes; + CleanupClosePushL( payloadTypes ); + + if ( aRole == EMceRoleAnswerer ) + { + decoded = DecodeRtpmapLinesL( aMediaLine, aStream, EMceRoleAnswerer ); + decoded += DecodeStaticPayloadsL( aMediaLine, aStream, payloadTypes, EMceRoleAnswerer ); + } + else + { + // static payloads are decoded first if role is offerer + decoded = DecodeStaticPayloadsL( aMediaLine, aStream, payloadTypes, EMceRoleOfferer ); + decoded += DecodeRtpmapLinesL( aMediaLine, aStream, EMceRoleOfferer ); + } + + UpdateSdpCodecIndexesL( aStream, payloadTypes ); + CleanupStack::PopAndDestroy( &payloadTypes ); + + return decoded; + } + +// ----------------------------------------------------------------------------- +// CMceMediaSdpCodec::UpdateSdpCodecIndexesL +// ----------------------------------------------------------------------------- +// +void CMceMediaSdpCodec::UpdateSdpCodecIndexesL( + CMceComMediaStream& aStream, + RArray& aPayloadTypes ) const + { + TInt index( 0 ); + TInt codecSdpIndex( 0 ); + while( index < aPayloadTypes.Count() ) + { + TUint payload = aPayloadTypes[ index++ ]; + CMceComCodec* codec = FindCodec( payload, aStream ); + if ( codec ) + { + codec->iCodecSdpIndex = codecSdpIndex++; + } + } + } + +// ----------------------------------------------------------------------------- +// CMceMediaSdpCodec::GetCorrespondingFmtpLineL +// ----------------------------------------------------------------------------- +// +TPtrC8 CMceMediaSdpCodec::GetCorrespondingFmtpLineL( + CSdpMediaField& aMediaLine, + CSdpFmtAttributeField& aRtpMapFormatLine ) const + { + const TDesC8& payloadTypeInRtpMap = aRtpMapFormatLine.Format(); + TUint rtpMapPT = ConvertDesToUintL( payloadTypeInRtpMap ); + + RPointerArray< CSdpFmtAttributeField >& formatLines = + aMediaLine.FormatAttributeFields(); + + TPtrC8 fmtp( KNullDesC8() ); + TBool found( EFalse ); + for ( TInt j = 0; j < formatLines.Count() && !found; j++ ) + { + CSdpFmtAttributeField* formatLine = formatLines[ j ]; + if ( formatLine->Attribute() == + SDP_STRING( SdpCodecStringConstants::EAttributeFmtp ) ) + { + TUint fmtpPT = ConvertDesToUintL( formatLine->Format() ); + if ( rtpMapPT == fmtpPT ) + { + fmtp.Set( formatLine->Value() ); + found = ETrue; + } + } + } + return fmtp; + } + +// End of file