multimediacommscontroller/mmccamrpayloadformat/src/amrpayloadencoder.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 "amrpayloadencoder.h"
       
    24 #include "amrcommonutil.h"
       
    25 
       
    26 
       
    27 // ============================= LOCAL FUNCTIONS ===============================
       
    28 
       
    29 // ============================ MEMBER FUNCTIONS ===============================
       
    30 
       
    31 // -----------------------------------------------------------------------------
       
    32 // CAmrPayloadEncoder::CAmrPayloadEncoder
       
    33 // C++ default constructor can NOT contain any code, that
       
    34 // might leave.
       
    35 // -----------------------------------------------------------------------------
       
    36 //
       
    37 CAmrPayloadEncoder::CAmrPayloadEncoder( TBool aIsNb ) : CAmrPayloadFormatter( aIsNb )
       
    38     {
       
    39     DP_AMR_ENCODE( "CAmrPayloadEncoder::CAmrPayloadEncoder" );       
       
    40         
       
    41     CAmrPayloadEncoder::InitializeFrameEncoder( );
       
    42     }
       
    43 
       
    44 
       
    45 // -----------------------------------------------------------------------------
       
    46 // CAmrPayloadEncoder::ConstructL
       
    47 // Symbian 2nd phase constructor can leave.
       
    48 // -----------------------------------------------------------------------------
       
    49 //
       
    50 void CAmrPayloadEncoder::ConstructL( )
       
    51     {
       
    52     DP_AMR_ENCODE( "CAmrPayloadEncoder::ConstructL" );
       
    53         
       
    54     // Allocate memory for iHeaderEncoder and iTocEntryEncoder
       
    55     iHeaderEncoder = CAmrPayloadHeader::NewL();
       
    56     iTocEntryEncoder = CAmrTocEntry::NewL();
       
    57     
       
    58     #ifdef FTD_ENABLED    
       
    59     User::LeaveIfError( iCodecStatsQueue.OpenGlobal( KMccCodecStats, EOwnerProcess ) ); 
       
    60     #endif    
       
    61     }
       
    62 
       
    63 
       
    64 // -----------------------------------------------------------------------------
       
    65 // CAmrPayloadEncoder::NewL
       
    66 // Two-phased constructor.
       
    67 // -----------------------------------------------------------------------------
       
    68 //
       
    69 CAmrPayloadEncoder* CAmrPayloadEncoder::NewL( TBool aIsNb )
       
    70     {
       
    71     DP_AMR_ENCODE( "CAmrPayloadEncoder::NewL" );
       
    72     
       
    73     CAmrPayloadEncoder* self = new( ELeave ) CAmrPayloadEncoder( aIsNb );
       
    74     
       
    75     CleanupStack::PushL( self );
       
    76     self->ConstructL( );
       
    77     CleanupStack::Pop( self );
       
    78 
       
    79     return self;
       
    80     }
       
    81 
       
    82 
       
    83 // Destructor
       
    84 CAmrPayloadEncoder::~CAmrPayloadEncoder( )
       
    85     {
       
    86     DP_AMR_ENCODE( "CAmrPayloadEncoder::~CAmrPayloadEncoder" );
       
    87         
       
    88     delete iHeaderEncoder;
       
    89     delete iTocEntryEncoder;
       
    90     
       
    91     #ifdef FTD_ENABLED
       
    92     
       
    93     iCodecStatsQueue.Close();
       
    94     
       
    95     #endif
       
    96     }
       
    97 
       
    98 // -----------------------------------------------------------------------------
       
    99 // CAmrPayloadEncoder::DoInitialize
       
   100 // Initialize encoder. Encoder MUST BE initialized when starting playing.
       
   101 // -----------------------------------------------------------------------------
       
   102 //
       
   103 void CAmrPayloadEncoder::DoInitialize()
       
   104     {
       
   105     DP_AMR_ENCODE( "CAmrPayloadEncoder::DoInitialize" );
       
   106         
       
   107     iRedIntervalCollected = EFalse;
       
   108     iFrameIndex = iRedCount;
       
   109     }
       
   110     
       
   111 // -----------------------------------------------------------------------------
       
   112 // CAmrPayloadEncoder::SetModeRequest
       
   113 // Set ModeRequest.
       
   114 // -----------------------------------------------------------------------------
       
   115 //
       
   116 void CAmrPayloadEncoder::SetModeRequest( TAmrModeRequest aRequest )
       
   117     {
       
   118     DP_AMR_ENCODE2( "CAmrPayloadEncoder::SetModeRequest - REQUEST: %d", aRequest );
       
   119         
       
   120     iModeRequest = aRequest;
       
   121     
       
   122     #ifdef FTD_ENABLED
       
   123     
       
   124     TMccCodecStats stats;
       
   125     stats.iCMRUplink = iModeRequest;
       
   126     stats.SetFieldUpdatedFlag( ECMRUplink );
       
   127     iCodecStatsQueue.Send( stats );
       
   128     
       
   129     #endif
       
   130     }
       
   131 
       
   132 
       
   133 // -----------------------------------------------------------------------------
       
   134 // CAmrPayloadEncoder::EncodeFrame
       
   135 // Encode a received AMR frame into the payload buffer to be sent.
       
   136 // If AMR FEC redundancy is used and we have collected needed count of redundant
       
   137 // frames, them are encoded first to the payload buffer. Last iRedCount frames
       
   138 // are saved to be used with next RTP packet. iRedCount first frames in the 
       
   139 // 'iFrames'-array are reserved for redundant frames info saving. Thus new 
       
   140 // frames starts from index iFrames[iRedCount].
       
   141 // -----------------------------------------------------------------------------
       
   142 //
       
   143 TBool CAmrPayloadEncoder::EncodeFrame( TInt aChannel,
       
   144                                        TAmrFrameType aFrameType,
       
   145                                        TUint8 aFrameQualityInd,
       
   146                                        const TDes8& aFrameData )
       
   147     {
       
   148     DP_AMR_ENCODE( "CAmrPayloadEncoder::EncodeFrame" );
       
   149         
       
   150     TBool payloadComplete( EFalse );
       
   151     
       
   152     // Encode redundant frames if there is some
       
   153     // Frame info relating to redundant frames is saved at the beginning of iFrames
       
   154     TInt count( iFrameDatas.Count() );
       
   155 
       
   156     if ( iRedCount == iFrameIndex && count && iRedIntervalCollected )
       
   157         {
       
   158         for ( TInt i = iRedCount - count; i < iRedCount; i++ )
       
   159             {
       
   160             const TUint8* redFrameData = iFrames[i].iFrameData;
       
   161             TInt speechBits = SpeechBitCount( iFrames[i].iFrameType );
       
   162             iFrameEncoder.Encode( redFrameData, 0, 0, speechBits );
       
   163             iTotalSpeechBits += speechBits;
       
   164             
       
   165             #ifdef _DEBUG
       
   166             if ( speechBits )
       
   167                 {
       
   168                 DP_AMR_ENCODE2( "ENCODING RED FRAME #%d: ", i );
       
   169                 DP_AMR_ENCODE6( "| %d | %d | %d | %d | %d |", redFrameData[KNumValue0],
       
   170                     redFrameData[KNumValue1], redFrameData[KNumValue2],
       
   171                     redFrameData[KNumValue3], redFrameData[KNumValue4] );    
       
   172                 }
       
   173             else
       
   174                 {
       
   175                 DP_AMR_ENCODE2( "ENCODING RED FRAME #%d: - NO DATA FRAME", i );
       
   176                 }
       
   177             #endif
       
   178             }
       
   179         }
       
   180 
       
   181     // Update iFrames array
       
   182     iFrames[iFrameIndex].iFrameType = aFrameType;
       
   183     iFrames[iFrameIndex].iFrameQualityInd = aFrameQualityInd;
       
   184     iFrames[iFrameIndex].iChannel = aChannel;
       
   185     if ( EAmrFrameNoData == aFrameType  )
       
   186         {
       
   187         DP_AMR_ENCODE( "FRAME TO ENCODE - NO DATA FRAME" );
       
   188 
       
   189         iFrames[iFrameIndex].iFrameData = NULL;
       
   190         iFrames[iFrameIndex].iBitIndex = 0;
       
   191         }
       
   192     else
       
   193         {
       
   194         iFrames[iFrameIndex].iFrameData = iPayload + iFrameEncoder.ByteIndex( );
       
   195         iFrames[iFrameIndex].iBitIndex = TUint( iFrameEncoder.BitIndex( ) );
       
   196         const TUint8* frameData = aFrameData.Ptr( );
       
   197 
       
   198         // Get the speech bit count of current frame
       
   199         TInt speechBits = SpeechBitCount( aFrameType ); 
       
   200         iFrameEncoder.Encode( frameData, 0, 0, speechBits );
       
   201 
       
   202         // Update TotalSpeechBits 
       
   203         iTotalSpeechBits += speechBits;
       
   204         
       
   205         #ifdef _DEBUG
       
   206         DP_AMR_ENCODE2( "ENCODED FRAME #%d: ", iFrameIndex );
       
   207         if ( aFrameData.Size() )
       
   208             {
       
   209             TStreamDecoder decoder;
       
   210             TUint8* refBufPtr = iFrames[iFrameIndex].iFrameData;
       
   211             decoder.Initialize( refBufPtr, 0, TInt( iFrames[iFrameIndex].iBitIndex ) );
       
   212             TUint32 vals[KNumValue5];
       
   213             for ( TInt v = 0; v < (TInt) KNumValue5; v++ )
       
   214                 {
       
   215                 vals[v] = decoder.Decode( KBitsIn1Byte );
       
   216                 }
       
   217             DP_AMR_ENCODE6( "| %d | %d | %d | %d | %d |", vals[KNumValue0],
       
   218             vals[KNumValue1], vals[KNumValue2], vals[KNumValue3], vals[KNumValue4] );
       
   219             }
       
   220         #endif            
       
   221         }
       
   222 
       
   223     iFrameIndex++;
       
   224     if ( iFrameIndex == iFrameCount + iRedCount )
       
   225         {
       
   226         DP_AMR_ENCODE( "CAmrPayloadEncoder::EncodeFrame - NEEDED FRAMES COLLECTED" );
       
   227 
       
   228         // Add header information to the RTP packet
       
   229         TInt payloadLen = Encode( iPayload );
       
   230         DP_AMR_ENCODE3( "CAmrPayloadEncoder::EncodeFrame - PAYLOAD SIZE: %d, TARGET MAX: %d",
       
   231             payloadLen, iPayloadPtr.MaxLength() );
       
   232         iPayloadPtr.SetLength( payloadLen );
       
   233 
       
   234         // Finish a payload
       
   235         iFrameIndex = iRedCount;
       
   236         iTotalSpeechBits = 0;
       
   237         SaveRedundantFrame( aFrameData );
       
   238         if ( iRedCount <= iFrameDatas.Count() )
       
   239             {
       
   240             iRedIntervalCollected = ETrue;
       
   241             }
       
   242         
       
   243         // Reset iFrameEncoder
       
   244         InitializeFrameEncoder( );
       
   245         payloadComplete = ETrue;
       
   246         }
       
   247     else if ( iRedCount && iFrameIndex > iFrameCount )
       
   248         {
       
   249         // Save iRedCount latest frames to be sent with next RTP packet as redundancy
       
   250         SaveRedundantFrame( aFrameData );
       
   251         }
       
   252     else
       
   253         {
       
   254         // Make PC-LINT happy.
       
   255         }        
       
   256 
       
   257     return payloadComplete;
       
   258     }
       
   259 
       
   260 // -----------------------------------------------------------------------------
       
   261 // CAmrPayloadEncoder::SaveRedundantFrame
       
   262 // Saves frame to the array reserved for redundancy saving.
       
   263 // -----------------------------------------------------------------------------
       
   264 //
       
   265 void CAmrPayloadEncoder::SaveRedundantFrame( const TDes8& aFrameData )
       
   266     {
       
   267     DP_AMR_ENCODE( "CAmrPayloadEncoder::SaveRedundantFrame" );
       
   268         
       
   269     HBufC8* hFrame = aFrameData.Alloc();
       
   270     if ( hFrame )
       
   271         {
       
   272         if ( iFrameDatas.Append( hFrame ) != KErrNone )
       
   273             {
       
   274             delete hFrame;
       
   275             }
       
   276         else if ( iRedCount < iFrameDatas.Count() )
       
   277             {
       
   278             delete iFrameDatas[0];
       
   279             iFrameDatas.Remove( 0 );
       
   280             }
       
   281         }
       
   282     }
       
   283     
       
   284 // -----------------------------------------------------------------------------
       
   285 // CAmrPayloadEncoder::ResetPayloadBuffer
       
   286 // Resets iFrames array. iRedCount newest frames from payload just sent are
       
   287 // copied to the beginning of the iFrames array, where is area reserved for
       
   288 // redundant frames keeping. That way frames can be encoded to the next payload
       
   289 // as redundat frames.
       
   290 // -----------------------------------------------------------------------------
       
   291 //
       
   292 void CAmrPayloadEncoder::ResetPayloadBuffer( )
       
   293     {
       
   294     DP_AMR_ENCODE( "CAmrPayloadEncoder::ResetPayloadBuffer" );
       
   295         
       
   296     iFrameIndex = iRedCount;
       
   297     iPayloadPtr.SetLength( 0 );
       
   298     
       
   299     // Save redCount newest frames to the beginning of iFrames array
       
   300     TInt numOfRedFrames = iFrameDatas.Count();
       
   301     if ( iRedCount - numOfRedFrames >= 0 )
       
   302         {
       
   303         for ( TInt i = iRedCount - numOfRedFrames; i < iRedCount; i++ )
       
   304             {
       
   305            	if ( i > KMaxFrameCountPerPacket )
       
   306    				{
       
   307        			DP_AMR_ENCODE3("CAmrPayloadEncoder::ResetPayloadBuffer,\
       
   308        				 i: %d > KMaxFrameCountPerPacket: %d",  \
       
   309        				 i , KMaxFrameCountPerPacket);	
       
   310         		}
       
   311         	if ( ( i + iFrameCount ) > KMaxFrameCountPerPacket )
       
   312    				{
       
   313        			DP_AMR_ENCODE3("CAmrPayloadEncoder::ResetPayloadBuffer, i + iFrameCount: %d > KMaxFrameCountPerPacket: %d",  \
       
   314         		(i + iFrameCount) , KMaxFrameCountPerPacket);	
       
   315         		}
       
   316         	
       
   317         	// Checking index limit to appease PC-lint
       
   318         	if ( ( i + iFrameCount ) < KMaxFrameCountPerPacket )	
       
   319         		{
       
   320         		iFrames[ i ] = iFrames[ i + iFrameCount ];
       
   321         		
       
   322             	}
       
   323             }
       
   324 
       
   325         for ( TInt j = 0; j < numOfRedFrames; j++ )
       
   326             {
       
   327             
       
   328             if ( ( j + ( iRedCount - numOfRedFrames )  ) > KMaxFrameCountPerPacket )
       
   329    				{
       
   330        			DP_AMR_ENCODE3("CAmrPayloadEncoder::ResetPayloadBuffer,\
       
   331        				j + ( iRedCount - numOfRedFrames ): %d > KMaxFrameCountPerPacket: %d", \
       
   332        				( j + ( iRedCount - numOfRedFrames ) ), KMaxFrameCountPerPacket);	
       
   333         		}
       
   334         		
       
   335             // Checking index limit to appease PC-lint
       
   336         	if ( ( j + ( iRedCount - numOfRedFrames )  ) < KMaxFrameCountPerPacket )
       
   337         		{
       
   338         		
       
   339             	// Move frame data ptr to point redundant frames
       
   340             	iFrames[ j + ( iRedCount - numOfRedFrames ) ].iFrameData
       
   341 	                = const_cast<TUint8*>( ( *iFrameDatas[ j ] ).Ptr() );
       
   342                 
       
   343             	}
       
   344             }
       
   345         }
       
   346     else
       
   347         {
       
   348         DP_AMR_ENCODE( "CAmrPayloadEncoder::ResetPayloadBuffer - TOO MANY RED FRAMES" );
       
   349         }        
       
   350         
       
   351     // NULL rest of frame datas
       
   352     TInt index( KMaxFrameCountPerPacket );
       
   353     while ( --index >= iRedCount )
       
   354         {
       
   355         iFrames[index].iFrameData = NULL;
       
   356         }
       
   357     }
       
   358 
       
   359 // -----------------------------------------------------------------------------
       
   360 // CAmrPayloadEncoder::SetChannelCount
       
   361 // Set number of audio channels.
       
   362 // -----------------------------------------------------------------------------
       
   363 //
       
   364 TInt CAmrPayloadEncoder::SetChannelCount( TInt aChannelCount )
       
   365     {
       
   366     DP_AMR_ENCODE2( "CAmrPayloadEncoder::SetChannelCount - COUNT: %d", aChannelCount );
       
   367         
       
   368     TInt ret = CAmrPayloadFormatter::SetChannelCount( aChannelCount );
       
   369     InitializeFrameEncoder( );
       
   370     return ret;
       
   371     }
       
   372 
       
   373 // -----------------------------------------------------------------------------
       
   374 // CAmrPayloadEncoder::SetFrameBlockCount
       
   375 // Set number of AMR frame blocks included in one RTP packet.
       
   376 // -----------------------------------------------------------------------------
       
   377 //
       
   378 TInt CAmrPayloadEncoder::SetFrameBlockCount( TInt aFrameblockCount )
       
   379     {
       
   380     DP_AMR_ENCODE2( "CAmrPayloadEncoder::SetFrameBlockCount - COUNT: %d", aFrameblockCount );
       
   381         
       
   382     TInt ret = CAmrPayloadFormatter::SetFrameBlockCount( aFrameblockCount );
       
   383     InitializeFrameEncoder( );
       
   384     return ret;
       
   385     }
       
   386 
       
   387 // -----------------------------------------------------------------------------
       
   388 // CAmrPayloadEncoder::SetRedFrameBlockCount
       
   389 // Set number of redundant AMR frame blocks to be included in one RTP packet.
       
   390 // -----------------------------------------------------------------------------
       
   391 //
       
   392 TInt CAmrPayloadEncoder::SetRedFrameBlockCount( TInt aRedBlockCount )
       
   393     {
       
   394     DP_AMR_ENCODE2( "CAmrPayloadEncoder::SetFrameBlockCount - COUNT: %d", aRedBlockCount );
       
   395         
       
   396     if ( KMaxAmrRedCount >= aRedBlockCount && 0 <= aRedBlockCount )
       
   397         {
       
   398         iRedCount = aRedBlockCount;
       
   399         return KErrNone;
       
   400         }
       
   401     else
       
   402         {
       
   403         return KErrArgument;
       
   404         }        
       
   405     }
       
   406     
       
   407 // -----------------------------------------------------------------------------
       
   408 // CAmrPayloadEncoder::Encode
       
   409 // Encode the AMR payload ( for one RTP packet ) into a given buffer.
       
   410 // If payload contains only NO_DATA frames, packet is not encoded at all.
       
   411 // NO_DATA frames at the end of payload are ripped off.
       
   412 // -----------------------------------------------------------------------------
       
   413 //
       
   414 TInt CAmrPayloadEncoder::Encode( TUint8* aBuffer )
       
   415     {
       
   416     DP_AMR_ENCODE( "CAmrPayloadEncoder::Encode" );
       
   417     
       
   418     TInt byteIndex( 0 );
       
   419     TInt bitIndex( 0 );
       
   420 
       
   421     // Rip off extra NO_DATA frames
       
   422     TInt framesDiscarded = DiscardExtraNoDataFrames( );
       
   423     if ( iRedIntervalCollected )
       
   424         {
       
   425         if ( framesDiscarded == iFrameCount + iRedCount )
       
   426             {
       
   427             DP_AMR_ENCODE( "PACKET WILL NOT BE SENT - ONLY NO DATA FRAMES" );
       
   428             return 0;
       
   429             }
       
   430         }
       
   431     else
       
   432         {
       
   433         if ( framesDiscarded == iFrameCount )
       
   434             {
       
   435             DP_AMR_ENCODE( "PACKET WILL NOT BE SENT - NEW FRAMES WERE NO DATA FRAMES" );
       
   436             DP_AMR_ENCODE2( "CAmrPayloadEncoder::Encode framesDiscarded: %d", framesDiscarded );
       
   437             return 0;
       
   438             }
       
   439         }        
       
   440 
       
   441     // Encode payload header
       
   442     iHeaderEncoder->iCmr = iModeRequest;
       
   443     iHeaderEncoder->Encode( aBuffer, byteIndex, bitIndex );
       
   444 
       
   445     // Encode TOC entries
       
   446     EncodeTableOfContents( aBuffer, byteIndex, bitIndex );
       
   447     
       
   448     // Pad last several bits if needed
       
   449     TInt totalBytes = iFrameEncoder.ByteIndex();
       
   450     
       
   451     if ( iFrameEncoder.BitIndex() != 0 )
       
   452         {
       
   453         // Padding Zeros
       
   454         iFrameEncoder.Encode( 0, KBitsIn1Byte - iFrameEncoder.BitIndex() );
       
   455         totalBytes++;
       
   456         }
       
   457     
       
   458     return totalBytes;
       
   459     }
       
   460 
       
   461 // -----------------------------------------------------------------------------
       
   462 // CAmrPayloadEncoder::DiscardExtraNoDataFrames
       
   463 // Unwanted NO_DATA frames are ripped off from payload according to RFC3267: 4.3.2.
       
   464 // TOC-fields indicating NO_DATA frame are deleted and speech bits following 
       
   465 // TOCs are moved to start earlier correspondingly.
       
   466 // -----------------------------------------------------------------------------
       
   467 //
       
   468 TInt CAmrPayloadEncoder::DiscardExtraNoDataFrames( )
       
   469     {
       
   470     DP_AMR_ENCODE( "CAmrPayloadEncoder::DiscardExtraNoDataFrames" );
       
   471         
       
   472     TInt endIndex( iFrameCount + iRedCount );
       
   473     iFramesDiscarded = 0;
       
   474     
       
   475     // write debug info if the endIndex is greater than the iFrames[] range
       
   476     if ( endIndex > KMaxFrameCountPerPacket )
       
   477    		{
       
   478        	DP_AMR_ENCODE3("CAmrPayloadEncoder::DiscardExtraNoDataFrames, endIndex: %d > KMaxFrameCountPerPacket: %d",  \
       
   479         	endIndex, KMaxFrameCountPerPacket);	
       
   480         }
       
   481     // Count NO_DATA frames to reject
       
   482     for ( TInt i = 0; i < endIndex; i++ )
       
   483         {
       
   484         if ( EAmrFrameNoData == iFrames[i].iFrameType )
       
   485             {
       
   486             iFramesDiscarded++;
       
   487             }
       
   488         else
       
   489             {
       
   490             iFramesDiscarded = 0;
       
   491             }                
       
   492         }
       
   493     
       
   494     // Move speech bits to start earlier if TOCs are removed
       
   495     if ( iFramesDiscarded )
       
   496         {
       
   497         DP_AMR_ENCODE2( "CAmrPayloadEncoder::DiscardExtraNoDataFrames - REJECT %d FRAMES", iFramesDiscarded );
       
   498         
       
   499         TStreamDecoder decoder;
       
   500         TStreamEncoder encoder;
       
   501 
       
   502         TInt numOfRedFrames( 0 );
       
   503         if ( iRedIntervalCollected )
       
   504             {
       
   505             numOfRedFrames = iFrameDatas.Count();
       
   506             }
       
   507         
       
   508         TInt writeByteIndex = ( KHeaderBitsBE 
       
   509             + KTOCFieldBitsBE * ( iFrameCount + numOfRedFrames - iFramesDiscarded ) )
       
   510             / KBitsIn1Byte;
       
   511 
       
   512         TInt writeBitIndex = ( KHeaderBitsBE
       
   513             + KTOCFieldBitsBE * ( iFrameCount + numOfRedFrames - iFramesDiscarded ) )
       
   514             % KBitsIn1Byte;
       
   515 
       
   516         encoder.Initialize( iPayload, writeByteIndex, writeBitIndex );
       
   517         
       
   518         DP_AMR_ENCODE3( "AMR ENCODER - START BYTE IND: %d, BIT IND: %d",
       
   519             encoder.ByteIndex(), encoder.BitIndex() );
       
   520         
       
   521         TInt readByteIndex = ( KHeaderBitsBE
       
   522             + KTOCFieldBitsBE * ( iFrameCount + numOfRedFrames ) )
       
   523             / KBitsIn1Byte;
       
   524         TInt readBitIndex = ( KHeaderBitsBE 
       
   525             + KTOCFieldBitsBE * ( iFrameCount + numOfRedFrames ) )
       
   526             % KBitsIn1Byte;
       
   527 
       
   528         decoder.Initialize( iPayload, readByteIndex, readBitIndex );
       
   529         
       
   530         // Move speech bits
       
   531         encoder.Encode( iPayload, readByteIndex, readBitIndex, iTotalSpeechBits );
       
   532         
       
   533         DP_AMR_ENCODE3( "AMR ENCODER - END BYTE IND: %d, BIT IND: %d",
       
   534             encoder.ByteIndex(), encoder.BitIndex() );
       
   535             
       
   536         // Update frame encoder position so that payload length is set correctly
       
   537         iFrameEncoder.Initialize( iPayload, encoder.ByteIndex(), encoder.BitIndex() );
       
   538         }
       
   539     
       
   540     return iFramesDiscarded;        
       
   541     }
       
   542     
       
   543 // -----------------------------------------------------------------------------
       
   544 // CAmrPayloadEncoder::ReEncodeFrame
       
   545 // Do bit shifting when AmrPayloadFormatPlugin is doing buffer flushing.
       
   546 // -----------------------------------------------------------------------------
       
   547 //
       
   548 TBool CAmrPayloadEncoder::ReEncodeFrameL( )
       
   549     {
       
   550     return ReEncodeFrameL( iPayload );
       
   551     }
       
   552 
       
   553 // -----------------------------------------------------------------------------
       
   554 // CAmrPayloadEncoder::ReEncodeFrame
       
   555 // Do bit shifting when AmrPayloadFormatPlugin is doing buffer flushing.
       
   556 // -----------------------------------------------------------------------------
       
   557 //
       
   558 TBool CAmrPayloadEncoder::ReEncodeFrameL( TUint8* aBuffer )
       
   559     {
       
   560     DP_AMR_ENCODE( "CAmrPayloadEncoder::ReEncodeFrameL" );
       
   561         
       
   562     // No outstanding buffer at all
       
   563     if ( iFrameIndex == iRedCount )
       
   564         {
       
   565         return EFalse;
       
   566         }
       
   567 
       
   568     // Only called when AmrPayloadFormatPlugin is flushing buffer out
       
   569     TInt byteIndex( 0 );
       
   570     TInt bitIndex( 0 );
       
   571 
       
   572     // Encode payload header
       
   573     iHeaderEncoder->iCmr = iModeRequest;
       
   574     iHeaderEncoder->Encode( aBuffer, byteIndex, bitIndex );
       
   575     
       
   576     // Encode TOC entries
       
   577     EncodeTableOfContents( aBuffer, byteIndex, bitIndex );
       
   578     
       
   579     // Do bit shifting for the speech bits
       
   580     // orginal starting position
       
   581     TInt frameByteIndex = ( KHeaderBitsBE
       
   582         + KTOCFieldBitsBE * ( iFrameCount + iRedCount ) ) / KBitsIn1Byte;
       
   583 
       
   584     TInt frameBitIndex = ( KHeaderBitsBE
       
   585         + KTOCFieldBitsBE * ( iFrameCount + iRedCount ) ) % KBitsIn1Byte;
       
   586     
       
   587     // Current speech data length
       
   588     TInt speechBytes
       
   589         = ( iTotalSpeechBits % KBitsIn1Byte == 0 )
       
   590         ? iTotalSpeechBits / KBitsIn1Byte : iTotalSpeechBits / KBitsIn1Byte + 1;
       
   591     
       
   592     // Read out speech data to temp buffer
       
   593     TUint8* tempBuf = static_cast<TUint8*>
       
   594         ( User::AllocL( sizeof( TUint8 ) * TUint8( speechBytes ) ) );
       
   595 
       
   596     CleanupStack::PushL( tempBuf );
       
   597     TStreamEncoder streamEnc;
       
   598     TStreamDecoder streamDec;
       
   599     streamEnc.Initialize( aBuffer, byteIndex, bitIndex );
       
   600     streamDec.Initialize( aBuffer, frameByteIndex, frameBitIndex );
       
   601     streamDec.Decode( tempBuf, 0, 0, iTotalSpeechBits );
       
   602     streamEnc.Encode( tempBuf, 0, 0, iTotalSpeechBits );
       
   603 
       
   604     if ( streamEnc.BitIndex( ) != 0 )
       
   605         {
       
   606         // Padding zeros
       
   607         streamEnc.Encode( 0, KBitsIn1Byte - streamEnc.BitIndex( ) );
       
   608         }
       
   609     
       
   610     TInt payloadLen = streamEnc.ByteIndex( );
       
   611     iPayloadPtr.SetLength( payloadLen );
       
   612 
       
   613     // Finish current payload
       
   614     iFrameIndex = iRedCount;
       
   615     // Reset iFrameEncoder
       
   616     InitializeFrameEncoder( );
       
   617     // Reset TotalSpeechBits counter
       
   618     iTotalSpeechBits = 0; 
       
   619 
       
   620     CleanupStack::PopAndDestroy( tempBuf );
       
   621     return ETrue;
       
   622     }
       
   623 
       
   624 // -----------------------------------------------------------------------------
       
   625 // CAmrPayloadEncoder::IsStartOfPeriod
       
   626 // Returns ETrue if next frame to be encoded starts a new packetization period.
       
   627 // -----------------------------------------------------------------------------
       
   628 //
       
   629 TBool CAmrPayloadEncoder::IsStartOfPeriod()
       
   630     {
       
   631     return ( iFrameIndex == iRedCount );
       
   632     }
       
   633 
       
   634 // -----------------------------------------------------------------------------
       
   635 // CAmrPayloadEncoder::EncodeTableOfContents
       
   636 // Encode 'Table of Contents' into a given buffer at the given position.
       
   637 // -----------------------------------------------------------------------------
       
   638 //
       
   639 void CAmrPayloadEncoder::EncodeTableOfContents( TUint8* aBuffer,
       
   640                                                 TInt& aByteIndex, 
       
   641                                                 TInt& aBitIndex )
       
   642     {
       
   643     DP_AMR_ENCODE( "CAmrPayloadEncoder::EncodeTableOfContents" );
       
   644     
       
   645     // Iterate iFrames array and encode each TOC entry
       
   646     // Encode TOCs for redundant frames if exist
       
   647     TInt ind( iRedCount );
       
   648     if ( iRedIntervalCollected )
       
   649         {
       
   650         ind = iRedCount - iFrameDatas.Count();
       
   651         }
       
   652 
       
   653     TInt endIndex = iFramesDiscarded ? iFrameIndex - iFramesDiscarded : iFrameIndex;
       
   654     // write debug info if the endIndex is greater than the iFrames[] range
       
   655     if ( endIndex > KMaxFrameCountPerPacket )
       
   656    		{
       
   657        	DP_AMR_ENCODE3("CAmrPayloadEncoder::EncodeTableOfContents, endIndex: %d > KMaxFrameCountPerPacket: %d",  \
       
   658         	endIndex, KMaxFrameCountPerPacket);	
       
   659         }
       
   660     for ( ; ind < endIndex; ind++ )
       
   661         {
       
   662         if ( ind == endIndex - 1 )
       
   663             {
       
   664             iTocEntryEncoder->iFrameFollowed = 0; // last frame in a payload
       
   665             }
       
   666         else
       
   667             {
       
   668             iTocEntryEncoder->iFrameFollowed = 1;
       
   669             }
       
   670 
       
   671         // Checking index limit to appease PC-lint
       
   672         if ( (ind) < KMaxFrameCountPerPacket )
       
   673         	{
       
   674         iTocEntryEncoder->iFrameQualityInd = iFrames[ind].iFrameQualityInd;
       
   675         iTocEntryEncoder->iFrameType = iFrames[ind].iFrameType;
       
   676         	}
       
   677         iTocEntryEncoder->Encode( aBuffer, aByteIndex, aBitIndex );
       
   678         }
       
   679     }
       
   680 
       
   681 
       
   682 // -----------------------------------------------------------------------------
       
   683 // CAmrPayloadEncoder::InitializeFrameEncoder
       
   684 // Initialize frame encoder ( Stream Encoder ). Starting position of first AMR
       
   685 // frame data is calculated. Refer to RFC3267 4.3.
       
   686 // -----------------------------------------------------------------------------
       
   687 //
       
   688 void CAmrPayloadEncoder::InitializeFrameEncoder( )
       
   689     {
       
   690     DP_AMR_ENCODE( "CAmrPayloadEncoder::InitializeFrameEncoder" );
       
   691         
       
   692     // Payload header: 4 bits; TOC: 6 bits
       
   693     // Total number of TOCs: iChannelCount * iFrameBlockCount
       
   694     TInt numOfRedFrames( 0 );
       
   695     if ( iRedIntervalCollected )
       
   696         {
       
   697         numOfRedFrames = iFrameDatas.Count();
       
   698         }
       
   699 
       
   700     // Save space for frame TOCs
       
   701     TInt frameByteIndex = ( KHeaderBitsBE
       
   702         + KTOCFieldBitsBE * ( iFrameCount + numOfRedFrames ) ) / KBitsIn1Byte;
       
   703     
       
   704     TInt frameBitIndex = ( KHeaderBitsBE 
       
   705         + KTOCFieldBitsBE * ( iFrameCount + numOfRedFrames ) ) % KBitsIn1Byte;
       
   706 
       
   707     iFrameEncoder.Initialize( iPayload, frameByteIndex, frameBitIndex );
       
   708     }
       
   709     
       
   710 
       
   711 // ========================== OTHER EXPORTED FUNCTIONS =========================
       
   712 
       
   713 //  End of File