multimediacommscontroller/mmccdtmfpayloadformat/src/dtmfpayloadencoder.cpp
changeset 0 1bce908db942
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/multimediacommscontroller/mmccdtmfpayloadformat/src/dtmfpayloadencoder.cpp	Tue Feb 02 01:04:58 2010 +0200
@@ -0,0 +1,538 @@
+/*
+* Copyright (c) 2006-2007 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:    DTMF RTP payload encoder for named telephone events
+*                and tones.
+*
+*/
+
+
+
+
+// INCLUDES
+#include <mmf/server/mmfdatabuffer.h>
+#include "dtmfpayloadformatdefs.h"
+#include "dtmfpayloadencoder.h"
+#include "dtmfeventpayloadinfo.h"
+#include "dtmftonepayloadinfo.h"
+#include "streamformatter.h"
+
+// CONSTANTS
+const TInt KEventLengthInBytes = 8;
+const TInt KByteIndex = 2;
+const TInt KReservedBits = 4;
+
+#ifdef VOIP_TRACE_ENABLED
+#include <voip_trace.h>
+#endif
+
+// ======== MEMBER FUNCTIONS ========
+
+
+// ---------------------------------------------------------------------------
+// CDTMFPayloadEncoder::CDTMFPayloadEncoder
+// C++ default constructor can NOT contain any code, that
+// might leave.
+// ---------------------------------------------------------------------------
+//
+CDTMFPayloadEncoder::CDTMFPayloadEncoder()
+    {
+    }
+
+// ---------------------------------------------------------------------------
+// CDTMFPayloadEncoder::NewL
+// Two-phased constructor.
+// ---------------------------------------------------------------------------
+//
+CDTMFPayloadEncoder* CDTMFPayloadEncoder::NewL()
+    {
+    #ifdef VOIP_TRACE_ENABLED
+        VoipTrace( "%x %x", MCC_TRACE, MCC_DTMF_PLF_ENC_NEWL );
+    #endif
+
+    CDTMFPayloadEncoder* self = new( ELeave ) CDTMFPayloadEncoder;
+    return self;
+    }
+
+// ---------------------------------------------------------------------------
+// CDTMFPayloadEncoder::~CDTMFPayloadEncoder
+// Destructor.
+// ---------------------------------------------------------------------------
+//
+CDTMFPayloadEncoder::~CDTMFPayloadEncoder()
+    {
+    #ifdef VOIP_TRACE_ENABLED
+        VoipTrace( "%x %x", MCC_TRACE, MCC_DTMF_PLF_ENC_DESTRUCTOR );
+    #endif
+    iEventArray.Reset();
+    }
+
+// ---------------------------------------------------------------------------
+// CDTMFPayloadEncoder::EncodeEvent
+// Forms payload for named events.
+// ---------------------------------------------------------------------------
+//
+/*
+    0                   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 
+   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 
+   |     event     |E|R| volume    |          duration             | 
+   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 
+*/  
+TInt CDTMFPayloadEncoder::EncodeEvent( 
+    const TDTMFEventPayloadInfo& aEventInfo,
+    CMMFBuffer* aOutputBuffer )
+    {
+    #ifdef VOIP_TRACE_ENABLED
+        VoipTrace( "%x %x", MCC_TRACE, MCC_DTMF_PLF_ENC_ENCEV );
+    #endif
+    if ( EDTMFPayloadFormatRedEvents == iPayloadFormat )
+        {
+        return EncodeRedundantEventPayload( aEventInfo, aOutputBuffer );
+        }
+
+    if ( aOutputBuffer )
+        {
+        // Possible events are: 0-9, * (10), # (11), A-D (12-15)
+        TInt eventAsInteger = EventAsInteger( aEventInfo.Event() );
+
+        TStreamEncoder streamEncoder;
+        TDes8& dataDes = 
+            static_cast<CMMFDataBuffer*>( aOutputBuffer )->Data();
+        const TUint8* seekPtr = dataDes.Ptr();
+         // 32 bits
+        dataDes.SetLength( KEventBlockLengthInBytes );
+        
+        streamEncoder.Initialize( const_cast<TUint8*>( seekPtr ), 0, 0 );
+        
+        // Encode Event Field
+        streamEncoder.Encode( eventAsInteger, KEventFieldBits );
+        
+        // Encode end bit for final packet.
+        streamEncoder.Encode( aEventInfo.EndBit(), 1 );
+        
+        // Encode reserved bit
+        streamEncoder.Encode( 0, 1 );
+        
+        // Encode volume field. Volume must be encoded only if it is relevant
+        // to the event. Otherwise it must be set to zero.
+        streamEncoder.Encode( aEventInfo.Volume(), KVolFieldBits );
+        
+        // Encode duration field
+        streamEncoder.Encode( aEventInfo.Duration(), KDurationFieldBits );
+        
+        // Update event array for redundant events encoding
+        iEventArray.Append( aEventInfo );
+        if ( KDTMFDefaultRedundancyCount < iEventArray.Count() )
+            {
+            iEventArray.Remove( 0 );
+            }
+        
+        return KErrNone;
+        }
+    else
+        {
+        return KErrArgument;
+        }
+    }
+
+// ---------------------------------------------------------------------------
+// CDTMFPayloadEncoder::EncodeRedundantEventPayload
+// Encodes events to Event Payload Format using Multi-Event Redundancy.
+// ---------------------------------------------------------------------------
+//
+/*
+   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 
+   |F|   block PT  |     timestamp offset      |   block length    | 
+   |1|     97      |            11200          |         4         | 
+   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 
+   |F|   block PT  |     timestamp offset      |   block length    | 
+   |1|     97      |   11200 - 6400 = 4800     |         4         | 
+   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 
+   |F|   Block PT  | 
+   |0|     97      | 
+   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 
+   |     digit     |E R| volume    |          duration             | 
+   |       9       |1 0|     7     |             1600              |  
+   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 
+   |     digit     |E R| volume    |          duration             | 
+   |       1       |1 0|    10     |             2000              |  
+   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 
+   |     digit     |E R| volume    |          duration             | 
+   |       1       |0 0|    20     |              400              |  
+   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 
+   */
+TInt CDTMFPayloadEncoder::EncodeRedundantEventPayload(
+    const TDTMFEventPayloadInfo& aEventInfo, CMMFBuffer* aOutputBuffer )
+    {
+    #ifdef VOIP_TRACE_ENABLED
+        VoipTrace( "%x %x", MCC_TRACE, MCC_DTMF_PLF_ENC_ENCREDEVPL );
+    #endif
+    if ( aOutputBuffer )
+        {
+        TStreamEncoder streamEncoder;
+        TDes8& dataDes = 
+            static_cast<CMMFDataBuffer*>( aOutputBuffer )->Data();
+        const TUint8* seekPtr = dataDes.Ptr();
+        
+        // Count length of packet. Event consists of 4 byte header and 4 byte
+        // payload. Length of the redundancy header of last event is one byte.
+        TInt length( iEventArray.Count() * KEventLengthInBytes - 3 );
+        if ( length > 0 && length < dataDes.MaxSize() )
+            {
+            dataDes.SetLength( length );    
+            }
+
+        streamEncoder.Initialize( const_cast<TUint8*>( seekPtr ), 0, 0 );
+        
+        // Update event array
+        iEventArray.Append( aEventInfo );
+        if ( KDTMFDefaultRedundancyCount < iEventArray.Count() )
+            {
+            iEventArray.Remove( 0 );
+            }
+            
+        // Encode redundancy headers
+        TInt eventCount( iEventArray.Count() );
+        for ( TInt i = 0; i < eventCount; i++ )
+            {
+            if ( i != eventCount - 1 )
+                {
+                // F-bit
+                streamEncoder.Encode( 1, 1 );
+                streamEncoder.Encode( iPayloadType, KBlockPTBits );
+                
+                // Encode Timestamp offset
+                TUint offset( iEventArray[eventCount - 1].TimeStamp().Int()
+                                         - iEventArray[i].TimeStamp().Int() );
+                streamEncoder.Encode( offset, KTimeStampOffsetBits );
+                
+                streamEncoder.Encode( KEventBlockLengthInBytes, 
+                                                        KBlockLengthBits );
+                }
+            else
+                {
+                // Last redundancy header
+                // F-bit
+                streamEncoder.Encode( 0, 1 );
+                streamEncoder.Encode( iPayloadType, KBlockPTBits );
+                }
+            }
+
+        // Encode payload blocks
+        for ( TInt index = 0; index < eventCount; index++ )
+            {
+            // Possible events are: 0-9, * (10), # (11), A-D (12-15)
+            TInt eventAsInteger = 
+                                EventAsInteger( iEventArray[index].Event() );
+
+            // Encode digit field
+            streamEncoder.Encode( eventAsInteger, KEventFieldBits );
+
+            // Encode E-bit
+            if ( index != eventCount - 1 )
+                {
+                streamEncoder.Encode( 1, 1 );
+                }
+            else
+                {
+                // Last event
+                streamEncoder.Encode( 0, 1 );
+                }
+
+            // Encode Reserved bit
+            streamEncoder.Encode( 0, 1 );
+
+            // Encode Volume Field
+            streamEncoder.Encode( iEventArray[index].Volume(), 
+                                                            KVolFieldBits );
+            
+            // Encode Duration Field
+            streamEncoder.Encode( iEventArray[index].Duration(), 
+                                                        KDurationFieldBits );
+            }
+
+        return KErrNone;
+        }
+    else
+        {
+        return KErrArgument;
+        }
+    }
+
+// ---------------------------------------------------------------------------
+// CDTMFPayloadEncoder::EncodeTone
+// Forms tone payload for DTMF digit.
+// ---------------------------------------------------------------------------
+//
+/*
+     0                   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 
+    +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 
+    |    modulation   |T|  volume   |          duration             | 
+    +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 
+    |R R R R|       frequency       |R R R R|       frequency       | 
+    +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 
+    |R R R R|       frequency       |R R R R|       frequency       | 
+    +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 
+        ...... 
+    
+    +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 
+    |R R R R|       frequency       |R R R R|      frequency        | 
+    +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 
+*/
+TInt CDTMFPayloadEncoder::EncodeTone( const TDTMFTonePayloadInfo& aToneInfo,
+    CMMFDataBuffer* aOutputBuffer ) const
+    {
+    #ifdef VOIP_TRACE_ENABLED
+        VoipTrace( "%x %x", MCC_TRACE, MCC_DTMF_PLF_ENC_ENCTONE );
+    #endif
+    if ( aOutputBuffer )
+        {
+        TInt toneAsInteger = EventAsInteger( aToneInfo.Tone() );
+        if ( toneAsInteger < 0 || toneAsInteger >= KDtmfGroupFrequencyCount )
+            {
+            return KErrArgument;
+            }
+        TUint lowGroupFrequency( KDTMFLowGroupFrequencies[ toneAsInteger ] );
+        TUint highGroupFrequency( 
+                                KDTMFHighGroupFrequencies[ toneAsInteger ] );
+        
+        TStreamEncoder streamEncoder;
+        TDes8& dataDes = 
+            STATIC_CAST( CMMFDataBuffer*, aOutputBuffer )->Data();
+        const TUint8* seekPtr = dataDes.Ptr();
+        // 2 * 32 bits
+        dataDes.SetLength( KEventLengthInBytes );
+        
+        streamEncoder.Initialize( const_cast<TUint8*>( seekPtr ), 0, 0 );
+        
+        // Encode modulation field
+        streamEncoder.Encode( aToneInfo.Modulation(), KModulationBits );
+        
+        // Encode T bit
+        streamEncoder.Encode( 0, 1 );
+        
+        // Encode Volume Field
+        streamEncoder.Encode( aToneInfo.Volume(), KVolFieldBits );
+        
+        // Encode Duration Field
+        streamEncoder.Encode( aToneInfo.Duration(), KDurationFieldBits );
+        
+        // Encode four R(eserved) bits
+        streamEncoder.Encode( 0, KReservedBits );
+        
+        // Encode first Frequency Field
+        streamEncoder.Encode( lowGroupFrequency, KFrequencyBits );
+        
+        // Encode four R(eserved) bits
+        streamEncoder.Encode( 0, KReservedBits );
+        
+        // Encode second Frequency Field
+        streamEncoder.Encode( highGroupFrequency, KFrequencyBits );
+        
+        return KErrNone;
+        }
+    else
+        {
+        return KErrArgument;
+        }
+    }
+
+// ---------------------------------------------------------------------------
+// CDTMFPayloadEncoder::UpdateEventPayload
+// Updates previously created event payload according to parameters.
+// ---------------------------------------------------------------------------
+//
+TInt CDTMFPayloadEncoder::UpdateEventPayload( const TBool aFinalPacket,
+    const TUint aDuration,
+    CMMFDataBuffer* aOutputBuffer ) const
+    {
+    #ifdef VOIP_TRACE_ENABLED
+        VoipTrace( "%x %x", MCC_TRACE, MCC_DTMF_PLF_ENC_UPDEVPL );
+    #endif
+    if ( aOutputBuffer )
+        {
+        TStreamEncoder streamEncoder;
+        TDes8& dataDes = STATIC_CAST( CMMFDataBuffer*, 
+                                                    aOutputBuffer )->Data();
+        const TUint8* seekPtr = dataDes.Ptr();
+        
+        // End bit starts from the beginning of second byte
+        streamEncoder.Initialize( const_cast<TUint8*>( seekPtr ), 1, 0 );
+        
+        // Encode End Bit
+        if ( aFinalPacket )
+            {
+            streamEncoder.Encode( 1, 1 );    
+            }
+            
+        // Duration Field starts from third byte
+        streamEncoder.SetBitIndex( 0 );
+        streamEncoder.SetByteIndex( KByteIndex );
+        
+        // Encode Duration Field with new value
+        streamEncoder.Encode( aDuration, KDurationFieldBits );
+        
+        return KErrNone;
+        }
+    else
+        {
+        return KErrArgument;
+        }
+    }
+
+
+// ---------------------------------------------------------------------------
+// CDTMFPayloadEncoder::UpdateTonePayload
+// Updates previously created tone payload according to parameters.
+// ---------------------------------------------------------------------------
+//     
+TInt CDTMFPayloadEncoder::UpdateTonePayload( const TUint aToneDuration,
+    CMMFDataBuffer* aOutputBuffer ) const
+    {
+    #ifdef VOIP_TRACE_ENABLED
+        VoipTrace( "%x %x", MCC_TRACE, MCC_DTMF_PLF_ENC_UPDTONEPL );
+    #endif
+
+    if ( aOutputBuffer )
+        {
+        TStreamEncoder streamEncoder;
+        TDes8& dataDes = STATIC_CAST( CMMFDataBuffer*, 
+                                      aOutputBuffer )->Data();
+        const TUint8* seekPtr = dataDes.Ptr();
+
+        // Duration Field starts from third byte
+        streamEncoder.Initialize( const_cast<TUint8*>( seekPtr ), 3, 0 );
+        
+        // Encode Duration Field with a new value
+        streamEncoder.Encode( aToneDuration, KDurationFieldBits );
+
+        return KErrNone;
+        }
+    else
+        {
+        return KErrArgument;
+        }
+    }
+
+// ---------------------------------------------------------------------------
+// CDTMFPayloadEncoder::PayloadFormat
+// Returns payload format in use.
+// ---------------------------------------------------------------------------
+//
+TDTMFPayloadFormat CDTMFPayloadEncoder::PayloadFormat( ) const
+    {
+    return iPayloadFormat;
+    }
+
+// ---------------------------------------------------------------------------
+// CDTMFPayloadEncoder::SetPayloadFormat
+// Sets payload format in use.
+// ---------------------------------------------------------------------------
+//
+TInt CDTMFPayloadEncoder::SetPayloadFormat( 
+    TDTMFPayloadFormat aPayloadFormat )
+    {
+    #ifdef VOIP_TRACE_ENABLED
+        VoipTrace( "%x %x %d", MCC_TRACE, MCC_DTMF_PLF_ENC_SETPLF, aPayloadFormat );
+    #endif
+
+    if ( EDTMFPayloadFormatEvent != aPayloadFormat
+         && EDTMFPayloadFormatTone != aPayloadFormat
+         && EDTMFPayloadFormatRedEvents != aPayloadFormat )
+        {
+        return KErrNotSupported;
+        }
+    else
+        {
+        iPayloadFormat = aPayloadFormat;
+        }
+
+    return KErrNone;
+    }
+
+// ---------------------------------------------------------------------------
+// CDTMFPayloadEncoder::PayloadType
+// Returns payload type in use.
+// ---------------------------------------------------------------------------
+//
+TUint8 CDTMFPayloadEncoder::PayloadType( ) const
+    {
+    return iPayloadType;
+    }
+
+// ---------------------------------------------------------------------------
+// CDTMFPayloadEncoder::SetPayloadType
+// Sets payload type in use.
+// ---------------------------------------------------------------------------
+//    
+void CDTMFPayloadEncoder::SetPayloadType( TUint8 aPayloadType )
+    {
+    iPayloadType = aPayloadType;
+    }
+     
+// ---------------------------------------------------------------------------
+// CDTMFPayloadEncoder::EventAsInteger
+// Converts DTMF digit / Tone represented as TChar to the integer encoding
+// used in payload.
+// ---------------------------------------------------------------------------
+//
+TInt CDTMFPayloadEncoder::EventAsInteger( const TChar& aEvent ) const
+    {
+    TInt returnValue( KErrNotFound );
+
+    // Conversion because of PC_LINT warning #1561
+    TChar argument( aEvent );
+    // For PC_LINT error   #1023
+    TUint nullChar( '0' );
+
+    if ( '0' <= aEvent && '9' >= aEvent )
+        {
+        returnValue = argument - nullChar;
+        }
+    else
+        {
+        switch ( aEvent )
+            {
+            case '*':
+                returnValue = KEventCodeForAsterisk;
+                break;
+            case '#':
+                returnValue = KEventCodeForHashMark;
+                break;
+            case 'a':
+            case 'A':
+                returnValue = KEventCodeForA;
+                break;
+            case 'b':
+            case 'B':
+                returnValue = KEventCodeForB;
+                break;
+            case 'c':                
+            case 'C':
+                returnValue = KEventCodeForC;
+                break;
+            case 'd':
+            case 'D':
+                returnValue = KEventCodeForD;
+                break;
+            default:
+                break;
+            }
+        }
+
+    return returnValue;
+    }
+
+//  End of File