Update contrib.
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".
8 // Initial Contributors:
9 // Nokia Corporation - initial contribution.
16 #include <bluetoothav.h>
17 #include <mmf/server/mmfcodec.h>
18 #include "mmfSBCCodecImplementationUIDs.hrh"
20 #include "A2dpCodecUtilities.h"
21 #include "AudioBufferArray.h"
22 #include "RTPStreamer.h"
28 enum TRTPStreamerPanic
30 ERTPStreamerSendPacketMiscount, //0
31 ERTPStreamerSendNotCompleted, //1
32 ERTPStreamerEmptyBuffer, //2
33 ERTPStreamerRTPEventError, //3
34 ERTPStreamerIncompleteSBCFrame, //4
35 ERTPStreamerUnexpectedEvent, //5
36 ERTPStreamerBufferProcessingLengthMismatch, //6
37 ERTPStreamerInvalidDataType, //7
38 ERTPStreamerNoConfiguration //8
42 static void Panic(TRTPStreamerPanic aPanic)
45 _LIT(KRTPStreamerPanicName, "RTP Streamer");
46 User::Panic(KRTPStreamerPanicName, aPanic);
52 Creates CActiveRTPStreamer
54 @param aSock RSocket that can be used to stream audio to the headset
55 @param aRTPStreamObserver mixin used to inform the CA2dpBTHeadsetAudioInterface
56 of asynchronous error events
57 @return CActiveRTPStreamer*
59 CActiveRTPStreamer* CActiveRTPStreamer::NewL(RSocket& aSock, MRTPStreamerObserver& aRTPStreamerObserver)
61 CActiveRTPStreamer* self = new (ELeave) CActiveRTPStreamer (aRTPStreamerObserver);
62 CleanupStack::PushL(self);
63 self->ConstructL(aSock);
64 CleanupStack::Pop(self);
70 Make priortiy high so other RunLs don't impact CTimer accuracy too much
72 CActiveRTPStreamer::CActiveRTPStreamer(MRTPStreamerObserver& aRTPStreamerObserver) : CTimer(EPriorityHigh), iRTPStreamerObserver(aRTPStreamerObserver), iRtpCanSend(ETrue)
74 CActiveScheduler::Add(this);
78 CActiveRTPStreamer::~CActiveRTPStreamer()
81 delete iAudioBufferArray;
83 //RTP defect fix DEF57144- RRtpSendSource Cancel()
84 //If the line of code below does not compile then your build is too old
85 iRTPSendSource.Cancel();
87 iRTPSendSource.Close();
92 void CActiveRTPStreamer::ConstructL(RSocket& aSock)
95 // get the MTU length limit
97 User::LeaveIfError(aSock.GetOpt(EAvdtpMediaGetMaximumPacketSize, KSolBtAVDTPMedia, mtu));
98 iMaxMTULength = mtu;//the line above wont accept iMaxMTULength directly because it is unsigned
99 iRTPSession.OpenL(aSock, iMaxMTULength);
100 iRTPSendSource = iRTPSession.NewSendSourceL();
102 //register callbacks - all terminal callbacks are one shot
103 iRTPSession.RegisterEventCallbackL(ERtpAnyEvent,RTPCallback,this);
104 iRTPSession.RegisterEventCallbackL(ERtpSessionFail,RTPCallback,this, ERtpOneShot);
105 iRTPSession.RegisterEventCallbackL(ERtpBufferOverflow,RTPCallback,this);
106 iRTPSession.RegisterEventCallbackL(ERtpUndersizedPacket,RTPCallback,this);
107 iRTPSendSource.RegisterEventCallbackL(ERtpAnyEvent,RTPSendSourceCallback,this);
108 iRTPSendSource.RegisterEventCallbackL(ERtpSendFail,RTPSendSourceCallback,this, ERtpOneShot);
113 Function called by the CA2dpBTHeadsetAudioInterface to set the codec and the codec
114 settings used by the CActiveRTPStreamer.
115 Calling this function forces a recalculation of all the timings the next
116 time Send() is called
118 @param aCodec the codec to be used. If this is set to NULL then no codec is used
119 only the CSBCCodec can be used here
120 @param aConfigType a Uid to identify the aConfigData used to configure the settings
121 only KMmfUidSBCConfigure is currently defined. In future other types may be defined
122 for mp3, AAC and ATRAC3
123 @param aConfigData The configuration data
124 @return standard SymbianOS error code
126 void CActiveRTPStreamer::SetCodec(CMMFCodec& aCodec)
128 //if there is a codec then it must be SBC else codec must be on the headset
133 void CActiveRTPStreamer::SetAudioConfiguration(const CA2dpAudioCodecConfiguration& aAudioCodecConfiguration)
135 iA2dpAudioCodecConfiguration = const_cast<CA2dpAudioCodecConfiguration*>(&aAudioCodecConfiguration);
136 //if there is a new codec configuration then cannot assume the buffer
137 //length will be the same so reset
139 iBufferParamsInitialized = EFalse;//will result in a call to InitializeForSendL
140 iTimeStampIncrement = 0;
141 iNumberOfInputBytesToMakeRTPPacket = 0;
145 Internal function to perform frame size related initialization
146 ie creation and setting of the RTPSendPacket audio buffer array.
147 Assumes all buffers are the same size (except for the last buffer)
149 @param The length of the audio buffer sent in Send()
151 void CActiveRTPStreamer::InitializeForSendL(const TDesC8& aData)
153 iSendBufferSize = aData.Size(); //store buffer length - this shouldn't change till the last buffer
154 __ASSERT_DEBUG(iSendBufferSize,Panic(ERTPStreamerEmptyBuffer));
155 __ASSERT_DEBUG(iA2dpAudioCodecConfiguration,Panic(ERTPStreamerNoConfiguration));
156 TUint encodedBufferSize = iSendBufferSize;
160 iCodec->ResetL(); //clear out any cached data from previous settings
161 //if we are using a local codec - ie SBC then we get the frame length
162 //and bit rate from the local codec settings
163 //since aData will contain pcm16
164 iFrameLength = iA2dpAudioCodecConfiguration->LocalSBCCodecConfiguration().CalcFrameLength();
165 iBitRate = iA2dpAudioCodecConfiguration->LocalSBCCodecConfiguration().CalcBitRate(iFrameLength)*1000;//*1000 as bitrate is in KHz
166 //if we are putting data through the local SBC codec then
167 //the encoded buffer size sent to the headset in not the same as the aData buffer in Send()
168 encodedBufferSize = iA2dpAudioCodecConfiguration->CalculateSBCBufferLength(iSendBufferSize);
172 //if we don't use a local codec then we get the frame legth and bit rate
173 //direct from the header
174 CA2dpCodecFrameHeaderParser* headerParser = CA2dpCodecFrameHeaderParser::NewL(iA2dpAudioCodecConfiguration->HeadsetCodecDataType(), aData);
175 iFrameLength = headerParser->FrameLength();
176 iBitRate = headerParser->BitRate();
179 iPayloadType = TRTPa2dpCodecSpecificUtils::PayloadType(iA2dpAudioCodecConfiguration->HeadsetCodecDataType());
181 //if the settings have changed then any existing buffered audio buffers
182 // will have the old settings so we need to delete the buffer array
183 //and recreate from new with the new settings.
184 //we also need to cancel in case we are waiting on a RTPSendSourceCallback
185 //from a previous send packet
186 //RTP defect fix DEF57144- RRtpSendSource Cancel() not in MCL
187 //decomment this out when the Cancel method is on the MCL
188 //iRTPSendSource.Cancel();
190 delete iAudioBufferArray;
191 iAudioBufferArray = NULL;
192 //calculate the size of the RTP header
193 TUint mediaPayloadHeaderLength = TRTPa2dpCodecSpecificUtils::MediaPayloadHeaderLength(iA2dpAudioCodecConfiguration->HeadsetCodecDataType());
194 TUint rtpHeaderLength = KRTPHeaderSize + mediaPayloadHeaderLength;
195 iAudioBufferArray = CAudioBufferArray::NewL(iRTPSendSource, KSendBucketSize, encodedBufferSize, iMaxMTULength, rtpHeaderLength, iFrameLength);
197 //determine the payload header
198 switch(const_cast<TFourCC&>(iA2dpAudioCodecConfiguration->HeadsetCodecDataType()).FourCC())
200 case KMMFFourCCCodeSBC:
201 iMediaPayloadHeader.Append(iAudioBufferArray->NumberOfFramesPerRtpPacket());
203 case KMMFFourCCCodeMP3:
204 //RFC2250-section 3.5 MBZ+Frag_Offset
205 //= 4 bytes all set to 0
206 iMediaPayloadHeader.FillZ(4); //0000
208 case KMMFFourCCCodeAAC:
210 case KMMFFourCCCodeATRAC3:
213 //the datatype is a non A2DP datatype
214 //which is not supported so panic
215 Panic(ERTPStreamerInvalidDataType);
219 //get the number of bytes of data sent that was sent to the RTP streamer
220 //that make up one RTP packet
221 //in the case of a codec this is the value pre codec processing
224 iNumberOfInputBytesToMakeRTPPacket = iSendBufferSize/iAudioBufferArray->NumberOfRtpPacketsPerAudioBuffer();
225 if (iNumberOfInputBytesToMakeRTPPacket%2)
226 {//we have an odd number of bytes
227 iNumberOfInputBytesToMakeRTPPacket++;//round up to next byte
232 iNumberOfInputBytesToMakeRTPPacket = iAudioBufferArray->InputBytesPerRTPPacket();
234 //else other codecs not supported
236 //we set the iFrameDuration which is used to trigger the timer
237 //this means that RunL should be called every iFrameDuration and
238 //if an RTP packet is ready to sent then it shall be sent
239 //since there is no control channel back from the headset, the best
240 //we can hope for is to send the data at approx the rate the headset
241 //would expect it and hope that the headset provides it's own approriate
243 //Note that dues to other AOs running the timing is not accurate and
244 //usually slower than the specified time - what is really needed
245 //here is a feedback loop where the initial time interval is somewhat
246 //faster than the calculated time interval and is adjusted against the
247 //system clock and bit rate throughput acordingly so the throughput always
248 //matches the bit rate.
249 iRTPPacketDuration = TTimeIntervalMicroSeconds32(TFrameTimingUtils::FrameDuration(iFrameLength,iBitRate).Int() * iAudioBufferArray->NumberOfFramesPerRtpPacket());
250 RDebug::Printf("RTP Packet Duration = %d mS", iRTPPacketDuration.Int());
251 TInt fastCounterFrequency;
252 HAL::Get(HALData::EFastCounterFrequency,fastCounterFrequency);
253 RDebug::Printf("sys clock timing frequency = %d Hz", fastCounterFrequency);
254 iTimeStampIncrement = TFrameTimingUtils::TimeStampIncrementPerFrame(iA2dpAudioCodecConfiguration->HeadsetCodecDataType(), iFrameLength, iBitRate, iA2dpAudioCodecConfiguration->SampleRate())
255 * iAudioBufferArray->NumberOfFramesPerRtpPacket();
256 RDebug::Printf("Calculated RTP packet time stamp increment = %d",iTimeStampIncrement);
257 RDebug::Printf("FrameLength = %d", iFrameLength);
258 RDebug::Printf("Calculated bitRate = %d", iBitRate);
259 RDebug::Printf("Number of frames per RTP packet = %d", iAudioBufferArray->NumberOfFramesPerRtpPacket());
260 RDebug::Printf("Number of RTP packets per audio buffer = %d", iAudioBufferArray->NumberOfRtpPacketsPerAudioBuffer());
261 RDebug::Printf("Sample rate = %d", iA2dpAudioCodecConfiguration->SampleRate());
266 Internal function to pass the pcm16 audio data in aData and use the codec
267 to process the data back in aPayload
269 @return the number of source bytes processed
271 TUint CActiveRTPStreamer::CodecProcessPayloadL(const TDesC8& aData,TDes8& aPayload)
273 TPtr8 srcBufferPtr(const_cast<TUint8*>(aData.Ptr()),aData.Length());
274 srcBufferPtr.SetLength(aData.Length());
275 //+1 -1 to skip SBC media payload header
276 TPtr8 dstBufferPtr(const_cast<TUint8*>(aPayload.Ptr()+1),aPayload.MaxLength()-1);
277 CMMFPtrBuffer* srcBuffer = CMMFPtrBuffer::NewL(srcBufferPtr);
278 CleanupStack::PushL(srcBuffer);
279 CMMFPtrBuffer* dstBuffer = CMMFPtrBuffer::NewL(dstBufferPtr);
280 CleanupStack::PushL(dstBuffer);
281 TCodecProcessResult result = iCodec->ProcessL(*srcBuffer,*dstBuffer);
282 if (result == TCodecProcessResult::EProcessIncomplete)
284 User::Leave(KErrArgument);
286 aPayload.Append(dstBuffer->Data());
287 CleanupStack::PopAndDestroy(dstBuffer);
288 CleanupStack::PopAndDestroy(srcBuffer);
289 return result.iSrcBytesProcessed;
294 This is the main function for CActiveRTPStreamer in that it is the
295 function used to send data to the headset over RTP.
296 The function is asynchronous to the RunL which does the actual sending.
297 The data is stored in the CRtpSendPackets FIFO and will be sent at the
298 next RunL provided the RTP can accept the data. If not it just stays
299 buffered in the CRtpSendPackets FIFO until it can be sent.
300 The request status is completed when the buffer is stored, not when it is sent
301 this is to more closely mimic the behaviour of the sound driver.
302 If adding the buffer to the CRtpSendPackets FIFO causes it to be full
303 then the request status won't be completed until there is space in the FIFO
304 which won't be until a callback from the RTP stack has been received
305 indicating that the CRtpSendPackets FIFO can now discard that entry.
306 Only one Send at a time is accepted ie the request status
307 of the previous send must be completed before Send can be called again.
308 To simplify the software and improve performance, fixed sized buffers are assumed.ie
309 the buffer length is only calculated once on the first frame and when the settings
312 @param aData The data to be sent to the headset. This may go via
313 a codec eg if the data is pcm16 or sent directly to the headset if the data is SBC,mp3,AAC,ATRAC3
314 It is the responsibility of the client ie CA2dpBTHeadsetAudioInterface to
315 call SetCodecConfiguration first.
319 void CActiveRTPStreamer::Send(const TDesC8& aData, TRequestStatus& aStatus)
323 __ASSERT_DEBUG((*iSendStatus != KRequestPending),Panic(ERTPStreamerSendNotCompleted));
325 iSendStatus = &aStatus;
326 *iSendStatus = KRequestPending;
328 if (iUnrecoverableError)
330 User::RequestComplete(iSendStatus,iUnrecoverableError);
334 if (!iBufferParamsInitialized)
336 TRAPD(err,InitializeForSendL(aData));
339 User::RequestComplete(iSendStatus,err);
342 iBufferParamsInitialized = ETrue;
345 TUint numberOfRtpPacketsPerAudioBuffer = iAudioBufferArray->NumberOfRtpPacketsPerAudioBuffer();
347 if (aData.Size() != iSendBufferSize)
349 //then we are on the last buffer
350 //in which case we need to recalculate the number of Rtp packets
351 //required to make up the audio frame since the last buffer
353 TUint lastBufferLength = aData.Size();
356 lastBufferLength = iA2dpAudioCodecConfiguration->CalculateSBCBufferLength(aData.Size());
358 //we keep the same number of RTP packets per audio buffer as before
359 TUint numberOfSBCFramesInLastBuffer = lastBufferLength/iFrameLength;
360 TUint numberOfFramesPerRtpPacket = iAudioBufferArray->NumberOfFramesPerRtpPacket();
362 //the devisor below may not always devide without a remainder
363 //which means the last Rtp packet sent will not be full
364 //if we have a remainder then we need another Rtp packet
365 numberOfRtpPacketsPerAudioBuffer = numberOfSBCFramesInLastBuffer/numberOfFramesPerRtpPacket;
366 if (numberOfSBCFramesInLastBuffer%numberOfFramesPerRtpPacket)
368 numberOfRtpPacketsPerAudioBuffer++;
373 CRtpSendPackets* sendPackets = iAudioBufferArray->CurrentAudioBufferRtpSendPackets();
374 TUint srcBytesProcessed = 0;
375 for (TUint i=0; i<numberOfRtpPacketsPerAudioBuffer;i++)
377 RDebug::Printf("NewRTPPacketReceived %d",User::FastCounter());
378 RRtpSendPacket& sendPacket = sendPackets->Packet(i);
379 sendPacket.SetPayloadType(iPayloadType);
380 sendPacket.SetTimestamp(iTimeStamp);
381 iTimeStamp += iTimeStampIncrement;
382 TDes8& payload = sendPacket.WritePayload();
384 payload.Append(iMediaPayloadHeader);
386 //aData may have to be sent as multiple packets
387 TUint8* sourceDataOffset = const_cast<TUint8*>(aData.Ptr())+srcBytesProcessed;
388 TPtr8 srcBufferPtr(sourceDataOffset,iNumberOfInputBytesToMakeRTPPacket);
389 TUint srcBytesStillRemaining = aData.Size() - srcBytesProcessed;
390 TUint lengthOfsrcBuffer = iNumberOfInputBytesToMakeRTPPacket;
391 if (srcBytesStillRemaining < lengthOfsrcBuffer )
392 {//probably a last buffer condition or modulo 2 pcm16 rounding condition
393 lengthOfsrcBuffer = srcBytesStillRemaining;
395 srcBufferPtr.SetLength(lengthOfsrcBuffer);
397 //sanity check - the following should always be true
398 __ASSERT_DEBUG((srcBytesProcessed == iNumberOfInputBytesToMakeRTPPacket*i),Panic(ERTPStreamerBufferProcessingLengthMismatch));
402 TRAPD(err,srcBytesProcessed += CodecProcessPayloadL(srcBufferPtr,payload));
405 //something has gone wrong so abort streaming
406 User::RequestComplete(iSendStatus,err);
410 else //no need to process via codec - aData can go straight to the headset
412 srcBytesProcessed +=lengthOfsrcBuffer;
413 payload.Append(srcBufferPtr);
415 }// for (TUint i=0; i<iAudioBufferArray->NumberOfRtpPacketsPerAudioBuffer();i++)
416 iAudioBufferArray->CurrentAudioBufferReadyToSend();
417 //else we have no more send packets so cannot complete request status
418 //until one of the send packets has been sent and acknowledged.
421 //we'll send an event to ourselves and either send the packet if we can
422 //we could complete the iSendStatus TRequestStatus here before returing
423 //from the Send but we won't in order to more closely mimic the existing
424 // sound driver PlayData behaviour
425 //if there is already a request active then it will be the timer
426 //ie this will effectively kick things off if the timer is not running
427 TRequestStatus* stat = &iStatus;
430 User::RequestComplete(stat, KErrNone);
437 Function to stop further internally buffered packets being sent to the headset
439 void CActiveRTPStreamer::Pause()
447 Function called after pause to resume sending buffers to the headset
449 void CActiveRTPStreamer::Resume()
454 TRequestStatus* stat = &iStatus;
457 User::RequestComplete(stat, KErrNone);
465 Function called from CA2dpBTHeadsetAudioInterface::CancelPlayData()
466 Used to cancel an outstanding status request for a Send()
468 void CActiveRTPStreamer::CancelLastSendBuffer()
472 if (*iSendStatus == KRequestPending)//make sure there is a pending request to cancel
474 iAudioBufferArray->CancelMostRecentAudioBuffer(!iRtpCanSend);
475 User::RequestComplete(iSendStatus, KErrCancel);
482 Function to flush out the bufferes stored in CRtpSenPackets
484 void CActiveRTPStreamer::FlushPendingSendBuffers()
486 iAudioBufferArray->FlushPendingPackets();
489 {//flush out codec cache
490 TRAP_IGNORE(iCodec->ResetL());
496 Function to return total number of bytes sent prior to codec processing
497 ie bytes of pcm16 not SBC
498 Note this the number of bytes sent is only updated when the packet
499 has been acknowledged as being sent correctly by the RTP stack
500 ie this value will always be slightly less than the bytes sent in Send()
502 TUint CActiveRTPStreamer::BytesSent() const
509 Function to reset the number of bytes sent
511 void CActiveRTPStreamer::ResetBytesSent()
518 The RunL is called every frame duration interval.
519 It checks to see if there are any packets to be sent to the headset
521 One issue to be resolved at integration testing is if there are no packets
522 to send then this is analogous to a KErrUnderflow condition on the
523 sound driver. Do we need to mimic this behaviour for the a2dp interface?
525 The Send request status is completed if there is room in the CRtpSendPackets
528 void CActiveRTPStreamer::RunL()
530 if ((iPaused)||(!iAudioBufferArray))
535 if(iRtpCanSend && iAudioBufferArray->NumberOfAudioBuffersReadyToSend())
537 RRtpSendPacket& sendPacket = iAudioBufferArray->CurrentSendPacket();
539 iRtpCanSend = EFalse; //have to wait for callback before we can send again
544 if ((iAudioBufferArray->NumberOfAudioBuffersReadyToSend() < KSendBucketSize)
545 &&(*iSendStatus == KRequestPending))
546 {//still some free packets to fill so complete request status
547 User::RequestComplete(iSendStatus, KErrNone);
550 //else if the iRtpSendPackets FIFO is full then we can't complete
551 //the request status until we've had an ERtpSendSucceeded event
553 //are there any more buffers that are ready to send?
554 //if so then send the next packet after a time delay
555 //keep calling this RunL every frame duration till as long as we have packets to send
556 //if there are no packets ready to send then we need to wait
557 //for another call to Send();
558 if (iAudioBufferArray->NumberOfAudioBuffersReadyToSend())
559 {//there are packets ready to send so fire off next RunL after one RTP packet duration
560 RDebug::Printf("RTPPacket Sent %d",User::FastCounter());
561 After(iRTPPacketDuration);
569 void CActiveRTPStreamer::DoCancel()
572 CompleteSendRequestStatus(KErrCancel);
577 Utility function to complete Send TRequestStatus with aError
579 void CActiveRTPStreamer::CompleteSendRequestStatus(TInt aError)
583 if (*iSendStatus == KRequestPending)
585 User::RequestComplete(iSendStatus, aError);
592 Called by RTP stack when a packet has been sent
593 If the packet was sent ok then complete the iSendStatus if it is pending
594 and update the number of bytes sent
595 If the packet was not sent ok then the error is regarded as unrecoverable
596 since this should not happen. If it does happen then the CA2dpBTHeadsetAudioInterface
597 is informed. If there is an outstanding Send TRequestStatus then this is
598 completed with KErrCommsFrame. Not sure if this is the most appropriate error code?
600 void CActiveRTPStreamer::PacketSent(TRtpEventType aEvent)
602 if (aEvent == ERtpSendSucceeded)
604 RDebug::Printf("Sent RTPPacket Acknowledged %d",User::FastCounter());
605 TBool entireAudioBufferSent = EFalse;
606 iAudioBufferArray->CurrentSendPacketSent(entireAudioBufferSent);
607 //check if there is an outstanding send request status
608 //we can only complete the send request status if all the
609 //RTP packets in the audio buffer have been sent.
610 if (entireAudioBufferSent)
612 CompleteSendRequestStatus(KErrNone);
615 iBytesSent += iNumberOfInputBytesToMakeRTPPacket;
617 else if (aEvent == ERtpSendFail)
619 //if we fail to send the packet then chances are something
620 //has gone wrong that may not be recoverable
621 //so we will complete the request status and halt further streaming
622 //some testing may be required to see if it is possible to
623 //recover in which case the packet could be sent again
624 iUnrecoverableError = KErrCommsFrame;//probably the nearest error code
625 CompleteSendRequestStatus(iUnrecoverableError);
626 //inform iRTPStreamerObserver ie the CA2dpBTHeadsetAudioInterface
627 //this will initiate a GAVDP state machine reset which will destroy the CActiveRTPStreamer
628 iRTPStreamerObserver.RTPStreamerEvent(iUnrecoverableError);
631 {//we've not registered for any other events so this shouldn't happen
632 Panic(ERTPStreamerUnexpectedEvent);
638 Called by RTP stack when some sort of general error has occured
639 eg switching off the headset, or the headset going out of range
640 The CA2dpBTHeadsetAudioInterface is informed.
642 void CActiveRTPStreamer::RTPSessionEvent(const TRtpEvent& aEvent)
644 switch(aEvent.Type())
646 case ERtpSessionFail:
647 iUnrecoverableError = KErrDisconnected;
649 case ERtpBufferOverflow:
650 iUnrecoverableError = KErrOverflow;
652 case ERtpUndersizedPacket:
653 iUnrecoverableError = KErrCommsFrame;
656 Panic(ERTPStreamerRTPEventError); //we haven't registered for anything else
660 //complete outstanding Send (CA2dpBTHeadsetAudioInterface::PlayData) request status
661 CompleteSendRequestStatus(iUnrecoverableError);
662 //inform CA2dpBTHeadsetAudioInterface
663 iRTPStreamerObserver.RTPStreamerEvent(iUnrecoverableError);
668 Static callback from RTP stack
670 void CActiveRTPStreamer::RTPSendSourceCallback(CActiveRTPStreamer* aStreamer, const TRtpEvent& aEvent)
672 __ASSERT_DEBUG((aEvent.IsSendSourceEvent()),Panic(ERTPStreamerRTPEventError));
673 __ASSERT_DEBUG((aEvent.SendSource() == aStreamer->iRTPSendSource),Panic(ERTPStreamerRTPEventError));
674 // for now assume it was sending complete
676 aStreamer->PacketSent(aEvent.Type());
681 Static callback from RTP stack
683 void CActiveRTPStreamer::RTPCallback(CActiveRTPStreamer* aStreamer, const TRtpEvent& aEvent)
685 __ASSERT_DEBUG((aEvent.IsSessionEvent()),Panic(ERTPStreamerRTPEventError));
686 __ASSERT_DEBUG((aEvent.Session() == aStreamer->iRTPSession),Panic(ERTPStreamerRTPEventError));
688 aStreamer->RTPSessionEvent(aEvent);