rtp/rtpstack/src/rtpstppacket.cpp
author hgs
Mon, 28 Jun 2010 19:10:29 +0300
changeset 30 d7640adb246b
parent 0 307788aac0a8
permissions -rw-r--r--
201025_01

/*
* 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:   
*
*/




// INCLUDES

#include <e32base.h>
#include <e32std.h>

#include "rtpstppacket.h"

//
// RTPLite header
//
// ****************************************
// Extract from "PoC Core Network RTP RP01" 
// ****************************************
//                       1                   2                   3
//    0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
//   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
//   |F M R C S|  PT | Sequence nbr  |      Checksum (optional)      |
//   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
//
//  Full header indication (F)  1 bit
//                              If this bit is set to zero then header format
//                              is reduced (otherwise full)
//
//  Marker (M)                  1 bit
//                              Indication of the start of speech item (value 1).
//                              It is set on the Nth first RTP packets including 
//                              speech frames within the RTP payload. N is expected
//                              to have a constant value in the order of 3 to 5. 
//                              Note: M-bit is zero for all embedded control packets.
//
//  Reserved bit (R)            1 bit
//                              This bit is reserved for future use. Default value is 1. 
//
//  Checksum indication (C)     1 bit
//                              C-bit is an indication if header includes at the end an
//                              optional checksum field. Value 1 indicates that checksum
//                              field exist on the header.
//
//  Speech Item toggle indication (S)   1 bit
//                              S-bit is used as an indication (toggled value) that speech
//                              item has been changed (toggled between two speech items 
//                              from same source; toggled between two speech items from 
//                              different users; toggled between two speech items from 
//                              different groups 1-to-1 call). This bit is on the same
//                              position for the respective leader, speech and trailing
//                              packets.
//
//  Payload Type (PT)           3 bits
//                              PT-field indicates what kind of information
//                              is carried on the paylaod area. Only two codes
//                              (000 and 001) are reserved at the first phase, 
//                              other values are reserved for future use.000 is
//                              used to indicate that embedded control signal
//                              information is in payload area and 001 indicates
//                              that payload contains speech packets coded with
//                              IETF AMR speech coding 8. In case of embedded 
//                              control signal coding then the first byte on the payload
//                              area has special coding rules, which are defined on section 5.3.4.
//                              Note: GSM HR (HalfRate) will be used for 1st integration testing 
//                              and related PT is 010.
//                              Note: Standard RTP header uses 7 bits for the same indication.
//
// Sequence Nbr (SN)            8 bits
//                              The sequence nbr increments by one for each
//                              RTP data packet sent, and may be used by the
//                              receiver to detect packet loss and restore
//                              packet sequence. The initial value (when S 
//                              bit is toggled) of the sequence number is zero. 
//                              Note one exception: during talkspurt 
//                              (for 1-to-1 call or group call) if one/few 
//                              RTP packets are not sent (on N*20ms interval)
//                              due to DTX usage (silence periods not sent) 
//                              the sequency number at the originator side 
//                              is anyhow incremented by one with the N*20ms 
//                              frequency. The value for N is 3 by default. 
//                              Very probably RTP packets are always sent in
//                              GPRS terminals during talkspurt to avoid TBF
//                              drop. RTP packet payload contains during 
//                              silence periods three NO_DATA -indication
//                              bytes to AMR decoder. In the future extented
//                              TFB timer feature may change this behaviour, 
//                              i.e. the sending of NO_DATA -indication bytes
//                              might be dropped (over GPRS).Within standard
//                              version of RTP header the length of SN is 16
//                              bits , but within PoC application it is enough
//                              to have 8 bits; it provides 7.62s (127*3*20ms)
//                              jitter buffering without any special number wrap
//                              control tricks (shown values are valid with N=3). 
//                              Note: On the uplink direction on each speech item,
//                              the Sequency Nbr is zero for all leading packets
//                              (the first leading packet is replicated few times,
//                              but the replicated messages are identical 
//                              (even concerning the SN field)) and the first RTP
//                              packet containing speech has SN value one.
//                              Note: for all embedded control signals the SN
//                              is set to zero.
//
//  CheckSum (CS)               16 bits (optional)
//                              Checksum field is optional and the existence
//                              of this field is indicated on the first octet
//                              by C-bit.  Checksum will be needed with RP01
//                              interface if RLC/LLC/UDP checksums are not
//                              available/used. UDP checksum is optional 
//                              with IPv4. Further more by using RTP level
//                              CRC in combination of UDP-lite it would be 
//                              possible to implement more efficient unequal
//                              error protection on AMR bits than UDP-lite 
//                              alone would offer.If checksum error is detected
//                              then whole RTP packet is discarded.
//                              Note: Checksum information is not available 
//                              within standard RTP header.
//                              Note: Taking the other aspects (header compression
//                              with Degermark) into account it currently means 
//                              that if checksum is included on RTPLite header
//                              the whole packet does fit to 8 kbit/s channel
//                              on the AIR interface only with AMR 4.75 coding.

// ================= MEMBER FUNCTIONS =======================

// ---------------------------------------------------------------------------
// C++ default constructor can NOT contain any code, that
// might leave.
// ---------------------------------------------------------------------------
// 
CRtpStpPacket::CRtpStpPacket() :
    iSize( 0 ),
    iData( 0 ),
    iDataPtr( 0 ),
    iSessionId( 0 )
    {
    }

// ---------------------------------------------------------------------------
// Symbian 2nd phase constructor can leave.
// ---------------------------------------------------------------------------
//
void CRtpStpPacket::ConstructL( TUint aPacketSize, TRtpId aSessionId )
    {
    iBuf = HBufC8::NewL( aPacketSize );
    iData = ( TUint8* ) iBuf->Des().Ptr();
    iSize = 0;
    iDataPtr = iData;
    iSessionId = aSessionId;
    }

// ---------------------------------------------------------------------------
// Destructor
// ---------------------------------------------------------------------------
// 
CRtpStpPacket::~CRtpStpPacket()
    {
    delete iBuf;
    }

// ---------------------------------------------------------------------------
// CRtpStpPacket::Close()
// works as destructor
// ---------------------------------------------------------------------------
//
void CRtpStpPacket::Close()
    {
    delete this;
    }

// ---------------------------------------------------------------------------
// CRtpStpPacket::RtpPacketReset()
// 
// ---------------------------------------------------------------------------
//
void CRtpStpPacket::RtpPacketReset()
    {
    iSize = 0;
    iDataPtr = iData;
    }

// ---------------------------------------------------------------------------
// CRtpStpPacket::RtpPacketResetPtr()
// 
// ---------------------------------------------------------------------------
//
void CRtpStpPacket::RtpPacketResetPtr()
    {
    iDataPtr = iData;
    }

// ---------------------------------------------------------------------------
// TInt CRtpStpPacket::RtpPacketBuild()
// 
// ---------------------------------------------------------------------------
//
TInt CRtpStpPacket::RtpPacketBuild( const TRtpSendHeader& aHeader, const TDesC8& aPayloadData )
    {
    TUint8* dataP;

    dataP = iData;

    // build the packet content
    Mem::FillZ( dataP, 4 );

    // Full header indication (F)
    dataP[0] |= ( 0 << 7 );

    // Marker (M) 
    dataP[0] |= static_cast<TUint8>( aHeader.iMarker << 6 );

    // Padding bit (P) = 1
    dataP[0] |= static_cast<TUint8>( aHeader.iPadding << 5 );

    // Checksum indecation (C)  if checkSumInd == 1, need checksum in the header
    dataP[0] |= static_cast<TUint8>( aHeader.iChecksumInd << 4 );

    // Speech Item toggle indication (S)
    dataP[0] |= static_cast<TUint8>( aHeader.iSpeechItemToggle << 3 );

    // payload type
    dataP[0] |= ( aHeader.iPayloadType & 0x07 );

    // sequence number
    dataP[1] = aHeader.iSeqNum;
    dataP += 2;

    // Optinal checksum
    if ( aHeader.iChecksumInd == 1 )
        {
        write16( dataP, aHeader.iChecksum );
        dataP += 2;
        }

    // copy payload data 
    Mem::Copy( dataP, aPayloadData.Ptr(), aPayloadData.Length() );
    iSize = aPayloadData.Length() + ( dataP - iData );

    return 0;
    }

// ---------------------------------------------------------------------------
// CRtpStpPacket::RtpPacketProcess()
// Return Value:
//    KErrNone if STP packet has been processed OK, or
//    KErrCorrupt if packet is invalid or some other error has occured
// ---------------------------------------------------------------------------
//
TInt CRtpStpPacket::RtpPacketProcess( TUint8* aBuf, TInt* aLength )
    {
    TRtpRecvHeader header;
    TUint8* dataP;

    dataP = iData;

    // Full header indication (F) 
    if ( ( dataP[0] & 0x80 ) != 0 )
        return KErrCorrupt;

    // Marker (M)
    header.iMarker = ( TUint8 ) ( ( dataP[0] & 0x40 ) >> 6 );

    // Padding bit (P)
    header.iPadding = ( TUint8 ) ( ( dataP[0] & 0x20 ) >> 5 );

    // Checksum indication (C) 
    header.iChecksumInd = ( TUint8 ) ( ( dataP[0] & 0x10 ) >> 4 );

    // Speech item toggle indication (S) 
    header.iSpeechItemToggle = ( TUint8 ) ( ( dataP[0] & 0x08 ) >> 3 );

    // Payload type (PT)
    header.iPayloadType = ( TUint8 ) ( ( dataP[0] & 0x07 ) );

    // Sequence number
    header.iSeqNum = ( TUint8 ) ( dataP[1] );
    dataP += 2;

    // Optinal checksum
    if ( header.iChecksumInd == 1 )
        {
        header.iChecksum = ( TUint16 ) read16( dataP ); 
        dataP += 2;
        }

    *aLength = iSize - ( dataP - iData );
    aBuf = ( TUint8 * ) dataP;

    TPtrC8 buf( aBuf, *aLength );

    if ( iObserver )
        iObserver->RtpPacketReceived( iSessionId /* streamId */, header, buf );

    return KErrNone;
    }

// ---------------------------------------------------------------------------
// 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 CRtpStpPacket::write16( TUint8* const aPointer, TUint32 aValue )
    {
    // check value range (16 bits)
    aPointer[0] = ( TUint8 ) ( ( aValue & 0xFF00 ) >> 8 );
    aPointer[1] = ( TUint8 ) ( aValue & 0x00FF );
    }

// ---------------------------------------------------------------------------
// 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.
// ---------------------------------------------------------------------------
//
TUint32 CRtpStpPacket::read16( const TUint8* const aPointer )
    {
    return( aPointer[1] + ( ( TUint32 ) aPointer[0] << 8 ) );
    }


#if !defined ( EKA2 ) && !defined ( RTP_UNIT_TEST )
// The E32Dll() entry point function
GLDEF_C TInt E32Dll( TDllReason /*aReason*/ )
    {
    return( KErrNone );
    }
#endif // EKA2

// ---------------------------------------------------------------------------
// Function to construct a CRtpPacketExt object. Note that this function
// is exported at ordinal 1 and is not a member of any class.
// ---------------------------------------------------------------------------
//
EXPORT_C MRtpPacketExt* NewL()
    {
    return new ( ELeave ) CRtpStpPacket;
    }


// End of File