bluetoothengine/btsac/src/btsacStreamerController.cpp
changeset 0 f63038272f30
child 1 6a1fe72036e3
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/bluetoothengine/btsac/src/btsacStreamerController.cpp	Mon Jan 18 20:28:57 2010 +0200
@@ -0,0 +1,1358 @@
+/*
+* Copyright (c) 2005-2009 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:  Implementation for CBTSACStreamerController class. This class constructs and
+*				 communicates with 'BT Audio Streamer' component to do RTP streaming.
+*
+*/
+
+
+// INCLUDE FILES
+#include "btsacStreamerController.h"
+#include "debug.h"
+
+// Subband codec-specific values
+// in bluetoothAV.h
+using namespace SymbianSBC;      
+
+
+// CONSTANTS
+_LIT(KBTAADLL, "btaudioadaptation.dll");
+
+//const TInt KUpgradeTimerDelay = 120000000;	// 2 minutes. How often we sill try to upgrade back to a better quality audio. 
+const TInt KRetryTimerDelay = 2000000;		// 2 seconds. If something fails, how soon should we retry. 
+const TInt KStabilizationDelay = 2000000;	// 2 seconds. Wait this long after bitpool change then start mononitor packet drops again
+const TInt KDataCollectDelay = 600000; 		// Time (600ms) to collect packet drop data
+
+// All tables below have to formed such a way that highest max bitpool value has to be in position 0 and etc.
+const TInt KMaxBitpoolValues[] = {59, 48, 40, 34}; // Max bitpool values
+const TInt KDeviationValues[] = {1000, 100000, 300000, 300000}; // maximum time (ys) between first and last packet dropped event
+
+const TInt KNumOfBitpoolValues = sizeof(KMaxBitpoolValues)/sizeof(TInt);
+#define MAXBITPOOLVALUEMAX KMaxBitpoolValues[0]
+#define MAXBITPOOLVALUEMIN KMaxBitpoolValues[KNumOfBitpoolValues-1]
+
+const float KReconfigureLimitFactor = 0.02; // 2% of during KDataCollectDelay transferred data
+const float KLimitCheckInterval = ((float)KDataCollectDelay/1000000.0); // Time (seconds) to collect packet drop data
+
+// MODULE DATA STRUCTURES
+
+// ================= MEMBER FUNCTIONS =======================
+
+// -----------------------------------------------------------------------------
+// CBTSACStreamerController::NewL
+// Two-phased constructor.
+// -----------------------------------------------------------------------------
+//
+CBTSACStreamerController* CBTSACStreamerController::NewL(MBTAudioAdaptationObserver& aObserver )
+    {
+    CBTSACStreamerController* self = new (ELeave) CBTSACStreamerController (aObserver);
+    CleanupStack::PushL( self );
+    self->ConstructL();
+    CleanupStack::Pop( self );
+    return self;
+    }
+
+    
+// -----------------------------------------------------------------------------
+// Destructor.
+// -----------------------------------------------------------------------------
+//
+CBTSACStreamerController::~CBTSACStreamerController()
+    {
+    TRACE_FUNC
+    Cancel();
+    if(iAudioInput)
+	    {
+	    iAudioInput->Stop();
+	    iAudioInput->Disconnect();
+	    }
+    delete iPacketDropIoctl;
+    delete iEncoderCI;
+    delete iBTStreamer;
+    delete iAudioInput;
+    iLib.Close();
+	iTimer.Close(); 
+	iBitpoolData.Close();
+    TRACE_INFO((_L("CBTSACStreamerController::~CBTSACStreamerController() completed")))
+    }
+
+// -----------------------------------------------------------------------------
+// CBTSACStreamerController::CBTSACStreamerController
+// C++ default constructor.
+// -----------------------------------------------------------------------------
+//
+CBTSACStreamerController::CBTSACStreamerController(MBTAudioAdaptationObserver& aObserver)
+    : CActive( EPriorityNormal ), iObserver(aObserver)
+    {
+	CActiveScheduler::Add(this);
+    }
+    
+// -----------------------------------------------------------------------------
+// CBTSACStreamerController::ConstructL
+// Symbian 2nd phase constructor.
+// -----------------------------------------------------------------------------
+//
+void CBTSACStreamerController::ConstructL( )
+    {
+    TRACE_FUNC
+
+	User::LeaveIfError(iTimer.CreateLocal()); 
+	iThread = RThread();
+
+	iBTStreamer = CBTAudioStreamer::NewL();
+
+    LEAVE_IF_ERROR( iLib.Load( KBTAADLL ) );
+    typedef TInt (*TOurLibraryFunction2)(MBTAudioStreamObserver&, MBTAudioErrorObserver&);
+    TOurLibraryFunction2 newL2 = reinterpret_cast<TOurLibraryFunction2>(iLib.Lookup(1));
+    iAudioInput = (CBTAudioStreamInputBase*)newL2(*iBTStreamer, *this);       
+
+	TInt ret;
+	ret = iAudioInput->Connect();
+	if (ret) 
+		{
+		TRACE_INFO((_L("CBTSACStreamerController::ConstructL() Audio Input Connect Error %d"), ret))
+		User::Leave(ret); 
+		}
+
+	ret = iAudioInput->SetFormat(KMMFFourCCCodeSBC);	
+	if (ret)
+   		{
+ 		TRACE_INFO((_L("CBTSACStreamerController::ConstructL() Audio Input SetFormat Error %d"), ret))
+  		User::Leave(ret);
+ 		}
+
+    iEncoderCI = reinterpret_cast<CSbcEncoderIntfc *> (iAudioInput->EncoderInterface(KUidSbcEncoderIntfc));
+	User::LeaveIfNull(iEncoderCI);
+
+	InitializeBitpoolDataL();
+    iState = EStateIdle;
+      
+    TRACE_INFO((_L("CBTSACStreamerController::ConstructL() completed")))
+    }
+    
+// -----------------------------------------------------------------------------
+// CBTSACStreamerController::StartStream
+// -----------------------------------------------------------------------------
+//
+TInt CBTSACStreamerController::StartStream(RSocket& aSocket, TInt aFrameLength )
+	{
+	TRACE_FUNC
+	
+	if (!(iBTStreamer) || !(iAudioInput) )    
+		{
+		return KErrNotFound;	
+		}
+    
+    if (iState == EStateError)
+    	{
+    	iState = EStateIdle;
+    	TInt err = iAudioInput->Connect();
+		if (!err) 
+			{
+			err = iAudioInput->SetFormat(KMMFFourCCCodeSBC);
+			}    	
+		if (err)
+	   		{
+	   		TRACE_INFO((_L("CBTSACStreamerController::StartStream() Audio Input initialization Error %d"), err))
+	  		return err;
+	 		}
+    	}
+    
+    if (iState == EStateIdle)    
+    	{
+	    TInt err = KErrNone;
+	    TRAP( err, iBTStreamer->StartL(aSocket, aFrameLength, iAudioInput, iCurrentBitrate));
+
+	    if ( err == KErrNone )
+	    	{
+	    	err = iAudioInput->Start(); 	
+	    	}
+
+		if ( err == KErrNone )
+			{			
+			TRACE_INFO((_L("CBTSACStreamerController::StartStream() Sending packet drop IOCTL")))
+    		TRAP( err, iPacketDropIoctl = CActivePacketDropIoctl::NewL(*this, aSocket));
+    		
+    		if( err == KErrNone )
+    			{
+    			iPacketDropDeviation = 0;
+				iTotalNbrOfDroppedPackets = 0;
+    			iState = EStateStreaming;
+				
+				if(iCurrentBitpoolData->iMaxBitpoolValue < iMatchCap.MaxBitpoolValue())
+					{
+					TRACE_INFO((_L("CBTSACStreamerController::StartStream(), upgrade bitrate.")))
+					// Streaming was stopped when the bitrate was lower than maximum, so upgrade it for starters.
+					// iPacketDropIoctl->Start will be called after self completion.
+					
+					// Update current bitpool data to be highest possible. Highest possible bitpool value can be found from position 
+					iCurrentBitpoolData = GetBitpoolData(0);
+					if(iCurrentBitpoolData)
+						{
+						DoSelfComplete(EUpgradeBitrate, KErrNone);
+						}
+					else
+						{
+						err = KErrArgument;
+						}
+					}
+				else if(iMatchCap.MaxBitpoolValue() > iBitpoolData[iBitpoolData.Count() - 1].iMaxBitpoolValue)
+					{
+					// Don't start receive packet drop events if max bitpool value is not bigger than min
+					// bitpool value (we can't downgrade bitpool, we already have lowest possible value).
+					DoSelfComplete(EStartStabilizingTimer, KErrNone);
+					}
+				TRACE_INFO((_L("CBTSACStreamerController::StartStream() completed")))
+    			}
+	    	}
+	    if( err )
+	    	{
+	    	// In case someting went wrong stop both audio adaptation and streamer
+	    	TRACE_INFO((_L("CBTSACStreamerController::StartStream() *Error: %d"), err))
+	    	iAudioInput->Stop();
+	    	iAudioInput->Disconnect();
+	    	iBTStreamer->Stop();
+      	
+	    	//make sure iAudioInput->Connect() & SetFormat() get called in StartStream()
+	    	iState = EStateError;
+	    	}
+	    return err;
+    	}
+    else
+    	{
+    	return KErrAlreadyExists;
+    	}
+	}
+        
+// -----------------------------------------------------------------------------
+// CBTSACStreamerController::StopStream
+// -----------------------------------------------------------------------------
+//
+TInt CBTSACStreamerController::StopStream()
+	{
+	TRACE_FUNC
+    Cancel();
+   	if (!(iBTStreamer) || !(iAudioInput))    
+		{
+		return KErrNotFound;	
+		}
+    else if (iState != EStateIdle )
+    	{
+      	iAudioInput->Stop();
+      	iBTStreamer->Stop();
+	   	delete iPacketDropIoctl; 
+	   	iPacketDropIoctl = NULL; 
+	   	iState = EStateIdle;    
+	 	return KErrNone;	
+    	}
+    else
+    	{
+    	return KErrAlreadyExists; 
+    	}
+	}
+
+// -----------------------------------------------------------------------------
+// CBTSACStreamerController::ResetAudioInput
+// -----------------------------------------------------------------------------
+//
+void CBTSACStreamerController::ResetAudioInput()
+	{
+	TRACE_FUNC
+	iAudioInput->Stop();
+	iAudioInput->Disconnect();
+    TInt err = iAudioInput->Connect();
+	if (!err) 
+		{
+		err = iAudioInput->SetFormat(KMMFFourCCCodeSBC);
+		}    	
+	if (err)
+		{
+		TRACE_INFO((_L("CBTSACStreamerController::ResetAudioInput() Audio Input initialization Error %d"), err))
+		}	
+	}
+
+// -----------------------------------------------------------------------------
+// CBTSACStreamerController::FillCapabilities
+// -----------------------------------------------------------------------------
+//	
+TInt CBTSACStreamerController::FillCapabilities( TSBCCodecCapabilities& aSbc )
+	{
+	TRACE_FUNC
+
+	TUint8 itemp = 0x00; 
+    // Sampling Frequency
+    TInt ret;
+	RArray<TUint> SupportedSamplingFrequencies; 
+	ret = iEncoderCI->GetSupportedSamplingFrequencies(SupportedSamplingFrequencies); 
+	if ( !ret)
+		{
+		 itemp = 0x00; 
+	
+		 for (TInt i=0; i<SupportedSamplingFrequencies.Count(); i++ )
+		 	{
+			 if ( SupportedSamplingFrequencies[i] == TUint(16000) )
+			 	{
+				itemp = E16kHz;	// 	E16kHz		= 0x8 
+				continue; 
+			 	}
+			 if ( SupportedSamplingFrequencies[i] == TUint(32000) )
+			 	{
+			 	itemp |= E32kHz; //	E32kHz		= 0x4
+			 	continue; 
+			 	}
+			 if ( SupportedSamplingFrequencies[i] == TUint(44100) )
+			 	{
+			 	itemp |= E44100Hz;	// E44100Hz	= 0x2
+			 	continue; 
+				}
+			 if ( SupportedSamplingFrequencies[i] == TUint(48000) )
+			 	{
+			 	itemp |= E48kHz;	// E48kHz	= 0x1
+			 	continue; 
+			 	}
+		 	}
+		 aSbc.SetSamplingFrequencies(itemp);
+		 TRACE_INFO((_L("CBTSACStreamerController::FillCapabilities() Encoder Sampling Frequencies: %d"), itemp))
+		}
+	else
+		{
+		return ret; 
+		}
+	
+	// Channel mode
+    RArray<CSbcEncoderIntfc::TSbcChannelMode> SupportedChannelModes; 
+    ret = iEncoderCI->GetSupportedChannelModes(SupportedChannelModes);
+	if ( !ret )
+		{
+		 itemp = 0x00; 
+	
+		 for (TInt i=0; i<SupportedChannelModes.Count(); i++ )
+		 	{
+			 if ( SupportedChannelModes[i] ==  CSbcEncoderIntfc::ESbcChannelMono)
+			 	{
+				itemp = EMono;	// 	EMono			= 0x8	 		 		
+				continue;		 		
+			 	}
+			 if ( SupportedChannelModes[i] == CSbcEncoderIntfc::ESbcChannelDual )
+			 	{
+		 		itemp |= EDualChannel;	// 	EDualChannel	= 0x4
+			 	continue;
+			 	}
+			 if ( SupportedChannelModes[i] == CSbcEncoderIntfc::ESbcChannelStereo )
+			 	{
+				itemp |= EStereo;	// 	EStereo			= 0x2	 		
+			 	continue;
+				}
+			 if ( SupportedChannelModes[i] == CSbcEncoderIntfc::ESbcChannelJointStereo )
+			 	{
+		 		itemp |= EJointStereo;	//	EJointStereo	= 0x1
+			 	continue;
+			 	}
+		 	}
+		 aSbc.SetChannelModes(itemp);
+		 TRACE_INFO((_L("CBTSACStreamerController::FillCapabilities() Encoder Channel modes: %d"), itemp))
+		}
+	else
+		{
+		return ret; 
+		}
+
+    // Blocks
+    RArray<TUint> SupportedNumOfBlocks; 
+    ret = iEncoderCI->GetSupportedNumOfBlocks(SupportedNumOfBlocks); 
+	if ( !ret )
+		{
+		 itemp = 0x00; 
+	
+		 for (TInt i=0; i<SupportedNumOfBlocks.Count(); i++ )
+		 	{
+			 if ( SupportedNumOfBlocks[i] ==  TUint(4))
+			 	{
+				itemp = EBlockLenFour;	//	 EBlockLenFour 		= 0x8		 		
+				continue;		 		
+			 	}
+			 if ( SupportedNumOfBlocks[i] == TUint(8) )
+			 	{
+			 	itemp |= EBlockLenEight;	// 	EBlockLenEight 		= 0x4
+			 	continue;
+			 	}
+			 if ( SupportedNumOfBlocks[i] == TUint(12) )
+			 	{
+			 	itemp |= EBlockLenTwelve;	// 	EBlockLenTwelve		= 0x2
+			 	continue;
+				}
+			 if ( SupportedNumOfBlocks[i] == TUint(16) )
+			 	{
+			 	itemp |= EBlockLenSixteen;	// 	EBlockLenSixteen	= 0x1
+			 	continue;
+			 	}
+		 	}
+		 aSbc.SetBlockLengths(itemp);
+		 TRACE_INFO((_L("CBTSACStreamerController::FillCapabilities() Encoder Blocks: %d"), itemp))
+		}
+	else
+		{
+		return ret; 
+		}
+		 
+	// Subbands
+	RArray<TUint> SupportedNumOfSubbands; 
+	ret = iEncoderCI->GetSupportedNumOfSubbands(SupportedNumOfSubbands);
+	if ( !ret )
+		{
+	    itemp = 0x0;
+		for (TInt i=0; i<SupportedNumOfSubbands.Count(); i++ )
+		 	{	
+			 if ( SupportedNumOfSubbands[i] == TUint(4) )
+			 	{
+				itemp = EFourSubbands; // 	EFourSubbands  = 0x02
+				continue; 
+			 	}
+			 if ( SupportedNumOfSubbands[i] == TUint(8) )
+			 	{
+			 	itemp |= EEightSubbands;	// 	EEightSubbands  = 0x01
+			 	continue; 
+			 	}
+		 	}
+		 aSbc.SetSubbands(itemp);
+		 TRACE_INFO((_L("CBTSACStreamerController::FillCapabilities() Encoder SubBands: %d"), itemp))
+		 }
+	else
+		{
+		return ret; 
+		}
+		 
+    // allocation method bitmask 
+    RArray<CSbcEncoderIntfc::TSbcAllocationMethod> SupportedAllocationMethods;
+    ret = iEncoderCI->GetSupportedAllocationMethods(SupportedAllocationMethods); 
+	if ( !ret )
+		{
+	    itemp = 0x0;
+		for (TInt i=0; i<SupportedAllocationMethods.Count(); i++ )
+		 	{	
+			 if ( SupportedAllocationMethods[i] == CSbcEncoderIntfc::ESbcAllocationSNR )
+			 	{
+				itemp = ESNR; // 	ESNR  = 0x02
+				continue; 
+			 	}
+			 if ( SupportedAllocationMethods[i] == CSbcEncoderIntfc::ESbcAllocationLoudness )
+			 	{
+			 	itemp |= ELoudness;	// 	ELoudness  = 0x01
+			 	continue; 
+			 	}
+		 	}
+		 aSbc.SetAllocationMethods(itemp);
+		 TRACE_INFO((_L("CBTSACStreamerController::FillCapabilities() Encoder Alloc method: %d"), itemp))
+		 }
+	else
+		{
+		return ret; 
+		}
+		 
+	// bitpools
+	TUint MinSupportedBitpoolSize; TUint MaxSupportedBitpoolSize; 
+	ret = iEncoderCI->GetSupportedBitpoolRange(MinSupportedBitpoolSize, 
+		                      				   MaxSupportedBitpoolSize);
+	if ( !ret )
+	 	{
+		if (MaxSupportedBitpoolSize > MAXBITPOOLVALUEMAX)
+	 	    {
+	 	    MaxSupportedBitpoolSize = MAXBITPOOLVALUEMAX;
+	 	    }
+	 	// TUint8 to TInt
+		aSbc.SetMaxBitpoolValue(MaxSupportedBitpoolSize);
+		TRACE_INFO((_L("CBTSACStreamerController::FillCapabilities() Encoder Max bitpool: %d"), MaxSupportedBitpoolSize))
+		aSbc.SetMinBitpoolValue(MinSupportedBitpoolSize);
+		TRACE_INFO((_L("CBTSACStreamerController::FillCapabilities() Encoder Min bitpool: %d"), MinSupportedBitpoolSize))
+	 	}
+	else
+		{
+		return ret; 
+		}	 
+		 
+    // save our local copy, 9 bytes on stack
+    iLocalCap = aSbc;
+	
+	TRACE_INFO((_L("CBTSACStreamerController::FillCapabilities() Return: %d"), ret));	
+	return ret;
+	}
+	
+// -----------------------------------------------------------------------------
+// CBTSACStreamerController::ConfigureSEP
+// -----------------------------------------------------------------------------
+//	
+TInt CBTSACStreamerController::ConfigureSEP( TSBCCodecCapabilities& aDec )
+	{
+	TRACE_FUNC
+	TInt err = KErrNone;
+	TRAP(err, InitializeBitpoolDataL());
+	if(err)
+		return err;
+	
+	err = GetMatchingCaps(aDec);
+	if(!err)
+		{
+		CheckAndAdjustBitpool(aDec);
+		// Save the matching Caps
+		iMatchCap = aDec;
+		ReorganizeBitpoolTable(iMatchCap.MaxBitpoolValue());
+		err = SetCurrentBitpoolData(iMatchCap.MaxBitpoolValue());
+		if(!err)
+			{
+			iEncoderCI->SetBitpoolSize(iMatchCap.MaxBitpoolValue());
+	  		// configure encoder
+			err = iEncoderCI->ApplyConfig();
+			}
+		}
+	TRACE_INFO((_L("CBTSACStreamerController::ConfigureSEP() return: %d"), err))
+	return err;
+	}
+
+// -----------------------------------------------------------------------------
+// CBTSACStreamerController::ConfigureSEPBitpool
+// -----------------------------------------------------------------------------
+//	
+TInt CBTSACStreamerController::ConfigureSEPBitpool(EOngoingAction aAction)
+	{
+	TRACE_FUNC
+    TInt err = KErrNone;
+	TSBCCodecCapabilities newDecConfiguration; 
+	memset(&newDecConfiguration, 0, sizeof(newDecConfiguration)); 
+	newDecConfiguration = iMatchCap;
+	TInt nextIndex = (aAction == EDowngradeBitrate) ? iCurrentBitpoolData->iDownBitpoolIndex : iCurrentBitpoolData->iUpBitpoolIndex;
+	if(!IndexValid(nextIndex))
+		{
+		return KErrArgument;
+		}
+	TInt BitpoolValue = iBitpoolData[nextIndex].iMaxBitpoolValue;
+	newDecConfiguration.SetMaxBitpoolValue(BitpoolValue);
+	CheckAndAdjustBitpool(newDecConfiguration);
+	
+	TRACE_INFO((_L("CBTSACStreamerController::ConfigureSEPBitpool() Current FrameLength: %d"), iCurrentFrameLength))
+	TRACE_INFO((_L("CBTSACStreamerController::ConfigureSEPBitpool() Current Bitrate: %d"), iCurrentBitrate))
+	
+	err = iBTStreamer->SetNewFrameLength(iCurrentFrameLength, iCurrentBitrate);
+	if(!err)
+		{
+		TRACE_INFO((_L("CBTSACStreamerController::ConfigureSEPBitpool(), Reconfiguring the encoder...")))
+		iEncoderCI->SetBitpoolSize(newDecConfiguration.MaxBitpoolValue());
+		// configure encoder
+		err = iEncoderCI->ApplyConfig();
+		if(!err)
+			{			
+			err = SetCurrentBitpoolData(newDecConfiguration.MaxBitpoolValue());
+			if(!err)
+				{
+				TRACE_INFO((_L("CBTSACStreamerController::ConfigureSEPBitpool(): Current BP: %d"), iCurrentBitpoolData->iMaxBitpoolValue))
+				}			
+			}
+		TRACE_INFO((_L("CBTSACStreamerController::ConfigureSEPBitpool() The encoder reconfigured.")))
+		}
+	TRACE_INFO((_L("CBTSACStreamerController::ConfigureSEPBitpool() return: %d"), err))
+	return err;
+	}
+
+// -----------------------------------------------------------------------------
+// CBTSACStreamerController::FrameLength
+// -----------------------------------------------------------------------------
+//
+TInt CBTSACStreamerController::FrameLength() const
+	{
+	TRACE_INFO((_L("CBTSACStreamerController::FrameLength() = %d"), iCurrentFrameLength))
+	return iCurrentFrameLength;
+	}
+
+// -----------------------------------------------------------------------------
+// CBTSACStreamerController::GetMatchingCaps
+// -----------------------------------------------------------------------------
+//
+TInt CBTSACStreamerController::GetMatchingCaps(TSBCCodecCapabilities& aCaps)
+	{
+	TRACE_FUNC
+	TInt ret = KErrNone; 
+	TUint8 MatchingFreq, MatchingChnl, MatchingBlck, MatchingSub, MatchingAlloc;
+	
+	MatchingFreq = (iLocalCap.SamplingFrequencies() & aCaps.SamplingFrequencies());
+	MatchingChnl = (iLocalCap.ChannelModes() & aCaps.ChannelModes()); 
+	MatchingBlck = (iLocalCap.BlockLengths() & aCaps.BlockLengths());
+	MatchingSub = (iLocalCap.Subbands() & aCaps.Subbands());
+	MatchingAlloc = (iLocalCap.AllocationMethods() & aCaps.AllocationMethods());
+	
+	if ( 	 MatchingFreq  &&
+			 MatchingChnl  &&
+			 MatchingBlck 	&&
+			 MatchingSub   &&
+			 MatchingAlloc &&
+		     ( iLocalCap.MinBitpoolValue() <= aCaps.MaxBitpoolValue() )  &&
+			 ( iLocalCap.MaxBitpoolValue() >= aCaps.MinBitpoolValue() ) )
+		{
+		TRACE_INFO((_L("CBTSACStreamerController::GetMatchingCaps() accessory configuration suits us")))
+
+		// Choose highest possible values that are supported
+			
+		// Sampling Frequency
+		SetSamplingFrequency(aCaps, MatchingFreq);
+		// Channel mode
+		SetChannelMode(aCaps, MatchingChnl);
+		// Blocks
+		SetBlockLen(aCaps, MatchingBlck);			
+		// Subbands			
+		SetNumOfSubbands(aCaps, MatchingSub);	
+		// Allocation method	
+		SetAllocationMethod(aCaps, MatchingAlloc);		
+		// Bitpool
+		SetBitpoolValues(aCaps);
+		}
+	else // no match
+		{
+		TRACE_INFO((_L("CBTSACStreamerController::GetMatchingCaps() **No Matching Capabilities**")))
+		ret = KErrNotFound; 
+		}
+	return ret;
+	}
+
+// -----------------------------------------------------------------------------
+// CBTSACStreamerController::CheckAndAdjustBitpool
+// -----------------------------------------------------------------------------
+//
+void CBTSACStreamerController::CheckAndAdjustBitpool(TSBCCodecCapabilities& aCap)
+	{
+  	TRACE_FUNC
+	// ******* Adjust bitpool if necessary *****
+	TInt targetbitrate; 
+	TInt nChnls = GetNumOfChannels(aCap);
+	TInt nSbands = GetNumOfSubbands(aCap);
+	TInt nBlck  = GetBlockLen(aCap);
+	TInt Freq = GetSamplingFrequency(aCap);
+	TInt frameLength = FrameLengthFormula(aCap);
+	// Note: this is the bitrate of the transmission. 
+	TInt bitrateInt = 8 * frameLength * Freq / nSbands / nBlck; 
+	
+	TRACE_INFO((_L("CBTSACStreamerController::CheckAndAdjustBitpool(), nChnls = %d"), nChnls))
+	TRACE_INFO((_L("CBTSACStreamerController::CheckAndAdjustBitpool(), nSbands = %d"), nSbands))
+	TRACE_INFO((_L("CBTSACStreamerController::CheckAndAdjustBitpool(), nBlck = %d"), nBlck))
+	TRACE_INFO((_L("CBTSACStreamerController::CheckAndAdjustBitpool(), Freq = %d"), Freq))
+	TRACE_INFO((_L("CBTSACStreamerController::CheckAndAdjustBitpool(), MaxBP = %d"), aCap.MaxBitpoolValue()))
+	TRACE_INFO((_L("CBTSACStreamerController::CheckAndAdjustBitpool(), Frame length = %d"), frameLength))
+	TRACE_INFO((_L("CBTSACStreamerController::CheckAndAdjustBitpool(), Bitrate = %d"), bitrateInt))
+
+	// max bit rate:	320kb/s for mono, 
+	//					512kb/s for two-channel modes
+	if (aCap.ChannelModes() & EMono)
+		{
+		if (bitrateInt <= 320000.0)		
+			{
+			targetbitrate = bitrateInt;
+		 	}
+		 else // target bitrate=320kbps
+		 	{
+		 	TRACE_INFO((_L("CBTSACStreamerController::CheckAndAdjustBitpool() Adjusting...")))
+		 	targetbitrate = 320000.0; 
+		 	TInt BP = ( ((targetbitrate*nSbands*nBlck)/Freq) - 32 - (4*nSbands*nChnls) ) / (nBlck*nChnls); 
+		 	aCap.SetMaxBitpoolValue(BP);
+		 	}
+		 }
+	else
+		 {
+		 if (bitrateInt <= 512000.0)
+		 	{
+			targetbitrate = bitrateInt; 
+		 	}
+		else // target bitrate=512kbps
+			{
+			TRACE_INFO((_L("CBTSACStreamerController::CheckAndAdjustBitpool() Adjusting...")))
+			targetbitrate = 512000.0; 
+			TInt BP = 0;
+			if (aCap.ChannelModes() & EDualChannel)
+		 		{
+		 	  	BP = ( ((targetbitrate*nSbands*nBlck)/Freq) - 32 - (4*nSbands*nChnls) ) / (nBlck*nChnls); 	
+	 	  		}
+			else
+				{
+				TInt join = (aCap.ChannelModes() & EJointStereo) ? 1 : 0; 
+		 	  	BP = ( ((targetbitrate*nSbands*nBlck)/Freq) - 32 - (4*nSbands*nChnls) -  (nSbands*join) ) / (nBlck);
+				}
+				
+			aCap.SetMaxBitpoolValue(BP);
+			// Calculate new frame length
+			frameLength = FrameLengthFormula(aCap);
+		 	}	
+		}
+
+	iCurrentFrameLength = frameLength;
+	iCurrentBitrate = targetbitrate; 	
+	TRACE_INFO((_L("CBTSACStreamerController::CheckAndAdjustBitpool(), After Adjustment MaxBP: %d"), aCap.MaxBitpoolValue()))
+	TRACE_INFO((_L("CBTSACStreamerController::CheckAndAdjustBitpool(), After Adjustment Frame length: %d"), iCurrentFrameLength))
+  	TRACE_INFO((_L("CBTSACStreamerController::CheckAndAdjustBitpool(), After Adjustment Bitrate: %d"), iCurrentBitrate))
+	}
+
+// -----------------------------------------------------------------------------
+// CBTSACStreamerController::RunL
+// -----------------------------------------------------------------------------
+//
+void CBTSACStreamerController::RunL()
+	{
+	TRACE_FUNC
+	switch(iStatus.Int())
+		{
+   		case KErrNone:
+      		{
+			switch( iOngoingAction )
+				{
+				case EErrorSending:
+					{
+					TRACE_INFO((_L("CBTSACStreamerController::RunL(), ErrorSending")))
+					
+					TRACE_INFO((_L("CBTSACStreamerController::RunL(), TotalNbrOfDroppedPackets: %d"), iTotalNbrOfDroppedPackets))
+					TInt TotalNbrOfDroppedBits = iTotalNbrOfDroppedPackets*8;
+					TRACE_INFO((_L("CBTSACStreamerController::RunL(), Total dropped bits: %d"), TotalNbrOfDroppedBits))
+					TRACE_INFO((_L("CBTSACStreamerController::RunL(), Current Bitrate: %d"), iCurrentBitrate))
+					TInt ReconfigureLimit = KLimitCheckInterval*iCurrentBitrate*KReconfigureLimitFactor;
+					TRACE_INFO((_L("CBTSACStreamerController::RunL(), Limit for reconfigure : %d bits"), ReconfigureLimit))
+					TRACE_INFO((_L("CBTSACStreamerController::RunL(), PacketDropDeviation: %d (limit %d)"), iPacketDropDeviation, iCurrentBitpoolData->iMaxDeviation))
+					
+					if((TotalNbrOfDroppedBits > ReconfigureLimit) && (iPacketDropDeviation >= iCurrentBitpoolData->iMaxDeviation))
+						{
+						iPacketDropIoctl->Cancel();
+						
+						if(iCurrentBitpoolData->iMinimumMaxBitpool)
+							{
+							TRACE_INFO((_L("CBTSACStreamerController::RunL(), Minimum max bitpool reached.")))
+							TRACE_INFO((_L("CBTSACStreamerController::RunL(), Stop receive packet drops.")))
+							return;
+							}												
+						
+						// Initialize values for upgrade timer. Only if setting min bitpool value fails, start retry timer.
+						TInt delay = KStabilizationDelay;
+						iOngoingAction = EStabilize;
+						TInt err = ConfigureSEPBitpool(EDowngradeBitrate);							
+						if(err)
+							{
+							iOngoingAction = EDowngradeBitrate;
+							delay = KRetryTimerDelay;
+							}
+
+		    			iTimer.After(iStatus, delay);
+		    			SetActive();
+						}
+					
+					iPacketDropDeviation = 0;
+					iTotalNbrOfDroppedPackets = 0;
+					break;
+					}					
+				
+				case EStabilize:
+					// Start receive overflow indications again
+					TRACE_INFO((_L("CBTSACStreamerController::RunL(), stabilize timer expired.")))
+					iPacketDropIoctl->Start();
+					break;
+
+				case EDowngradeBitrate:
+				case EUpgradeBitrate:
+				case EStartStabilizingTimer:
+					{
+					TRACE_INFO((_L("CBTSACStreamerController::RunL(), Action = %d"), iOngoingAction))
+					TInt err = KErrNone;
+					TInt delay = KStabilizationDelay;
+					if(iOngoingAction != EStartStabilizingTimer)
+						{
+						err = ConfigureSEPBitpool(iOngoingAction);
+						}
+					if(err)
+						{
+						delay = KRetryTimerDelay;
+						}
+					else
+						{
+	    				TRACE_INFO((_L("CBTSACStreamerController::RunL(), stabilize timer started")))
+	    				iOngoingAction = EStabilize;
+						}
+
+    				iTimer.After(iStatus, delay);
+    				SetActive();
+					break;
+					}				
+				}
+        	break;
+      		}
+      	
+		case KErrGeneral: // We have received error from audio adaptation
+			{
+			TRACE_INFO((_L("CBTSACStreamerController::RunL(), KErrGeneral")))
+			iAudioInput->Stop();
+			iAudioInput->Disconnect();
+			iObserver.NotifyError(KErrGeneral);
+			break;
+			}
+			
+   		default:
+   			TRACE_INFO((_L("CBTSACStreamerController::RunL(), #default")))
+      		break;
+   		}  
+    TRACE_INFO((_L("CBTSACStreamerController::RunL() completed")))
+	}
+
+// -----------------------------------------------------------------------------
+// CBTSACStreamerController::DoCancel
+// -----------------------------------------------------------------------------
+//
+void CBTSACStreamerController::DoCancel()
+	{
+	TRACE_FUNC
+    iTimer.Cancel();
+    TRACE_INFO((_L("CBTSACStreamerController::DoCancel() completed")))
+	}
+
+// -----------------------------------------------------------------------------
+// CBTSACStreamerController::RunError
+// -----------------------------------------------------------------------------
+//
+TInt CBTSACStreamerController::RunError(TInt /*aError*/)    
+	{
+	TRACE_FUNC
+	return 0;
+	}
+    
+// -----------------------------------------------------------------------------
+// CBTSACStreamerController::Error
+// -----------------------------------------------------------------------------
+//
+TInt CBTSACStreamerController::Error(const TInt aError) 
+	{
+	TRACE_INFO((_L("CBTSACStreamerController::Error() %d"), aError))
+	TInt ret = KErrNone;
+	switch(aError)
+		{
+		case KErrOverflow:
+		case KErrUnderflow:
+			{
+			DoSelfComplete(EErrorSending, KErrNone);
+			break;
+			}
+		case KErrGeneral:
+			{
+			if(iState != EStateError)
+				{
+				iState = EStateError;
+				DoSelfComplete(iOngoingAction, KErrGeneral);
+				}
+			break;
+			}
+		default:
+			{
+			ret = KErrUnknown;
+			break;
+			}
+		}
+	return ret;
+	}
+
+// -----------------------------------------------------------------------------
+// CBTSACStreamerController::GetCaps
+// -----------------------------------------------------------------------------
+//
+TSBCCodecCapabilities& CBTSACStreamerController::GetCaps()
+	{
+	return iLocalCap;
+	}
+
+// -----------------------------------------------------------------------------
+// CBTSACStreamerController::SetBlockLen
+// -----------------------------------------------------------------------------
+//
+void CBTSACStreamerController::SetBlockLen(TSBCCodecCapabilities& aCap, TUint8 aBlockLen)
+	{
+	// Set Block Lenght, select highest one
+	if ( aBlockLen & EBlockLenSixteen )
+		{
+		iEncoderCI->SetNumOfBlocks(TUint(16));
+		aCap.SetBlockLengths(EBlockLenSixteen);
+		TRACE_INFO((_L("CBTSACStreamerController::SetBlockLen(), BlockLength: EBlockLenSixteen")))
+		}
+	else if ( aBlockLen & EBlockLenTwelve )
+		{
+		iEncoderCI->SetNumOfBlocks(TUint(12));
+		aCap.SetBlockLengths(EBlockLenTwelve);	
+		TRACE_INFO((_L("CBTSACStreamerController::SetBlockLen(), BlockLength: EBlockLenTwelve")))
+		}
+	else if ( aBlockLen & EBlockLenEight )
+		{
+		iEncoderCI->SetNumOfBlocks(TUint(8));
+		aCap.SetBlockLengths(EBlockLenEight);
+		TRACE_INFO((_L("CBTSACStreamerController::SetBlockLen(), BlockLength: EBlockLenEight")))
+		}
+	else if ( aBlockLen & EBlockLenFour )
+		{
+		iEncoderCI->SetNumOfBlocks(TUint(4));
+		aCap.SetBlockLengths(EBlockLenFour);
+		TRACE_INFO((_L("CBTSACStreamerController::SetBlockLen(), BlockLength: EBlockLenFour")))
+		}
+	else
+		{
+		TRACE_INFO((_L("CBTSACStreamerController::SetBlockLen(), No matching Block Length")))
+		}
+	}
+	
+// -----------------------------------------------------------------------------
+// CBTSACStreamerController::GetBlockLen
+// -----------------------------------------------------------------------------
+//
+TInt CBTSACStreamerController::GetBlockLen(TSBCCodecCapabilities& aCap) const
+	{
+	TInt nBlck  = 0;
+	switch( aCap.BlockLengths() )
+		{
+		case EBlockLenSixteen:
+			nBlck = 16;
+			break;
+		case EBlockLenTwelve:
+			nBlck = 12;
+			break;
+		case EBlockLenEight:
+			nBlck = 8;
+			break;
+		case EBlockLenFour:
+			nBlck = 4;
+			break;
+		default:
+			TRACE_INFO((_L("CBTSACStreamerController::GetBlockLen(), #default")))
+			nBlck = 16;
+			break;
+		}
+	return nBlck;
+	}
+
+// -----------------------------------------------------------------------------
+// CBTSACStreamerController::SetBitpoolValues
+// -----------------------------------------------------------------------------
+//
+void CBTSACStreamerController::SetBitpoolValues(TSBCCodecCapabilities& aCap)
+	{
+	// Define max bitpool
+	TInt MaxBP = 0;
+	TBool ProperMaxBitpoolFound = EFalse;
+	for(TInt i = 0 ; i < KNumOfBitpoolValues ; i++)
+		{
+		if(aCap.MaxBitpoolValue() >= KMaxBitpoolValues[i])
+			{
+			MaxBP = KMaxBitpoolValues[i];
+			ProperMaxBitpoolFound = ETrue;
+			break;
+			}
+		}
+	if(!ProperMaxBitpoolFound)
+		{
+		// None of our proposed max bitpool values weren't suitable for accessory.
+		// Let's use the one which was proposed by the accessory.
+		MaxBP = aCap.MaxBitpoolValue();
+		}
+	
+	// Define min bitpool. This bitpool value is negotiated with sink.
+	TInt MinBP = (iLocalCap.MinBitpoolValue() < aCap.MinBitpoolValue()) ? aCap.MinBitpoolValue() : iLocalCap.MinBitpoolValue();
+	
+	// Define bitpool which is used for medium quality streaming (when streaming is interfered for some reason).
+	// This is real lowest bitpool value which is used for streaming.
+	
+	// Check if selected max bitpool value is smaller than our default min bitpool value, if it is, set
+	// minimum max bitpool value to be same as max value otherwise just update it with our default min value.
+	if(MaxBP < MAXBITPOOLVALUEMIN)
+		{
+		// Update the minumum bitpool data
+		iBitpoolData[iBitpoolData.Count()-1].iMaxBitpoolValue = MaxBP;
+		}
+	else if(MAXBITPOOLVALUEMIN < MinBP) // Check also that minimum max bitpool value is not smaller than bitpool which is negotiated for the link.
+		{
+		iBitpoolData[iBitpoolData.Count()-1].iMaxBitpoolValue = MinBP;
+		}
+	
+	TRACE_INFO((_L("CBTSACStreamerController::SetBitpoolValues(), Remote Max Bitpool: %d"), aCap.MaxBitpoolValue()))
+	TRACE_INFO((_L("CBTSACStreamerController::SetBitpoolValues(), Remote Min Bitpool: %d"), aCap.MinBitpoolValue()))
+	
+	aCap.SetMaxBitpoolValue(MaxBP);
+	TRACE_INFO((_L("CBTSACStreamerController::SetBitpoolValues(), Max Bitpool: %d"), MaxBP))
+	aCap.SetMinBitpoolValue(MinBP);
+	TRACE_INFO((_L("CBTSACStreamerController::SetBitpoolValues(), Min Bitpool: %d"), MinBP))
+	}
+
+// -----------------------------------------------------------------------------
+// CBTSACStreamerController::SetAllocationMethod
+// -----------------------------------------------------------------------------
+//
+void CBTSACStreamerController::SetAllocationMethod(TSBCCodecCapabilities& aCap, TUint8 aAllocationMethod)
+	{
+	// Set Allocation Method, select highest one
+	if ( aAllocationMethod & ELoudness )
+		{
+		iEncoderCI->SetAllocationMethod(CSbcEncoderIntfc::ESbcAllocationLoudness);
+		aCap.SetAllocationMethods(ELoudness);
+		TRACE_INFO((_L("CBTSACStreamerController::SetAllocationMethod(), AllocationMethod: ELoudness")))
+		}
+	else if ( aAllocationMethod & ESNR )
+		{
+		iEncoderCI->SetAllocationMethod(CSbcEncoderIntfc::ESbcAllocationSNR);
+		aCap.SetAllocationMethods(ESNR);
+		TRACE_INFO((_L("CBTSACStreamerController::SetAllocationMethod(), AllocationMethod: ESNR")))
+		}
+	else
+		{
+		TRACE_INFO((_L("CBTSACStreamerController::SetAllocationMethod(), No matching Allocation Method")))
+		}
+	}
+// -----------------------------------------------------------------------------
+// CBTSACStreamerController::SetChannelMode
+// -----------------------------------------------------------------------------
+//
+void CBTSACStreamerController::SetChannelMode(TSBCCodecCapabilities& aCap, TUint8 aChannelMode)
+	{
+	// Set Channel mode, select highest one
+	if ( aChannelMode & EJointStereo )
+		{
+		iEncoderCI->SetChannelMode(CSbcEncoderIntfc::ESbcChannelJointStereo);
+		aCap.SetChannelModes(EJointStereo);
+		TRACE_INFO((_L("CBTSACStreamerController::SetChannelMode(), ChannelMode: EJointStereo")))
+		}
+	else if ( aChannelMode & EStereo )
+		{
+		iEncoderCI->SetChannelMode(CSbcEncoderIntfc::ESbcChannelStereo);
+		aCap.SetChannelModes(EStereo);	
+		TRACE_INFO((_L("CBTSACStreamerController::SetChannelMode(), ChannelMode: EStereo")))
+		}
+	else if ( aChannelMode & EDualChannel )
+		{
+		iEncoderCI->SetChannelMode(CSbcEncoderIntfc::ESbcChannelDual);
+		aCap.SetChannelModes(EDualChannel);
+		TRACE_INFO((_L("CBTSACStreamerController::SetChannelMode(), ChannelMode: EDualChannel")))
+		}
+	else if ( aChannelMode & EMono )
+		{
+		iEncoderCI->SetChannelMode(CSbcEncoderIntfc::ESbcChannelMono);
+		aCap.SetChannelModes(EMono);
+		TRACE_INFO((_L("CBTSACStreamerController::SetChannelMode(), ChannelMode: EMono")))
+		}
+	else
+		{
+		TRACE_INFO((_L("CBTSACStreamerController::SetChannelMode(), No matching Channel Mode")))
+		}
+	}
+
+// -----------------------------------------------------------------------------
+// CBTSACStreamerController::SetSamplingFrequency
+// -----------------------------------------------------------------------------
+//
+void CBTSACStreamerController::SetSamplingFrequency(TSBCCodecCapabilities& aCap, TUint8 aFrequency)
+	{
+	// Set Sampling Frequency, select highest one
+	if ( aFrequency & E48kHz )
+		{
+		iEncoderCI->SetSamplingFrequency(TUint(48000));
+		aCap.SetSamplingFrequencies(E48kHz);
+		TRACE_INFO((_L("CBTSACStreamerController::SetSamplingFrequency(), Sampling Frequency: E48kHz")))
+		}
+	else if ( aFrequency & E44100Hz )
+		{
+		iEncoderCI->SetSamplingFrequency(TUint(44100));
+		aCap.SetSamplingFrequencies(E44100Hz);
+		TRACE_INFO((_L("CBTSACStreamerController::SetSamplingFrequency(), Sampling Frequency: E44100Hz")))
+		}
+	else if ( aFrequency & E32kHz )
+		{
+		iEncoderCI->SetSamplingFrequency(TUint(32000));
+		aCap.SetSamplingFrequencies(E32kHz);
+		TRACE_INFO((_L("CBTSACStreamerController::SetSamplingFrequency(), Sampling Frequency: E32kHz")))
+		}
+	else if ( aFrequency & E16kHz )
+		{
+		iEncoderCI->SetSamplingFrequency(TUint(16000));
+		aCap.SetSamplingFrequencies(E16kHz);
+		TRACE_INFO((_L("CBTSACStreamerController::SetSamplingFrequency(), Sampling Frequency: E16kHz")))
+		}
+	else
+		{
+		TRACE_INFO((_L("CBTSACStreamerController::SetSamplingFrequency(), No matching Sampling Frequency")))
+		}
+	}
+
+// -----------------------------------------------------------------------------
+// CBTSACStreamerController::GetSamplingFrequency
+// -----------------------------------------------------------------------------
+//
+TInt CBTSACStreamerController::GetSamplingFrequency(TSBCCodecCapabilities& aCap) const
+	{
+	TInt Freq  = 0;
+	switch( aCap.SamplingFrequencies() )
+		{
+		case E48kHz:
+			Freq = 48000;
+			break;
+		case E44100Hz:
+			Freq = 44100;
+			break;
+		case E32kHz:
+			Freq = 32000;
+			break;
+		case E16kHz:
+			Freq = 16000;
+			break;
+		default:
+			TRACE_INFO((_L("CBTSACStreamerController::GetSamplingFrequency(), #default")))
+			Freq = 48000;
+			break;
+		}
+	return Freq;
+	}
+
+// -----------------------------------------------------------------------------
+// CBTSACStreamerController::GetNumOfChannels
+// -----------------------------------------------------------------------------
+//
+TInt CBTSACStreamerController::GetNumOfChannels(TSBCCodecCapabilities& aCap) const
+	{
+	TInt nChnls = (aCap.ChannelModes() & EMono) ? 1 : 2;
+	return nChnls;
+	}
+
+// -----------------------------------------------------------------------------
+// CBTSACStreamerController::SetNumOfSubbands
+// -----------------------------------------------------------------------------
+//
+void CBTSACStreamerController::SetNumOfSubbands(TSBCCodecCapabilities& aCap, TUint8 aNumOfSubbands)
+	{	
+	// Set Number of Subbands, select highest one
+	if ( aNumOfSubbands & EEightSubbands )
+		{
+		iEncoderCI->SetNumOfSubbands(TUint(8));
+		aCap.SetSubbands(EEightSubbands);
+		TRACE_INFO((_L("CBTSACStreamerController::SetNumOfSubbands(), Subband: EEightSubbands")))
+		}
+	else if ( aNumOfSubbands & EFourSubbands )
+		{
+		iEncoderCI->SetNumOfSubbands(TUint(4));
+		aCap.SetSubbands(EFourSubbands);
+		TRACE_INFO((_L("CBTSACStreamerController::SetNumOfSubbands(), Subband: EFourSubbands")))
+		}
+	else
+		{
+		TRACE_INFO((_L("CBTSACStreamerController::SetNumOfSubbands(), No matching Subband")))
+		}
+	}
+
+// -----------------------------------------------------------------------------
+// CBTSACStreamerController::GetNumOfSubbands
+// -----------------------------------------------------------------------------
+//
+TInt CBTSACStreamerController::GetNumOfSubbands(TSBCCodecCapabilities& aCap) const
+	{
+	TInt nSbands = (aCap.Subbands() & EEightSubbands) ? 8 : 4;
+	return nSbands;
+	}
+
+// -----------------------------------------------------------------------------
+// CBTSACStreamerController::FrameLengthFormula
+// -----------------------------------------------------------------------------
+//
+TInt CBTSACStreamerController::FrameLengthFormula(TSBCCodecCapabilities& aCap) const
+	{
+	TInt join = ( aCap.ChannelModes() & EJointStereo ) ? 1 : 0; 
+	TInt nChnls = GetNumOfChannels(aCap);
+	TInt nSbands = GetNumOfSubbands(aCap);
+	TInt nBlck  = GetBlockLen(aCap);
+	
+	// For mono (and dual channel) mode the formula is slightly differend than for stereo mode(s). 
+	TInt frameLength = 
+		( (aCap.ChannelModes() & EMono) || (aCap.ChannelModes() & EDualChannel) ) ? 
+		  4 + ((4 * nSbands * nChnls) / 8) + ( (nBlck * nChnls * aCap.MaxBitpoolValue()) / 8): 
+		  4 + ((4 * nSbands * nChnls) / 8) + ( (join * nSbands + nBlck * aCap.MaxBitpoolValue()) / 8)/* + join*/; 
+
+	// Note:	last "+ join" in latter version of the formula is for joint stereo. 
+	//			Otherwise the formula doesn't calculate the extra byte that's in the header.
+	return frameLength;
+	}
+
+// -----------------------------------------------------------------------------
+// CBTSACStreamerController::PacketsDropped
+// -----------------------------------------------------------------------------
+//
+void CBTSACStreamerController::PacketsDropped(TInt aError)
+	{
+	TRACE_FUNC
+	if(!iTotalNbrOfDroppedPackets)
+		{
+		// This is first packet drop indication after previous sample interval
+		iFirstPacketDropTime.UniversalTime();
+		}
+	TTime timeNow;
+	timeNow.UniversalTime();
+    iPacketDropDeviation = static_cast<TInt32>(timeNow.MicroSecondsFrom(iFirstPacketDropTime).Int64());
+	
+	iTotalNbrOfDroppedPackets += aError;
+	
+	if(!IsActive())
+		{
+		iOngoingAction = EErrorSending;
+		iTimer.After(iStatus, KDataCollectDelay);
+		SetActive();
+		}
+	}
+
+// -----------------------------------------------------------------------------
+// CBTSACStreamerController::SetCurrentBitpoolData
+// -----------------------------------------------------------------------------
+//
+TInt CBTSACStreamerController::SetCurrentBitpoolData(TInt aBitpool)
+	{
+	TRACE_FUNC
+	TInt err = KErrNone;
+	TInt Index = GetIndex(aBitpool);
+	if(Index >= 0)
+		{
+		iCurrentBitpoolData = GetBitpoolData(Index);
+		}
+	else
+		{
+		err = KErrNotFound;
+		}
+	return err;
+	}
+// -----------------------------------------------------------------------------
+// CBTSACStreamerController::GetIndex
+// -----------------------------------------------------------------------------
+//
+TInt CBTSACStreamerController::GetIndex(TInt aBitpool)
+	{
+	TInt Bitpool = aBitpool;
+	if(aBitpool > iMatchCap.MaxBitpoolValue())
+		{
+		Bitpool = iMatchCap.MaxBitpoolValue();
+		}
+	for(TInt i = 0 ; i < iBitpoolData.Count() ; i++)
+		{
+		if(Bitpool == iBitpoolData[i].iMaxBitpoolValue)
+			{
+			return i;
+			}
+		}
+	return KErrNotFound;
+	}
+
+// -----------------------------------------------------------------------------
+// CBTSACStreamerController::IndexValid
+// -----------------------------------------------------------------------------
+//
+TBool CBTSACStreamerController::IndexValid(TInt aIndex)
+	{
+	if(aIndex >= 0 && aIndex < iBitpoolData.Count())
+		return ETrue;
+	else
+		return EFalse;
+	}
+
+// -----------------------------------------------------------------------------
+// CBTSACStreamerController::InitializeBitpoolData
+// -----------------------------------------------------------------------------
+//
+void CBTSACStreamerController::InitializeBitpoolDataL()
+	{
+	TRACE_FUNC
+	TBitpoolData data;
+	iBitpoolData.Reset();
+	for(TInt i = 0 ; i < KNumOfBitpoolValues ; i++)
+		{
+		data.iMaxBitpoolValue = KMaxBitpoolValues[i];
+		data.iMaxDeviation = KDeviationValues[i];
+		//data.iUpgradeDelay = KUpgradeDelays[i];
+		data.iUpBitpoolIndex = (i == 0) ? i : i - 1;
+		data.iIndex = i;
+		data.iDownBitpoolIndex = (i == KNumOfBitpoolValues - 1) ? i : i + 1;
+		data.iMinimumMaxBitpool = (i == KNumOfBitpoolValues - 1) ? ETrue : EFalse;
+		iBitpoolData.AppendL(data);
+		}
+	}
+
+// -----------------------------------------------------------------------------
+// CBTSACStreamerController::GetBitpoolData
+// -----------------------------------------------------------------------------
+//
+TBitpoolData* CBTSACStreamerController::GetBitpoolData(TInt aIndex)
+	{
+	if(aIndex < 0 || aIndex >= iBitpoolData.Count())
+		return NULL;
+	
+	return &iBitpoolData[aIndex];
+	}
+
+// -----------------------------------------------------------------------------
+// CBTSACStreamerController::ReorganizeBitpoolTable
+// -----------------------------------------------------------------------------
+//
+void CBTSACStreamerController::ReorganizeBitpoolTable(TInt aNegotiatedMaxBitpool)
+	{
+	TRACE_INFO((_L("CBTSACStreamerController::ReorganizeBitpoolTable(), Negotiated Max Bitpool %d"), aNegotiatedMaxBitpool))
+	// Start checking from the lowest possible bitpool value	
+	for(TInt i = (KNumOfBitpoolValues - 1) ; i > 0 ; i--)
+		{
+		if(aNegotiatedMaxBitpool <= KMaxBitpoolValues[i])
+			{
+			TInt ii;
+			for(ii = 0 ; ii < i ; ii++)
+				{
+				iBitpoolData.Remove(0);				
+				}
+			TRACE_INFO((_L("CBTSACStreamerController::ReorganizeBitpoolTable(), Tables removed: %d"), ii))
+			for(TInt j = 0 ; j < iBitpoolData.Count() ; j++)
+				{
+				if(j == 0)
+					{
+					iBitpoolData[j].iMaxBitpoolValue = aNegotiatedMaxBitpool;
+					}
+				iBitpoolData[j].iIndex = j;
+				iBitpoolData[j].iUpBitpoolIndex = (j == 0) ? j : j - 1;
+				iBitpoolData[j].iDownBitpoolIndex = (j == iBitpoolData.Count() - 1) ? j : j + 1;
+				}
+			break;
+			}
+		}
+	TRACE_INFO((_L("CBTSACStreamerController::ReorganizeBitpoolTable(), Tables left: %d"), iBitpoolData.Count()))
+	for(TInt k = 0 ; k < iBitpoolData.Count() ; k++)
+		{
+		TRACE_INFO((_L("CBTSACStreamerController::ReorganizeBitpoolTable(), Table[%d] MaxBP: %d"), k, iBitpoolData[k].iMaxBitpoolValue))
+		}
+	}
+
+// -----------------------------------------------------------------------------
+// CBTSACStreamerController::DoSelfComplete
+// -----------------------------------------------------------------------------
+//
+void CBTSACStreamerController::DoSelfComplete(EOngoingAction aAction, TInt aError)
+	{
+	TRACE_FUNC
+	if (IsActive())
+    	{
+    	// Stop timer
+    	Cancel();
+    	}
+    if (!IsActive())
+    	{
+		// Just self complete here, handle error in RunL
+		iOngoingAction = aAction;
+		TRequestStatus *status = &iStatus;
+		iStatus = KRequestPending;
+ 		iThread.RequestComplete(status, aError);
+ 		SetActive();
+    	}
+    else
+    	{
+    	TRACE_INFO((_L("CBTSACStreamerController::DoSelfComplete((), Couldn't do self complete")))
+    	}
+	}
+//  End of File