rtp/rtpstack/src/rtppacket.cpp
changeset 0 307788aac0a8
child 19 b5e99d8877c7
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/rtp/rtpstack/src/rtppacket.cpp	Tue Feb 02 01:03:15 2010 +0200
@@ -0,0 +1,1308 @@
+/*
+* Copyright (c) 2002-2003 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 <e32base.h>
+#include <e32std.h>
+
+#include "rtputil.h"
+#include "rtpsdes.h"
+#include "rtppacket.h"
+#include "rtpmanager.h"
+
+// CONSTANTS
+const TInt KRtpVersion = 2;    // Current protocol version          
+const TUint8 KNullTerm( '\0' );
+const TUint KMinRtpHeaderLen( 12 );
+const TUint KMinRtcpAppLen( 3 );
+
+const TInt KCSRCListMax = 15;
+
+// ================= MEMBER FUNCTIONS =======================
+
+// ---------------------------------------------------------------------------
+// C++ default constructor can NOT contain any code, that
+// might leave.
+// ---------------------------------------------------------------------------
+//
+CRtpPacket::CRtpPacket( const TUint32* aRtpTimeRates ) :
+    iSize( 0 ),
+    iProfileRTPTimeRates( aRtpTimeRates )
+    {
+    }
+
+// ---------------------------------------------------------------------------
+// Symbian 2nd phase constructor can leave.
+// ---------------------------------------------------------------------------
+//
+void CRtpPacket::ConstructL( TUint aPacketSize )
+    {
+    iBuf = HBufC8::NewL( aPacketSize );
+    iData = const_cast<TUint8*>( iBuf->Des().Ptr() );
+    iDataPtr = iData;
+    iExdataAlloc =EFalse;
+	iCsrcAlloc= EFalse;
+    }
+
+// ---------------------------------------------------------------------------
+// Two-phased constructor.
+// ---------------------------------------------------------------------------
+//
+CRtpPacket* CRtpPacket::NewL( TUint aPacketSize, const TUint32* aRtpTimeRates )
+    {
+    CRtpPacket* self = new ( ELeave ) CRtpPacket( aRtpTimeRates );
+    CleanupStack::PushL( self );
+    self->ConstructL( aPacketSize );
+    CleanupStack::Pop(); //self
+    return self;
+    }
+
+// ---------------------------------------------------------------------------
+// Destructor
+// ---------------------------------------------------------------------------
+//
+CRtpPacket::~CRtpPacket()
+    {
+    delete iBuf; iBuf = NULL;
+    }
+
+// ---------------------------------------------------------------------------
+// 
+// 
+// ---------------------------------------------------------------------------
+//
+void CRtpPacket::RtpPacketReset()
+    {
+    iSize = 0;
+    iDataPtr = iData;
+    }
+
+// ---------------------------------------------------------------------------
+// CRtpPacket::RtpPacketResetPtr()
+// 
+// ---------------------------------------------------------------------------
+//
+void CRtpPacket::RtpPacketResetPtr()
+    {
+    iDataPtr = iData;
+    }
+
+// ---------------------------------------------------------------------------
+// CRtpPacket::RtpPacketBuildRtp()
+// 
+// ---------------------------------------------------------------------------
+//
+TInt CRtpPacket::RtpPacketBuildRtp( TRtpPacketStreamParam* aStreamParam, 
+                                    TRtpPacketIOParam* aInitParam )
+    {
+    //Get a pointer to the beginning of iBuf
+    TUint8* dataP = iData;
+    
+    //Fill dataP with binary zeroes (i.e. 0x00), replacing any existing content
+    Mem::FillZ( dataP, KMinRtpHeaderLen );
+
+    /****************************
+     * dataP[0] = 8 bit         *
+     *                          *
+     *    2 bit = version       *
+     *    1 bit = padding       *
+     *    1 bit = CRSRC Count   *
+     *    4 bit = extension     *
+     ****************************/
+    
+    //version (2 bit)
+    // 0111001
+    // 1100000
+    // -------
+    // 1111001
+    dataP[0] |= ( KRtpVersion << 6 );
+
+    // padding (1 bit)
+    dataP[0] |= static_cast<TUint8>( ( aInitParam->TRTP.padding << 5 ) );
+
+    // header extension (1 bit)
+    if ( aInitParam->TRTP.fHeaderExtension)
+        {
+        dataP[0] |= ( 1 << 4 );
+        }
+
+    // CC = 0 (1 bit)
+    
+    /****************************
+     * dataP[1] = 8 bit         *
+     *                          *
+     *    1 bit = marker        *
+     *    1 bit = payload type  *
+     ****************************/
+    
+    // marker (1 bit)
+    dataP[1] |= static_cast<TUint8>( aInitParam->TRTP.marker << 7 );
+
+    // payload type (7 bit)
+    // confirm that payload can fit the 7 bit (0 - 127)
+    if(aStreamParam->TRTP.payload > KPayloadTypeMax )
+    	{
+    	return KErrTooBig;
+    	}
+        
+    
+    dataP[1] |= aStreamParam->TRTP.payload;
+    
+    //set the pointer to point at the beginning of the sequence number.
+    dataP += 2;
+    // sequence number (16 bit)
+    Write16( dataP, aStreamParam->TRTP.seqNum );
+    
+    //set the pointer to point at the beginning of the time stamp.
+    dataP += 2; 
+    // RTP timestamp (32 bit)
+    Write32( dataP, aStreamParam->TRTP.timeStamp );
+    
+    //set the pointer to point at the beginning of SSRC.
+    dataP += 4;
+    // SSRC (32 bit)
+    Write32( dataP, aStreamParam->TRTP.SSRC );
+
+    //set the pointer to point to the first bit after SSRC
+    dataP += 4;
+
+    if ( aInitParam->TRTP.fHeaderExtension )
+        {
+	    
+	    //calculate 8 bit values to 32 bit words
+	    TInt16 length32 =
+            static_cast<TInt16>( aInitParam->TRTP.extension.length / 4 );
+        
+        //if length mod 4 != 0, 
+        if ( aInitParam->TRTP.extension.length % 4 )
+	        {
+    		length32++;
+    		}
+
+	    // header extension type defined by profile
+        // aInitParam->TRTP.extension.type is 32-bit and part of the API
+        // (i.e. unchangeable), so we have to extract the 16-LSB
+	    Write16( dataP, aInitParam->TRTP.extension.type & 0xFFFF );
+	    dataP += 2;
+
+	    // header extension length in number of 32-bit words
+	    Write16( dataP, length32 );
+	    dataP += 2;
+
+	    // header extension data
+	    if (length32 && aInitParam->TRTP.extension.data )
+		    {
+		    Mem::FillZ( dataP, length32 * 4 );
+		    for ( TInt i = 0; i < aInitParam->TRTP.extension.length; i++ )
+		        {
+	    		dataP[i] = aInitParam->TRTP.extension.data[i];
+	    		}
+		    dataP += ( length32 * 4 );	
+		    }
+	    }
+    
+    //Copy(Target, Source, Length)
+    Mem::Copy( dataP, aInitParam->TRTP.payloadData,
+               aInitParam->TRTP.payloadDataLen );
+    iSize = aInitParam->TRTP.payloadDataLen + ( dataP - iData );
+    return KErrNone;
+
+    }
+
+// ---------------------------------------------------------------------------
+// TInt CRtpPacket::RtpPacketBuildRtcp()
+// 
+// ---------------------------------------------------------------------------
+//
+TInt CRtpPacket::RtpPacketBuildRtcp( TRtpPacketStreamParam* aStreamParam, 
+                                     TRtpPacketIOParam* aInitParam )
+    {
+    Mem::FillZ( iDataPtr, 4 );
+
+    // version
+    iDataPtr[0] |= ( KRtpVersion << 6 );
+
+    // padding = 0
+    iDataPtr[0] |= ( 0 << 5 );
+
+    // source count
+    iDataPtr[0] |= static_cast<TUint8>( aInitParam->TRTCP_HEADER.sourceCount );
+
+    // packet type
+    iDataPtr[1] = static_cast<TUint8>( aInitParam->TRTCP_HEADER.pt );
+    iDataPtr += 2;
+
+    // length of RTCP packet
+    // aInitParam->TRTCP_HEADER.length is 32-bit and part of the API
+    // (i.e. unchangeable), so we have to extract the 16-LSB
+    Write16( iDataPtr, aInitParam->TRTCP_HEADER.length & 0xFFFF );
+    iDataPtr += 2;
+
+    // SSRC of sender in case of RR
+    if ( aInitParam->TRTCP_HEADER.pt == ERTCP_RR )
+        {
+	    Write32( iDataPtr, aStreamParam->TRTCP_HEADER.SSRC );
+	    iDataPtr += 4;
+	    }
+
+    iSize += ( aInitParam->TRTCP_HEADER.length + 1 ) * 4;
+
+    return KErrNone;
+    }
+        
+// ---------------------------------------------------------------------------
+// TInt CRtpPacket::RtpPacketBuildApp()
+// 
+// ---------------------------------------------------------------------------
+//
+TInt CRtpPacket::RtpPacketBuildApp( TRtpPacketStreamParam* aStreamParam, 
+                                    TRtpPacketIOParam* aInitParam )
+    {
+    // SSRC
+    Write32( iDataPtr, aStreamParam->TRTCP_APP.SSRC );
+    iDataPtr += 4;
+
+    // name
+    Mem::Copy( iDataPtr, aInitParam->TRTCP_APP.name, 4 );
+    iDataPtr += 4;
+
+    // application data
+    Mem::Copy( iDataPtr, aInitParam->TRTCP_APP.appData,
+               aInitParam->TRTCP_APP.appDataLen );
+
+    iDataPtr += aInitParam->TRTCP_APP.appDataLen;
+
+    return KErrNone;
+    }
+
+// ---------------------------------------------------------------------------
+// TInt CRtpPacket::RtpPacketBuildBye()
+// 
+// ---------------------------------------------------------------------------
+//
+TInt CRtpPacket::RtpPacketBuildBye( TRtpPacketStreamParam* aStreamParam, 
+                                    TRtpPacketIOParam* aInitParam )
+    {
+    TUint8 theIndex( 0 );
+    // SSRC
+    Write32( iDataPtr, aStreamParam->TRTCP_BYE.SSRC );
+    iDataPtr += 4;
+
+    // reason
+    iDataPtr[0] = static_cast<TUint8>( aInitParam->TRTCP_BYE.reasonSize );
+    iDataPtr += 1;
+
+    Mem::Copy( iDataPtr, aInitParam->TRTCP_BYE.reason,
+               aInitParam->TRTCP_BYE.reasonSize );
+
+    iDataPtr += aInitParam->TRTCP_BYE.reasonSize;
+
+    // padding
+    if ( aInitParam->TRTCP_BYE.paddingSize != 0 )
+        {
+	    for ( theIndex = 0; theIndex < aInitParam->TRTCP_BYE.paddingSize;
+              theIndex++ )
+	        {
+    		iDataPtr[theIndex] = KNullTerm;
+    		}
+
+	    iDataPtr += aInitParam->TRTCP_BYE.paddingSize;
+	    }
+
+    return KErrNone;
+    }
+
+// ---------------------------------------------------------------------------
+// TInt CRtpPacket::RtpPacketBuildRr()
+// 
+// ---------------------------------------------------------------------------
+//
+TInt CRtpPacket::RtpPacketBuildRr( TRtpPacketStreamParam* aStreamParam, 
+                                   TRtpPacketIOParam* aInitParam )
+    {
+    // SSRC
+    Write32( iDataPtr, aStreamParam->TRTCP_RR.SSRC );
+    iDataPtr += 4;
+
+    // fraction lost
+    iDataPtr[0] = aStreamParam->TRTCP_RR.fractionLost;
+    iDataPtr++;
+
+    // cumulative number of packets lost
+    Write24( iDataPtr, aStreamParam->TRTCP_RR.cumNumPacketsLost );
+    iDataPtr += 3;
+
+    // extended highest sequence number received
+    Write32( iDataPtr, aStreamParam->TRTCP_RR.seqNumReceived );
+    iDataPtr += 4;
+
+    // interarrival jitter
+    Write32( iDataPtr, aStreamParam->TRTCP_RR.arrivalJitter );
+    iDataPtr += 4;
+
+    // last SR timestamp
+    Write32( iDataPtr, aInitParam->TRTCP_RR.lastSRTimeStamp );
+    iDataPtr += 4;
+
+    // delay since last SR timestamp
+    Write32( iDataPtr, aInitParam->TRTCP_RR.delaySinceLSR );
+    iDataPtr += 4;
+
+    return KErrNone;
+    }
+
+// ---------------------------------------------------------------------------
+// TInt CRtpPacket::RtpPacketBuildSr()
+// 
+// ---------------------------------------------------------------------------
+//
+TInt CRtpPacket::RtpPacketBuildSr( TRtpPacketStreamParam* aStreamParam, 
+                                   TRtpPacketIOParam* aInitParam )
+    {
+    // SSRC
+    Write32( iDataPtr, aStreamParam->TRTCP_SR.SSRC );
+    iDataPtr += 4;
+
+    // NTP timestamp (seconds)
+    Write32( iDataPtr, aInitParam->TRTCP_SR.NTPTimeStampSec );
+    iDataPtr += 4;
+
+    // NTP timestamp (fraction)
+    Write32( iDataPtr, aInitParam->TRTCP_SR.NTPTimeStampFrac );
+    iDataPtr += 4;
+
+    // RTP timestamp
+    Write32( iDataPtr, aInitParam->TRTCP_SR.timeStamp );
+    iDataPtr += 4;
+
+    // sender's packet count
+    Write32( iDataPtr, aStreamParam->TRTCP_SR.numPacketsSent );
+    iDataPtr += 4;
+
+    // sender's octet count
+    Write32( iDataPtr, aStreamParam->TRTCP_SR.cumNumOctetsSent );
+    iDataPtr += 4;
+
+    return KErrNone;
+    }
+
+// ---------------------------------------------------------------------------
+// TInt CRtpPacket::RtpPacketBuildSdes()
+// 
+// ---------------------------------------------------------------------------
+//
+TInt CRtpPacket::RtpPacketBuildSdes( TRtpPacketStreamParam* aStreamParam, 
+                                     TRtpPacketIOParam* aInitParam )
+    {
+    TUint8 theIndex( 0 );
+
+    // SSRC
+    Write32( iDataPtr, aStreamParam->TRTCP_SDES.SSRC );
+    iDataPtr += 4;
+
+    // SDES items
+    for ( theIndex = 0; theIndex < ERTCP_NUM_OF_SDES_ITEMS; theIndex++ )
+        {
+        if ( aInitParam->TRTCP_SDES.sdesItemsSize[theIndex] != 0 )
+            {
+
+            iDataPtr[0] = static_cast<TUint8>( theIndex + 1 );
+            iDataPtr[1] = static_cast<TUint8>(
+                              aInitParam->TRTCP_SDES.sdesItemsSize[theIndex] );
+            iDataPtr += 2;
+
+            Mem::Copy( iDataPtr,
+            		 aInitParam->TRTCP_SDES.sdesItems[theIndex],
+            		 aInitParam->TRTCP_SDES.sdesItemsSize[theIndex] );
+
+            iDataPtr += aInitParam->TRTCP_SDES.sdesItemsSize[theIndex];
+            }
+        }
+
+    // include end of list null octet
+    iDataPtr[0] = KNullTerm;
+    iDataPtr++;
+
+    // padding
+    if ( aInitParam->TRTCP_SDES.paddingSize != 0 )
+        {
+	    for ( theIndex = 0; theIndex < aInitParam->TRTCP_SDES.paddingSize;
+              theIndex++ )
+	        {
+    		iDataPtr[theIndex] = KNullTerm;
+    		}
+
+	    iDataPtr += aInitParam->TRTCP_SDES.paddingSize;
+	    }
+
+    return KErrNone;
+    }
+
+// ---------------------------------------------------------------------------
+// TInt CRtpPacket::RtpPacketBuild()
+// 
+// ---------------------------------------------------------------------------
+//
+TInt CRtpPacket::RtpPacketBuild( TRtpPacketStreamParam* aStreamParam, 
+                                 TRtpPacketIOParam* aInitParam )
+    {
+    TInt result( KErrNone );
+    if ( !aStreamParam || !aInitParam )
+        {
+        return KErrUnderflow;
+        }
+
+    // build the packet content
+    switch ( iType )
+        {
+        case ERTP:
+            result = RtpPacketBuildRtp( aStreamParam, aInitParam );
+            break;
+
+        case ERTCP_HEADER:
+            result = RtpPacketBuildRtcp( aStreamParam, aInitParam );
+            break;
+
+        case ERTCP_SR:
+            result = RtpPacketBuildSr( aStreamParam, aInitParam );
+            break;
+
+        case ERTCP_RR:
+            result = RtpPacketBuildRr( aStreamParam, aInitParam );
+            break;
+
+        case ERTCP_SDES:
+            result = RtpPacketBuildSdes( aStreamParam, aInitParam );
+            break;
+
+        case ERTCP_BYE:
+            result = RtpPacketBuildBye( aStreamParam, aInitParam );
+            break;
+
+        case ERTCP_APP:
+            result = RtpPacketBuildApp( aStreamParam, aInitParam );
+            break;
+            
+        default:
+            result = ERTCP_PACKET_ERROR; //unknown packet type
+            break; 
+        }
+
+    return result;
+    }
+
+// ---------------------------------------------------------------------------
+// TRtpSSRC CRtpPacket::RtpPacketGetSSRC()
+// assumed to be called for an RTCP packet only after 
+// RTCP_HEADER has determined the packet type
+// ---------------------------------------------------------------------------
+TRtpSSRC CRtpPacket::RtpPacketGetSSRC()
+    {
+    TUint8* dataP;
+
+    // parse the packet content
+    switch ( iType )
+        {
+        case ERTP:
+            {
+            dataP = iData + 8;
+            return ( Read32( dataP ) );
+            }
+
+        case ERTCP_HEADER:
+            {
+            dataP = iData + 4;
+            return ( Read32( dataP ) );
+            }
+
+        case ERTCP_SR:
+        case ERTCP_RR:
+        case ERTCP_SDES:
+        case ERTCP_BYE:
+        case ERTCP_APP:
+            {
+            dataP = iDataPtr;
+            return ( Read32( dataP ) );
+            }
+
+        default:
+            break;
+        }
+
+    return 0;
+    }
+// ----------------------------------------------------------------------------
+// CRtpPacket::RtpPacketGetPayloadType()
+// ----------------------------------------------------------------------------
+//
+TRtpPayloadType CRtpPacket::RtpPacketGetPayloadType()
+	{
+    TUint8* dataP = iData;
+    // payload type
+    return static_cast<TUint8>( dataP[1] & 0x7F );
+	
+	}
+
+// ----------------------------------------------------------------------------
+// CRtpPacket::RtpPacketProcessRtp()
+// ----------------------------------------------------------------------------
+//
+TRtpRtcpEnum CRtpPacket::RtpPacketProcessRtpL( 
+                             TRtpPacketStreamParam* aStreamParam,
+                             TRtpPacketIOParam* aExtractParam )
+    {
+    RTP_DEBUG_PACKET( "CRtpPacket::RtpPacketProcessRtpL Entry" );
+    TInt k;
+    TInt err( KErrNone );
+    TUint8* dataP = iData;
+
+    // version          
+    //   0xC0 = 1100 0000 
+    // & 0xC0 removes all ones except the version number from the bit stream
+    // 
+    //   11011011
+    //   11000000
+    //   --------
+    //   11000000 >> 6 = 00000011
+    if ( ( ( dataP[0] & 0xC0 ) >> 6 ) != KRtpVersion )
+        {
+        RTP_DEBUG_DETAIL( "RtpPacketProcess: invalid version" );
+        
+        return ERTCP_PACKET_ERROR;
+        }
+    
+    // padding         
+    //    0x20 = 0010 0000 
+    //
+    // Checks if padding bit is set
+    if ( dataP[0] & 0x20 )
+        {
+        
+        // The last octet of the packet must contain a valid octet count
+        // ( octet count < the total packet lenght minus the header size)
+        if ( ( iSize - iData[ iSize - 1] - KMinRtpHeaderSize ) > 0 )
+            {
+            aExtractParam->TRTP.padding = 1;
+
+            // The last octet of the padding contains a count of how many 
+            // padding octets should be ignored, including itself.
+            iSize -= iData[iSize - 1];
+            }
+        else
+            {
+            // Invalid padding value
+            RTP_DEBUG_DETAIL( "RtpPacketProcess: invalid padding size" );
+          
+            return ERTCP_PACKET_ERROR;
+            }
+        }
+    else //padding bit == 0
+        {
+        aExtractParam->TRTP.padding = 0;
+        }
+
+    // header extension
+    aExtractParam->TRTP.fHeaderExtension =
+        static_cast<TUint8>( ( dataP[0] & 0x10 ) >> 4 );
+
+    // CC
+    aExtractParam->TRTP.numCSRC = static_cast<TUint8>( dataP[0] & 0x0F );
+
+    // marker
+    aExtractParam->TRTP.marker =
+        static_cast<TUint8>( ( dataP[1] & 0x80 ) >> 7 );
+
+    // payload type
+    aStreamParam->TRTP.payload = static_cast<TUint8>( dataP[1] & 0x7F );
+    
+    
+   /**
+    * The payload type must be known, and in particular it must not 
+    * be equal to SR or RR[RFC3550]
+    *
+    * 7 bit (= 127) is only reserved for payload, so no need to check 
+    * that payload differ from SR (SR = 200) and RR (RR = 201)
+    * Since it always &0x7F so there is no possiblility to be more than
+    * 127 
+    **/
+   
+    dataP += 2;
+
+    // sequence number
+    aStreamParam->TRTP.seqNum = static_cast<TUint16>( Read16( dataP ) );
+    dataP += 2;
+
+    // RTP timestamp
+    aStreamParam->TRTP.timeStamp = Read32( dataP );
+    dataP += 4;
+
+    // SSRC
+    aStreamParam->TRTP.SSRC = Read32( dataP );
+    dataP += 4;
+
+    // CSRCs
+    if ( aExtractParam->TRTP.numCSRC >0 )
+        {
+        // Calculate the minimum required size of the remainder of this
+        // packet, in number of 8-bit words
+        TInt minRequiredSizeLeft = aExtractParam->TRTP.numCSRC * 4;
+
+        // Make sure there is are CSRCs to read
+        if ( ( iSize - ( dataP - iData ) ) < minRequiredSizeLeft )
+            {
+            RTP_DEBUG_DETAIL( "RtpPacketProcess: invalid CSRC size" );
+
+            return ERTCP_PACKET_ERROR;
+            }
+
+        // Originally Allocate memory for all CSRC:s
+        //it will have memeory resouce problem so only allocate when
+        // CSRC<2
+        if ( aExtractParam->TRTP.numCSRC < KCSRCListMax )
+        	{
+        	if ( !aExtractParam->TRTP.CSRCarray )
+	        	{
+	             TRAP( err,
+	                   aExtractParam->TRTP.CSRCarray =
+	                       static_cast<TUint32*>(
+	                       User::AllocL( sizeof(TUint32) * aExtractParam->TRTP.numCSRC ) )
+	                 );
+	 
+	             if (err==0)
+	             	{
+	             	iCsrcAlloc = ETrue;
+	             	}
+	            }
+	        if ( err || !aExtractParam->TRTP.CSRCarray )
+	            {
+	            RTP_DEBUG_DETAIL( "RtpPacketProcess: CSRC missing" );
+
+	            return ERTCP_PACKET_ERROR;
+	            }
+	        int count=0;    	
+	        for ( k = 0; k < aExtractParam->TRTP.numCSRC; k++ )
+	            {
+	            // CSRCs ignored
+	            TUint32 temp =Read32( dataP );
+	            if (!temp)
+	            	{
+	            	return ERTCP_PACKET_ERROR;
+	            	}
+	            aExtractParam->TRTP.CSRCarray[k] = Read32( dataP );
+	            dataP += 4;
+	            count ++;
+	            }
+	        if (count!= aExtractParam->TRTP.numCSRC)
+	        	{
+	        	RTP_DEBUG_DETAIL( "RtpPacketProcess: numCSRC is not matched" );
+	        	return ERTCP_PACKET_ERROR;
+	        	}
+        	}
+    	else
+    		{
+    		for ( k = 0; k < aExtractParam->TRTP.numCSRC; k++ )
+	    		{
+	            // CSRCs ignored
+	        	dataP += 4;
+	       	 	}
+    		}
+        }
+    if ( aExtractParam->TRTP.fHeaderExtension )
+        {
+        // Make sure there is a header extension to read
+        if ( ( iSize - ( dataP - iData ) ) < 4 )
+            {
+            RTP_DEBUG_DETAIL( "RtpPacketProcess: invalid extension size" );
+			return ERTCP_PACKET_ERROR;
+            }
+
+        // header extension type defined by profile
+        aExtractParam->TRTP.extension.type = Read16( dataP );
+        dataP += 2;
+
+        // header extension length in number of 32-bit words
+        aExtractParam->TRTP.extension.length = Read16( dataP );
+        dataP += 2;
+
+		// Calculate the extension length in number of 8-bit words
+        TInt extensionLen8 = aExtractParam->TRTP.extension.length * 4;
+
+        // Make sure the extension length is valid
+        if ( ( iSize - ( dataP - iData ) ) < extensionLen8 )
+            {
+            RTP_DEBUG_DETAIL( "RtpPacketProcess: invalid extension length" );
+
+            return ERTCP_PACKET_ERROR;
+            }
+
+        if ( !aExtractParam->TRTP.extension.data )
+            {
+             TRAP( err,
+                   aExtractParam->TRTP.extension.data = static_cast<TUint8*>(
+                   User::AllocL( aExtractParam->TRTP.extension.length * 4 ) )
+                 );
+             if(err==KErrNone)
+             	{
+             	 iExdataAlloc= ETrue; 
+             	}     
+            }
+        if ( err || !aExtractParam->TRTP.extension.data )
+            {
+            RTP_DEBUG_DETAIL( "RtpPacketProcess: extension missing" );
+
+            return ERTCP_PACKET_ERROR;
+            }
+
+        // header extension data
+        for ( k = 0; k < aExtractParam->TRTP.extension.length*4; k++ )
+            {
+            aExtractParam->TRTP.extension.data[k] = dataP[k];
+            }
+        dataP += ( aExtractParam->TRTP.extension.length * 4 );
+        }
+
+    // Make sure there is a payload
+    if ( ( iSize - ( dataP - iData ) ) > 0 )
+        {
+        aExtractParam->TRTP.payloadDataLen = iSize - ( dataP - iData );
+        aExtractParam->TRTP.payloadData = static_cast<TText8*>( dataP );
+        }
+    else
+        {
+        aExtractParam->TRTP.payloadDataLen = 0;
+        aExtractParam->TRTP.payloadData = NULL;
+        
+        RTP_DEBUG_DETAIL( "RtpPacketProcess: packet length is 0" );
+        }
+	RTP_DEBUG_PACKET( "CRtpPacket::RtpPacketProcessRtpL Exit" );
+    return ERTCP_NO_ERROR;
+    }
+
+// ----------------------------------------------------------------------------
+// CRtpPacket::RtpPacketProcessRtcp()
+// ----------------------------------------------------------------------------
+//
+TRtpRtcpEnum CRtpPacket::RtpPacketProcessRtcp( 
+                             TRtpPacketStreamParam* aStreamParam,
+                             TRtpPacketIOParam* aExtractParam )
+    {
+    // version
+    if ( ( ( iDataPtr[0] & 0xC0 ) >> 6 ) != KRtpVersion )
+        {
+        RTP_DEBUG_DETAIL( "ERROR: Wrong Rtp version in header" );
+        return ERTCP_PACKET_ERROR;
+        }
+
+    // padding
+    if ( iDataPtr[0] & 0x20 )
+        {
+    	iSize -= iData[iSize - 1];
+    	}
+
+    // determine RTCP packet type
+    aExtractParam->TRTCP_HEADER.pt =
+        static_cast<TRtpPacketType>( iDataPtr[1] );
+
+    if ( ( aExtractParam->TRTCP_HEADER.pt != ERTCP_SR ) &&
+	     ( aExtractParam->TRTCP_HEADER.pt != ERTCP_RR ) &&
+	     ( aExtractParam->TRTCP_HEADER.pt != ERTCP_SDES ) &&
+	     ( aExtractParam->TRTCP_HEADER.pt != ERTCP_BYE ) &&
+	     ( aExtractParam->TRTCP_HEADER.pt != ERTCP_APP ) )
+        {
+        
+        RTP_DEBUG_DETAIL( "ERROR: Incorrect packet type in header" );
+        
+	    return ERTCP_PACKET_ERROR;
+        }
+
+    // source/report Count
+    aExtractParam->TRTCP_HEADER.sourceCount = ( iDataPtr[0] & 0x1F );
+
+    iDataPtr += 2;
+    
+    aExtractParam->TRTCP_HEADER.length =
+        static_cast<TInt>( Read16( iDataPtr ) );
+
+    if ( aExtractParam->TRTCP_HEADER.length * 4 > iSize )
+        {
+        RTP_DEBUG_DETAIL( "ERROR: Incorrect packet size in header" );
+        return ERTCP_PACKET_ERROR;
+        }
+    iDataPtr += 2;
+
+    // SSRC of sender in case of RR
+    if ( aExtractParam->TRTCP_HEADER.pt == ERTCP_RR )
+        {
+	    aStreamParam->TRTCP_HEADER.SSRC = Read32( iDataPtr );
+	    iDataPtr += 4;
+        }
+                        
+    return ERTCP_NO_ERROR;
+    }
+        
+// ----------------------------------------------------------------------------
+// CRtpPacket::RtpPacketProcessApp()
+// ----------------------------------------------------------------------------
+//
+TRtpRtcpEnum CRtpPacket::RtpPacketProcessAppL( 
+                             TRtpPacketStreamParam* aStreamParam,
+                             TRtpPacketIOParam* aExtractParam )
+    {
+    TInt err( KErrNone );
+
+    // TRTCP_APP.totalPacketLen is the 32-bit packet length MINUS ONE.
+    TUint totalLen( aStreamParam->TRTCP_APP.totalPacketLen );
+
+    // Calculate the length of the data in the packet in number of 8-bit words
+    TUint appDataLen8 = ( totalLen + 1 - KMinRtcpAppLen ) * 4;
+
+    // The packet is faulty if the total length of the packet is results in a
+    // negative memory allocation . Also, it cannot be too big due to framework
+    // restrictions on memory allocation.
+    if ( ( totalLen + 1 < KMinRtcpAppLen ) ||
+         ( sizeof( TUint8 ) * appDataLen8 > ( KMaxTInt / 2 ) ) )
+        {
+        return ERTCP_PACKET_ERROR;
+        }
+
+    // SSRC
+    aStreamParam->TRTCP_APP.SSRC = Read32( iDataPtr );
+    iDataPtr += 4;
+
+    // name
+    Mem::Copy( aExtractParam->TRTCP_APP.name, iDataPtr, 4 );
+
+    iDataPtr += 4;
+
+    // Allocate memory for application data
+    TRAP ( err,
+           aExtractParam->TRTCP_APP.appData =
+           static_cast<TUint8*>
+               (
+		       User::AllocL( sizeof( TUint8 ) * appDataLen8 ) )
+               );
+
+    if ( err )
+        {
+    	return ERTCP_PACKET_ERROR; 
+    	}
+
+    Mem::Copy( aExtractParam->TRTCP_APP.appData, iDataPtr, appDataLen8 );
+    iDataPtr += appDataLen8;
+    aExtractParam->TRTCP_APP.appDataLen = appDataLen8;
+
+    return ERTCP_NO_ERROR;
+    }
+        
+// ----------------------------------------------------------------------------
+// CRtpPacket::RtpPacketProcessBye()
+// ----------------------------------------------------------------------------
+//
+TRtpRtcpEnum CRtpPacket::RtpPacketProcessByeL( 
+                             TRtpPacketStreamParam* aStreamParam,
+                             TRtpPacketIOParam* aExtractParam )
+    {
+    TInt err;
+    TUint8 theIndex( 0 );
+
+    // SSRC
+    aStreamParam->TRTCP_BYE.SSRC = Read32( iDataPtr );
+    iDataPtr += 4;
+
+    // reason
+    aExtractParam->TRTCP_BYE.reasonSize = iDataPtr[0];
+
+    iDataPtr += 1;
+
+    TRAP ( err, aExtractParam->TRTCP_BYE.reason = static_cast<TText8*>(
+		   User::AllocL( sizeof( TText8 ) *
+           ( aExtractParam->TRTCP_BYE.reasonSize + 1 /* trailing NULL */) ) )
+         );
+
+    if ( err )
+        {
+    	return ERTCP_PACKET_ERROR;
+    	}
+
+    Mem::Copy( aExtractParam->TRTCP_BYE.reason, iDataPtr,
+               aExtractParam->TRTCP_BYE.reasonSize );
+
+    *( aExtractParam->TRTCP_BYE.reason + aExtractParam->TRTCP_BYE.reasonSize )
+        = KNullTerm;
+
+    iDataPtr += aExtractParam->TRTCP_BYE.reasonSize;
+
+    // calculate size of padding
+    if ( ( 1 + aExtractParam->TRTCP_BYE.reasonSize ) % 4 != 0 )
+        {
+	    aExtractParam->TRTCP_BYE.paddingSize =
+            4 - ( 1 + aExtractParam->TRTCP_BYE.reasonSize ) % 4;
+        }
+    else
+        {
+	    aExtractParam->TRTCP_BYE.paddingSize = 0;
+        }
+                        
+    for ( theIndex = 0; theIndex < aExtractParam->TRTCP_BYE.paddingSize;
+          theIndex++ )
+        {
+	    iDataPtr++;
+        }
+    return ERTCP_NO_ERROR;
+    }
+        
+// ----------------------------------------------------------------------------
+// CRtpPacket::RtpPacketProcessRr()
+// ----------------------------------------------------------------------------
+//
+TRtpRtcpEnum CRtpPacket::RtpPacketProcessRr( 
+                             TRtpPacketStreamParam* aStreamParam,
+                             TRtpPacketIOParam* aExtractParam )
+    {
+    // SSRC
+    aStreamParam->TRTCP_RR.SSRC = Read32( iDataPtr );
+    iDataPtr += 4;
+
+    // fraction lost
+    aStreamParam->TRTCP_RR.fractionLost = iDataPtr[0];
+    iDataPtr++;
+
+    // cumulative number of packets lost
+    aStreamParam->TRTCP_RR.cumNumPacketsLost = Read24( iDataPtr );
+    iDataPtr += 3;
+
+    // extended highest sequence number received
+    aStreamParam->TRTCP_RR.seqNumReceived = Read32( iDataPtr );
+    iDataPtr += 4;
+
+    // interarrival jitter
+    aStreamParam->TRTCP_RR.arrivalJitter = Read32( iDataPtr );
+    iDataPtr += 4;
+
+    // last SR timestamp
+    aExtractParam->TRTCP_RR.lastSRTimeStamp = Read32( iDataPtr );
+    iDataPtr += 4;
+
+    // delay since last SR timestamp
+    aExtractParam->TRTCP_RR.delaySinceLSR = Read32( iDataPtr );
+    iDataPtr += 4;
+
+    return ERTCP_NO_ERROR;
+    }
+        
+// ----------------------------------------------------------------------------
+// CRtpPacket::RtpPacketProcessSr()
+// ----------------------------------------------------------------------------
+//
+TRtpRtcpEnum CRtpPacket::RtpPacketProcessSr( 
+                             TRtpPacketStreamParam* aStreamParam,
+                             TRtpPacketIOParam* aExtractParam )
+    {
+    // SSRC
+    aStreamParam->TRTCP_SR.SSRC = Read32( iDataPtr );
+    iDataPtr += 4;
+
+    // NTP timestamp (seconds)
+    aExtractParam->TRTCP_SR.NTPTimeStampSec = Read32( iDataPtr );
+    iDataPtr += 4;
+
+    // NTP timestamp (fraction)
+    aExtractParam->TRTCP_SR.NTPTimeStampFrac = Read32( iDataPtr );
+    iDataPtr += 4;
+
+    // RTP timestamp
+    aExtractParam->TRTCP_SR.timeStamp = Read32( iDataPtr );
+    iDataPtr += 4;
+
+    // sender's packet count
+    aStreamParam->TRTCP_SR.numPacketsSent = Read32( iDataPtr );
+    iDataPtr += 4;
+
+    // sender's octet count
+    aStreamParam->TRTCP_SR.cumNumOctetsSent = Read32( iDataPtr );
+    iDataPtr += 4;
+
+    return ERTCP_NO_ERROR;
+    }
+        
+// ----------------------------------------------------------------------------
+// CRtpPacket::RtpPacketProcessSdes()
+// ----------------------------------------------------------------------------
+//
+TRtpRtcpEnum CRtpPacket::RtpPacketProcessSdesL( 
+                             TRtpPacketStreamParam* aStreamParam,
+                             TRtpPacketIOParam* aExtractParam )
+    {
+    TUint8 theIndex( 0 );
+    TUint8 tempValue( 0 );
+    TInt err( KErrNone );
+    TUint8 sdesItems = 0;
+    TUint32 totalSDESSize( 0 );
+
+    // SSRC
+    aStreamParam->TRTCP_SDES.SSRC = Read32( iDataPtr );
+    iDataPtr += 4;
+                        
+    for ( theIndex = 0; theIndex < ERTCP_NUM_OF_SDES_ITEMS; theIndex++ )
+        {
+	    aExtractParam->TRTCP_SDES.sdesItemsSize[theIndex] = 0;
+        }
+
+    // Read each SDES items
+    for ( theIndex = 0; theIndex < ERTCP_NUM_OF_SDES_ITEMS; theIndex++ )
+        {
+	    if ( iDataPtr[0] != KNullTerm )
+	        {
+		    tempValue = iDataPtr[0];
+
+		    if ( tempValue != ( theIndex + 1 ) )
+		        {
+			    aExtractParam->TRTCP_SDES.sdesItemsSize[theIndex] = 0;
+			    TRAP( err, aExtractParam->TRTCP_SDES.sdesItems[theIndex] = 
+					static_cast<TUint8*>( User::AllocL( sizeof( TUint8 ) ) ) );
+			    if ( err )
+			        { 
+    				return ERTCP_PACKET_ERROR;
+    				}
+
+			    *( aExtractParam->TRTCP_SDES.sdesItems[theIndex] ) = KNullTerm;
+		        }
+		    else
+		        {
+			    aExtractParam->TRTCP_SDES.sdesItemsSize[theIndex] = iDataPtr[1];
+
+			    // keep track of number of SDES items
+			    sdesItems++;
+			    totalSDESSize +=
+                    aExtractParam->TRTCP_SDES.sdesItemsSize[theIndex];
+
+			    iDataPtr += 2;
+
+			    TRAP( err, aExtractParam->TRTCP_SDES.sdesItems[theIndex] =
+                        static_cast<TUint8*>(
+					    User::AllocL( sizeof( TUint8 ) * (
+                        aExtractParam->TRTCP_SDES.sdesItemsSize[theIndex] + 1 )
+                        ) ) );
+
+			    if ( err )
+			        {
+				    return ERTCP_PACKET_ERROR;
+				    }
+                        
+			    Mem::Copy( aExtractParam->TRTCP_SDES.sdesItems[theIndex],
+                           iDataPtr,
+                           aExtractParam->TRTCP_SDES.sdesItemsSize[theIndex] );
+        
+			    *( aExtractParam->TRTCP_SDES.sdesItems[theIndex] +
+                aExtractParam->TRTCP_SDES.sdesItemsSize[theIndex] ) = KNullTerm;
+    
+			    iDataPtr += aExtractParam->TRTCP_SDES.sdesItemsSize[theIndex];
+		        }
+	        }
+	    }
+
+
+    iDataPtr++;    // take into account end null octet
+
+    for ( theIndex = tempValue; theIndex < ERTCP_NUM_OF_SDES_ITEMS; theIndex++ )
+        {
+
+	    TRAP( err, aExtractParam->TRTCP_SDES.sdesItems[theIndex] =
+                   static_cast<TUint8*>( User::AllocL( sizeof( TUint8 ) ) )
+            );
+
+	    if ( err )
+	        {
+    		return ERTCP_PACKET_ERROR;
+    		}
+
+	    *( aExtractParam->TRTCP_SDES.sdesItems[theIndex] ) = KNullTerm;
+		  }
+
+    // calculate size of padding
+    if ( ( sdesItems * 2 + totalSDESSize + 1 ) % 4 != 0 )
+        {
+    	aExtractParam->TRTCP_SDES.paddingSize =
+            4 - ( sdesItems * 2 + totalSDESSize + 1 ) % 4;
+    	}
+    else
+        {
+    	aExtractParam->TRTCP_SDES.paddingSize = 0;
+    	}
+
+    for ( theIndex = 0; theIndex < aExtractParam->TRTCP_SDES.paddingSize;
+          theIndex++ )
+        {
+    	iDataPtr++;
+    	}
+    return ERTCP_NO_ERROR;
+    }
+    
+// ---------------------------------------------------------------------------
+// Return Value:
+//     0  : if RTP packet has been processed OK or
+//          if RTCP packet has been processed OK and there are no more RTCP
+//          packets in this compound packet to be processed
+//     1  : if RTCP packet has been processed OK and there is still RTCP
+//          packets in this compound packet to be processed
+//    -1  : if packet is invalid or some other error has occured
+// ---------------------------------------------------------------------------
+TRtpRtcpEnum CRtpPacket::RtpPacketProcessL( TRtpPacketStreamParam* aStreamParam,
+                                           TRtpPacketIOParam* aExtractParam )
+    {
+    TRtpRtcpEnum result( ERTCP_NO_ERROR );
+
+    // parse the packet content
+    switch ( iType )
+        {
+        case ERTP:
+            result = RtpPacketProcessRtpL( aStreamParam, aExtractParam );
+            return result;
+            // no break necessary
+
+        case ERTCP_HEADER:
+            result = RtpPacketProcessRtcp( aStreamParam, aExtractParam );
+            break;
+
+        case ERTCP_SR:
+            result = RtpPacketProcessSr( aStreamParam, aExtractParam );
+            break;
+
+        case ERTCP_RR:
+            result = RtpPacketProcessRr( aStreamParam, aExtractParam );
+            break;
+
+        case ERTCP_SDES:
+            result = RtpPacketProcessSdesL( aStreamParam, aExtractParam );
+            break;
+
+        case ERTCP_BYE:
+            result = RtpPacketProcessByeL( aStreamParam, aExtractParam );
+            break;
+
+        case ERTCP_APP:
+            result = RtpPacketProcessAppL( aStreamParam, aExtractParam );
+            break;
+
+        default:
+            // unknown packet type, return error
+            result = ERTCP_PACKET_ERROR;
+            break;
+        }
+       
+        // Only RTCP packets get this far
+        if ( result != ERTCP_NO_ERROR )
+            {
+            return result;
+            }
+ 
+        // check if RTCP compound is ready
+        if ( iDataPtr == ( iData + iSize ) )
+            {
+            iDataPtr = iData;
+            return ERTCP_NO_ERROR;
+            }
+        else if ( iDataPtr < ( iData + iSize ) )
+            {
+            return ERTCP_PACKET_MORE;
+            }
+        else
+            {
+            return ERTCP_PACKET_ERROR;
+            }
+    }
+
+// ---------------------------------------------------------------------------
+// CRtpPacket::Write16()
+// Write a 16-bit value as 2 consecutive bytes in MSB order
+// Memory (at least 2 bytes) must have been allocated to pointer
+// before the function is called.
+// ---------------------------------------------------------------------------
+void CRtpPacket::Write16( TUint8* const aPointer, TUint16 aValue )
+    {
+    // check value range (16 bits)
+    aPointer[0] = static_cast<TUint8>( ( aValue & 0xFF00 ) >> 8 );
+    aPointer[1] = static_cast<TUint8>( aValue & 0x00FF );
+    }
+
+// ---------------------------------------------------------------------------
+// TUint16 CRtpPacket::Read16()
+// Read a 16-bit value given as 2 consecutive bytes in MSB order
+// Memory (at least 2 bytes) must have been allocated to pointer
+// before the function is called.
+// ---------------------------------------------------------------------------
+TUint16 CRtpPacket::Read16( const TUint8* const aPointer )
+    {
+    return static_cast<TUint16>( aPointer[1] + ( aPointer[0] << 8 ) );
+    }
+
+// ---------------------------------------------------------------------------
+// CRtpPacket::Write32()
+// Write a 32-bit aValue as 4 consecutive bytes in MSB order
+// Memory (at least 4 bytes) must have been allocated to aPointer
+// before the function is called.
+// ---------------------------------------------------------------------------
+void CRtpPacket::Write32( TUint8* const aPointer, TUint32 aValue )
+    {
+    aPointer[0] = static_cast<TUint8>( ( aValue & 0xFF000000 ) >> 24 );
+    aPointer[1] = static_cast<TUint8>( ( aValue & 0x00FF0000 ) >> 16 );
+    aPointer[2] = static_cast<TUint8>( ( aValue & 0x0000FF00 ) >> 8 );
+    aPointer[3] = static_cast<TUint8>( aValue & 0x000000FF );
+    }
+
+// ---------------------------------------------------------------------------
+// TUint32 CRtpPacket::Read32()
+// Read a 32-bit aValue given as 4 consecutive bytes in MSB order
+// Memory (at least 4 bytes) must have been allocated to aPointer
+// before the function is called.
+// ---------------------------------------------------------------------------
+TUint32 CRtpPacket::Read32( const TUint8* const aPointer )
+    {
+    return ( aPointer[3] +
+             ( static_cast<TUint32>( aPointer[2] ) << 8 ) +
+             ( static_cast<TUint32>( aPointer[1] ) << 16 ) +
+             ( static_cast<TUint32>( aPointer[0] ) << 24 ) );
+    }
+
+// ---------------------------------------------------------------------------
+// CRtpPacket::Write24()
+// 
+// ---------------------------------------------------------------------------
+//
+void CRtpPacket::Write24( TUint8* const aPointer, TUint32 aValue )
+    {
+    aPointer[0] = static_cast<TUint8>( ( aValue & 0xFF0000 ) >> 16 );
+    aPointer[1] = static_cast<TUint8>( ( aValue & 0x00FF00 ) >> 8 );
+    aPointer[2] = static_cast<TUint8>( aValue & 0x0000FF );
+    }
+
+// ---------------------------------------------------------------------------
+// TUint32 CRtpPacket::Read24()
+// 
+// ---------------------------------------------------------------------------
+//
+TUint32 CRtpPacket::Read24( const TUint8 *const aPointer )
+    {
+    return ( aPointer[2] + ( static_cast<TUint32>( aPointer[1] ) << 8 ) +
+             ( static_cast<TUint32>( aPointer[0] ) << 16 ) );
+    }
+
+
+//  End of File