multimediacommscontroller/mmccdtmfpayloadformat/src/dtmfpayloaddecoder.cpp
changeset 0 1bce908db942
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/multimediacommscontroller/mmccdtmfpayloadformat/src/dtmfpayloaddecoder.cpp	Tue Feb 02 01:04:58 2010 +0200
@@ -0,0 +1,521 @@
+/*
+* Copyright (c) 2006 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 decoder for named telephone events
+*                and tones.
+*
+*/
+
+
+
+
+// INCLUDES
+#include <mmf/server/mmfdatabuffer.h>
+#include "dtmfpayloaddecoder.h"
+#include "streamformatter.h"
+
+// CONSTANTS
+const TInt KBitIndex = 8;
+const TInt KReservedBits = 4;
+const TUint KMaxEventInteger = 9;
+
+#ifdef VOIP_TRACE_ENABLED
+#include <voip_trace.h>
+#endif
+
+// ======== MEMBER FUNCTIONS ========
+
+
+// ---------------------------------------------------------------------------
+// CDTMFPayloadDecoder::CDTMFPayloadDecoder
+// C++ default constructor can NOT contain any code, that
+// might leave.
+// ---------------------------------------------------------------------------
+//
+CDTMFPayloadDecoder::CDTMFPayloadDecoder()
+    {
+    }
+
+// ---------------------------------------------------------------------------
+// CDTMFPayloadDecoder::NewL
+// Two-phased constructor.
+// ---------------------------------------------------------------------------
+//
+CDTMFPayloadDecoder* CDTMFPayloadDecoder::NewL()
+    {
+    DP_DTMF_DECODE( _L("CDTMFPayloadDecoder::NewL") );
+    #ifdef VOIP_TRACE_ENABLED
+        VoipTrace( "%x %x", MCC_TRACE, MCC_DTMF_PLF_DEC_NEWL );
+    #endif
+    
+    CDTMFPayloadDecoder* self = new( ELeave ) CDTMFPayloadDecoder;
+    return self;
+    }
+
+// ---------------------------------------------------------------------------
+// CDTMFPayloadDecoder::~CDTMFPayloadDecoder
+// Destructor.
+// ---------------------------------------------------------------------------
+//
+CDTMFPayloadDecoder::~CDTMFPayloadDecoder()
+    {
+    DP_DTMF_DECODE( _L("CDTMFPayloadDecoder::~CDTMFPayloadDecoder") );
+    #ifdef VOIP_TRACE_ENABLED
+        VoipTrace( "%x %x", MCC_TRACE, MCC_DTMF_PLF_DEC_DESTRUCTOR );
+    #endif
+    
+    iEventArray.Reset();
+    }
+
+// ---------------------------------------------------------------------------
+// CDTMFPayloadDecoder::DecodeEventPayload
+// Decodes one DTMF digit or mutually exclusive events from Event Payload
+// Format packet.
+// ---------------------------------------------------------------------------
+//
+/*
+    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 CDTMFPayloadDecoder::DecodeEventPayload( CMMFBuffer* aSourceBuffer,
+    RArray<TDTMFEventPayloadInfo>& aEventInfos )
+    {
+    DP_DTMF_DECODE( _L("CDTMFPayloadDecoder::DecodeEventPayload") );
+    #ifdef VOIP_TRACE_ENABLED
+        VoipTrace( "%x %x %x", MCC_TRACE, MCC_DTMF_PLF_DEC_DECEVENTPAYLOAD,
+        aSourceBuffer );
+    #endif
+    
+    if ( EDTMFPayloadFormatRedEvents == iPayloadFormat )
+        {
+        return DecodeRedundantEventPayload( aSourceBuffer, aEventInfos );
+        }
+        
+    if ( aSourceBuffer )
+        {
+        TDes8& dataDes = 
+            static_cast<CMMFDataBuffer*>( aSourceBuffer )->Data();
+        const TUint8* seekPtr = dataDes.Ptr();
+        TInt events = dataDes.Length( ) / KEventBlockLengthInBytes;
+        
+        TStreamDecoder streamDecoder;
+        
+        streamDecoder.Initialize( const_cast<TUint8*>( seekPtr ), 0, 0 );
+        
+        while ( events-- )
+            {
+            // Decode Event Field
+            TInt eventCode = streamDecoder.Decode( KEventFieldBits );
+            TChar charRepresentation;
+            if ( KErrNone == ConvertToChar( eventCode, charRepresentation ) )
+                {
+                iDecodedEventInfo.SetEvent( charRepresentation );
+                
+                // Decode end bit for final packet
+                iDecodedEventInfo.SetEndBit( streamDecoder.Decode( 1 ) );
+                
+                // Decode reserved bit
+                streamDecoder.Decode( 1 );
+                
+                // Decode volume field.
+                // Volume field must be ignored if event 
+                // is not DTMF digit (RFC 2833)
+                if ( KEventCodeForD > eventCode )
+                    {
+                    iDecodedEventInfo.SetVolume( 
+                                        streamDecoder.Decode(KVolFieldBits) );
+                    }
+                else
+                    {
+                    streamDecoder.Decode( KVolFieldBits );
+                    iDecodedEventInfo.SetVolume( 0 );
+                    }
+                
+                // Decode duration field
+                iDecodedEventInfo.SetDuration( 
+                                streamDecoder.Decode(KDurationFieldBits) );
+                
+                // Time stamp from RTP header
+                iDecodedEventInfo.SetTimeStamp( iCurTimeStamp );
+                
+                aEventInfos.Append( iDecodedEventInfo );
+                        
+                DP_DTMF_DECODE5(
+                    _L( "Decoded event: %d, EndBit: %d, Volume: %d, Duration: %d" ),
+                                 static_cast<TUint>( iDecodedEventInfo.Event() ), 
+                                 iDecodedEventInfo.EndBit(), 
+                                 iDecodedEventInfo.Volume(), 
+                                 iDecodedEventInfo.Duration() );
+                }
+            else
+                {
+                DP_DTMF_DECODE( _L( "CDTMFPayloadDecoder::DecodeEventPayload - Not supported event! ") );
+                }                
+            }
+        
+        return KErrNone;    
+        }
+    else
+        {
+        return KErrArgument;
+        }
+    }    
+
+// ---------------------------------------------------------------------------
+// CDTMFPayloadDecoder::DecodeRedundantEventPayload
+// Decodes events from Event Payload Format where is used 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 CDTMFPayloadDecoder::DecodeRedundantEventPayload( 
+    CMMFBuffer* aSourceBuffer,
+    RArray<TDTMFEventPayloadInfo>& aEventInfos )
+    {
+    DP_DTMF_DECODE( _L("CDTMFPayloadDecoder::DecodeRedundantEventPayload") );
+    
+    #ifdef VOIP_TRACE_ENABLED
+        VoipTrace( "%x %x %x", MCC_TRACE, MCC_DTMF_PLF_DEC_DECREDEVPL, aSourceBuffer );
+    #endif
+    
+    if ( aSourceBuffer )
+        {
+        TDes8& dataDes = 
+            static_cast<CMMFDataBuffer*>( aSourceBuffer )->Data();
+        const TUint8* seekPtr = dataDes.Ptr();
+        
+        TStreamDecoder streamDecoder;
+        
+        streamDecoder.Initialize( const_cast<TUint8*>( seekPtr ), 0, 0 );
+        
+        aEventInfos.Reset();
+        
+        // Count events in a payload from the redundancy headers
+        TInt eventCount( 0 );
+        TBool FBitSet( ETrue );
+        RArray< TTimeIntervalMicroSeconds32 > timeStamps;
+        
+        while ( FBitSet )
+            {
+            eventCount++;
+            
+            FBitSet = static_cast<TBool>( streamDecoder.Decode( 1 ) );
+            streamDecoder.Decode( KBlockPTBits );
+            
+            if ( FBitSet )
+                {
+                TUint offset = streamDecoder.Decode( KTimeStampOffsetBits );
+                timeStamps.Append( TTimeIntervalMicroSeconds32( 
+                                            iCurTimeStamp.Int() - offset ) );
+                }
+            else
+                {
+                timeStamps.Append( TTimeIntervalMicroSeconds32( 
+                                                    iCurTimeStamp.Int() ) );
+                }                
+
+            // Jump to the beginning of next redundancy header
+            streamDecoder.Initialize( const_cast<TUint8*>( seekPtr ), 
+                                eventCount * KEventBlockLengthInBytes, 0 );
+            }
+
+        // Count index of first real event.
+        // Last redundancy header consists of F-bit and PT only.
+        streamDecoder.Initialize( const_cast<TUint8*>( seekPtr ), 
+                                  eventCount * KEventBlockLengthInBytes - 
+                                  KEventBlockLengthInBytes, KBitIndex );
+
+        // Decode all events from payload to the event info array.
+        for ( TInt i = 0; i < eventCount; i++ )
+            {
+            // Decode Event Field
+            TInt eventCode = streamDecoder.Decode( KEventFieldBits );
+            TChar charRepresentation;
+            
+            if ( KErrNone == ConvertToChar( eventCode, charRepresentation ) )
+                {
+                iDecodedEventInfo.SetEvent( charRepresentation );
+                
+                // Decode end bit for final packet
+                iDecodedEventInfo.SetEndBit( streamDecoder.Decode( 1 ) );
+                
+                // Decode reserved bit
+                streamDecoder.Decode( 1 );
+                
+                // Decode volume field.
+                iDecodedEventInfo.SetVolume( streamDecoder.Decode( 
+                                                            KVolFieldBits ) );
+                
+                // Decode duration field
+                iDecodedEventInfo.SetDuration( streamDecoder.Decode( 
+                                                    KDurationFieldBits ) );
+                
+                // Set time stamp
+                iDecodedEventInfo.SetTimeStamp( timeStamps[i] );
+                
+                aEventInfos.Append( iDecodedEventInfo );
+                }
+            else
+                {
+                DP_DTMF_DECODE( _L( "CDTMFPayloadDecoder::DecodeRedEventPayload" ) );
+                DP_DTMF_DECODE( _L( "- Not supported event! ") );
+                }                
+            }
+
+        timeStamps.Reset();
+
+        // Delete already played events from the beginning of aEventInfos
+        // array based on time stamp
+        TInt latestRecordedEventInd( iEventArray.Count() - 1 );
+        
+        if ( 0 <= latestRecordedEventInd )
+            {
+            while ( aEventInfos.Count() && aEventInfos[0].TimeStamp() 
+                <= iEventArray[ latestRecordedEventInd ].TimeStamp() )
+                {
+                // Redundant event has earlier time stamp than latest played
+                // event we must delete this.
+                aEventInfos.Remove( 0 );
+                }
+            }
+
+        // Copy count of accepted events to the end of iEventArray and delete
+        // same count from the beginning of array. Decoder must keep copies of
+        // EventInfos, because PayloadFormatRead may make Reset() for a
+        // aEventInfos Array.
+        for ( TInt j = 0; j < aEventInfos.Count(); j++ )
+            {
+            iEventArray.Append( aEventInfos[ j ] );
+            if ( KDTMFDefaultRedundancyCount < iEventArray.Count() )
+                {
+                iEventArray.Remove( 0 );
+                }
+            }
+
+        return KErrNone;
+        }
+    else
+        {
+        return KErrArgument;
+        }
+    }
+
+// ---------------------------------------------------------------------------
+// CDTMFPayloadDecoder::DecodeTonePayload
+// Decodes tones from Tone Payload Format packet.
+// Currently only DTMF tones are decoded (first tone).
+// Format of line event tones are unclear. Are multiple parts containing
+// line events encoded in one RTP packet or one part per RTP packet.
+// No proper support at DevSound / AudioServer to play out tone payload.
+// ---------------------------------------------------------------------------
+//
+/*
+     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 CDTMFPayloadDecoder::DecodeTonePayload( CMMFBuffer* aSourceBuffer,
+    RArray<TDTMFTonePayloadInfo>& aToneInfos )
+    {
+    DP_DTMF_DECODE( _L( "CDTMFPayloadDecoder::DecodeTonePayload" ) );
+    #ifdef VOIP_TRACE_ENABLED
+        VoipTrace( "%x %x %x", MCC_TRACE, MCC_DTMF_PLF_DEC_DECTONEPL, aSourceBuffer );
+    #endif
+    
+    if ( aSourceBuffer )
+        {
+        TDes8& dataDes = 
+            static_cast<CMMFDataBuffer*>( aSourceBuffer )->Data();
+        const TUint8* seekPtr = dataDes.Ptr();
+        
+        TStreamDecoder streamDecoder;
+        
+        streamDecoder.Initialize( const_cast<TUint8*>( seekPtr ), 0, 0 );
+        
+        // Encode modulation field
+        iDecodedToneInfo.SetModulation( streamDecoder.Decode( 
+                                                        KModulationBits ) );
+        
+        // Encode T bit
+        iDecodedToneInfo.SetTBit( streamDecoder.Decode( 1 ) );
+        
+        // Encode Volume Field
+        iDecodedToneInfo.SetVolume( streamDecoder.Decode( KVolFieldBits ) );
+        
+        // Encode Duration Field
+        iDecodedToneInfo.SetDuration( streamDecoder.Decode( 
+                                                    KDurationFieldBits ) );
+        
+        // Encode four R(eserved) bits
+        streamDecoder.Decode( KReservedBits );
+        
+        // Encode first Frequency Field
+        iDecodedToneInfo.SetLowFrequency( streamDecoder.Decode( 
+                                                        KFrequencyBits ) );
+        
+        // Encode four R(eserved) bits
+        streamDecoder.Decode( KReservedBits );
+        
+        // Encode second Frequency Field
+        iDecodedToneInfo.SetHighFrequency( streamDecoder.Decode( 
+                                                        KFrequencyBits ) );
+        
+        aToneInfos.Append( iDecodedToneInfo );
+        
+        return KErrNone;
+        }
+    else
+        {
+        return KErrArgument;
+        }
+    }
+
+// ---------------------------------------------------------------------------
+// CDTMFPayloadDecoder::PayloadFormat
+// Returns payload format in use.
+// ---------------------------------------------------------------------------
+//
+TDTMFPayloadFormat CDTMFPayloadDecoder::PayloadFormat( ) const
+    {
+    DP_DTMF_DECODE2( _L( "CDTMFPayloadDecoder::PayloadFormat - Format: %d" ),
+        iPayloadFormat );
+    
+    return iPayloadFormat;
+    }
+
+// ---------------------------------------------------------------------------
+// CDTMFPayloadDecoder::SetPayloadFormat
+// Sets payload format in use.
+// ---------------------------------------------------------------------------
+//    
+TInt CDTMFPayloadDecoder::SetPayloadFormat( 
+    TDTMFPayloadFormat aPayloadFormat )
+    {
+    DP_DTMF_DECODE2( _L( "CDTMFPayloadDecoder::SetPayloadFormat - Format: %d" ),
+        aPayloadFormat );
+    #ifdef VOIP_TRACE_ENABLED
+        VoipTrace( "%x %x %d", MCC_TRACE, MCC_DTMF_PLF_DEC_SETPLF, aPayloadFormat );
+    #endif
+    
+    if ( EDTMFPayloadFormatEvent != aPayloadFormat
+         && EDTMFPayloadFormatTone != aPayloadFormat
+         && EDTMFPayloadFormatRedEvents != aPayloadFormat )
+        {
+        return KErrNotSupported;
+        }
+    else
+        {
+        iPayloadFormat = aPayloadFormat;
+        }
+        
+    return KErrNone;
+    }
+
+// ---------------------------------------------------------------------------
+// CDTMFPayloadDecoder::SetCurTimeStamp
+// Sets the time stamp of a RTP packet containing payload which is decoded 
+// next.
+// ---------------------------------------------------------------------------
+//      
+void CDTMFPayloadDecoder::SetCurTimeStamp( 
+    const TTimeIntervalMicroSeconds32& aTimeStamp )
+    {
+    DP_DTMF_DECODE2( _L( "CDTMFPayloadDecoder::SetCurTimeStamp - TimeStamp: %d" ),
+        aTimeStamp.Int() );
+        
+    #ifdef VOIP_TRACE_ENABLED
+        VoipTrace( "%x %x %d", MCC_TRACE, MCC_DTMF_PLF_DEC_SETCURTS, aTimeStamp.Int() );
+    #endif
+    
+    iCurTimeStamp = aTimeStamp;
+    }
+
+// ---------------------------------------------------------------------------
+// CDTMFPayloadDecoder::ConvertToChar
+// Converts integer presentation used in a payload format to the character.
+// ---------------------------------------------------------------------------
+//
+TInt CDTMFPayloadDecoder::ConvertToChar( TUint aEvent, TChar& aChar ) const
+    {
+    TInt conversionResult( KErrNone );
+
+    if ( aEvent <= KMaxEventInteger )
+        {
+        aChar = TChar( aEvent + '0' );
+        }
+    else
+        {
+        switch ( aEvent )
+            {
+            case KEventCodeForAsterisk:
+                aChar = '*';
+                break;
+            case KEventCodeForHashMark:
+                aChar = '#';
+                break;
+            case KEventCodeForA:
+                aChar = 'a';
+                break;
+            case KEventCodeForB:
+                aChar = 'b';
+                break;
+            case KEventCodeForC:
+                aChar = 'c';
+                break;
+            case KEventCodeForD:
+                aChar = 'd';
+                break;
+            default:
+                conversionResult = KErrNotSupported;
+                break;
+            }
+        }    
+
+    return conversionResult;
+    }
+
+//  End of File