bluetoothengine/btaudiostreamer/src/btaudiostreamsender.cpp
changeset 0 f63038272f30
equal deleted inserted replaced
-1:000000000000 0:f63038272f30
       
     1 /*
       
     2 * Copyright (c) 2005 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:  Contains an implementation of CBTAudioStreamSender class.
       
    15 *
       
    16 */
       
    17 
       
    18 
       
    19 #include "btaudiostreamsender.h"
       
    20 #include "btaudiostreamsendersbc.h"
       
    21 #include "btaudiostreamerdebug.h" 
       
    22 #include <btsockaddr.h> // TBTSockAddr 
       
    23 
       
    24 // ---------------------------------------------------------------------------
       
    25 // Constructor. 
       
    26 // ---------------------------------------------------------------------------
       
    27 //
       
    28 CBTAudioStreamSender::CBTAudioStreamSender(MBTAudioStreamSenderObserver& aObserver, RRtpSession& aSession) :
       
    29     CActive(EPriorityHigh),     
       
    30     iObserver(aObserver), 
       
    31     iRtpSession(aSession), 
       
    32     iPayloadDesC(NULL,NULL), 
       
    33     iLinkOptimiserAvailable(EFalse)
       
    34     {
       
    35     BT_AUDIO_STREAMER_TRACE_OPT( KPRINTFTRACE, FLOG(_L("[BTAudioStreamer]\t CBTAudioStreamSender::CBTAudioStreamSender() ->")));
       
    36     CActiveScheduler::Add(this);    
       
    37     BT_AUDIO_STREAMER_TRACE_OPT( KPRINTFTRACE, FLOG(_L("[BTAudioStreamer]\t CBTAudioStreamSender::CBTAudioStreamSender() <-")));
       
    38     }
       
    39 
       
    40 // ---------------------------------------------------------------------------
       
    41 // Symbian OS second phase contruction. 
       
    42 // ---------------------------------------------------------------------------
       
    43 //
       
    44 void CBTAudioStreamSender::ConstructL()
       
    45     {
       
    46     BT_AUDIO_STREAMER_TRACE_OPT( KPRINTFTRACE, FLOG(_L("[BTAudioStreamer]\t CBTAudioStreamSender::ConstructL() ->")));   
       
    47 
       
    48     iSendSrc = iRtpSession.NewSendSourceL();
       
    49     BT_AUDIO_STREAMER_TRACE_OPT( KPRINTFTRACE, FLOG(_L("[BTAudioStreamer]\t New send source created.")));
       
    50     iSendSrc.PrivRegisterEventCallbackL(ERtpSendSucceeded, (TRtpCallbackFunction)CBTAudioStreamSender::PacketSent, this);
       
    51     iSendSrc.PrivRegisterEventCallbackL(ERtpSendFail, (TRtpCallbackFunction)CBTAudioStreamSender::SendError, this);
       
    52     BT_AUDIO_STREAMER_TRACE_OPT( KPRINTFTRACE, FLOG(_L("[BTAudioStreamer]\t Callbacks registered.")));
       
    53 
       
    54     iStreamerState = EStopped; 
       
    55     BT_AUDIO_STREAMER_TRACE_OPT( KPRINTSTATE, FLOG(_L("[BTAudioStreamer]\t State changed to: EStopped")));
       
    56 
       
    57     iThread = RThread();
       
    58 
       
    59     iCurrentSendPacket = new (ELeave) RRtpSendPacket; 
       
    60 
       
    61     iSpareSendPacket = new (ELeave) RRtpSendPacket; 
       
    62 
       
    63     if(iA2DPOptimiser.Open() == KErrNone)
       
    64         {
       
    65         iLinkOptimiserAvailable = ETrue; 
       
    66         }
       
    67 
       
    68     BT_AUDIO_STREAMER_TRACE_OPT( KPRINTFTRACE, FLOG(_L("[BTAudioStreamer]\t CBTAudioStreamSender::ConstructL() <-")));
       
    69     }
       
    70 
       
    71 // ---------------------------------------------------------------------------
       
    72 // Static factory method. 
       
    73 // ---------------------------------------------------------------------------
       
    74 //
       
    75 CBTAudioStreamSender* CBTAudioStreamSender::NewL(MBTAudioStreamSenderObserver& aObserver, RRtpSession& aSession)
       
    76     {
       
    77     BT_AUDIO_STREAMER_TRACE_OPT( KPRINTFTRACE, FLOG(_L("[BTAudioStreamer]\t CBTAudioStreamSender::NewL() ->")));
       
    78     if (!aSession.IsOpen())
       
    79         {
       
    80         User::Leave(KErrArgument);
       
    81         }
       
    82     BT_AUDIO_STREAMER_TRACE_OPT( KPRINTFTRACE, FLOG(_L("[BTAudioStreamer]\t CBTAudioStreamSender::NewL() <-")));
       
    83     return CBTAudioStreamSenderSBC::NewL(aObserver, aSession); 
       
    84     }
       
    85 
       
    86 // ---------------------------------------------------------------------------
       
    87 // Destructor. 
       
    88 // ---------------------------------------------------------------------------
       
    89 //
       
    90 CBTAudioStreamSender::~CBTAudioStreamSender()
       
    91     {
       
    92     BT_AUDIO_STREAMER_TRACE_OPT( KPRINTFTRACE, FLOG(_L("[BTAudioStreamer]\t CBTAudioStreamSender::~CBTAudioStreamSender() ->")));
       
    93     Cancel();
       
    94     if(iCurrentSendPacket) 
       
    95         {
       
    96         if(iCurrentSendPacket->IsOpen() != EFalse)
       
    97             {
       
    98    			iCurrentSendPacket->Close();
       
    99             }
       
   100          delete iCurrentSendPacket; 
       
   101          iCurrentSendPacket = NULL; 
       
   102          }
       
   103 
       
   104     if(iSpareSendPacket) 
       
   105         {
       
   106         if(iSpareSendPacket->IsOpen() != EFalse)
       
   107             {
       
   108             iSpareSendPacket->Close(); 
       
   109             }
       
   110         delete iSpareSendPacket; 
       
   111         iSpareSendPacket = NULL; 
       
   112         }
       
   113     iSendSrc.Close();
       
   114 
       
   115     if(iLinkOptimiserAvailable)
       
   116         {
       
   117         iA2DPOptimiser.Close();
       
   118         }
       
   119 
       
   120     BT_AUDIO_STREAMER_TRACE_OPT( KPRINTFTRACE, FLOG(_L("[BTAudioStreamer]\t CBTAudioStreamSender::~CBTAudioStreamSender() <-")));
       
   121     }
       
   122 
       
   123 // ---------------------------------------------------------------------------
       
   124 // This is the static callback method which CBTAudioStreamSender registers with the RtpSession to be called
       
   125 // when a packet is _successfully_ sent.  It is a static method so simply calls a processing
       
   126 // method on the class pointed to be aPtr (which is the CBTAudioStreamSender which registered the cb).
       
   127 // ---------------------------------------------------------------------------
       
   128 //
       
   129 void CBTAudioStreamSender::PacketSent(CBTAudioStreamSender* aPtr, const TRtpEvent& /*aEvent*/)
       
   130     {
       
   131     BT_AUDIO_STREAMER_TRACE_OPT( KPRINTFTRACE, FLOG(_L("[BTAudioStreamer]\t CBTAudioStreamSender::PacketSent() ->")));
       
   132     aPtr->DoPacketSent();
       
   133     BT_AUDIO_STREAMER_TRACE_OPT( KPRINTFTRACE, FLOG(_L("[BTAudioStreamer]\t CBTAudioStreamSender::PacketSent() <-")));
       
   134     }
       
   135 
       
   136 // ---------------------------------------------------------------------------
       
   137 // An instance method which is called by the static callback function.  We simply notify the
       
   138 // observer if all data has been sent. If it hasn't, then we send more data. 
       
   139 // ---------------------------------------------------------------------------
       
   140 //
       
   141 void CBTAudioStreamSender::DoPacketSent()
       
   142     {
       
   143     BT_AUDIO_STREAMER_TRACE_OPT( KPRINTFTRACE, FLOG(_L("[BTAudioStreamer]\t CBTAudioStreamSender::DoPacketSent() ->")));
       
   144 
       
   145 	// First check if we're Stopping. 
       
   146     if(iStreamerState == EStopped)
       
   147         {
       
   148 	    BT_AUDIO_STREAMER_TRACE_OPT( KPRINTSTATE, FLOG(_L("[BTAudioStreamer]\t Stopping and packet sending completed.")));
       
   149         iObserver.NotifyBufferSent(*iBuffer); // Return the buffer. 
       
   150 		return; // No need to do more here, we're stopping. 
       
   151         }
       
   152 	else
       
   153 		{
       
   154 		iStreamerState = EBuffering; 
       
   155     	BT_AUDIO_STREAMER_TRACE_OPT( KPRINTSTATE, FLOG(_L("[BTAudioStreamer]\t State changed to: EBuffering")));
       
   156 		}
       
   157 
       
   158     PacketSendingCompleted(iPayloadDesC); 
       
   159  
       
   160     // If we're here, then there either is data in the buffer or it has been emptied completely. 
       
   161     // Check this by calling the method again. If we consumed the buffer completely, 
       
   162     // the method just signals the observer. 
       
   163     if(iNonprocessedDataInBuffer != EFalse) 
       
   164         {
       
   165 				// Check if we need to start using new sendpacket. 
       
   166         if(iChangingFrameLength != EFalse)
       
   167             {
       
   168         	  SwitchToNewSendPacket(); 
       
   169 		        }
       
   170             ConsumeBuffer(); 
       
   171         }
       
   172     else 
       
   173         {
       
   174         iObserver.NotifyBufferSent(*iBuffer); 
       
   175         }
       
   176 
       
   177     BT_AUDIO_STREAMER_TRACE_OPT( KPRINTFTRACE, FLOG(_L("[BTAudioStreamer]\t CBTAudioStreamSender::DoPacketSent() <-")));
       
   178 }
       
   179 
       
   180 // ---------------------------------------------------------------------------
       
   181 // This is the static callback method which CBTAudioStreamSender registers with the RtpSession to be called
       
   182 // when a packet sending fails.
       
   183 // ---------------------------------------------------------------------------
       
   184 //
       
   185 void CBTAudioStreamSender::SendError(CBTAudioStreamSender* aPtr, const TRtpEvent& /*aEvent*/)
       
   186     {
       
   187     BT_AUDIO_STREAMER_TRACE_OPT( KPRINTFTRACE, FLOG(_L("[BTAudioStreamer]\t CBTAudioStreamSender::SendError() ->")));
       
   188     aPtr->DoSendError();
       
   189     BT_AUDIO_STREAMER_TRACE_OPT( KPRINTFTRACE, FLOG(_L("[BTAudioStreamer]\t CBTAudioStreamSender::SendError() <-")));
       
   190     }
       
   191 
       
   192 // ---------------------------------------------------------------------------
       
   193 // An instance method which is called by the static callback function.  
       
   194 // We set the state to EErrorSending and handle the error next time in RunL. 
       
   195 // ---------------------------------------------------------------------------
       
   196 //
       
   197 void CBTAudioStreamSender::DoSendError()
       
   198     {
       
   199     BT_AUDIO_STREAMER_TRACE_OPT( KPRINTFTRACE, FLOG(_L("[BTAudioStreamer]\t CBTAudioStreamSender::DoSendError() ->")));
       
   200     
       
   201     iStreamerState = EErrorSending; 
       
   202     BT_AUDIO_STREAMER_TRACE_OPT( KPRINTSTATE, FLOG(_L("[BTAudioStreamer]\t State changed to: EErrorSending")));
       
   203     if (!IsActive())
       
   204         {
       
   205         TRequestStatus *status = &iStatus;
       
   206         iStatus = KRequestPending;
       
   207         iThread.RequestComplete(status, KErrNone);
       
   208         SetActive();
       
   209         }
       
   210     BT_AUDIO_STREAMER_TRACE_OPT( KPRINTFTRACE, FLOG(_L("[BTAudioStreamer]\t CBTAudioStreamSender::DoSendError() <-")));
       
   211     }
       
   212 
       
   213 // ---------------------------------------------------------------------------
       
   214 // This method is for setting the sender up. 
       
   215 // ---------------------------------------------------------------------------
       
   216 //
       
   217 TInt CBTAudioStreamSender::SetNewFrameLength(TUint aOutboundMTUSize, const TUint aFrameLength, const TUint aTargetBitrate)
       
   218     {
       
   219     BT_AUDIO_STREAMER_TRACE_OPT( KPRINTFTRACE, FLOG(_L("[BTAudioStreamer]\t CBTAudioStreamSender::SetNewFrameLength() ->")));
       
   220 		TInt retVal = KErrGeneral;
       
   221 
       
   222 		// Don't proceed if the previous change is not completed yet. 
       
   223 		if(iChangingFrameLength != EFalse)
       
   224 		    {
       
   225         BT_AUDIO_STREAMER_TRACE_OPT( KPRINTFTRACE, FLOG(_L("[BTAudioStreamer]\t Previous frame length change still ongoing!")));
       
   226         BT_AUDIO_STREAMER_TRACE_OPT( KPRINTFTRACE, FLOG(_L("[BTAudioStreamer]\t CBTAudioStreamSender::SetNewFrameLength() <-")));
       
   227 		    return KErrInUse; 
       
   228 		    }
       
   229 
       
   230     if(iSpareSendPacket) 
       
   231         {
       
   232         __ASSERT_DEBUG(!iSpareSendPacket->IsOpen(),User::Invariant());
       
   233         }
       
   234 
       
   235     TInt requiredPacketLength = CalculatePacketLength(aOutboundMTUSize, aFrameLength); 
       
   236 
       
   237     if(requiredPacketLength > 0) 
       
   238         {
       
   239 		    iNewFrameLength = aFrameLength; 
       
   240 
       
   241     		BT_AUDIO_STREAMER_TRACE_OPT( KPRINTFTRACE, FLOG(_L("[BTAudioStreamer]\t Creating new sendpacket.")));
       
   242 			__ASSERT_DEBUG(iSpareSendPacket, User::Invariant());
       
   243     		TRAPD(ret, *iSpareSendPacket = iSendSrc.NewSendPacketL(requiredPacketLength));
       
   244         	if( ret )
       
   245         		{
       
   246         		BT_AUDIO_STREAMER_TRACE_OPT( KPRINTFTRACE, FLOG(_L("[BTAudioStreamer]\t ERROR! Creating new sendpacket failed.")));
       
   247         		return KErrGeneral;
       
   248         		}
       
   249         	iChangingFrameLength = ETrue; 
       
   250 			retVal = KErrNone; 
       
   251       }
       
   252     else 
       
   253         {
       
   254         BT_AUDIO_STREAMER_TRACE_OPT( KPRINTSTATE, FLOG(_L("[BTAudioStreamer]\t Error! Packet length must be greater than zero!")));
       
   255         retVal = KErrArgument; 
       
   256         }
       
   257     BT_AUDIO_STREAMER_TRACE_OPT( KPRINTFTRACE, FLOG(_L("[BTAudioStreamer]\t CBTAudioStreamSender::SetNewFrameLength() <-")));
       
   258 
       
   259     iTargetBitrate = aTargetBitrate; 
       
   260     return retVal; 
       
   261     }
       
   262 
       
   263 
       
   264 // ---------------------------------------------------------------------------
       
   265 // This method is for setting the sender up. 
       
   266 // ---------------------------------------------------------------------------
       
   267 //
       
   268 void CBTAudioStreamSender::StartL(TUint aOutboundMTUSize, const TUint aFrameLength, const TUint aTargetBitrate)
       
   269     {
       
   270     BT_AUDIO_STREAMER_TRACE_OPT( KPRINTFTRACE, FLOG(_L("[BTAudioStreamer]\t CBTAudioStreamSender::StartL() ->")));
       
   271     if(iCurrentSendPacket) 
       
   272         {
       
   273         __ASSERT_DEBUG(!iCurrentSendPacket->IsOpen(),User::Invariant());
       
   274         }
       
   275     TInt requiredPacketLength = CalculatePacketLength(aOutboundMTUSize, aFrameLength); 
       
   276 
       
   277     if(requiredPacketLength > 0) 
       
   278         {
       
   279 		__ASSERT_DEBUG(iCurrentSendPacket, User::Invariant());
       
   280         *iCurrentSendPacket = iSendSrc.NewSendPacketL(requiredPacketLength); 
       
   281         iTargetBitrate = aTargetBitrate; 
       
   282         InitSender(*iCurrentSendPacket, iPayloadDesC, iTargetBitrate); 
       
   283         iStreamerState = EBuffering; 
       
   284         BT_AUDIO_STREAMER_TRACE_OPT( KPRINTSTATE, FLOG(_L("[BTAudioStreamer]\t State changed to: EBuffering")));
       
   285       }
       
   286     else 
       
   287         {
       
   288         BT_AUDIO_STREAMER_TRACE_OPT( KPRINTSTATE, FLOG(_L("[BTAudioStreamer]\t Error! Packet length must be greater than zero!")));
       
   289         User::Leave(KErrArgument); 
       
   290         }
       
   291 
       
   292     // Streaming started, optimise the ACL link if optimiser service is available. 
       
   293     if(iLinkOptimiserAvailable)
       
   294         {
       
   295         // The below code is to get the connected device's BT Address.
       
   296         TBTSockAddr addr; 
       
   297         iRtpSession.RtpSocket()->RemoteName(addr); 
       
   298         TUint accessLatency = MaxFramesPerPacket() * CalculateFrameDuration(aFrameLength, aTargetBitrate); 
       
   299         // Not checking the return code, because it doesn't matter if it fails. 
       
   300         iA2DPOptimiser.OptimiseAclForAudioStreaming(addr.BTAddr(), aTargetBitrate, accessLatency);
       
   301         }
       
   302     BT_AUDIO_STREAMER_TRACE_OPT( KPRINTFTRACE, FLOG(_L("[BTAudioStreamer]\t CBTAudioStreamSender::StartL() <-")));
       
   303     }
       
   304 
       
   305 // ---------------------------------------------------------------------------
       
   306 // This method is for closing the sender down. 
       
   307 // ---------------------------------------------------------------------------
       
   308 //
       
   309 void CBTAudioStreamSender::Stop()
       
   310     {
       
   311     BT_AUDIO_STREAMER_TRACE_OPT( KPRINTFTRACE, FLOG(_L("[BTAudioStreamer]\t CBTAudioStreamSender::Stop() ->")));
       
   312 	// Make sure that the packet is not out at the moment. 
       
   313 	Cancel(); 
       
   314     if(iCurrentSendPacket->IsOpen() != EFalse)
       
   315         {
       
   316    		iCurrentSendPacket->Close(); 
       
   317         }
       
   318 
       
   319     if(iSpareSendPacket->IsOpen() != EFalse)
       
   320         {
       
   321     	iSpareSendPacket->Close(); 
       
   322         }
       
   323 
       
   324     // Remove the ACL link optimisation if optimiser service is available. 
       
   325     if(iLinkOptimiserAvailable)
       
   326         {
       
   327 	    TBTSockAddr addr; 
       
   328     	iRtpSession.RtpSocket()->RemoteName(addr); 
       
   329 	    // Not checking the return code, because it doesn't matter if it fails. 
       
   330     	iA2DPOptimiser.RemoveAclOptimisation(addr.BTAddr());
       
   331 		}
       
   332     iStreamerState = EStopped; 
       
   333     BT_AUDIO_STREAMER_TRACE_OPT( KPRINTSTATE, FLOG(_L("[BTAudioStreamer]\t State changed to: EStopped")));
       
   334 
       
   335     BT_AUDIO_STREAMER_TRACE_OPT( KPRINTFTRACE, FLOG(_L("[BTAudioStreamer]\t CBTAudioStreamSender::Stop() <-")));
       
   336     }
       
   337 
       
   338 // ---------------------------------------------------------------------------
       
   339 // From class CBTAudioStreamSender.
       
   340 // RunL will be called when ConsumeBuffer has decided that we have enough 
       
   341 // frames for one packet, or DoSendError was called. 
       
   342 // ---------------------------------------------------------------------------
       
   343 //
       
   344 void CBTAudioStreamSender::RunL()
       
   345     {        
       
   346     BT_AUDIO_STREAMER_TRACE_OPT( KPRINTFTRACE, FLOG(_L("[BTAudioStreamer]\t CBTAudioStreamSender::RunL() ->")));
       
   347     switch(iStreamerState)
       
   348         {
       
   349         case ESending: 
       
   350             {    
       
   351             // Set A2DP media packet header. 
       
   352             AddHeaderToSendPacket(iPayloadDesC); 
       
   353 
       
   354             // Use the timestamp from the first buffer. 
       
   355             BT_AUDIO_STREAMER_TRACE_OPT( KPRINTFTRACE, FLOG(_L("[BTAudioStreamer]\t Adjust and set timestamp.")));
       
   356             iCurrentSendPacket->SetTimestamp(iAdjustedTimestamp); 
       
   357 
       
   358             // Set the length and send the packet. 
       
   359             BT_AUDIO_STREAMER_TRACE_OPT( KPRINTFTRACE, FLOG(_L("[BTAudioStreamer]\t Set length.")));
       
   360             iCurrentSendPacket->WritePayload().SetLength(iPayloadDesC.Length());
       
   361 
       
   362             BT_AUDIO_STREAMER_TRACE_OPT( KPRINTFTRACE, FLOG(_L("[BTAudioStreamer]\t Send.")));
       
   363             iCurrentSendPacket->Send();
       
   364 
       
   365             BT_AUDIO_STREAMER_TRACE_OPT( KPRINTFTRACE, FLOG(_L("[BTAudioStreamer]\t Packet has transferred to RTP API.")));
       
   366             }
       
   367             break; 
       
   368         case EBuffering: 
       
   369             {
       
   370             // Note: Here we will check that no packets were discarded while waiting for the sending to complete. 
       
   371             // If that happens, we could inform SAC and then try to decrease the bitrate. 
       
   372     
       
   373             BT_AUDIO_STREAMER_TRACE_OPT( KPRINTFTRACE, FLOG(_L("[BTAudioStreamer]\t Packet sent succesfully.")));
       
   374             iPayloadDesC.Zero(); 
       
   375             }
       
   376             break; 
       
   377         case EErrorSending: 
       
   378             {
       
   379             // Note: Inform the observer 
       
   380             BT_AUDIO_STREAMER_TRACE_OPT( KPRINTFTRACE, FLOG(_L("[BTAudioStreamer]\t Packet sending failed.")));
       
   381             iPayloadDesC.Zero(); 
       
   382             PacketSendingCompleted(iPayloadDesC); 
       
   383             iStreamerState = EBuffering; 
       
   384             
       
   385             // Tell client that we're ready for more data. Method name is misleading, but we will request for more 
       
   386             // until the observer tells us to stop. 
       
   387             iObserver.NotifyBufferSent(*iBuffer); 
       
   388 
       
   389             BT_AUDIO_STREAMER_TRACE_OPT( KPRINTSTATE, FLOG(_L("[BTAudioStreamer]\t State changed to: EBuffering")));
       
   390             }
       
   391             break; 
       
   392         default: 
       
   393             {
       
   394           BT_AUDIO_STREAMER_TRACE_OPT( KPRINTFTRACE, FLOG(_L("[BTAudioStreamer]\t Error: RunL is in incorrect state!")));
       
   395             }
       
   396             break; 
       
   397         }
       
   398     BT_AUDIO_STREAMER_TRACE_OPT( KPRINTFTRACE, FLOG(_L("[BTAudioStreamer]\t CBTAudioStreamSender::RunL() <-")));
       
   399     }
       
   400 
       
   401 // ---------------------------------------------------------------------------
       
   402 // For sending the frames. 
       
   403 // ---------------------------------------------------------------------------
       
   404 //
       
   405 TInt CBTAudioStreamSender::SendThisBuffer(const TDesC8& aBuffer, TTimeIntervalMicroSeconds aTimestamp)
       
   406     {
       
   407     BT_AUDIO_STREAMER_TRACE_OPT( KPRINTFTRACE, FLOG(_L("[BTAudioStreamer]\t CBTAudioStreamSender::SendThisBuffer() ->")));
       
   408 
       
   409     BT_AUDIO_STREAMER_TRACE_OPT( KPRINTFTRACE, FPrint(_L("[BTAudioStreamer]\t Received timestamp low: %d"), I64LOW(aTimestamp.Int64()))); 
       
   410     BT_AUDIO_STREAMER_TRACE_OPT( KPRINTFTRACE, FPrint(_L("[BTAudioStreamer]\t Received timestamp high: %d"), I64HIGH(aTimestamp.Int64()))); 
       
   411 
       
   412     // Store the buffer's address for later reference. 
       
   413     iBuffer = &aBuffer; 
       
   414 
       
   415 		if(iChangingFrameLength != EFalse) 
       
   416 		{
       
   417 			// Check the new framelength... 
       
   418 			if(aBuffer.Length() == iNewFrameLength)  // Check if the buffer exactly of the new length. 
       
   419 			{
       
   420 						// If we have data with previous frame length in buffer, send it first. 
       
   421             if(iNonprocessedDataInBuffer != EFalse)
       
   422                 {
       
   423 	              ProceedToPacketSending(); 
       
   424                 return KErrNone; 
       
   425                 }
       
   426             else	// Else we can switch to new packet immediately and continue processing this buffer. 
       
   427                 {
       
   428 								SwitchToNewSendPacket(); 
       
   429                 }
       
   430 			}
       
   431 			else if(aBuffer.Length() > iNewFrameLength) // Check if it's safe to peek at index iNewFrameLength. 
       
   432 			{
       
   433 				if(aBuffer[iNewFrameLength] == 0x9c) // Check if the index iNewFrameLength the syncword. 
       
   434 				    {
       
   435 						// If we have data with previous frame length in buffer, send it first. 
       
   436             if(iNonprocessedDataInBuffer != EFalse)
       
   437                 {
       
   438 	              ProceedToPacketSending(); 
       
   439                 return KErrNone; 
       
   440                 }
       
   441             else	// Else we can switch to new packet immediately and continue processing this buffer. 
       
   442                 {
       
   443 								SwitchToNewSendPacket(); 
       
   444                 }
       
   445 						}
       
   446 				else 
       
   447 				{
       
   448             BT_AUDIO_STREAMER_TRACE_OPT( KPRINTFTRACE, FLOG(_L("[BTAudioStreamer]\t CBTAudioStreamSender: Still waiting for packets of the new frame length...")));
       
   449 				}
       
   450 			}
       
   451 			else 
       
   452 			{
       
   453         BT_AUDIO_STREAMER_TRACE_OPT( KPRINTFTRACE, FLOG(_L("[BTAudioStreamer]\t CBTAudioStreamSender: Still waiting for packets of the new frame length...")));
       
   454 				// Encoder has not yet started to use the new frame length. 
       
   455 			}
       
   456 		}
       
   457     else if(iStreamerState != EBuffering) 
       
   458         {
       
   459         // Previous sending is not yet completed or there is was an error that is not yet handled. 
       
   460         // Just discard the incoming frame. 
       
   461         BT_AUDIO_STREAMER_TRACE_OPT( KPRINTFTRACE, FLOG(_L("[BTAudioStreamer]\t CBTAudioStreamSender error: Previous buffer sending hasn't completed - discarding this buffer.")));
       
   462         iObserver.NotifyBufferSent(aBuffer); 
       
   463         BT_AUDIO_STREAMER_TRACE_OPT( KPRINTFTRACE, FLOG(_L("[BTAudioStreamer]\t CBTAudioStreamSender::SendThisBuffer() <-")));
       
   464         return KErrOverflow; 
       
   465         }
       
   466 
       
   467 		// Store the timestamp for later use. 
       
   468     iTimestamp = aTimestamp.Int64(); 
       
   469 
       
   470     iNonprocessedDataInBuffer = ETrue; 
       
   471     ConsumeBuffer(); 
       
   472 
       
   473     BT_AUDIO_STREAMER_TRACE_OPT( KPRINTFTRACE, FLOG(_L("[BTAudioStreamer]\t CBTAudioStreamSender::SendThisBuffer() <-")));
       
   474     return KErrNone; 
       
   475     }
       
   476 
       
   477 // ---------------------------------------------------------------------------
       
   478 // From class CActive.
       
   479 // Cancellation. 
       
   480 // ---------------------------------------------------------------------------
       
   481 //
       
   482 void CBTAudioStreamSender::DoCancel()
       
   483     {
       
   484     BT_AUDIO_STREAMER_TRACE_OPT( KPRINTFTRACE, FLOG(_L("[BTAudioStreamer]\t CBTAudioStreamSender::DoCancel() ->")));
       
   485     BT_AUDIO_STREAMER_TRACE_OPT( KPRINTFTRACE, FLOG(_L("[BTAudioStreamer]\t CBTAudioStreamSender::DoCancel() <-")));
       
   486     }
       
   487 
       
   488 inline void CBTAudioStreamSender::ConsumeBuffer()
       
   489     {
       
   490     BT_AUDIO_STREAMER_TRACE_OPT( KPRINTFTRACE, FLOG(_L("[BTAudioStreamer]\t CBTAudioStreamSender::ConsumeBuffer() ->")));
       
   491     if (!IsActive())
       
   492         {    
       
   493         BT_AUDIO_STREAMER_TRACE_OPT( KPRINTFTRACE, FLOG(_L("[BTAudioStreamer]\t CBTAudioStreamSender::ConsumeBuffer() ok to send")));				
       
   494 
       
   495         TInt spaceLeftInSendPacket = AddBufferToSendPacket(*iBuffer); 
       
   496 				iAdjustedTimestamp = iTimestamp;  // take a copy, because we want to keep the original timestamp. 
       
   497         if(spaceLeftInSendPacket >= 0) 
       
   498             {
       
   499             iNonprocessedDataInBuffer = EFalse; // This indicates that there's no need to call this method after sending. 
       
   500             }
       
   501         ProceedToPacketSending(); 
       
   502         }
       
   503     BT_AUDIO_STREAMER_TRACE_OPT( KPRINTFTRACE, FLOG(_L("[BTAudioStreamer]\t CBTAudioStreamSender::ConsumeBuffer() <-")));
       
   504     }
       
   505 
       
   506 
       
   507 inline void CBTAudioStreamSender::ProceedToPacketSending()
       
   508 {
       
   509     BT_AUDIO_STREAMER_TRACE_OPT( KPRINTFTRACE, FLOG(_L("[BTAudioStreamer]\t CBTAudioStreamSender::ProceedToPacketSending() ->")));
       
   510     iStreamerState = ESending; 
       
   511     BT_AUDIO_STREAMER_TRACE_OPT( KPRINTSTATE, FLOG(_L("[BTAudioStreamer]\t State changed to: ESending")));
       
   512     TRequestStatus *status = &iStatus;
       
   513     iStatus = KRequestPending;
       
   514     iThread.RequestComplete(status, KErrNone);
       
   515     SetActive();
       
   516     BT_AUDIO_STREAMER_TRACE_OPT( KPRINTFTRACE, FLOG(_L("[BTAudioStreamer]\t CBTAudioStreamSender::ProceedToPacketSending() <-")));
       
   517 }
       
   518 
       
   519 inline void CBTAudioStreamSender::SwitchToNewSendPacket()
       
   520     {
       
   521     BT_AUDIO_STREAMER_TRACE_OPT( KPRINTFTRACE, FLOG(_L("[BTAudioStreamer]\t CBTAudioStreamSender::SwitchToNewSendPacket() ->")));
       
   522 
       
   523 		// Make the iCurrentSendPacket point to the spare packet opened when the frame length change came. 
       
   524     RRtpSendPacket* oldSendPacket; 
       
   525     oldSendPacket = iCurrentSendPacket; 
       
   526     iCurrentSendPacket = iSpareSendPacket; 
       
   527 		iSpareSendPacket = oldSendPacket; 
       
   528 		
       
   529     // The previously used send packet (which has now become the spare send packet) can be closed. 
       
   530 		oldSendPacket->Close(); 
       
   531 
       
   532 		// The rest of the initializations: 
       
   533     InitSender(*iCurrentSendPacket, iPayloadDesC, iTargetBitrate); 
       
   534 
       
   535 		iChangingFrameLength = EFalse; 
       
   536 
       
   537     BT_AUDIO_STREAMER_TRACE_OPT( KPRINTFTRACE, FLOG(_L("[BTAudioStreamer]\t CBTAudioStreamSender::SwitchToNewSendPacket() <-")));
       
   538 	  }