devsound/sounddevbt/src/A2dpBlueTooth/headsetaudioif/AudioBufferArray.cpp
changeset 0 40261b775718
equal deleted inserted replaced
-1:000000000000 0:40261b775718
       
     1 // Copyright (c) 2005-2009 Nokia Corporation and/or its subsidiary(-ies).
       
     2 // All rights reserved.
       
     3 // This component and the accompanying materials are made available
       
     4 // under the terms of "Eclipse Public License v1.0"
       
     5 // which accompanies this distribution, and is available
       
     6 // at the URL "http://www.eclipse.org/legal/epl-v10.html".
       
     7 //
       
     8 // Initial Contributors:
       
     9 // Nokia Corporation - initial contribution.
       
    10 //
       
    11 // Contributors:
       
    12 //
       
    13 // Description:
       
    14 //
       
    15 
       
    16 #include "AudioBufferArray.h"
       
    17 #include "BtSBCFrameParameters.h"
       
    18 #include "A2dpCodecUtilities.h"
       
    19 
       
    20 /**
       
    21 Audio Buffer Array Panics
       
    22 **/
       
    23 enum TAudioBufferArrayPanic
       
    24 	{
       
    25 	EAudioBufferArrayIncompleteFrame, //0
       
    26 	EAudioBufferArrayMiscount, //1
       
    27 	EAudioBufferArrayNonA2dpDataType, //2
       
    28 	EAudioBufferArrayNoRTPPacketsPerAudioBuffer //3
       
    29 	};
       
    30 
       
    31 
       
    32 static void Panic(TAudioBufferArrayPanic aPanic)
       
    33 // Panic client
       
    34 	{
       
    35 	_LIT(KAudioBufferArrayPanicName, "A2DP Audio Buf Panic");
       
    36 	User::Panic(KAudioBufferArrayPanicName, aPanic);
       
    37 	}
       
    38 	
       
    39 
       
    40 /**
       
    41 Creates a CRtpSendPackets array of RRtpSendPackets
       
    42 
       
    43 @param aRtpSendSource
       
    44 @param aNumberOfPackets this is the number of RRtpSendPackets stored in
       
    45 the array
       
    46 */	
       
    47 CRtpSendPackets* CRtpSendPackets::NewL(RRtpSendSource& aRtpSendSource, TUint aNumberOfPackets)
       
    48 	{
       
    49 	CRtpSendPackets* self = new (ELeave) CRtpSendPackets ();
       
    50 	CleanupStack::PushL(self);
       
    51 	self->ConstructL(aRtpSendSource, aNumberOfPackets);
       
    52 	CleanupStack::Pop(self);
       
    53 	return self;
       
    54 	}
       
    55 
       
    56 	
       
    57 void CRtpSendPackets::ConstructL(RRtpSendSource& aRtpSendSource, TUint aNumberOfPackets)
       
    58 	{
       
    59 	// create all the RTP send packets now	
       
    60 	TInt err = KErrNone;
       
    61 	for (TInt i=0; i<aNumberOfPackets; i++)
       
    62 		{
       
    63 		RRtpSendPacket sendPacket = aRtpSendSource.NewSendPacketL();
       
    64 		err = iRtpSendPackets.Append(sendPacket);
       
    65 		if (err)
       
    66 			{//probably run out of memory so need to close the packets
       
    67 			CloseAndResetSendPackets();
       
    68 			User::Leave(err);
       
    69 			}
       
    70 		}
       
    71 	}
       
    72 
       
    73 	
       
    74 CRtpSendPackets::~CRtpSendPackets()
       
    75 	{
       
    76 	CloseAndResetSendPackets();
       
    77 	}
       
    78 
       
    79 
       
    80 void CRtpSendPackets::CloseAndResetSendPackets()
       
    81 	{
       
    82 	// destroy all the RTP send packets now
       
    83 	TUint numberOfSendPackets = iRtpSendPackets.Count();
       
    84 	for (TInt i=0; i<numberOfSendPackets; i++)
       
    85 		{
       
    86 		RRtpSendPacket& p = iRtpSendPackets[i];
       
    87 		p.Close();
       
    88 		}
       
    89 	iRtpSendPackets.Reset();
       
    90 	}
       
    91 
       
    92 /**
       
    93 Creates  a FIFO array of audio buffers stored as CRtpSendPackets
       
    94 The paramers passed in are used to determine the size and number
       
    95 of RTP packets required to store an audio buffer
       
    96 The payload size on aRtpSendSource is set.
       
    97 
       
    98 @param aRtpSendSource used to create the send packets that contain
       
    99 the audio buffers.  The payload size is set on the aRtpSendSource to
       
   100 a value calculated from the other parameters
       
   101 @param aNumberOfAudioBuffers this is the number of audio buffers
       
   102 stored in the FIFO
       
   103 @param aAudioBufferLength this is the length of the audio buffer that needs
       
   104 to be sent to the headset ie buffer size after SBC processing in the case of SBC
       
   105 @param aMTULength this is the max data length allowing for the restriction imposed
       
   106 by the underlying MTU bearer ie bluetooth and the headset.
       
   107 @param aTotalRTPHeaderLength the RTP header length including the 
       
   108 RTP media payload header ie RTP header length + media payload header length
       
   109 @param aFrameLength 
       
   110 */	
       
   111 CAudioBufferArray* CAudioBufferArray::NewL(RRtpSendSource& aRtpSendSource, 
       
   112 									TUint aNumberOfAudioBuffers, 
       
   113 									TUint aAudioBufferLength, 
       
   114 									TUint aMTULength, 
       
   115 								    TUint aTotalRTPHeaderLength,
       
   116 									TUint aFrameLength)
       
   117 	{
       
   118 	CAudioBufferArray* self = new (ELeave) CAudioBufferArray();
       
   119 	CleanupStack::PushL(self);
       
   120 	self->ConstructL(aRtpSendSource, aNumberOfAudioBuffers, aAudioBufferLength, aMTULength, aTotalRTPHeaderLength, aFrameLength);
       
   121 	CleanupStack::Pop(self);
       
   122 	return self;
       
   123 	}
       
   124 
       
   125 
       
   126 void CAudioBufferArray::ConstructL(RRtpSendSource& aRtpSendSource,
       
   127 						TUint aNumberOfAudioBuffers,
       
   128 						TUint aAudioBufferLength,
       
   129 						TUint aMTULength,
       
   130 						TUint aTotalRTPHeaderLength,
       
   131 						TUint aFrameLength)
       
   132 	{
       
   133 	//the buffer should always contain an intiger number of audio frames
       
   134 	//the following ASSERT_DEBUG should be present but is commented out as the RVCT 
       
   135 	//compiler generates a warning
       
   136 	//__ASSERT_DEBUG(!(aAudioBufferLength%aFrameLength),EAudioBufferArrayIncompleteFrame);
       
   137 	
       
   138 	//calculate the number of frames in the audio buffer size and if 
       
   139 	//more than 15 frames then calculate the highest common factor and use this 
       
   140 	//calculate the frames length
       
   141 	iFrameLength = aFrameLength;
       
   142 
       
   143 	//calculate the total number of frames in the buffer
       
   144 	TUint numberOfFramesPerAudioBuffer = aAudioBufferLength/iFrameLength;
       
   145 	//for now set the number of audio frames in an RTP packet to the total
       
   146 	iNumberOfFramesPerRtpPacket = numberOfFramesPerAudioBuffer;
       
   147 	
       
   148 	TUint lengthOfAudioDataInRtpPacket = 0;
       
   149 	TInt usableRTPPayloadLength = aMTULength-aTotalRTPHeaderLength;
       
   150 	
       
   151 	//check whether all the audio frames will actually fit into one RTP packet
       
   152 	if ((numberOfFramesPerAudioBuffer > KMaxNumberOfSBCFramesPerRTPPacket)||((aAudioBufferLength+iFrameLength)>usableRTPPayloadLength))//+iFrameLength in case of cached frame
       
   153 		{
       
   154 		//we cannot get all the audio frames into a single RTP packet
       
   155 		//for SBC only a max of 15 SBC frames allowed per packet
       
   156 		//if the buffer size exceeds 15 frames and/or is too large
       
   157 		//for the underlying MTU size then we need to break
       
   158 		//the buffer into buffers of less then 16 frames.
       
   159 		//for non SBC the frames are generaly larger so we'll keep
       
   160 		//the 15 for now even for non SBC
       
   161 		//we need to calculate how may frames should go into
       
   162 		//each RTP packet and how many RTP packets we need to send a
       
   163 		//complete audio buffer
       
   164 		//we are going to calculate such that every RTP packet
       
   165 		//has the same number of frames
       
   166 		//note that if we are using non SBC then the frame size tends to be larger
       
   167 		//so the MTU limit is likely to be the dominant factor
       
   168 		//although in principle this code should only use the 15 frame limit for
       
   169 		//for SBC
       
   170 		iNumberOfFramesPerRtpPacket = 0; 
       
   171 		
       
   172 		
       
   173 		//only a max of 15 SBC frames allowed per packet
       
   174 		//if the buffer size exceeds 15 frames then we need to break
       
   175 		//the buffer into buffers of less then 16 frames.
       
   176 		//so find HCF 
       
   177 		//-1 for cached frames ie if iNumberOfFramesPerRtpPacket
       
   178 		//was the same as KMaxNumberOfSBCFramesPerRTPPacket and we got a cached frame
       
   179 		//then we would blow the limit
       
   180 		for (TUint i=KMaxNumberOfSBCFramesPerRTPPacket-1; i; i--)
       
   181 			{
       
   182 			if (!(numberOfFramesPerAudioBuffer%i))
       
   183 				{
       
   184 				//check we don't blow the MTU size
       
   185 				if ((i*iFrameLength) <= usableRTPPayloadLength)
       
   186 					{
       
   187 					iNumberOfFramesPerRtpPacket = i;
       
   188 					break;
       
   189 					}
       
   190 				}
       
   191 			}
       
   192 		if (!iNumberOfFramesPerRtpPacket)
       
   193 			{//the frame length was too big for the MTU length
       
   194 			//one frame of audio + one frame of cached audio
       
   195 			//would exceed the length supported by the underlying bearer
       
   196 			//note that the A2DP specification section 4.3.4 does allow
       
   197 			//SBC frames to be fragmented across multiple packets if
       
   198 			//less than one frame, but this ref implementation
       
   199 			//does not support this, since this should be rare.
       
   200 			//this may happen more often for non SBC eg mp3 frames
       
   201 			//but we don't support fragmented frames
       
   202 			User::Leave(KErrTooBig);
       
   203 			}
       
   204 		iNumberOfRtpPacketsPerAudioBuffer = numberOfFramesPerAudioBuffer/iNumberOfFramesPerRtpPacket;
       
   205 		
       
   206 		//this could probably be optimized somewhat such that the
       
   207 		//iInputBytesPerRtpPacket value was such that no caching was required 
       
   208 		//in the codec
       
   209 		
       
   210 		if (!iNumberOfRtpPacketsPerAudioBuffer)//this isn't really necessary or could be ASSERT but needed supress armv5 compiler warning
       
   211 			{
       
   212 			Panic(EAudioBufferArrayNoRTPPacketsPerAudioBuffer);
       
   213 			}
       
   214 			
       
   215 		iInputBytesPerRtpPacket = aAudioBufferLength/iNumberOfRtpPacketsPerAudioBuffer;
       
   216 		if (iInputBytesPerRtpPacket%2)
       
   217 			{//we have an odd number of bytes
       
   218 			iInputBytesPerRtpPacket++;//round up to next byte
       
   219 			}
       
   220 		lengthOfAudioDataInRtpPacket = iNumberOfFramesPerRtpPacket*iFrameLength;
       
   221 		}//if ((numberOfFramesPerAudioBuffer > KMaxNumberOfSBCFramesPerRTPPacket)||((encodedAudioBufferLength+iFrameLength)>aMaxMTULength))
       
   222 	else
       
   223 		{//we can fit the entire buffer in one RTP packet
       
   224 		iNumberOfRtpPacketsPerAudioBuffer = 1;
       
   225 		iInputBytesPerRtpPacket = aAudioBufferLength;
       
   226 		lengthOfAudioDataInRtpPacket = aAudioBufferLength;
       
   227 		}
       
   228 
       
   229 	TUint payloadSize = aTotalRTPHeaderLength+lengthOfAudioDataInRtpPacket+iFrameLength;//+ extra framelength for cached frames
       
   230 	aRtpSendSource.SetDefaultPayloadSize(payloadSize);
       
   231 	
       
   232 	//now we have set the payload size we can create the audio buffers
       
   233 	//stored as CRtpSendPackets* 
       
   234 	for (TInt i=0; i<aNumberOfAudioBuffers; i++)
       
   235 		{
       
   236 		CRtpSendPackets* sendPacketArray = CRtpSendPackets::NewL(aRtpSendSource, iNumberOfRtpPacketsPerAudioBuffer);
       
   237 		User::LeaveIfError(iAudioBufferArray.Append(sendPacketArray));
       
   238 		}
       
   239 	}
       
   240 
       
   241 	
       
   242 CAudioBufferArray::~CAudioBufferArray()
       
   243 	{
       
   244 	// destroy all the audio buffers now
       
   245 	TUint numberOfAudioBuffers = iAudioBufferArray.Count();
       
   246 	for (TInt i=0; i<numberOfAudioBuffers; i++)
       
   247 		{
       
   248 		CRtpSendPackets* sendPacketArray = iAudioBufferArray[i];
       
   249 		delete sendPacketArray;
       
   250 		}
       
   251 	iAudioBufferArray.Close();
       
   252 	}
       
   253 
       
   254 
       
   255 /**
       
   256 This function is called when the current audio buffer has been filled
       
   257 with audio and is in a state to be sent to the headset
       
   258 The function updates the next audio buffer to fill to the next 
       
   259 available free audio buffer
       
   260 */
       
   261 void CAudioBufferArray::CurrentAudioBufferReadyToSend()
       
   262 	{
       
   263 	iNextAudioBufferToFill++;
       
   264 	if (iNextAudioBufferToFill >= iAudioBufferArray.Count())
       
   265 		{
       
   266 		iNextAudioBufferToFill = 0;
       
   267 		}
       
   268 	iNumberOfReadyAudioBuffers++;
       
   269 	__ASSERT_DEBUG((iNumberOfReadyAudioBuffers<=iAudioBufferArray.Count()),Panic(EAudioBufferArrayMiscount));
       
   270 	}
       
   271 
       
   272 
       
   273 /**
       
   274 This function cancels the most recently filled audio buffer that is ready to send
       
   275 The audio buffer corresponds to the audio buffer sent in the last CActiveRTPStreamer::Send()
       
   276 This is used in order to cancel a Send request.
       
   277 It effectively undoes the operation performed in CurrentAudioBufferReadyToSend()
       
   278 so CurrentAudioBufferReadyToSend() must have been called at least once prior.
       
   279 
       
   280 @param aSendInProgress set to ETrue if an audio buffer is currently being
       
   281 sent
       
   282 */
       
   283 void CAudioBufferArray::CancelMostRecentAudioBuffer(TBool aSendInProgress)
       
   284 	{
       
   285 	__ASSERT_DEBUG((iNumberOfReadyAudioBuffers),Panic(EAudioBufferArrayMiscount));
       
   286 	if ((iNumberOfReadyAudioBuffers == 1) && (aSendInProgress))
       
   287 		{//then we only have one ready buffer , which is being sent
       
   288 		//so we want to stop any further sending of the current buffer
       
   289 		__ASSERT_DEBUG((iAudioBufferBeingSent == iNextAudioBufferToFill),Panic(EAudioBufferArrayMiscount));
       
   290 		//now we need prevent any further send packets in the current audio buffer being sent
       
   291 		//the following line of code will force us to move onto the next audio 
       
   292 		//buffer discarding any RTP packets in the current audio buffer
       
   293 		//see CurrentSendPacketSent()
       
   294 		iNextRtpPacketToSend = iNumberOfRtpPacketsPerAudioBuffer-1;
       
   295 		}
       
   296 	else if (iNumberOfReadyAudioBuffers)
       
   297 		{
       
   298 		if (!iNextAudioBufferToFill)
       
   299 			{
       
   300 			iNextAudioBufferToFill = iAudioBufferArray.Count();
       
   301 			}
       
   302 		else
       
   303 			{
       
   304 			iNextAudioBufferToFill--;
       
   305 			}
       
   306 		iNumberOfReadyAudioBuffers--;
       
   307 		}	
       
   308 	}
       
   309 	
       
   310 
       
   311 /**
       
   312 This function flushes the pending send packets that are ready to send.
       
   313 Only the current send packet is valid
       
   314 */
       
   315 void CAudioBufferArray::FlushPendingPackets()	
       
   316 	{
       
   317 	//check that we actually have some audio buffers to flush
       
   318 	if (iNumberOfReadyAudioBuffers > 1)
       
   319 		{
       
   320 		if (iAudioBufferBeingSent >= iAudioBufferArray.Count())
       
   321 			{
       
   322 			iNextAudioBufferToFill = 0;
       
   323 			}
       
   324 		else
       
   325 			{
       
   326 			iNextAudioBufferToFill = iAudioBufferBeingSent+1;
       
   327 			}
       
   328 		iNumberOfReadyAudioBuffers = 1; //the current send packet
       
   329 		}
       
   330 	else if (iNumberOfReadyAudioBuffers == 1)
       
   331 		{
       
   332 		//now we need to flush out the send packets in the current audio buffer being sent
       
   333 		//the following line of code will force us to move onto the next audio 
       
   334 		//buffer discarding any RTP packets in the current audio buffer
       
   335 		//see CurrentSendPacketSent()
       
   336 		iNextRtpPacketToSend = iNumberOfRtpPacketsPerAudioBuffer-1;
       
   337 		}
       
   338 	}
       
   339 
       
   340 	
       
   341 /*
       
   342 This function returns the current RTP packet to be sent to the headet
       
   343 if there are no packets that are ready to be sent
       
   344 ie iNumberOfReadyPackets = 0 then the RRtpSendPacket
       
   345 will be invalid.
       
   346 CurrentSendPacketSent() needs to be called when a send packet has been
       
   347 acknowledged as being sent by the RTP stack
       
   348 */	
       
   349 RRtpSendPacket& CAudioBufferArray::CurrentSendPacket()
       
   350 	{
       
   351 	CRtpSendPackets* currentSendAudioBuffer = iAudioBufferArray[iAudioBufferBeingSent];
       
   352 	return currentSendAudioBuffer->Packet(iNextRtpPacketToSend);
       
   353 	}	
       
   354 
       
   355 
       
   356 /*
       
   357 This function is called when the RTP module has made the callback indicating that the 
       
   358 current send packet has been sent.
       
   359 The function updates the current send packet to the next packet to be sent
       
   360 
       
   361 @param aEntireAudioBufferSent this is set to true if the 
       
   362 current entire audio buffer has been sent.  The RTPStreamer uses
       
   363 this information to determine whether to complete the send request status
       
   364 */	
       
   365 void CAudioBufferArray::CurrentSendPacketSent(TBool& aEntireAudioBufferSent)
       
   366 	{
       
   367 	aEntireAudioBufferSent = EFalse;
       
   368 	if (iNumberOfReadyAudioBuffers)//this could be 0 if the current packet sent was sent and subsequently cancelled
       
   369 		{
       
   370 		iNextRtpPacketToSend++;
       
   371 		if (iNextRtpPacketToSend >= iNumberOfRtpPacketsPerAudioBuffer)
       
   372 			{//then we have sent all the RTP packets in the current audio buffer
       
   373 			iNextRtpPacketToSend = 0;
       
   374 			iAudioBufferBeingSent++; //we've finished with this audio buffer so move onto the next one
       
   375 			//do something to show we are finished with audio buffer and complete request status
       
   376 			if (iAudioBufferBeingSent >= iAudioBufferArray.Count())
       
   377 				{
       
   378 				iAudioBufferBeingSent = 0;
       
   379 				}
       
   380 			iNumberOfReadyAudioBuffers--;
       
   381 			aEntireAudioBufferSent = ETrue;	
       
   382 			}		
       
   383 		}
       
   384 	//else if iNumberOfReadyAudioBuffers = 0 then the packet must have been canceled so do nothing
       
   385 	__ASSERT_DEBUG((iNumberOfReadyAudioBuffers<=iAudioBufferArray.Count()),Panic(EAudioBufferArrayMiscount));//check underflow
       
   386 	}
       
   387 	
       
   388 
       
   389 
       
   390 
       
   391 
       
   392 
       
   393 
       
   394 	
       
   395 
       
   396 
       
   397 
       
   398 
       
   399 
       
   400 
       
   401 	
       
   402