--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/bluetoothengine/btaudiostreamer/src/btaudiostreamsender.cpp Mon Jan 18 20:28:57 2010 +0200
@@ -0,0 +1,538 @@
+/*
+* Copyright (c) 2005 Nokia Corporation and/or its subsidiary(-ies).
+* All rights reserved.
+* This component and the accompanying materials are made available
+* under the terms of "Eclipse Public License v1.0"
+* which accompanies this distribution, and is available
+* at the URL "http://www.eclipse.org/legal/epl-v10.html".
+*
+* Initial Contributors:
+* Nokia Corporation - initial contribution.
+*
+* Contributors:
+*
+* Description: Contains an implementation of CBTAudioStreamSender class.
+*
+*/
+
+
+#include "btaudiostreamsender.h"
+#include "btaudiostreamsendersbc.h"
+#include "btaudiostreamerdebug.h"
+#include <btsockaddr.h> // TBTSockAddr
+
+// ---------------------------------------------------------------------------
+// Constructor.
+// ---------------------------------------------------------------------------
+//
+CBTAudioStreamSender::CBTAudioStreamSender(MBTAudioStreamSenderObserver& aObserver, RRtpSession& aSession) :
+ CActive(EPriorityHigh),
+ iObserver(aObserver),
+ iRtpSession(aSession),
+ iPayloadDesC(NULL,NULL),
+ iLinkOptimiserAvailable(EFalse)
+ {
+ BT_AUDIO_STREAMER_TRACE_OPT( KPRINTFTRACE, FLOG(_L("[BTAudioStreamer]\t CBTAudioStreamSender::CBTAudioStreamSender() ->")));
+ CActiveScheduler::Add(this);
+ BT_AUDIO_STREAMER_TRACE_OPT( KPRINTFTRACE, FLOG(_L("[BTAudioStreamer]\t CBTAudioStreamSender::CBTAudioStreamSender() <-")));
+ }
+
+// ---------------------------------------------------------------------------
+// Symbian OS second phase contruction.
+// ---------------------------------------------------------------------------
+//
+void CBTAudioStreamSender::ConstructL()
+ {
+ BT_AUDIO_STREAMER_TRACE_OPT( KPRINTFTRACE, FLOG(_L("[BTAudioStreamer]\t CBTAudioStreamSender::ConstructL() ->")));
+
+ iSendSrc = iRtpSession.NewSendSourceL();
+ BT_AUDIO_STREAMER_TRACE_OPT( KPRINTFTRACE, FLOG(_L("[BTAudioStreamer]\t New send source created.")));
+ iSendSrc.PrivRegisterEventCallbackL(ERtpSendSucceeded, (TRtpCallbackFunction)CBTAudioStreamSender::PacketSent, this);
+ iSendSrc.PrivRegisterEventCallbackL(ERtpSendFail, (TRtpCallbackFunction)CBTAudioStreamSender::SendError, this);
+ BT_AUDIO_STREAMER_TRACE_OPT( KPRINTFTRACE, FLOG(_L("[BTAudioStreamer]\t Callbacks registered.")));
+
+ iStreamerState = EStopped;
+ BT_AUDIO_STREAMER_TRACE_OPT( KPRINTSTATE, FLOG(_L("[BTAudioStreamer]\t State changed to: EStopped")));
+
+ iThread = RThread();
+
+ iCurrentSendPacket = new (ELeave) RRtpSendPacket;
+
+ iSpareSendPacket = new (ELeave) RRtpSendPacket;
+
+ if(iA2DPOptimiser.Open() == KErrNone)
+ {
+ iLinkOptimiserAvailable = ETrue;
+ }
+
+ BT_AUDIO_STREAMER_TRACE_OPT( KPRINTFTRACE, FLOG(_L("[BTAudioStreamer]\t CBTAudioStreamSender::ConstructL() <-")));
+ }
+
+// ---------------------------------------------------------------------------
+// Static factory method.
+// ---------------------------------------------------------------------------
+//
+CBTAudioStreamSender* CBTAudioStreamSender::NewL(MBTAudioStreamSenderObserver& aObserver, RRtpSession& aSession)
+ {
+ BT_AUDIO_STREAMER_TRACE_OPT( KPRINTFTRACE, FLOG(_L("[BTAudioStreamer]\t CBTAudioStreamSender::NewL() ->")));
+ if (!aSession.IsOpen())
+ {
+ User::Leave(KErrArgument);
+ }
+ BT_AUDIO_STREAMER_TRACE_OPT( KPRINTFTRACE, FLOG(_L("[BTAudioStreamer]\t CBTAudioStreamSender::NewL() <-")));
+ return CBTAudioStreamSenderSBC::NewL(aObserver, aSession);
+ }
+
+// ---------------------------------------------------------------------------
+// Destructor.
+// ---------------------------------------------------------------------------
+//
+CBTAudioStreamSender::~CBTAudioStreamSender()
+ {
+ BT_AUDIO_STREAMER_TRACE_OPT( KPRINTFTRACE, FLOG(_L("[BTAudioStreamer]\t CBTAudioStreamSender::~CBTAudioStreamSender() ->")));
+ Cancel();
+ if(iCurrentSendPacket)
+ {
+ if(iCurrentSendPacket->IsOpen() != EFalse)
+ {
+ iCurrentSendPacket->Close();
+ }
+ delete iCurrentSendPacket;
+ iCurrentSendPacket = NULL;
+ }
+
+ if(iSpareSendPacket)
+ {
+ if(iSpareSendPacket->IsOpen() != EFalse)
+ {
+ iSpareSendPacket->Close();
+ }
+ delete iSpareSendPacket;
+ iSpareSendPacket = NULL;
+ }
+ iSendSrc.Close();
+
+ if(iLinkOptimiserAvailable)
+ {
+ iA2DPOptimiser.Close();
+ }
+
+ BT_AUDIO_STREAMER_TRACE_OPT( KPRINTFTRACE, FLOG(_L("[BTAudioStreamer]\t CBTAudioStreamSender::~CBTAudioStreamSender() <-")));
+ }
+
+// ---------------------------------------------------------------------------
+// This is the static callback method which CBTAudioStreamSender registers with the RtpSession to be called
+// when a packet is _successfully_ sent. It is a static method so simply calls a processing
+// method on the class pointed to be aPtr (which is the CBTAudioStreamSender which registered the cb).
+// ---------------------------------------------------------------------------
+//
+void CBTAudioStreamSender::PacketSent(CBTAudioStreamSender* aPtr, const TRtpEvent& /*aEvent*/)
+ {
+ BT_AUDIO_STREAMER_TRACE_OPT( KPRINTFTRACE, FLOG(_L("[BTAudioStreamer]\t CBTAudioStreamSender::PacketSent() ->")));
+ aPtr->DoPacketSent();
+ BT_AUDIO_STREAMER_TRACE_OPT( KPRINTFTRACE, FLOG(_L("[BTAudioStreamer]\t CBTAudioStreamSender::PacketSent() <-")));
+ }
+
+// ---------------------------------------------------------------------------
+// An instance method which is called by the static callback function. We simply notify the
+// observer if all data has been sent. If it hasn't, then we send more data.
+// ---------------------------------------------------------------------------
+//
+void CBTAudioStreamSender::DoPacketSent()
+ {
+ BT_AUDIO_STREAMER_TRACE_OPT( KPRINTFTRACE, FLOG(_L("[BTAudioStreamer]\t CBTAudioStreamSender::DoPacketSent() ->")));
+
+ // First check if we're Stopping.
+ if(iStreamerState == EStopped)
+ {
+ BT_AUDIO_STREAMER_TRACE_OPT( KPRINTSTATE, FLOG(_L("[BTAudioStreamer]\t Stopping and packet sending completed.")));
+ iObserver.NotifyBufferSent(*iBuffer); // Return the buffer.
+ return; // No need to do more here, we're stopping.
+ }
+ else
+ {
+ iStreamerState = EBuffering;
+ BT_AUDIO_STREAMER_TRACE_OPT( KPRINTSTATE, FLOG(_L("[BTAudioStreamer]\t State changed to: EBuffering")));
+ }
+
+ PacketSendingCompleted(iPayloadDesC);
+
+ // If we're here, then there either is data in the buffer or it has been emptied completely.
+ // Check this by calling the method again. If we consumed the buffer completely,
+ // the method just signals the observer.
+ if(iNonprocessedDataInBuffer != EFalse)
+ {
+ // Check if we need to start using new sendpacket.
+ if(iChangingFrameLength != EFalse)
+ {
+ SwitchToNewSendPacket();
+ }
+ ConsumeBuffer();
+ }
+ else
+ {
+ iObserver.NotifyBufferSent(*iBuffer);
+ }
+
+ BT_AUDIO_STREAMER_TRACE_OPT( KPRINTFTRACE, FLOG(_L("[BTAudioStreamer]\t CBTAudioStreamSender::DoPacketSent() <-")));
+}
+
+// ---------------------------------------------------------------------------
+// This is the static callback method which CBTAudioStreamSender registers with the RtpSession to be called
+// when a packet sending fails.
+// ---------------------------------------------------------------------------
+//
+void CBTAudioStreamSender::SendError(CBTAudioStreamSender* aPtr, const TRtpEvent& /*aEvent*/)
+ {
+ BT_AUDIO_STREAMER_TRACE_OPT( KPRINTFTRACE, FLOG(_L("[BTAudioStreamer]\t CBTAudioStreamSender::SendError() ->")));
+ aPtr->DoSendError();
+ BT_AUDIO_STREAMER_TRACE_OPT( KPRINTFTRACE, FLOG(_L("[BTAudioStreamer]\t CBTAudioStreamSender::SendError() <-")));
+ }
+
+// ---------------------------------------------------------------------------
+// An instance method which is called by the static callback function.
+// We set the state to EErrorSending and handle the error next time in RunL.
+// ---------------------------------------------------------------------------
+//
+void CBTAudioStreamSender::DoSendError()
+ {
+ BT_AUDIO_STREAMER_TRACE_OPT( KPRINTFTRACE, FLOG(_L("[BTAudioStreamer]\t CBTAudioStreamSender::DoSendError() ->")));
+
+ iStreamerState = EErrorSending;
+ BT_AUDIO_STREAMER_TRACE_OPT( KPRINTSTATE, FLOG(_L("[BTAudioStreamer]\t State changed to: EErrorSending")));
+ if (!IsActive())
+ {
+ TRequestStatus *status = &iStatus;
+ iStatus = KRequestPending;
+ iThread.RequestComplete(status, KErrNone);
+ SetActive();
+ }
+ BT_AUDIO_STREAMER_TRACE_OPT( KPRINTFTRACE, FLOG(_L("[BTAudioStreamer]\t CBTAudioStreamSender::DoSendError() <-")));
+ }
+
+// ---------------------------------------------------------------------------
+// This method is for setting the sender up.
+// ---------------------------------------------------------------------------
+//
+TInt CBTAudioStreamSender::SetNewFrameLength(TUint aOutboundMTUSize, const TUint aFrameLength, const TUint aTargetBitrate)
+ {
+ BT_AUDIO_STREAMER_TRACE_OPT( KPRINTFTRACE, FLOG(_L("[BTAudioStreamer]\t CBTAudioStreamSender::SetNewFrameLength() ->")));
+ TInt retVal = KErrGeneral;
+
+ // Don't proceed if the previous change is not completed yet.
+ if(iChangingFrameLength != EFalse)
+ {
+ BT_AUDIO_STREAMER_TRACE_OPT( KPRINTFTRACE, FLOG(_L("[BTAudioStreamer]\t Previous frame length change still ongoing!")));
+ BT_AUDIO_STREAMER_TRACE_OPT( KPRINTFTRACE, FLOG(_L("[BTAudioStreamer]\t CBTAudioStreamSender::SetNewFrameLength() <-")));
+ return KErrInUse;
+ }
+
+ if(iSpareSendPacket)
+ {
+ __ASSERT_DEBUG(!iSpareSendPacket->IsOpen(),User::Invariant());
+ }
+
+ TInt requiredPacketLength = CalculatePacketLength(aOutboundMTUSize, aFrameLength);
+
+ if(requiredPacketLength > 0)
+ {
+ iNewFrameLength = aFrameLength;
+
+ BT_AUDIO_STREAMER_TRACE_OPT( KPRINTFTRACE, FLOG(_L("[BTAudioStreamer]\t Creating new sendpacket.")));
+ __ASSERT_DEBUG(iSpareSendPacket, User::Invariant());
+ TRAPD(ret, *iSpareSendPacket = iSendSrc.NewSendPacketL(requiredPacketLength));
+ if( ret )
+ {
+ BT_AUDIO_STREAMER_TRACE_OPT( KPRINTFTRACE, FLOG(_L("[BTAudioStreamer]\t ERROR! Creating new sendpacket failed.")));
+ return KErrGeneral;
+ }
+ iChangingFrameLength = ETrue;
+ retVal = KErrNone;
+ }
+ else
+ {
+ BT_AUDIO_STREAMER_TRACE_OPT( KPRINTSTATE, FLOG(_L("[BTAudioStreamer]\t Error! Packet length must be greater than zero!")));
+ retVal = KErrArgument;
+ }
+ BT_AUDIO_STREAMER_TRACE_OPT( KPRINTFTRACE, FLOG(_L("[BTAudioStreamer]\t CBTAudioStreamSender::SetNewFrameLength() <-")));
+
+ iTargetBitrate = aTargetBitrate;
+ return retVal;
+ }
+
+
+// ---------------------------------------------------------------------------
+// This method is for setting the sender up.
+// ---------------------------------------------------------------------------
+//
+void CBTAudioStreamSender::StartL(TUint aOutboundMTUSize, const TUint aFrameLength, const TUint aTargetBitrate)
+ {
+ BT_AUDIO_STREAMER_TRACE_OPT( KPRINTFTRACE, FLOG(_L("[BTAudioStreamer]\t CBTAudioStreamSender::StartL() ->")));
+ if(iCurrentSendPacket)
+ {
+ __ASSERT_DEBUG(!iCurrentSendPacket->IsOpen(),User::Invariant());
+ }
+ TInt requiredPacketLength = CalculatePacketLength(aOutboundMTUSize, aFrameLength);
+
+ if(requiredPacketLength > 0)
+ {
+ __ASSERT_DEBUG(iCurrentSendPacket, User::Invariant());
+ *iCurrentSendPacket = iSendSrc.NewSendPacketL(requiredPacketLength);
+ iTargetBitrate = aTargetBitrate;
+ InitSender(*iCurrentSendPacket, iPayloadDesC, iTargetBitrate);
+ iStreamerState = EBuffering;
+ BT_AUDIO_STREAMER_TRACE_OPT( KPRINTSTATE, FLOG(_L("[BTAudioStreamer]\t State changed to: EBuffering")));
+ }
+ else
+ {
+ BT_AUDIO_STREAMER_TRACE_OPT( KPRINTSTATE, FLOG(_L("[BTAudioStreamer]\t Error! Packet length must be greater than zero!")));
+ User::Leave(KErrArgument);
+ }
+
+ // Streaming started, optimise the ACL link if optimiser service is available.
+ if(iLinkOptimiserAvailable)
+ {
+ // The below code is to get the connected device's BT Address.
+ TBTSockAddr addr;
+ iRtpSession.RtpSocket()->RemoteName(addr);
+ TUint accessLatency = MaxFramesPerPacket() * CalculateFrameDuration(aFrameLength, aTargetBitrate);
+ // Not checking the return code, because it doesn't matter if it fails.
+ iA2DPOptimiser.OptimiseAclForAudioStreaming(addr.BTAddr(), aTargetBitrate, accessLatency);
+ }
+ BT_AUDIO_STREAMER_TRACE_OPT( KPRINTFTRACE, FLOG(_L("[BTAudioStreamer]\t CBTAudioStreamSender::StartL() <-")));
+ }
+
+// ---------------------------------------------------------------------------
+// This method is for closing the sender down.
+// ---------------------------------------------------------------------------
+//
+void CBTAudioStreamSender::Stop()
+ {
+ BT_AUDIO_STREAMER_TRACE_OPT( KPRINTFTRACE, FLOG(_L("[BTAudioStreamer]\t CBTAudioStreamSender::Stop() ->")));
+ // Make sure that the packet is not out at the moment.
+ Cancel();
+ if(iCurrentSendPacket->IsOpen() != EFalse)
+ {
+ iCurrentSendPacket->Close();
+ }
+
+ if(iSpareSendPacket->IsOpen() != EFalse)
+ {
+ iSpareSendPacket->Close();
+ }
+
+ // Remove the ACL link optimisation if optimiser service is available.
+ if(iLinkOptimiserAvailable)
+ {
+ TBTSockAddr addr;
+ iRtpSession.RtpSocket()->RemoteName(addr);
+ // Not checking the return code, because it doesn't matter if it fails.
+ iA2DPOptimiser.RemoveAclOptimisation(addr.BTAddr());
+ }
+ iStreamerState = EStopped;
+ BT_AUDIO_STREAMER_TRACE_OPT( KPRINTSTATE, FLOG(_L("[BTAudioStreamer]\t State changed to: EStopped")));
+
+ BT_AUDIO_STREAMER_TRACE_OPT( KPRINTFTRACE, FLOG(_L("[BTAudioStreamer]\t CBTAudioStreamSender::Stop() <-")));
+ }
+
+// ---------------------------------------------------------------------------
+// From class CBTAudioStreamSender.
+// RunL will be called when ConsumeBuffer has decided that we have enough
+// frames for one packet, or DoSendError was called.
+// ---------------------------------------------------------------------------
+//
+void CBTAudioStreamSender::RunL()
+ {
+ BT_AUDIO_STREAMER_TRACE_OPT( KPRINTFTRACE, FLOG(_L("[BTAudioStreamer]\t CBTAudioStreamSender::RunL() ->")));
+ switch(iStreamerState)
+ {
+ case ESending:
+ {
+ // Set A2DP media packet header.
+ AddHeaderToSendPacket(iPayloadDesC);
+
+ // Use the timestamp from the first buffer.
+ BT_AUDIO_STREAMER_TRACE_OPT( KPRINTFTRACE, FLOG(_L("[BTAudioStreamer]\t Adjust and set timestamp.")));
+ iCurrentSendPacket->SetTimestamp(iAdjustedTimestamp);
+
+ // Set the length and send the packet.
+ BT_AUDIO_STREAMER_TRACE_OPT( KPRINTFTRACE, FLOG(_L("[BTAudioStreamer]\t Set length.")));
+ iCurrentSendPacket->WritePayload().SetLength(iPayloadDesC.Length());
+
+ BT_AUDIO_STREAMER_TRACE_OPT( KPRINTFTRACE, FLOG(_L("[BTAudioStreamer]\t Send.")));
+ iCurrentSendPacket->Send();
+
+ BT_AUDIO_STREAMER_TRACE_OPT( KPRINTFTRACE, FLOG(_L("[BTAudioStreamer]\t Packet has transferred to RTP API.")));
+ }
+ break;
+ case EBuffering:
+ {
+ // Note: Here we will check that no packets were discarded while waiting for the sending to complete.
+ // If that happens, we could inform SAC and then try to decrease the bitrate.
+
+ BT_AUDIO_STREAMER_TRACE_OPT( KPRINTFTRACE, FLOG(_L("[BTAudioStreamer]\t Packet sent succesfully.")));
+ iPayloadDesC.Zero();
+ }
+ break;
+ case EErrorSending:
+ {
+ // Note: Inform the observer
+ BT_AUDIO_STREAMER_TRACE_OPT( KPRINTFTRACE, FLOG(_L("[BTAudioStreamer]\t Packet sending failed.")));
+ iPayloadDesC.Zero();
+ PacketSendingCompleted(iPayloadDesC);
+ iStreamerState = EBuffering;
+
+ // Tell client that we're ready for more data. Method name is misleading, but we will request for more
+ // until the observer tells us to stop.
+ iObserver.NotifyBufferSent(*iBuffer);
+
+ BT_AUDIO_STREAMER_TRACE_OPT( KPRINTSTATE, FLOG(_L("[BTAudioStreamer]\t State changed to: EBuffering")));
+ }
+ break;
+ default:
+ {
+ BT_AUDIO_STREAMER_TRACE_OPT( KPRINTFTRACE, FLOG(_L("[BTAudioStreamer]\t Error: RunL is in incorrect state!")));
+ }
+ break;
+ }
+ BT_AUDIO_STREAMER_TRACE_OPT( KPRINTFTRACE, FLOG(_L("[BTAudioStreamer]\t CBTAudioStreamSender::RunL() <-")));
+ }
+
+// ---------------------------------------------------------------------------
+// For sending the frames.
+// ---------------------------------------------------------------------------
+//
+TInt CBTAudioStreamSender::SendThisBuffer(const TDesC8& aBuffer, TTimeIntervalMicroSeconds aTimestamp)
+ {
+ BT_AUDIO_STREAMER_TRACE_OPT( KPRINTFTRACE, FLOG(_L("[BTAudioStreamer]\t CBTAudioStreamSender::SendThisBuffer() ->")));
+
+ BT_AUDIO_STREAMER_TRACE_OPT( KPRINTFTRACE, FPrint(_L("[BTAudioStreamer]\t Received timestamp low: %d"), I64LOW(aTimestamp.Int64())));
+ BT_AUDIO_STREAMER_TRACE_OPT( KPRINTFTRACE, FPrint(_L("[BTAudioStreamer]\t Received timestamp high: %d"), I64HIGH(aTimestamp.Int64())));
+
+ // Store the buffer's address for later reference.
+ iBuffer = &aBuffer;
+
+ if(iChangingFrameLength != EFalse)
+ {
+ // Check the new framelength...
+ if(aBuffer.Length() == iNewFrameLength) // Check if the buffer exactly of the new length.
+ {
+ // If we have data with previous frame length in buffer, send it first.
+ if(iNonprocessedDataInBuffer != EFalse)
+ {
+ ProceedToPacketSending();
+ return KErrNone;
+ }
+ else // Else we can switch to new packet immediately and continue processing this buffer.
+ {
+ SwitchToNewSendPacket();
+ }
+ }
+ else if(aBuffer.Length() > iNewFrameLength) // Check if it's safe to peek at index iNewFrameLength.
+ {
+ if(aBuffer[iNewFrameLength] == 0x9c) // Check if the index iNewFrameLength the syncword.
+ {
+ // If we have data with previous frame length in buffer, send it first.
+ if(iNonprocessedDataInBuffer != EFalse)
+ {
+ ProceedToPacketSending();
+ return KErrNone;
+ }
+ else // Else we can switch to new packet immediately and continue processing this buffer.
+ {
+ SwitchToNewSendPacket();
+ }
+ }
+ else
+ {
+ BT_AUDIO_STREAMER_TRACE_OPT( KPRINTFTRACE, FLOG(_L("[BTAudioStreamer]\t CBTAudioStreamSender: Still waiting for packets of the new frame length...")));
+ }
+ }
+ else
+ {
+ BT_AUDIO_STREAMER_TRACE_OPT( KPRINTFTRACE, FLOG(_L("[BTAudioStreamer]\t CBTAudioStreamSender: Still waiting for packets of the new frame length...")));
+ // Encoder has not yet started to use the new frame length.
+ }
+ }
+ else if(iStreamerState != EBuffering)
+ {
+ // Previous sending is not yet completed or there is was an error that is not yet handled.
+ // Just discard the incoming frame.
+ BT_AUDIO_STREAMER_TRACE_OPT( KPRINTFTRACE, FLOG(_L("[BTAudioStreamer]\t CBTAudioStreamSender error: Previous buffer sending hasn't completed - discarding this buffer.")));
+ iObserver.NotifyBufferSent(aBuffer);
+ BT_AUDIO_STREAMER_TRACE_OPT( KPRINTFTRACE, FLOG(_L("[BTAudioStreamer]\t CBTAudioStreamSender::SendThisBuffer() <-")));
+ return KErrOverflow;
+ }
+
+ // Store the timestamp for later use.
+ iTimestamp = aTimestamp.Int64();
+
+ iNonprocessedDataInBuffer = ETrue;
+ ConsumeBuffer();
+
+ BT_AUDIO_STREAMER_TRACE_OPT( KPRINTFTRACE, FLOG(_L("[BTAudioStreamer]\t CBTAudioStreamSender::SendThisBuffer() <-")));
+ return KErrNone;
+ }
+
+// ---------------------------------------------------------------------------
+// From class CActive.
+// Cancellation.
+// ---------------------------------------------------------------------------
+//
+void CBTAudioStreamSender::DoCancel()
+ {
+ BT_AUDIO_STREAMER_TRACE_OPT( KPRINTFTRACE, FLOG(_L("[BTAudioStreamer]\t CBTAudioStreamSender::DoCancel() ->")));
+ BT_AUDIO_STREAMER_TRACE_OPT( KPRINTFTRACE, FLOG(_L("[BTAudioStreamer]\t CBTAudioStreamSender::DoCancel() <-")));
+ }
+
+inline void CBTAudioStreamSender::ConsumeBuffer()
+ {
+ BT_AUDIO_STREAMER_TRACE_OPT( KPRINTFTRACE, FLOG(_L("[BTAudioStreamer]\t CBTAudioStreamSender::ConsumeBuffer() ->")));
+ if (!IsActive())
+ {
+ BT_AUDIO_STREAMER_TRACE_OPT( KPRINTFTRACE, FLOG(_L("[BTAudioStreamer]\t CBTAudioStreamSender::ConsumeBuffer() ok to send")));
+
+ TInt spaceLeftInSendPacket = AddBufferToSendPacket(*iBuffer);
+ iAdjustedTimestamp = iTimestamp; // take a copy, because we want to keep the original timestamp.
+ if(spaceLeftInSendPacket >= 0)
+ {
+ iNonprocessedDataInBuffer = EFalse; // This indicates that there's no need to call this method after sending.
+ }
+ ProceedToPacketSending();
+ }
+ BT_AUDIO_STREAMER_TRACE_OPT( KPRINTFTRACE, FLOG(_L("[BTAudioStreamer]\t CBTAudioStreamSender::ConsumeBuffer() <-")));
+ }
+
+
+inline void CBTAudioStreamSender::ProceedToPacketSending()
+{
+ BT_AUDIO_STREAMER_TRACE_OPT( KPRINTFTRACE, FLOG(_L("[BTAudioStreamer]\t CBTAudioStreamSender::ProceedToPacketSending() ->")));
+ iStreamerState = ESending;
+ BT_AUDIO_STREAMER_TRACE_OPT( KPRINTSTATE, FLOG(_L("[BTAudioStreamer]\t State changed to: ESending")));
+ TRequestStatus *status = &iStatus;
+ iStatus = KRequestPending;
+ iThread.RequestComplete(status, KErrNone);
+ SetActive();
+ BT_AUDIO_STREAMER_TRACE_OPT( KPRINTFTRACE, FLOG(_L("[BTAudioStreamer]\t CBTAudioStreamSender::ProceedToPacketSending() <-")));
+}
+
+inline void CBTAudioStreamSender::SwitchToNewSendPacket()
+ {
+ BT_AUDIO_STREAMER_TRACE_OPT( KPRINTFTRACE, FLOG(_L("[BTAudioStreamer]\t CBTAudioStreamSender::SwitchToNewSendPacket() ->")));
+
+ // Make the iCurrentSendPacket point to the spare packet opened when the frame length change came.
+ RRtpSendPacket* oldSendPacket;
+ oldSendPacket = iCurrentSendPacket;
+ iCurrentSendPacket = iSpareSendPacket;
+ iSpareSendPacket = oldSendPacket;
+
+ // The previously used send packet (which has now become the spare send packet) can be closed.
+ oldSendPacket->Close();
+
+ // The rest of the initializations:
+ InitSender(*iCurrentSendPacket, iPayloadDesC, iTargetBitrate);
+
+ iChangingFrameLength = EFalse;
+
+ BT_AUDIO_STREAMER_TRACE_OPT( KPRINTFTRACE, FLOG(_L("[BTAudioStreamer]\t CBTAudioStreamSender::SwitchToNewSendPacket() <-")));
+ }