Example Showing the use of the SDP Codec API

The following sections explain how to create an SDP description with the required fields.

Creating an SDP description

  1. Open the String Pool

  2. Access the predefined SDP constants in the string table

  3. Close the String Pool after you finish with the SDP description

SdpCodecStringPool::OpenL();
RStringPool pool = SdpCodecStringPool::StringPoolL();

Creating a CSdpDocument object

The following code snippet shows how to create the CSdpDocument object. This includes all SDP fields in the structural format:

CSdpDocument* sdpDocument = CSdpDocument::NewLC();

Defining the session name field for the SDP description

The following code snippet shows how to define the session name field for the SDP description:

sdpDocument->SetSessionNameL(_L8("SipSession"));

Creating an instance of the Origin field class

The following code snippet shows how to create an instance of the Origin field class and set into the SDP description:

TInt64 sessionId( TUint( 2890844526 ) );
TInt64 sessionVersion( TUint( 2890842807 ) );
TInetAddr address;
const TUint32 KInetAddr = INET_ADDR(10,47,16,5);
address.SetAddress( KInetAddr );
CSdpOriginField* originfield =  CSdpOriginField::NewL(_L8("username"), sessionId, sessionversion, address);
sdpDocument->SetOriginField(originfield);

Fetching the network type and the address type

The following code snippet shows how to fetch the predefined network type and the address type for the connection field from the String Pool:

RStringF netType = pool.StringF( SdpCodecStringConstants::ENetType, SdpCodecStringConstants::Table );RStringF addressTypeIP4 = pool.StringF( SdpCodecStringConstants::EAddressTypeIP4, SdpCodecStringConstants::Table );

Creating and setting the connection field into the sdpDocument

The following code snippet shows how to create the connection field and set the SDP parameters of the SIP message into the SDP description:

_LIT8( KAddress, "10.47.16.5" );
CSdpConnectionField* connectionfield = CSdpConnectionField::NewL( netType, addressTypeIP4, KAddress );
sdpDocument->SetConnectionField(connectionfield);

Defining the session part attribute and direction-attribute

The following code snippet shows how to define the session part attribute for the SDP description. The direction-attribute is not one of the predefined attributes in the string table, it must be defined dynamically to the String Pool.

_LIT8(KSDPAttributeDirectionBoth,"both");
RStringF modifier = pool.OpenFStringL(_L8("direction"));
CleanupClosePushL(modifier);
CSdpAttributeField* attrField = CSdpAttributeField::NewL(modifier, KSDPAttributeDirectionBoth);
User::LeaveIfError((sdpDocument->AttributeFields()).Append(attrField));
CleanupStack::PopAndDestroy();

Creating the first media field

The following code snippet shows how to create the first media field:

RStringF mediaVideo = pool.StringF( SdpCodecStringConstants::EMediaVideo, SdpCodecStringPool::StringTableL());
RStringF protocol = pool.StringF(SdpCodecStringConstants::EProtocolRtpAvp, SdpCodecStringPool::StringTableL());
CSdpMediaField* media1 = CSdpMediaField::NewLC(mediaVideo, 49152, protocol, _L8("96"));

Add the sendonly attribute (“a=sendonly”) to the first media field:

RStringF sendonlyAttr = iPool.StringF( SdpCodecStringConstants:: EAttributeSendonly, SdpCodecStringPool::StringTableL() );
CSdpAttributeField* attr1 = CSdpAttributeField::NewLC(sendonlyAttr, _L8(""));
User::LeaveIfError((media1->AttributeFields()).Append(attr1));
CleanupStack::Pop(); //attr1

Add the rtpmap attribute (“a=rtpmap:96 H263-2000/90000”) to the first media field and then add the rtpmap specific attribute (“a=ptime:15”):

_LIT8( KEncodingName, "H263-2000" );
_LIT8( KClockRate, "90000" );
_LIT8( KEncodingParam, "" );
TSdpRtpmapValue rtpmapValue( KEncodingName(), KClockRate(), KEncodingParam() );
HBufC8* rtpmapBuf = rtpmapValue.EncodeL();
CleanupStack::PushL(rtpmapBuf);
RStringF rtpmapStr = pool.StringF( SdpCodecStringConstants::EAttributeRtpmap, SdpCodecStringPool::StringTableL() );
CSdpFmtAttributeField* rtpmapAttribute = CSdpFmtAttributeField::NewLC(rtpmapStr, _L8("96"), *rtpmapBuf);
User::LeaveIfError(media1->FormatAttributeFields().Append (rtpmapAttribute));
CleanupStack::Pop(); // rtpmapAttribute
CleanupStack::PopAndDestroy(); // rtpmapBuf
// add a rtpmap specific attribute
RStringF ptimeAttrStr = iPool.StringF( SdpCodecStringConstants:: EAttributePtime, SdpCodecStringPool::StringTableL() );
CSdpAttributeField* ptimeAttr = CSdpAttributeField::NewLC(ptimeAttrStr, _L8("15"));
ptimeAttr->AssignTo(*(media1->FormatAttributeFields())[0]);
User::LeaveIfError(media1->AttributeFields().Append(ptimeAttr));
CleanupStack::Pop(); //ptimeAttr

Creating the second media field

The following code snippet shows how to create the second media field:

RStringF mediaAudio = pool.StringF( SdpCodecStringConstants:: EMediaAudio, SdpCodecStringPool::StringTableL());
CSdpMediaField* media2 = CSdpMediaField::NewLC(mediaAudio, 57344, protocol, _L8("97"));

Create the sendonly attribute for the second media field:

CSdpAttributeField* attr2 = CSdpAttributeField::NewLC(sendonlyAttr, 
_L8(""));
User::LeaveIfError((media2->AttributeFields()).Append(attr2));
CleanupStack::Pop();

Create the rtpmap attribute (“a=rtpmap:97 AMR/8000”) for the second media field:

_LIT8( KEncodingName1, "AMR" );
_LIT8( KClockRate1, "8000" );
TSdpRtpmapValue rtpmapValue1( KEncodingName1(), KClockRate1(), KEncodingParam() );
HBufC8* rtpmapBuf1 = rtpmapValue1.EncodeL();
CleanupStack::PushL(rtpmapBuf1);
CSdpFmtAttributeField* rtpmapAttribute1 = CSdpFmtAttributeField::NewLC(rtpmapStr, _L8("97"), *rtpmapBuf1);
User::LeaveIfError(media2->FormatAttributeFields().Append (rtpmapAttribute1));
CleanupStack::Pop(); // rtpmapAttribute1
CleanupStack::PopAndDestroy(); //rtpmapBuf1

Assigning the media fields to the CSdpDocument object

The following code snippet shows how to assign the media fields to the CSdpDocument object and then remove the buffers from the cleanup stack:

User::LeaveIfError(doc->MediaFields().Append(media1));
User::LeaveIfError(doc->MediaFields().Append(media2));
CleanupStack::Pop(); //media2
CleanupStack::Pop(); //media1

Deleting the sdpDocument and closing the SdpCodecStringPool

To close the String Pool the CSdpDocument object must be removed and deleted from the cleanup stack. The following code snippet shows how to remove and delete the CSdpDocument object from the cleanup stack and close the String Pool:

CleanupStack::PopAndDestroy(); //sdpDocument
SdpCodecStringPool::Close();

The SDP description created in the preceding example has the following fields:

v=0
o=username 2890844526 2890842807 IN IP4 10.47.16.5
s=SipSession
c=IN IP4 10.47.16.5
t=0 0
a=direction:both
m=video 49152 RTP/AVP 96
a=sendonly
a=rtpmap:96 H263-2000/90000
m=audio 57344 RTP/AVP 97
a=sendonly
a=rtpmap:97 AMR/8000