diff -r 000000000000 -r 307788aac0a8 rtp/rtpstack/src/rtppacket.cpp --- /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 +#include + +#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( 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( ( 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( 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( 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( aInitParam->TRTCP_HEADER.sourceCount ); + + // packet type + iDataPtr[1] = static_cast( 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( 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( theIndex + 1 ); + iDataPtr[1] = static_cast( + 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( 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( ( dataP[0] & 0x10 ) >> 4 ); + + // CC + aExtractParam->TRTP.numCSRC = static_cast( dataP[0] & 0x0F ); + + // marker + aExtractParam->TRTP.marker = + static_cast( ( dataP[1] & 0x80 ) >> 7 ); + + // payload type + aStreamParam->TRTP.payload = static_cast( 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( 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( + 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( + 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( 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( 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( 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 + ( + 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( + 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( 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( + 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( 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( ( aValue & 0xFF00 ) >> 8 ); + aPointer[1] = static_cast( 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( 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( ( aValue & 0xFF000000 ) >> 24 ); + aPointer[1] = static_cast( ( aValue & 0x00FF0000 ) >> 16 ); + aPointer[2] = static_cast( ( aValue & 0x0000FF00 ) >> 8 ); + aPointer[3] = static_cast( 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( aPointer[2] ) << 8 ) + + ( static_cast( aPointer[1] ) << 16 ) + + ( static_cast( aPointer[0] ) << 24 ) ); + } + +// --------------------------------------------------------------------------- +// CRtpPacket::Write24() +// +// --------------------------------------------------------------------------- +// +void CRtpPacket::Write24( TUint8* const aPointer, TUint32 aValue ) + { + aPointer[0] = static_cast( ( aValue & 0xFF0000 ) >> 16 ); + aPointer[1] = static_cast( ( aValue & 0x00FF00 ) >> 8 ); + aPointer[2] = static_cast( aValue & 0x0000FF ); + } + +// --------------------------------------------------------------------------- +// TUint32 CRtpPacket::Read24() +// +// --------------------------------------------------------------------------- +// +TUint32 CRtpPacket::Read24( const TUint8 *const aPointer ) + { + return ( aPointer[2] + ( static_cast( aPointer[1] ) << 8 ) + + ( static_cast( aPointer[0] ) << 16 ) ); + } + + +// End of File