multimediacommscontroller/mmccg729payloadformat/src/g729payloadformatwrite.cpp
changeset 0 1bce908db942
equal deleted inserted replaced
-1:000000000000 0:1bce908db942
       
     1 /*
       
     2 * Copyright (c) 2004-2007 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:    Payload format component capable to write RTP payload
       
    15 *                containing G729 audio.
       
    16 *
       
    17 */
       
    18 
       
    19 
       
    20 
       
    21 
       
    22 // INCLUDE FILES
       
    23 #include    "g729payloadformatwrite.h"
       
    24 #include    "g729payloadformatutil.h"
       
    25 #include    "mccrtpdatasink.h"
       
    26 #include    "mmccinterfacedef.h"
       
    27 #include    "mccuids.hrh"
       
    28 #include    "mccdef.h"
       
    29 #include    "streamformatter.h"
       
    30 #include    "mccrtpmediaclock.h" 
       
    31 #include    "mccredpayloadwrite.h"
       
    32 
       
    33 
       
    34 // ============================= LOCAL FUNCTIONS ===============================
       
    35 
       
    36 // ============================ MEMBER FUNCTIONS ===============================
       
    37 
       
    38 // -----------------------------------------------------------------------------
       
    39 // CG729PayloadFormatWrite::CG729PayloadFormatWrite
       
    40 // C++ default constructor can NOT contain any code, that
       
    41 // might leave.
       
    42 // -----------------------------------------------------------------------------
       
    43 //
       
    44 CG729PayloadFormatWrite::CG729PayloadFormatWrite()
       
    45     {
       
    46     
       
    47     }
       
    48 
       
    49 // -----------------------------------------------------------------------------
       
    50 // CG729PayloadFormatWrite::ConstructL
       
    51 // Symbian 2nd phase constructor can leave.
       
    52 // -----------------------------------------------------------------------------
       
    53 //
       
    54 void CG729PayloadFormatWrite::ConstructL (MDataSink* aSink)
       
    55     {
       
    56     #ifdef TRACE_G729_PAYLOAD_FORMAT_WRITE
       
    57         RDebug::Print( _L("CG729PayloadFormatWrite::ConstructL()") );
       
    58     #endif
       
    59 
       
    60     // Set default values
       
    61     iFramesPerPacket = 2;
       
    62     iFourCC.Set( KMccFourCCIdG729 );
       
    63 
       
    64     // Set data sink
       
    65     iIsRtpSink = ( KMccRtpSinkUid  == aSink->DataSinkType() ); 
       
    66     TBool isRedEncoder 
       
    67         = ( TUid::Uid( KImplUidRedPayloadFormatEncode ) == aSink->DataSinkType() );
       
    68     
       
    69     if ( iIsRtpSink )
       
    70         {
       
    71         CMccRtpDataSink* tmp = static_cast<CMccRtpDataSink*>( aSink );
       
    72         iRtpDataSink = static_cast<MMccRtpDataSink*>( tmp );
       
    73         }
       
    74     else if ( isRedEncoder )
       
    75         {
       
    76         CMccRedPayloadWrite* tmp = static_cast<CMccRedPayloadWrite*>( aSink );
       
    77         iRtpDataSink = static_cast<MMccRtpDataSink*>( tmp );
       
    78         iIsRtpSink = ETrue;
       
    79         }
       
    80     else
       
    81         {
       
    82         #ifdef TRACE_G729_PAYLOAD_FORMAT_WRITE
       
    83         RDebug::Print( _L("CG729PayloadFormatWrite::ConstructL, sink not RTP one" ) );
       
    84         #endif
       
    85         }
       
    86     
       
    87     iClip = aSink;
       
    88 
       
    89     // Initialize state machine
       
    90     iStateMachine = CFormatEncodeStateMachine::NewL( this );
       
    91     }
       
    92 
       
    93 // -----------------------------------------------------------------------------
       
    94 // CG729PayloadFormatWrite::NewL
       
    95 // Two-phased constructor.
       
    96 // -----------------------------------------------------------------------------
       
    97 //
       
    98 CG729PayloadFormatWrite* CG729PayloadFormatWrite::NewL (MDataSink* aSink)
       
    99     {
       
   100     #ifdef TRACE_G729_PAYLOAD_FORMAT_WRITE
       
   101             RDebug::Print (_L ("CG729PayloadFormatWrite::NewL()"));
       
   102     #endif
       
   103 
       
   104     __ASSERT_ALWAYS( aSink, User::Leave( KErrArgument ) );
       
   105     
       
   106     CG729PayloadFormatWrite* self = new (ELeave) CG729PayloadFormatWrite;
       
   107     CleanupStack::PushL ( self );
       
   108     self->ConstructL ( aSink );
       
   109     CleanupStack::Pop( self );
       
   110     return self;
       
   111     }
       
   112     
       
   113 
       
   114 // -----------------------------------------------------------------------------
       
   115 // CG729PayloadFormatWrite::~CG729PayloadFormatWrite
       
   116 // Destructor..
       
   117 // -----------------------------------------------------------------------------
       
   118 //
       
   119 CG729PayloadFormatWrite::~CG729PayloadFormatWrite ()
       
   120     {
       
   121     #ifdef TRACE_G729_PAYLOAD_FORMAT_WRITE
       
   122         RDebug::Print( _L("CG729PayloadFormatWrite::~CG729PayloadFormatWrite()") );
       
   123     #endif
       
   124     
       
   125     if ( iStateMachine )
       
   126         {
       
   127         iStateMachine->Cancel();
       
   128         }
       
   129     
       
   130     // Media clock is not owned
       
   131     if ( iRtpMediaClock )
       
   132         {
       
   133         iRtpMediaClock->UnregisterMediaFormat( iKey );
       
   134         }
       
   135         
       
   136     delete iSourceBuffer;
       
   137     delete iSinkBuffer;
       
   138     delete iStateMachine;
       
   139     }
       
   140     
       
   141 // -----------------------------------------------------------------------------
       
   142 // CG729PayloadFormatWrite::SinkThreadLogon
       
   143 // Passes the logon command to the sink clip
       
   144 // -----------------------------------------------------------------------------
       
   145 //
       
   146 TInt CG729PayloadFormatWrite::SinkThreadLogon(
       
   147     MAsyncEventHandler& aEventHandler )
       
   148     {
       
   149     iClip->SinkThreadLogon( aEventHandler );
       
   150     return KErrNone;
       
   151     }
       
   152 
       
   153 // -----------------------------------------------------------------------------
       
   154 // CG729PayloadFormatWrite::SinkThreadLogoff
       
   155 // Passes the logoff command to the sink clip
       
   156 // -----------------------------------------------------------------------------
       
   157 //
       
   158 void CG729PayloadFormatWrite::SinkThreadLogoff()
       
   159     {
       
   160     iClip->SinkThreadLogoff();
       
   161     }
       
   162 
       
   163 // -----------------------------------------------------------------------------
       
   164 // CG729PayloadFormatWrite::CreateSinkBufferL
       
   165 // Create a sink buffer
       
   166 // -----------------------------------------------------------------------------
       
   167 //
       
   168 CMMFBuffer* CG729PayloadFormatWrite::CreateSinkBufferL( TMediaId aMediaId, 
       
   169                                                         TBool &aReference )
       
   170     {
       
   171     #ifdef TRACE_G729_PAYLOAD_FORMAT_WRITE
       
   172         RDebug::Print( _L("CG729PayloadFormatWrite::CreateSinkBufferL()") );
       
   173     #endif
       
   174     
       
   175     if ( KUidMediaTypeAudio != aMediaId.iMediaType )
       
   176         {
       
   177         User::Leave( KErrNotSupported );
       
   178         }
       
   179 
       
   180     aReference = ETrue;
       
   181 
       
   182     // Create buffer for data transfer between ULDataPath and FormatWrite
       
   183     return CreateSinkBufferOfSizeL( KG729CodecEncBufSize );
       
   184     }
       
   185 
       
   186 // -----------------------------------------------------------------------------
       
   187 // CG729PayloadFormatWrite::CreateSinkBufferOfSizeL
       
   188 // Create a sink buffer of the given size.
       
   189 // -----------------------------------------------------------------------------
       
   190 //
       
   191 CMMFDataBuffer* CG729PayloadFormatWrite::CreateSinkBufferOfSizeL( TUint aSize )
       
   192     {
       
   193     #ifdef TRACE_G729_PAYLOAD_FORMAT_WRITE
       
   194         RDebug::Print( _L("CG729PayloadFormatWrite::CreateSinkBufferOfSizeL()") );
       
   195     #endif
       
   196     
       
   197     // Need to create a source buffer
       
   198     if ( !iSourceBuffer )
       
   199 	    {  
       
   200 	    iSourceBuffer = CMMFDataBuffer::NewL( aSize );
       
   201     	iSourceBuffer->Data().FillZ( aSize );
       
   202     	iSourceBuffer->SetRequestSizeL( aSize );
       
   203 	    }
       
   204 	    
       
   205     return iSourceBuffer;
       
   206     }
       
   207 
       
   208 // -----------------------------------------------------------------------------
       
   209 // CG729PayloadFormatWrite::EmptyBufferL
       
   210 // Empty the given source buffer
       
   211 // -----------------------------------------------------------------------------
       
   212 //
       
   213 void CG729PayloadFormatWrite::EmptyBufferL( CMMFBuffer* aBuffer, 
       
   214     MDataSource* aSupplier, TMediaId aMediaId )
       
   215     {
       
   216     #ifdef TRACE_G729_PAYLOAD_FORMAT_WRITE
       
   217         RDebug::Print( _L("CG729PayloadFormatWrite::EmptyBufferL aBuffer[0x%x]"), aBuffer);
       
   218     #endif
       
   219     
       
   220     __ASSERT_ALWAYS( aBuffer, User::Leave( KErrArgument ) );
       
   221     __ASSERT_ALWAYS ( aBuffer == iSourceBuffer, User::Leave( KErrArgument ) );
       
   222     __ASSERT_ALWAYS( aSupplier, User::Leave( KErrArgument ) );
       
   223     __ASSERT_ALWAYS( KUidMediaTypeAudio == aMediaId.iMediaType,
       
   224         User::Leave( KErrNotSupported ) );
       
   225     
       
   226     // Save source buffer parameters and change the state.
       
   227     iDataPath = aSupplier;
       
   228     iMediaId = aMediaId;
       
   229     iSourceBuffer = static_cast<CMMFDataBuffer*>( aBuffer );
       
   230     
       
   231     if ( !iSinkBuffer )
       
   232         {
       
   233         #ifdef TRACE_G729_PAYLOAD_FORMAT_WRITE
       
   234             RDebug::Print( _L("CG729PayloadFormatWrite::EmptyBufferL, sink not ready!") );
       
   235         #endif
       
   236         
       
   237         iStateMachine->ChangeState( ESourceBufferEmptied );
       
   238         return;
       
   239         }
       
   240     
       
   241     TUint32 ts = 0;
       
   242     User::LeaveIfError( iRtpMediaClock->GetTimeStamp( iKey, ts ) );
       
   243 
       
   244     if ( iRtpMediaClock->TimeBasedIncrement() )
       
   245     	{
       
   246     	iFirstPacketFinished = EFalse;
       
   247     	}
       
   248     
       
   249     if ( 0 == iFrameIndex )
       
   250         {
       
   251         #ifdef TRACE_G729_PAYLOAD_FORMAT_WRITE
       
   252             RDebug::Print( _L("CG729PayloadFormatWrite::EmptyBufferL, SetTimeToPlay") );
       
   253         #endif
       
   254         
       
   255         iSinkBuffer->SetTimeToPlay( TInt64( ts ) );
       
   256         iSinkBuffer->SetFrameNumber( aBuffer->FrameNumber() );
       
   257         }
       
   258     
       
   259     #ifdef TRACE_G729_PAYLOAD_FORMAT_WRITE
       
   260     
       
   261     TDesC8& data = iSourceBuffer->Data();
       
   262     RDebug::Print( _L("CG729PayloadFormatWrite::EmptyBufferL DATALEN: %d"), data.Length() );
       
   263     RDebug::Print( _L("CG729PayloadFormatWrite::EmptyBufferL DATA_SZ: %d"), data.Size() );
       
   264     
       
   265     if( data.Length() > KG729NumOfHeaderBytes )
       
   266         {
       
   267         RDebug::Print( _L("CG729PayloadFormatWrite::EmptyBufferL DATA[0]: %u"), data[0] );
       
   268         RDebug::Print( _L("CG729PayloadFormatWrite::EmptyBufferL DATA[1]: %u"), data[1] );
       
   269         }
       
   270     
       
   271     #endif
       
   272     
       
   273     iStateMachine->ChangeState( EEmptySourceBuffer );
       
   274     }
       
   275 
       
   276 // -----------------------------------------------------------------------------
       
   277 // CG729PayloadFormatWrite::SetSinkDataTypeCode
       
   278 // Set the sink data type to the given four CC code for the given media
       
   279 // -----------------------------------------------------------------------------
       
   280 //
       
   281 TInt CG729PayloadFormatWrite::SetSinkDataTypeCode( TFourCC aSinkFourCC, 
       
   282     TMediaId aMediaId )
       
   283     {
       
   284     #ifdef TRACE_G729_PAYLOAD_FORMAT_WRITE
       
   285         RDebug::Print (_L ("CG729PayloadFormatWrite::SetSinkDataTypeCode()"));
       
   286     #endif
       
   287 
       
   288     if ( KUidMediaTypeAudio != aMediaId.iMediaType ) 
       
   289         {
       
   290         return KErrNotSupported;
       
   291         }
       
   292     
       
   293     iFourCC = aSinkFourCC;
       
   294     
       
   295     return KErrNone;
       
   296     }
       
   297 
       
   298 // -----------------------------------------------------------------------------
       
   299 // CG729PayloadFormatWrite::SinkDataTypeCode
       
   300 // Return the sink data type (four CC code) for the given media ID
       
   301 // -----------------------------------------------------------------------------
       
   302 //
       
   303 TFourCC CG729PayloadFormatWrite::SinkDataTypeCode( TMediaId aMediaId )
       
   304     {
       
   305     if ( KUidMediaTypeAudio == aMediaId.iMediaType )
       
   306         {
       
   307         return iFourCC;
       
   308         }
       
   309     else
       
   310         {
       
   311         return TFourCC(); //defaults to 'NULL' fourCC
       
   312         }
       
   313     }
       
   314 
       
   315 // -----------------------------------------------------------------------------
       
   316 // CG729PayloadFormatWrite::BufferEmptiedL
       
   317 // Called after payload buffer is completely emptied by RtpDataSink.
       
   318 // -----------------------------------------------------------------------------
       
   319 //
       
   320 void CG729PayloadFormatWrite::BufferEmptiedL( CMMFBuffer* /*aBuffer*/ )
       
   321     {
       
   322     
       
   323     }
       
   324 
       
   325 // -----------------------------------------------------------------------------
       
   326 // CG729PayloadFormatWrite::NumChannels
       
   327 // Returns number of channels
       
   328 // -----------------------------------------------------------------------------
       
   329 //
       
   330 TUint CG729PayloadFormatWrite::NumChannels()
       
   331     {
       
   332     return KMono;
       
   333     }
       
   334 
       
   335 // -----------------------------------------------------------------------------
       
   336 // CG729PayloadFormatWrite::SampleRate
       
   337 // Returns SampleRate
       
   338 // -----------------------------------------------------------------------------
       
   339 //
       
   340 TUint CG729PayloadFormatWrite::SampleRate()
       
   341     {
       
   342     return KG729SampleRate;
       
   343     }
       
   344 
       
   345 // -----------------------------------------------------------------------------
       
   346 // CG729PayloadFormatWrite::SetSampleRate
       
   347 // Set SampleRate
       
   348 // -----------------------------------------------------------------------------
       
   349 //
       
   350 TInt CG729PayloadFormatWrite::SetSampleRate( TUint aSampleRate )
       
   351     {
       
   352     return ( KG729SampleRate == aSampleRate ) ? KErrNone : KErrNotSupported;
       
   353     }
       
   354 
       
   355 // -----------------------------------------------------------------------------
       
   356 // CG729PayloadFormatWrite::FrameTimeInterval
       
   357 // Return the frame time interval for the given media
       
   358 // -----------------------------------------------------------------------------
       
   359 //
       
   360 TTimeIntervalMicroSeconds CG729PayloadFormatWrite::FrameTimeInterval(
       
   361                                                     TMediaId aMediaId) const
       
   362     {
       
   363     if ( KUidMediaTypeAudio == aMediaId.iMediaType )
       
   364         {
       
   365         return iFrameTimeInterval;
       
   366         }
       
   367     else
       
   368         {
       
   369         return TTimeIntervalMicroSeconds( TInt64( 0 ) );
       
   370         }
       
   371     }
       
   372 
       
   373 // -----------------------------------------------------------------------------
       
   374 // CG729PayloadFormatWrite::Duration
       
   375 // Return the frame time interval for the given media
       
   376 // NOT SUPPORTED
       
   377 // -----------------------------------------------------------------------------
       
   378 //
       
   379 TTimeIntervalMicroSeconds CG729PayloadFormatWrite::Duration(
       
   380                                               TMediaId /*aMediaType*/) const
       
   381     {
       
   382     return TTimeIntervalMicroSeconds( TInt64( 0 ) );
       
   383     }
       
   384 
       
   385 // -----------------------------------------------------------------------------
       
   386 // CG729PayloadFormatWrite::EmptySourceBufferL
       
   387 // Empty the given sourcebuffer
       
   388 // Sourcebuffer is given in iSourceBuffer.
       
   389 // Called by statemachine
       
   390 // -----------------------------------------------------------------------------
       
   391 //
       
   392 void CG729PayloadFormatWrite::EmptySourceBufferL()
       
   393     {
       
   394     #ifdef TRACE_G729_PAYLOAD_FORMAT_WRITE
       
   395         RDebug::Print (_L ("CG729PayloadFormatWrite::EmptySourceBufferL - SRC BUF SIZE: %d"),
       
   396         iSourceBuffer->Data().Size() );
       
   397     #endif
       
   398 
       
   399     TPtrC8 audioFrame( iSourceBuffer->Data().Mid( KG729NumOfHeaderBytes ) );
       
   400     TPtrC8 dtxHeader( iSourceBuffer->Data().Left( KG729NumOfHeaderBytes ) );
       
   401 
       
   402     if ( KAudioFrameHeaderByte == dtxHeader[0] )
       
   403         {
       
   404         #ifdef TRACE_G729_PAYLOAD_FORMAT_WRITE
       
   405             RDebug::Print (_L ("CG729PayloadFormatWrite::EmptySourceBufferL - AUDIO FRAME") );
       
   406         #endif
       
   407 
       
   408         iFrameIndex++;
       
   409         DoBitPacking( audioFrame, iSinkBuffer->Data(), EFalse );
       
   410         }
       
   411     else if ( KCNoiseFrameHeaderByte == dtxHeader[0] )
       
   412         {
       
   413         #ifdef TRACE_G729_PAYLOAD_FORMAT_WRITE
       
   414             RDebug::Print (_L ("CG729PayloadFormatWrite::EmptySourceBufferL - CNOISE FRAME") );
       
   415         #endif
       
   416         
       
   417         // This is first comfort noise received. Audio in buffer must send 
       
   418         // immediately with CN frame at the end of buffer. RFC3551 4.5.6.
       
   419         iFrameIndex = 0;
       
   420         if ( KErrNone == DoBitPacking( audioFrame, iSinkBuffer->Data(), ETrue ) )
       
   421             {
       
   422             DeliverPacketL( *iSinkBuffer );
       
   423             }
       
   424         }
       
   425     else
       
   426         {
       
   427         #ifdef TRACE_G729_PAYLOAD_FORMAT_WRITE
       
   428             RDebug::Print (_L ("CG729PayloadFormatWrite::EmptySourceBufferL - NULL BIT RATE FRAME") );
       
   429         #endif
       
   430         }
       
   431     
       
   432     if ( iFrameIndex == iFramesPerPacket )
       
   433         {
       
   434         // Packetization interval amount of audio frames is received
       
   435         iFrameIndex = 0;
       
   436         DeliverPacketL( *iSinkBuffer );
       
   437         }  
       
   438         
       
   439     iStateMachine->ChangeState( ESourceBufferEmptied );
       
   440     }
       
   441 
       
   442 // -----------------------------------------------------------------------------
       
   443 // CG729PayloadFormatWrite::DeliverPacketL
       
   444 // Prepare the packet header and deliver the packet to the datasink.
       
   445 // -----------------------------------------------------------------------------
       
   446 //
       
   447 void CG729PayloadFormatWrite::DeliverPacketL( CMMFDataBuffer& aPayload )
       
   448     {
       
   449     #ifdef TRACE_G729_PAYLOAD_FORMAT_WRITE
       
   450         RDebug::Print( _L("CG729PayloadFormatWrite::DeliverPacketL - TSTAMP: %u"),
       
   451             static_cast<TUint32>( aPayload.TimeToPlay().Int64() ) );
       
   452     #endif
       
   453 
       
   454     // Set the marker bit if it is very first packet.
       
   455     if ( !iFirstPacketFinished )
       
   456         {
       
   457         iRtpSendHeader.iMarker = 1;
       
   458         iFirstPacketFinished = ETrue;
       
   459         }
       
   460     else
       
   461         {
       
   462         iRtpSendHeader.iMarker = 0;
       
   463         }
       
   464     
       
   465     if ( !iClip )
       
   466         {
       
   467         User::Leave( KErrNotReady );
       
   468         }
       
   469 
       
   470     // Construct RTP header.                     
       
   471     iRtpSendHeader.iPayloadType = iCInfo.iPayloadType;
       
   472     iRtpSendHeader.iTimestamp 
       
   473         = static_cast<TUint32>( aPayload.TimeToPlay().Int64() );
       
   474     
       
   475     if ( aPayload.Data().Size() )
       
   476         {  
       
   477         if ( iIsRtpSink )
       
   478             {
       
   479             iRtpDataSink->EmptyBufferL( &aPayload, this, iMediaId, iRtpSendHeader );
       
   480             }
       
   481         else
       
   482             {
       
   483     	    aPayload.SetLastBuffer( iRtpSendHeader.iMarker );
       
   484             iClip->EmptyBufferL( &aPayload, this, iMediaId );
       
   485             }
       
   486         }
       
   487 
       
   488 
       
   489     // Reset the payload buffer -- only if previous EmptyBufferL() is a 
       
   490     // synchronous call
       
   491     aPayload.Data().Zero();
       
   492     }
       
   493 
       
   494 // -----------------------------------------------------------------------------
       
   495 // CG729PayloadFormatWrite::SourceBufferEmptiedL
       
   496 // Handle the event that sourcebuffer has been emptied.
       
   497 // Sourcebuffer is given in "iSourceBuffer".
       
   498 // Called by the statemachine.
       
   499 // -----------------------------------------------------------------------------
       
   500 //
       
   501 void CG729PayloadFormatWrite::SourceBufferEmptiedL()
       
   502     {
       
   503     #ifdef TRACE_G729_PAYLOAD_FORMAT_WRITE
       
   504         RDebug::Print (_L ("CG729PayloadFormatWrite::SourceBufferEmptiedL()"));
       
   505     #endif
       
   506 
       
   507     iDataPath->BufferEmptiedL(iSourceBuffer);
       
   508     }
       
   509 
       
   510 // -----------------------------------------------------------------------------
       
   511 // CG729PayloadFormatWrite::SinkPrimeL
       
   512 // Prime sink
       
   513 // -----------------------------------------------------------------------------
       
   514 //
       
   515 void CG729PayloadFormatWrite::SinkPrimeL()
       
   516     {
       
   517     #ifdef TRACE_G729_PAYLOAD_FORMAT_WRITE
       
   518         RDebug::Print (_L ("CG729PayloadFormatWrite::SinkPrimeL()"));
       
   519     #endif
       
   520 
       
   521     iClip->SinkPrimeL();
       
   522     }
       
   523 
       
   524 // -----------------------------------------------------------------------------
       
   525 // CG729PayloadFormatWrite::SinkPlayL
       
   526 // Start playing.
       
   527 // -----------------------------------------------------------------------------
       
   528 //
       
   529 void CG729PayloadFormatWrite::SinkPlayL()
       
   530     {
       
   531     #ifdef TRACE_G729_PAYLOAD_FORMAT_WRITE
       
   532         RDebug::Print (_L ("CG729PayloadFormatWrite::SinkPlayL()"));
       
   533     #endif
       
   534     
       
   535     // Allocate buffer for data transfer between 
       
   536     // FormatWrite - MDataSink AND FormatWrite - redundancy payload encoder
       
   537     delete iSinkBuffer;
       
   538     iSinkBuffer = NULL;
       
   539     iSinkBuffer = CMMFDataBuffer::NewL( iCInfo.iFrameSize * iFramesPerPacket );
       
   540         
       
   541     // Start state machine
       
   542     iStateMachine->ChangeState( EEncodeIdle );
       
   543     // RTP Header marker-bit must be set to 1 when starting stream
       
   544     iFirstPacketFinished = EFalse;
       
   545     
       
   546     // Start a new cycle of frame collecting
       
   547     iFrameIndex = 0;
       
   548     
       
   549     if ( iSinkBuffer )
       
   550         {
       
   551         iSinkBuffer->SetLastBuffer( EFalse );
       
   552         }
       
   553 
       
   554     iClip->SinkPlayL();
       
   555     }
       
   556 
       
   557 // -----------------------------------------------------------------------------
       
   558 // CG729PayloadFormatWrite::SinkPauseL
       
   559 // Pause sink
       
   560 // -----------------------------------------------------------------------------
       
   561 //
       
   562 void CG729PayloadFormatWrite::SinkPauseL()
       
   563     {
       
   564     #ifdef TRACE_G729_PAYLOAD_FORMAT_WRITE
       
   565             RDebug::Print (_L ("CG729PayloadFormatWrite::SinkPauseL()"));
       
   566     #endif
       
   567     
       
   568     iStateMachine->Cancel();
       
   569     iStateMachine->ChangeState( EEncodeIdle );
       
   570     
       
   571     iClip->SinkPauseL();
       
   572     }
       
   573 
       
   574 // -----------------------------------------------------------------------------
       
   575 // CG729PayloadFormatWrite::SinkStopL
       
   576 // Stop sink
       
   577 // -----------------------------------------------------------------------------
       
   578 //
       
   579 void CG729PayloadFormatWrite::SinkStopL()
       
   580     {
       
   581     #ifdef TRACE_G729_PAYLOAD_FORMAT_WRITE
       
   582             RDebug::Print( _L("CG729PayloadFormatWrite::SinkStopL") );
       
   583     #endif
       
   584      
       
   585     // Stop state machine
       
   586     iStateMachine->Cancel();
       
   587     iStateMachine->ChangeState( EEncodeIdle );
       
   588     iClip->SinkStopL();
       
   589     }
       
   590 
       
   591 // ---------------------------------------------------------------------------
       
   592 // CG729PayloadFormatWrite::DoBitPacking
       
   593 // Does bit-packing for encoded speech parameters got from encoder.
       
   594 // ---------------------------------------------------------------------------
       
   595 //
       
   596 TInt CG729PayloadFormatWrite::DoBitPacking( const TDesC8& aSourceBuf,
       
   597     TDes8& aDestBuf, TBool aIsCNoise ) const
       
   598     {
       
   599     if ( aDestBuf.MaxLength() - aDestBuf.Length() < KG729FrameSize10ms )
       
   600         {
       
   601         #ifdef TRACE_G729_PAYLOAD_FORMAT_WRITE
       
   602             RDebug::Print ( _L ( "CG729PayloadFormatWrite::DoBitPacking - DESTINATION BUF TOO SMALL!" ) );
       
   603         #endif
       
   604         
       
   605         return KErrArgument;
       
   606         }
       
   607     else
       
   608         {
       
   609         TStreamEncoder encoder;
       
   610         encoder.Initialize( const_cast<TUint8*>( aDestBuf.Ptr() ), aDestBuf.Length(), 0 );
       
   611         
       
   612         TUint8 numOfParams( 0 );
       
   613         if ( aIsCNoise )
       
   614             {
       
   615             numOfParams = KG729NumOfCNoiseParams;
       
   616             aDestBuf.SetLength( aDestBuf.Length() + KG729CNFrameSize );
       
   617             }
       
   618         else
       
   619             {
       
   620             numOfParams = KG729NumOfAudioParams;
       
   621             aDestBuf.SetLength( aDestBuf.Length() + KG729FrameSize10ms );
       
   622             }
       
   623 
       
   624         TUint8 curParamBits( 0 );
       
   625         TInt byteIndex( 0 );
       
   626         TUint8 lsb( 0 );
       
   627         TUint8 msb( 0 );
       
   628         
       
   629         for ( TInt i = 0; i < numOfParams; i++ )
       
   630             {
       
   631             if ( aIsCNoise )
       
   632                 {
       
   633                 curParamBits = KG729CodecBufCNoiseBits[i];
       
   634                 }
       
   635             else
       
   636                 {
       
   637                 curParamBits = KG729CodecBufAudioBits[i];
       
   638                 }
       
   639             
       
   640             if ( KBitsInByte >= curParamBits )
       
   641                 {
       
   642                 lsb = aSourceBuf[ byteIndex ];
       
   643                 encoder.Encode( TUint32( lsb ), curParamBits );
       
   644                 }
       
   645             else
       
   646                 {
       
   647                 lsb = aSourceBuf[ byteIndex ];
       
   648                 msb = aSourceBuf[ byteIndex + 1 ];
       
   649                 encoder.Encode( TUint32( msb ), curParamBits - KBitsInByte );
       
   650                 encoder.Encode( TUint32( lsb ), KBitsInByte );
       
   651                 }
       
   652                 
       
   653             byteIndex += 2;
       
   654             }
       
   655             
       
   656         return KErrNone;            
       
   657         }        
       
   658     }
       
   659 
       
   660 // ---------------------------------------------------------------------------
       
   661 // CG729PayloadFormatWrite::ConfigurePayloadFormatL
       
   662 // Configure payload encoding parameters
       
   663 // ---------------------------------------------------------------------------
       
   664 //
       
   665 void CG729PayloadFormatWrite::ConfigurePayloadFormatL( 
       
   666         const TDesC8& aConfigParams, 
       
   667         CMccRtpMediaClock& aClock  )
       
   668     {
       
   669     #ifdef TRACE_G729_PAYLOAD_FORMAT_WRITE
       
   670         RDebug::Print( _L("CG729PayloadFormatWrite::ConfigurePayloadFormatL IN") );
       
   671     #endif
       
   672     __ASSERT_ALWAYS( aConfigParams.Size() == sizeof( TMccCodecInfo ),
       
   673         User::Leave( KErrArgument ) );
       
   674     
       
   675     TMccCodecInfoBuffer infoBuffer;
       
   676     infoBuffer.Copy( aConfigParams );
       
   677     
       
   678     if ( !infoBuffer().iIsUpdate )
       
   679         {
       
   680         iCInfo = infoBuffer();
       
   681         iRtpMediaClock = &aClock; 
       
   682         iKey = iRtpMediaClock->RegisterMediaFormat( KG729SampleRate ,iCInfo.iHwFrameTime ); 
       
   683         
       
   684         iCInfo.iHwFrameTime = KG729FrameTimeInMs;   
       
   685         iFramesPerPacket = iCInfo.iPtime / iCInfo.iHwFrameTime;
       
   686         iCInfo.iFrameSize = KG729FrameSize10ms;
       
   687         iFrameTimeInterval = TInt64( iCInfo.iHwFrameTime * TInt8( iFramesPerPacket ) );
       
   688 
       
   689         #ifdef TRACE_G729_PAYLOAD_FORMAT_WRITE
       
   690             RDebug::Print( _L( "CG729PayloadFormatWrite::ConfigurePayloadFormatL - FramesPerPacket: %d, FrameSize: %d" ), iFramesPerPacket, iCInfo.iFrameSize );
       
   691         #endif
       
   692 
       
   693         if ( EGenRedUsed == iCInfo.iAlgoUsed )
       
   694             {
       
   695             #ifdef TRACE_G729_PAYLOAD_FORMAT_WRITE
       
   696             RDebug::Print( _L("CG729PayloadFormatWrite::ConfigurePayloadFormatL, RED LEVEL: %d"),
       
   697                 iCInfo.iRedundancyCount );
       
   698             #endif
       
   699             
       
   700             CPayloadFormatWrite* redEncoder
       
   701                 = static_cast<CMccRedPayloadWrite*>( iClip );
       
   702             
       
   703             TMccRedPayloadWriteConfig config;
       
   704             config.iRedBlockCount = iCInfo.iRedundancyCount;
       
   705             config.iMaxPayloadSize = iCInfo.iFrameSize * iFramesPerPacket;
       
   706             config.iNumOfEncodings = 1;
       
   707             config.iRedPayloadType = iCInfo.iRedundantPayload;
       
   708             config.InitPayloadTypes();
       
   709             config.iEncPayloadTypes[0] = iCInfo.iPayloadType;
       
   710             TMccRedPayloadWritePckg pckg( config );
       
   711             redEncoder->ConfigurePayloadFormatL( pckg, *iRtpMediaClock );
       
   712             }
       
   713         }
       
   714     else
       
   715         {
       
   716         UpdateConfigurationL( infoBuffer() ); 
       
   717         }
       
   718     
       
   719     #ifdef TRACE_G729_PAYLOAD_FORMAT_WRITE
       
   720     RDebug::Print ( _L ( "CG729PayloadFormatWrite::ConfigurePayloadFormatL OUT" ) );
       
   721     #endif
       
   722     }
       
   723 
       
   724 // -----------------------------------------------------------------------------
       
   725 // CG729PayloadFormatWrite::UpdateConfigurationL
       
   726 // Update payload encoding parameters
       
   727 // -----------------------------------------------------------------------------
       
   728 //
       
   729 void CG729PayloadFormatWrite::UpdateConfigurationL( const TMccCodecInfo& aCodecInfo )
       
   730     {
       
   731     #ifdef TRACE_G729_PAYLOAD_FORMAT_WRITE
       
   732         RDebug::Print( _L("CG729PayloadFormatWrite::UpdateConfigurationL IN") );
       
   733     #endif
       
   734     
       
   735     iCInfo.iPtime = aCodecInfo.iPtime;    
       
   736     iCInfo.iPayloadType = aCodecInfo.iPayloadType;
       
   737     iFramesPerPacket = iCInfo.iPtime / iCInfo.iHwFrameTime;
       
   738     iFrameTimeInterval = TInt64( iCInfo.iHwFrameTime * TInt8( iFramesPerPacket ) );
       
   739                                                             
       
   740     // Allocate buffer for data transfer between 
       
   741     // FormatWrite - MDataSink AND FormatWrite - redundancy payload encoder
       
   742     delete iSinkBuffer;
       
   743     iSinkBuffer = NULL;
       
   744     iSinkBuffer = CMMFDataBuffer::NewL( iCInfo.iFrameSize * iFramesPerPacket );
       
   745                                         
       
   746     // Start a new cycle of frame collecting
       
   747     iFrameIndex = 0;
       
   748     
       
   749     #ifdef TRACE_G729_PAYLOAD_FORMAT_WRITE
       
   750         RDebug::Print( _L("CG729PayloadFormatWrite::UpdateConfigurationL OUT") );
       
   751     #endif
       
   752     }    
       
   753 // ========================== OTHER EXPORTED FUNCTIONS =========================
       
   754 
       
   755 //  End of File