multimediacommscontroller/mmccamrpayloadformat/src/amrpayloaddecoder.cpp
changeset 0 1bce908db942
equal deleted inserted replaced
-1:000000000000 0:1bce908db942
       
     1 /*
       
     2 * Copyright (c) 2002-2006 Nokia Corporation and/or its subsidiary(-ies).
       
     3 * All rights reserved.
       
     4 * This component and the accompanying materials are made available
       
     5 * under the terms of "Eclipse Public License v1.0"
       
     6 * which accompanies this distribution, and is available
       
     7 * at the URL "http://www.eclipse.org/legal/epl-v10.html".
       
     8 *
       
     9 * Initial Contributors:
       
    10 * Nokia Corporation - initial contribution.
       
    11 *
       
    12 * Contributors:
       
    13 *
       
    14 * Description:    PayloadFormat plugin capable to read RTP payload containing
       
    15 *                AMR audio.
       
    16 *
       
    17 */
       
    18 
       
    19 
       
    20 
       
    21 
       
    22 // INCLUDE FILES
       
    23 #include "amrpayloaddecoder.h"
       
    24 #include "amrcommonutil.h"
       
    25 #include "amrpayloadheader.h"
       
    26 #include "amrtocentry.h"
       
    27 
       
    28 // ============================= LOCAL FUNCTIONS ===============================
       
    29 
       
    30 // ============================ MEMBER FUNCTIONS ===============================
       
    31 
       
    32 // -----------------------------------------------------------------------------
       
    33 // CAmrPayloadDecoder::CAmrPayloadDecoder
       
    34 // C++ default constructor can NOT contain any code, that
       
    35 // might leave.
       
    36 // -----------------------------------------------------------------------------
       
    37 //
       
    38 CAmrPayloadDecoder::CAmrPayloadDecoder( TBool aIsNb ) : CAmrPayloadFormatter( aIsNb )
       
    39     {
       
    40    	DP_AMR_DECODE ("CAmrPayloadDecoder::CAmrPayloadDecoder");
       
    41     }
       
    42 
       
    43 
       
    44 // -----------------------------------------------------------------------------
       
    45 // CAmrPayloadEncoder::ConstructL
       
    46 // Symbian 2nd phase constructor can leave.
       
    47 // -----------------------------------------------------------------------------
       
    48 //
       
    49 void CAmrPayloadDecoder::ConstructL( )
       
    50     {
       
    51     DP_AMR_DECODE( "CAmrPayloadDecoder::ConstructL" );
       
    52         
       
    53     // Allocate memory for iHeaderDecoder and iTocEntryDecoder
       
    54     iHeaderDecoder = CAmrPayloadHeader::NewL();
       
    55     iTocEntryDecoder = CAmrTocEntry::NewL();
       
    56     
       
    57     #ifdef FTD_ENABLED
       
    58     
       
    59     User::LeaveIfError( iCodecStatsQueue.OpenGlobal( KMccCodecStats, 
       
    60         EOwnerProcess ) );   
       
    61     User::LeaveIfError( iJBufStatsQueue.OpenGlobal( KMccJBufferStats, 
       
    62         EOwnerProcess ) );    
       
    63     
       
    64     #endif
       
    65     }
       
    66 
       
    67 
       
    68 // -----------------------------------------------------------------------------
       
    69 // CAmrPayloadDecoder::NewL
       
    70 // Two-phased constructor.
       
    71 // -----------------------------------------------------------------------------
       
    72 //
       
    73 CAmrPayloadDecoder* CAmrPayloadDecoder::NewL( TBool aIsNb )
       
    74     {
       
    75     DP_AMR_DECODE( "CAmrPayloadDecoder::NewL" );
       
    76   
       
    77     CAmrPayloadDecoder* self = new( ELeave ) CAmrPayloadDecoder( aIsNb );
       
    78     
       
    79     CleanupStack::PushL( self );
       
    80     self->ConstructL( );
       
    81     CleanupStack::Pop( self );
       
    82 
       
    83     return self;
       
    84     }
       
    85 
       
    86 // -----------------------------------------------------------------------------
       
    87 // CAmrPayloadDecoder::~CAmrPayloadDecoder
       
    88 // Destructor
       
    89 // -----------------------------------------------------------------------------
       
    90 //
       
    91 CAmrPayloadDecoder::~CAmrPayloadDecoder( )
       
    92     {
       
    93     DP_AMR_DECODE( "CAmrPayloadDecoder::~CAmrPayloadDecoder" );
       
    94 
       
    95     delete iHeaderDecoder;
       
    96     delete iTocEntryDecoder;
       
    97 
       
    98     #ifdef FTD_ENABLED
       
    99     
       
   100     iCodecStatsQueue.Close();
       
   101     iJBufStatsQueue.Close();
       
   102     
       
   103     #endif
       
   104     }
       
   105 
       
   106 // -----------------------------------------------------------------------------
       
   107 // CAmrPayloadDecoder::DoInitialize
       
   108 // Initialize decoder. Decoder should be initialized when starting playing.
       
   109 // -----------------------------------------------------------------------------
       
   110 //
       
   111 void CAmrPayloadDecoder::DoInitialize()
       
   112     {
       
   113     DP_AMR_DECODE( "CAmrPayloadDecoder::DoInitialize" );
       
   114 
       
   115     }
       
   116     
       
   117 // -----------------------------------------------------------------------------
       
   118 // CAmrPayloadDecoder::DecodePayload
       
   119 // Decode payload data received in the payload buffer.
       
   120 // If AMR FEC is used and redundant frames are discarded, time stamp is
       
   121 // increased to correspond start of remaining frames.
       
   122 // -----------------------------------------------------------------------------
       
   123 //
       
   124 TInt CAmrPayloadDecoder::DecodePayload( TUint32& aTimeStamp, TUint32 aTimeStampInc )
       
   125     {
       
   126     DP_AMR_DECODE( "CAmrPayloadDecoder::DecodePayload" );
       
   127        
       
   128     iTimeStamp = aTimeStamp;
       
   129     iTimeStampInc = aTimeStampInc;
       
   130     Decode( iPayload, iPayloadSize );
       
   131     aTimeStamp = iTimeStamp;
       
   132     iFrameIndex = 0;
       
   133     return iDecodedFrames;
       
   134     }
       
   135 
       
   136 
       
   137 // -----------------------------------------------------------------------------
       
   138 // CAmrPayloadDecoder::ModeRequest
       
   139 // Get AMR codec mode request ( CMR ) received in the payload.
       
   140 // -----------------------------------------------------------------------------
       
   141 //
       
   142 TAmrModeRequest CAmrPayloadDecoder::ModeRequest() const
       
   143     {
       
   144     DP_AMR_DECODE( "CAmrPayloadDecoder::ModeRequest" );
       
   145        
       
   146     return iModeRequest;
       
   147     }
       
   148 
       
   149 
       
   150 // -----------------------------------------------------------------------------
       
   151 // CAmrPayloadDecoder::Frames
       
   152 // Get AMR frames decoded from the payload.
       
   153 // -----------------------------------------------------------------------------
       
   154 //
       
   155 TAmrFrame* CAmrPayloadDecoder::Frames( )
       
   156     {
       
   157     DP_AMR_DECODE( "CAmrPayloadDecoder::Frames" );
       
   158    
       
   159     return iFrames;
       
   160     }
       
   161 
       
   162 // -----------------------------------------------------------------------------
       
   163 // CAmrPayloadDecoder::CompareBuffers
       
   164 // Compares contents of two buffers.
       
   165 // -----------------------------------------------------------------------------
       
   166 //
       
   167 TBool CAmrPayloadDecoder::CompareBuffers( const TDesC8& aBuffer,
       
   168                                           const TAmrFrame& aFrameToCmp, 
       
   169                                           TInt aOctetsToCmp ) const
       
   170     {
       
   171     DP_AMR_DECODE( "CAmrPayloadDecoder::CompareBuffers" );
       
   172 
       
   173     TBool isSame( ETrue );
       
   174     if ( EAmrFrameNoData == aFrameToCmp.iFrameType )
       
   175         {
       
   176         if ( aBuffer.Size() )
       
   177             {
       
   178             return EFalse;
       
   179             }
       
   180         else
       
   181             {
       
   182             return ETrue;
       
   183             }
       
   184         }
       
   185     else
       
   186         {
       
   187         if ( 0 == aBuffer.Size() )
       
   188             {
       
   189             return EFalse;
       
   190             }
       
   191         }        
       
   192 
       
   193     TStreamDecoder decoder;
       
   194     decoder.Initialize( aFrameToCmp.iFrameData, 0, aFrameToCmp.iBitIndex );
       
   195     
       
   196     TInt octetsToCmp = aOctetsToCmp < aBuffer.Size() ? aOctetsToCmp : aBuffer.Size();
       
   197     for ( TInt i = 0; i < octetsToCmp && isSame; i++ )
       
   198         {
       
   199         TUint8 val = TUint8( decoder.Decode( KBitsIn1Byte ) );
       
   200         if ( aBuffer[i] != val )
       
   201             {
       
   202             isSame = EFalse;
       
   203             }
       
   204         }
       
   205        
       
   206     return isSame;
       
   207     }
       
   208     
       
   209 // -----------------------------------------------------------------------------
       
   210 // CAmrPayloadDecoder::Decode
       
   211 // Decode the AMR payload ( for one RTP packet ) from a given buffer.
       
   212 // If more frames is received than expected based on SDPs PTIme negotiation,
       
   213 // we may have AMR FEC frames in a payload. Frames from previous payload are
       
   214 // compared to first frame in a new payload. If match is found we have received
       
   215 // that frame before and have redundant frames, which MUST be discarded.
       
   216 // After processing frames them are saved for redundancy check at next round.
       
   217 // -----------------------------------------------------------------------------
       
   218 //
       
   219 void CAmrPayloadDecoder::Decode( const TUint8* aBuffer, 
       
   220                                  TInt aBufferSize )
       
   221     {
       
   222     DP_AMR_DECODE( "CAmrPayloadDecoder::Decode" );
       
   223         
       
   224     TInt byteIndex( 0 ); 
       
   225     TInt bitIndex( 0 );
       
   226     
       
   227     // Decode Payload Header first
       
   228     iHeaderDecoder->Decode( aBuffer, byteIndex, bitIndex );
       
   229     iModeRequest = iHeaderDecoder->iCmr;
       
   230     
       
   231     // Decode TOC entries
       
   232     iDecodedFrames = DecodeTableOfContents( aBuffer, aBufferSize, byteIndex, bitIndex );
       
   233     
       
   234     // Update frame positions in the `iFrames' array.
       
   235     CalculateFramePosition( aBuffer, iDecodedFrames );
       
   236     
       
   237     // Discard redundand frames already received
       
   238     TUint framesToDel( 0 );
       
   239     TInt numOfFramesSaved( iFrameDatas.Count() );
       
   240     DP_AMR_DECODE2( "CAmrPayloadDecoder::Decode - NUM OF SAVED FRAMES %d", numOfFramesSaved );
       
   241     
       
   242     DP_AMR_DECODE2( "CAmrPayloadDecoder::Decode - DECODED FRAMES %d", iDecodedFrames );
       
   243     
       
   244     TInt i = 0;
       
   245     TInt ind = 0;
       
   246 
       
   247     #ifdef _DEBUG
       
   248    	if ( iDecodedFrames > KMaxFrameCountPerPacket )
       
   249    		{
       
   250        	DP_AMR_DECODE3("CAmrPayloadDecoder::Decode, iDecodedFrames: %d > KMaxFrameCountPerPacket: %d",  \
       
   251         	iDecodedFrames , KMaxFrameCountPerPacket);	
       
   252         }
       
   253     for ( i = 0; i < iDecodedFrames; i++ )
       
   254         {
       
   255         DP_AMR_DECODE2( "DECODED FRAME #%d: ", i );
       
   256         if ( EAmrFrameNoData != iFrames[i].iFrameType )
       
   257             {
       
   258             TStreamDecoder decoder;
       
   259             TUint8* refBufPtr = iFrames[i].iFrameData;
       
   260             decoder.Initialize( refBufPtr, 0, iFrames[i].iBitIndex );
       
   261             TUint32 vals[KNumValue5];
       
   262             for ( ind = 0; ind < (TInt) KNumValue5; ind ++ )
       
   263                 {
       
   264                 vals[ind] = decoder.Decode( KBitsIn1Byte );
       
   265                 }
       
   266             DP_AMR_DECODE6( "| %d | %d | %d | %d | %d |", vals[KNumValue0], vals[KNumValue1],
       
   267             	vals[KNumValue2], vals[KNumValue3], vals[KNumValue4] );
       
   268             }
       
   269         else
       
   270             {
       
   271             DP_AMR_DECODE( "DECODED FRAME - NO DATA FRAME" );
       
   272             }            
       
   273         }
       
   274 
       
   275     for ( i = 0; i < numOfFramesSaved; i++ )
       
   276         {
       
   277         if ( (*iFrameDatas[i] ).Size() )
       
   278             {
       
   279             DP_AMR_DECODE3( "SAVED FRAME #%d, l: %d", i, (*iFrameDatas[i] ).Size() );
       
   280             }
       
   281         else
       
   282             {
       
   283             DP_AMR_DECODE2( "SAVED FRAME #%d - NO DATA FRAME: ", i  );
       
   284             }            
       
   285         }
       
   286     #endif
       
   287 
       
   288     // Last frame in previous payload is always other than NO_DATA frame,
       
   289     // so newly received frames can be compared to it.
       
   290     TInt lastFrameInd = numOfFramesSaved - 1 >= 0 ? numOfFramesSaved - 1 : 0;
       
   291     for ( i = 0; i < iDecodedFrames && numOfFramesSaved; i++ )
       
   292         {
       
   293         DP_AMR_DECODE2( "CMP LAST FRAME FROM PREV PAYLOAD TO NEW FRAME #%d", i );
       
   294         if ( CompareBuffers( *iFrameDatas[lastFrameInd],
       
   295                               iFrames[i],
       
   296                               KMaxCompareOctets ) )
       
   297             {
       
   298             // Last frame from previous payload matched with some frame in a
       
   299             // new payload. Frames from this point onwards can be accepted.
       
   300             framesToDel = i + 1;
       
   301             for ( ind = 0; ind < iDecodedFrames; ind++ )
       
   302                 {
       
   303                 iFrames[ ind ] = iFrames[ ind + framesToDel ];
       
   304                 }
       
   305 
       
   306             i = iDecodedFrames;     // Stop loop
       
   307             iDecodedFrames -= framesToDel;
       
   308             if ( iDecodedFrames <= 0 )
       
   309                 {
       
   310                 DP_AMR_DECODE( "Amr::Decode - NO FRAMES REMAINING AFTER RED CHECK" );
       
   311                 iDecodedFrames = 0;
       
   312                 }
       
   313             iTimeStamp += iTimeStampInc * framesToDel;
       
   314             }
       
   315         }
       
   316 
       
   317     DP_AMR_DECODE2( "NUMBER OF RED FRAMES SKIPPED %d: ", framesToDel );
       
   318 
       
   319     // Save received frames for redundancy check purposes
       
   320     if ( iDecodedFrames )
       
   321         {
       
   322         iFrameDatas.ResetAndDestroy();
       
   323         }
       
   324 
       
   325 	if ( iDecodedFrames > KMaxFrameCountPerPacket )
       
   326    		{
       
   327        	DP_AMR_DECODE3("CAmrPayloadDecoder::Decode, iDecodedFrames: %d > KMaxFrameCountPerPacket: %d",  \
       
   328         	iDecodedFrames , KMaxFrameCountPerPacket);	
       
   329         }
       
   330     for ( i = 0; i < iDecodedFrames; i++ )
       
   331         {
       
   332         if ( EAmrFrameNoData != iFrames[i].iFrameType )
       
   333             {
       
   334             TInt dataLen = SpeechBitCount( iFrames[i].iFrameType );
       
   335             HBufC8* frame = HBufC8::New( dataLen / KBitsIn1Byte + 1 );
       
   336             if (frame)
       
   337             	{
       
   338 	            TUint8* toBuf = const_cast<TUint8*>( ( *frame ).Ptr() );
       
   339     	        TStreamEncoder encoder;
       
   340         	    encoder.Initialize( toBuf, 0, 0 );
       
   341             	encoder.Encode( iFrames[i].iFrameData, 0, iFrames[i].iBitIndex, dataLen );
       
   342             	TPtr8 dataPtr = frame->Des();
       
   343             	dataPtr.SetLength( dataLen / KBitsIn1Byte + 1 );
       
   344             	if (iFrameDatas.Append( frame ) != KErrNone)
       
   345             		{
       
   346             		delete frame;
       
   347             		}
       
   348             	}
       
   349             }
       
   350         else
       
   351             {
       
   352             HBufC8* frame = HBufC8::New( 0 );
       
   353             if (frame && iFrameDatas.Append( frame ) != KErrNone)
       
   354             	{
       
   355             	delete frame;
       
   356             	}
       
   357             }            
       
   358         }
       
   359 
       
   360     #ifdef FTD_ENABLED
       
   361     
       
   362     TMccCodecStats stats;
       
   363     stats.iCMRDownlink = iModeRequest;
       
   364     stats.SetFieldUpdatedFlag( ECMRDownlink );
       
   365     iCodecStatsQueue.Send( stats );
       
   366     
       
   367     TMccJBufferStats jStats;
       
   368     jStats.iRedLevel = framesToDel;
       
   369     jStats.iSampleSizeMultiplier = iDecodedFrames;
       
   370     jStats.SetFieldUpdatedFlag( ERedLevel );
       
   371     jStats.SetFieldUpdatedFlag( ESampleSizeMultiplier );
       
   372         
       
   373     iJBufStatsQueue.Send( jStats );
       
   374     
       
   375     #endif        
       
   376     }
       
   377 
       
   378 // -----------------------------------------------------------------------------
       
   379 // CAmrPayloadDecoder::DecodeTableOfContents
       
   380 // Decode TOC ( Table of contents ) entries from the payload buffer.
       
   381 // Decoded values are put in `iFrames[]' array.
       
   382 // Return number of TOC entries decoded.
       
   383 // -----------------------------------------------------------------------------
       
   384 //
       
   385 TInt CAmrPayloadDecoder::DecodeTableOfContents( const TUint8* aBuffer, 
       
   386                                                 TInt aBufferSize,
       
   387                                                 TInt& aByteIndex, 
       
   388                                                 TInt& aBitIndex )
       
   389     {
       
   390     DP_AMR_DECODE( "CAmrPayloadDecoder::DecodeTableOfContents" );
       
   391         
       
   392     TInt curChannel( 0 );
       
   393     TInt i( 0 );
       
   394     
       
   395     for ( i = 0; ( i < KMaxFrameCountPerPacket ) && ( aByteIndex < aBufferSize ); i++ )
       
   396         {
       
   397         iTocEntryDecoder->Decode( aBuffer, aByteIndex, aBitIndex );
       
   398         iFrames[i].iFrameType = iTocEntryDecoder->iFrameType;
       
   399         iFrames[i].iFrameQualityInd = iTocEntryDecoder->iFrameQualityInd;
       
   400         iFrames[i].iChannel = curChannel;
       
   401 
       
   402         if ( !( iTocEntryDecoder->iFrameFollowed ) )
       
   403             {
       
   404             break;
       
   405             }
       
   406             
       
   407         // Update currentChannel
       
   408         curChannel++;
       
   409         if ( curChannel == iChannelCount )
       
   410             {
       
   411             curChannel = 0;
       
   412             }
       
   413         }
       
   414 
       
   415     return i + 1;
       
   416     }
       
   417 
       
   418 // -----------------------------------------------------------------------------
       
   419 // CAmrPayloadDecoder::CalculateFramePosition
       
   420 // Calculate frames' starting Byte and Bit positions.
       
   421 // -----------------------------------------------------------------------------
       
   422 //
       
   423 void CAmrPayloadDecoder::CalculateFramePosition( const TUint8* aBuffer, 
       
   424                                                  TInt aFrameCount )
       
   425     {
       
   426     DP_AMR_DECODE( "CAmrPayloadDecoder::CalculateFramePosition" );
       
   427         
       
   428     TUint frameByteIndex;
       
   429     TUint frameBitIndex;
       
   430     
       
   431     // Number of bits for CMR and TOC entries
       
   432     TUint bitCount = KHeaderBitsBE + KTOCFieldBitsBE * TUint( aFrameCount );    
       
   433 
       
   434     if ( aFrameCount > KMaxFrameCountPerPacket )
       
   435    		{
       
   436        	DP_AMR_DECODE3("CAmrPayloadDecoder::CalculateFramePosition, aFrameCount: %d > KMaxFrameCountPerPacket: %d",  \
       
   437         	aFrameCount, KMaxFrameCountPerPacket);	
       
   438         }
       
   439     for ( TInt i = 0; i < aFrameCount; i++ )
       
   440         {
       
   441         frameByteIndex = bitCount >> KNumValue3;
       
   442         frameBitIndex = bitCount & KBitIndex7;
       
   443         if ( EAmrFrameNoData == iFrames[i].iFrameType )
       
   444             {
       
   445             iFrames[i].iBitIndex = 0;
       
   446             iFrames[i].iFrameData = NULL;
       
   447             }
       
   448         else
       
   449             {
       
   450             // Set frame byte and bit positions
       
   451             iFrames[i].iBitIndex = frameBitIndex;
       
   452             iFrames[i].iFrameData = const_cast<TUint8*>( aBuffer ) + frameByteIndex;
       
   453             }
       
   454 
       
   455         // Update bit-count for next frame entry.
       
   456         bitCount = bitCount + TUint( SpeechBitCount( iFrames[i].iFrameType ) );
       
   457         }
       
   458     }
       
   459 
       
   460 
       
   461 // ========================== OTHER EXPORTED FUNCTIONS =========================
       
   462 
       
   463 //  End of File  
       
   464