1 /* |
1 /* |
2 * Copyright (c) 2008 Nokia Corporation and/or its subsidiary(-ies). |
2 * Copyright (c) 2008 Nokia Corporation and/or its subsidiary(-ies). |
3 * All rights reserved. |
3 * All rights reserved. |
4 * This component and the accompanying materials are made available |
4 * This component and the accompanying materials are made available |
5 * under the terms of "Eclipse Public License v1.0" |
5 * under the terms of "Eclipse Public License v1.0" |
6 * which accompanies this distribution, and is available |
6 * which accompanies this distribution, and is available |
7 * at the URL "http://www.eclipse.org/legal/epl-v10.html". |
7 * at the URL "http://www.eclipse.org/legal/epl-v10.html". |
8 * |
8 * |
9 * Initial Contributors: |
9 * Initial Contributors: |
10 * Nokia Corporation - initial contribution. |
10 * Nokia Corporation - initial contribution. |
11 * |
11 * |
12 * Contributors: |
12 * Contributors: |
13 * |
13 * |
14 * Description: Implementation of Mcc Jitterbuffer |
14 * Description: Implementation of Mcc Jitterbuffer |
15 * |
15 * |
16 */ |
16 */ |
17 |
|
18 |
17 |
19 // INCLUDE FILES |
18 // INCLUDE FILES |
20 #include <e32base.h> |
19 #include <e32base.h> |
21 #include <mmcccodecinformation.h> //codec FourCC declarations |
20 #include <mmcccodecinformation.h> //codec FourCC declarations |
22 #include "debugtracemacros.h" |
21 #include "debugtracemacros.h" |
23 #include "CngGenerator.h" |
22 #include "CngGenerator.h" |
24 #include "InternalDef.h" |
23 #include "InternalDef.h" |
25 #include "JitterBufferObserver.h" |
24 #include "JitterBufferObserver.h" |
26 #include "JitterBufferImpl.h" |
25 #include "JitterBufferImpl.h" |
27 |
26 |
28 |
|
29 // ----------------------------------------------------------------------------- |
27 // ----------------------------------------------------------------------------- |
30 // TJitterBufferElement::CompareSeqNum |
28 // TJitterBufferElement::CompareSeqNum |
31 // Compare SequenceNumber |
29 // Compare SequenceNumber |
32 // ----------------------------------------------------------------------------- |
30 // ----------------------------------------------------------------------------- |
33 // |
31 // |
34 TInt TJitterBufferElement::CompareSeqNum(const TJitterBufferElement& aElem1, |
32 TInt TJitterBufferElement::CompareSeqNum(const TJitterBufferElement& aElem1, |
35 const TJitterBufferElement& aElem2) |
33 const TJitterBufferElement& aElem2) |
36 { |
34 { |
37 if (aElem1.iSequenceNumber > aElem2.iSequenceNumber) |
35 if (aElem1.iSequenceNumber > aElem2.iSequenceNumber) |
38 { |
36 { |
39 return (-1); |
37 return (-1); |
40 } |
38 } |
74 // CVoIPJitterBufferImpl::CVoIPJitterBufferImpl |
72 // CVoIPJitterBufferImpl::CVoIPJitterBufferImpl |
75 // C++ default constructor can NOT contain any code, that might leave. |
73 // C++ default constructor can NOT contain any code, that might leave. |
76 // ----------------------------------------------------------------------------- |
74 // ----------------------------------------------------------------------------- |
77 // |
75 // |
78 CVoIPJitterBufferImpl::CVoIPJitterBufferImpl(MJitterBufferObserver* aObserver) : |
76 CVoIPJitterBufferImpl::CVoIPJitterBufferImpl(MJitterBufferObserver* aObserver) : |
79 iBufStampSorter(TLinearOrder<TJitterBufferElement>( |
77 iBufStampSorter(TLinearOrder<TJitterBufferElement> ( |
80 TJitterBufferElement::CompareStamp)), |
78 TJitterBufferElement::CompareStamp)), |
81 iBufSequenceSorter(TLinearOrder<TJitterBufferElement>( |
79 iBufSequenceSorter(TLinearOrder<TJitterBufferElement> ( |
82 TJitterBufferElement::CompareSeqNum)) |
80 TJitterBufferElement::CompareSeqNum)) |
83 { |
81 { |
84 iObserver = aObserver; |
82 iObserver = aObserver; |
85 iTonePlayTime.UniversalTime(); |
83 iTonePlayTime.UniversalTime(); |
86 iSampleRate = KDefaultSampleRateInkHz; |
84 iSampleRate = KDefaultSampleRateInkHz; |
87 iPlay = EFalse; |
85 iPlay = EFalse; |
92 // CVoIPJitterBufferImpl::NewL |
90 // CVoIPJitterBufferImpl::NewL |
93 // Static constructor. |
91 // Static constructor. |
94 // ----------------------------------------------------------------------------- |
92 // ----------------------------------------------------------------------------- |
95 // |
93 // |
96 CVoIPJitterBufferImpl* CVoIPJitterBufferImpl::NewL( |
94 CVoIPJitterBufferImpl* CVoIPJitterBufferImpl::NewL( |
97 MJitterBufferObserver* aObserver) |
95 MJitterBufferObserver* aObserver) |
98 { |
96 { |
99 CVoIPJitterBufferImpl* self = new(ELeave) CVoIPJitterBufferImpl(aObserver); |
97 CVoIPJitterBufferImpl* self = new (ELeave) CVoIPJitterBufferImpl(aObserver); |
100 CleanupStack::PushL(self); |
98 CleanupStack::PushL(self); |
101 self->ConstructL(); |
99 self->ConstructL(); |
102 CleanupStack::Pop(self); |
100 CleanupStack::Pop(self); |
103 return self; |
101 return self; |
104 } |
102 } |
143 // CVoIPJitterBufferImpl::SetupL |
141 // CVoIPJitterBufferImpl::SetupL |
144 // Setup Jitter buffer |
142 // Setup Jitter buffer |
145 // ----------------------------------------------------------------------------- |
143 // ----------------------------------------------------------------------------- |
146 // |
144 // |
147 void CVoIPJitterBufferImpl::SetupL(const TFourCC aCodec, |
145 void CVoIPJitterBufferImpl::SetupL(const TFourCC aCodec, |
148 const TVoIPJBConfig& aJBConfig) |
146 const TVoIPJBConfig& aJBConfig) |
149 { |
147 { |
150 TRACE_PRN_FN_ENT; |
148 TRACE_PRN_FN_ENT; |
151 |
149 |
152 __ASSERT_ALWAYS(aJBConfig.iJitterLatency, User::Leave(KErrArgument)); |
150 __ASSERT_ALWAYS(aJBConfig.iJitterLatency, User::Leave(KErrArgument)); |
153 __ASSERT_ALWAYS(aJBConfig.iJBBufferLength, User::Leave(KErrArgument)); |
151 __ASSERT_ALWAYS(aJBConfig.iJBBufferLength, User::Leave(KErrArgument)); |
228 |
226 |
229 iBuffer.Reset(); |
227 iBuffer.Reset(); |
230 |
228 |
231 // Calculate needed elements |
229 // Calculate needed elements |
232 iBufferLength = iJBConfig.iJBBufferLength * bufLenMultiplier; |
230 iBufferLength = iJBConfig.iJBBufferLength * bufLenMultiplier; |
233 |
231 |
234 if (iJBConfig.iJBThreshold >= iBufferLength) |
232 if (iJBConfig.iJBThreshold >= iBufferLength) |
235 { |
233 { |
236 // adjust threshold size (no need to leave here) |
234 // adjust threshold size (no need to leave here) |
237 iJBConfig.iJBThreshold = iBufferLength / 2; |
235 iJBConfig.iJBThreshold = iBufferLength / 2; |
238 } |
236 } |
239 |
237 |
240 // If the difference between buffer length and threshold is less than 10 |
238 // If the difference between buffer length and threshold is less than 10 |
241 // increase buffer length, so the differences is 10. This helps handle |
239 // increase buffer length, so the differences is 10. This helps handle |
242 // buffer overflow more easily. |
240 // buffer overflow more easily. |
243 CheckThresholdBufferLength(iBufferLength, iJBConfig.iJBThreshold); |
241 CheckThresholdBufferLength(iBufferLength, iJBConfig.iJBThreshold); |
318 newElement.iDataFrame = buf; |
315 newElement.iDataFrame = buf; |
319 newElement.iSequenceNumber = -1; |
316 newElement.iSequenceNumber = -1; |
320 newElement.iTimeStamp = -1; |
317 newElement.iTimeStamp = -1; |
321 iBuffer.AppendL(newElement); |
318 iBuffer.AppendL(newElement); |
322 CleanupStack::Pop(buf); |
319 CleanupStack::Pop(buf); |
323 |
320 |
324 iBufferLength++; |
321 iBufferLength++; |
325 |
322 |
326 // Insert one NO_DATA frame into the audio stream, so the jitterbuffer has |
323 // Insert one NO_DATA frame into the audio stream, so the jitterbuffer has |
327 // the possibility to grow at least one frame from the current size. If |
324 // the possibility to grow at least one frame from the current size. If |
328 // the current playout threshold is zero, then there is ongoing playback or |
325 // the current playout threshold is zero, then there is ongoing playback or |
435 } |
432 } |
436 |
433 |
437 TRACE_PRN_FN_EXT; |
434 TRACE_PRN_FN_EXT; |
438 } |
435 } |
439 |
436 |
|
437 #ifdef __FEATURE_NOT_SUPPORTED__ |
440 // ----------------------------------------------------------------------------- |
438 // ----------------------------------------------------------------------------- |
441 // CVoIPJitterBufferImpl::CalculateDelay |
439 // CVoIPJitterBufferImpl::CalculateDelay |
442 // Calculates the current jitter buffer playback |
440 // Calculates the current jitter buffer playback |
443 // ----------------------------------------------------------------------------- |
441 // ----------------------------------------------------------------------------- |
444 // |
442 // |
445 TTimeIntervalMicroSeconds32 CVoIPJitterBufferImpl::CalculateDelay() const |
443 TTimeIntervalMicroSeconds32 CVoIPJitterBufferImpl::CalculateDelay() const |
446 { |
444 { |
447 TTimeIntervalMicroSeconds32 delay = |
445 TTimeIntervalMicroSeconds32 delay = iJBConfig.iJitterLatency * |
448 iJBConfig.iJitterLatency * iPacketsInBuffer; |
446 iPacketsInBuffer; |
449 |
447 |
450 // TRACE_PRN_N1(_L("JB-CalculateDelay-> Delay [%d]"), delay); |
448 //TRACE_PRN_N1(_L("JB-CalculateDelay-> Delay [%d]"), delay); |
451 |
449 |
452 return delay; |
450 return delay; |
453 } |
451 } |
|
452 #endif //__FEATURE_NOT_SUPPORTED__ |
454 |
453 |
455 // ----------------------------------------------------------------------------- |
454 // ----------------------------------------------------------------------------- |
456 // CVoIPJitterBufferImpl::AddDataFrame |
455 // CVoIPJitterBufferImpl::AddDataFrame |
457 // Adds audio frame into the jitter buffer |
456 // Adds audio frame into the jitter buffer |
458 // ----------------------------------------------------------------------------- |
457 // ----------------------------------------------------------------------------- |
487 // 3.1 DTX start packet may be lost |
486 // 3.1 DTX start packet may be lost |
488 // 3.2 DTX UPDATE packet may be lost (if used) |
487 // 3.2 DTX UPDATE packet may be lost (if used) |
489 // |
488 // |
490 |
489 |
491 TUint index = FindLargestSeqNum(); |
490 TUint index = FindLargestSeqNum(); |
492 |
491 |
493 if (iLastPlayedSeqNum < KMaxSeqNumber - iSeqNumIncrement) |
492 if (iLastPlayedSeqNum < KMaxSeqNumber - iSeqNumIncrement) |
494 { |
493 { |
495 iIsWrappedAround = IsSeqNumWrappedAround(iLargestSeqNum, |
494 iIsWrappedAround = IsSeqNumWrappedAround(iLargestSeqNum, |
496 iCurrentSeqNum); |
495 iCurrentSeqNum); |
497 } |
496 } |
498 else |
497 else |
499 { |
498 { |
500 // If the last played frame was larger than the current largest |
499 // If the last played frame was larger than the current largest |
501 // in JB we are most likely running in the wrap-around mode. |
500 // in JB we are most likely running in the wrap-around mode. |
502 iIsWrappedAround = IsSeqNumWrappedAround(iLastPlayedSeqNum, |
501 iIsWrappedAround = IsSeqNumWrappedAround(iLastPlayedSeqNum, |
503 iLargestSeqNum); |
502 iLargestSeqNum); |
504 } |
503 } |
505 |
504 |
506 if (iIsWrappedAround) |
505 if (iIsWrappedAround) |
507 { |
506 { |
508 iLastPlayedSeqNum = -1; |
507 iLastPlayedSeqNum = -1; |
511 TRACE_PRN_N1(_L("JB-> [ADD] LARGEST IN [%d]"), TInt32(iLargestSeqNum)); |
510 TRACE_PRN_N1(_L("JB-> [ADD] LARGEST IN [%d]"), TInt32(iLargestSeqNum)); |
512 TRACE_PRN_N1(_L("JB-> [ADD] THIS FRAME [%d]"), TInt32(iCurrentSeqNum)); |
511 TRACE_PRN_N1(_L("JB-> [ADD] THIS FRAME [%d]"), TInt32(iCurrentSeqNum)); |
513 TRACE_PRN_N1(_L("JB-> [ADD] LAST PLAYED [%d]"), TInt32(iLastPlayedSeqNum)); |
512 TRACE_PRN_N1(_L("JB-> [ADD] LAST PLAYED [%d]"), TInt32(iLastPlayedSeqNum)); |
514 TRACE_PRN_N1(_L("JB-> [ADD] PACKETS [%d]"), iPacketsInBuffer); |
513 TRACE_PRN_N1(_L("JB-> [ADD] PACKETS [%d]"), iPacketsInBuffer); |
515 |
514 |
516 iDataBuffer = static_cast<CMMFDataBuffer*>(aDataBuffer); |
515 iDataBuffer = static_cast<CMMFDataBuffer*> (aDataBuffer); |
517 |
516 |
518 if (iCurrentSeqNum > iLastPlayedSeqNum) |
517 if (iCurrentSeqNum > iLastPlayedSeqNum) |
519 { |
518 { |
520 if (IsFull()) |
519 if (IsFull()) |
521 { |
520 { |
610 if (aBuffer == NULL) |
609 if (aBuffer == NULL) |
611 { |
610 { |
612 return KErrNotReady; |
611 return KErrNotReady; |
613 } |
612 } |
614 |
613 |
615 iDataBuffer = static_cast<CMMFDataBuffer*>(aBuffer); |
614 iDataBuffer = static_cast<CMMFDataBuffer*> (aBuffer); |
616 TDes8& playBuffer(iDataBuffer->Data()); |
615 TDes8& playBuffer(iDataBuffer->Data()); |
617 iFramesPlayed++; |
616 iFramesPlayed++; |
618 |
617 |
619 if (IsEmpty()) |
618 if (IsEmpty()) |
620 { |
619 { |
621 // Buffer is empty, so we need to generate CN frames. During DTX period |
620 // Buffer is empty, so we need to generate CN frames. During DTX period |
622 // this is where we'll end up. If we are empty because of DTX period, |
621 // this is where we'll end up. If we are empty because of DTX period, |
623 // the CN generator will do the error concealment. |
622 // the CN generator will do the error concealment. |
624 TRACE_PRN_N(_L("JB-> [GET] BUFFER EMPTY")); |
623 TRACE_PRN_N(_L("JB-> [GET] BUFFER EMPTY")); |
625 |
624 |
626 iCNGenerator->GenerateSidPacket(playBuffer, iDataBuffer->RequestSize()); |
625 iCNGenerator->GenerateSidPacket(playBuffer, |
627 |
626 iDataBuffer->RequestSize()); |
|
627 |
628 // Used for talkburst; when talk-burst is over, reset buffer |
628 // Used for talkburst; when talk-burst is over, reset buffer |
629 // and sequence number |
629 // and sequence number |
630 if (iJBConfig.iJBInactivityTimeOut > 0 && iInactivityTime >= 0) |
630 if (iJBConfig.iJBInactivityTimeOut > 0 && iInactivityTime >= 0) |
631 { |
631 { |
632 // Currently it is only used for AMR codec. |
632 // Currently it is only used for AMR codec. |
633 iInactivityTime += iSampleInterval; |
633 iInactivityTime += iSampleInterval; |
634 |
634 |
635 if (iInactivityTime >= iJBConfig.iJBInactivityTimeOut) |
635 if (iInactivityTime >= iJBConfig.iJBInactivityTimeOut) |
636 { |
636 { |
637 TRACE_PRN_N1(_L("JB-> [GET] Inactivity Time Detected [%d]"), |
637 TRACE_PRN_N1(_L("JB-> [GET] Inactivity Time Detected [%d]"), |
638 iInactivityTime); |
638 iInactivityTime); |
639 iInactivityTime = -1; |
639 iInactivityTime = -1; |
640 ResetBuffer(); |
640 ResetBuffer(); |
641 } |
641 } |
642 } |
642 } |
643 } |
643 } |
647 if (iPacketsInBuffer < iCurrentPlayThreshold) |
647 if (iPacketsInBuffer < iCurrentPlayThreshold) |
648 { |
648 { |
649 // Give comfort noise when we are buffering before playback starts |
649 // Give comfort noise when we are buffering before playback starts |
650 TRACE_PRN_N(_L("JB-> [GET] THRESHOLD NOT REACHED")); |
650 TRACE_PRN_N(_L("JB-> [GET] THRESHOLD NOT REACHED")); |
651 iCNGenerator->GenerateSidPacket(playBuffer, |
651 iCNGenerator->GenerateSidPacket(playBuffer, |
652 iDataBuffer->RequestSize()); |
652 iDataBuffer->RequestSize()); |
653 } |
653 } |
654 else |
654 else |
655 { |
655 { |
656 // Reset threshold, so we can play current talk-spurt till the |
656 // Reset threshold, so we can play current talk-spurt till the |
657 // end without affecting speech quality. This means that we will |
657 // end without affecting speech quality. This means that we will |
658 // play the buffer until it is empty. After that, it is either |
658 // play the buffer until it is empty. After that, it is either |
659 // DTX period or packet loss. |
659 // DTX period or packet loss. |
660 iCurrentPlayThreshold = 0; |
660 iCurrentPlayThreshold = 0; |
661 |
661 |
662 // The actual sequence number which is in the buffer |
662 // The actual sequence number which is in the buffer |
663 // const TInt64 frameToPlay( |
663 //const TInt64 frameToPlay( |
664 // iBuffer[iPacketsInBuffer - 1].iSequenceNumber); |
664 //iBuffer[iPacketsInBuffer - 1].iSequenceNumber); |
665 |
665 |
666 TRACE_PRN_N1(_L("JB-> [GET] FRAME TO PLAY [%d]"), |
666 TRACE_PRN_N1(_L("JB-> [GET] FRAME TO PLAY [%d]"), |
667 TInt32(iBuffer[iPacketsInBuffer - 1].iSequenceNumber)); |
667 TInt32(iBuffer[iPacketsInBuffer - 1].iSequenceNumber)); |
668 TRACE_PRN_N1(_L("JB-> [GET] LAST PLAYED [%d]"), |
668 TRACE_PRN_N1(_L("JB-> [GET] LAST PLAYED [%d]"), |
669 TInt32(iLastPlayedSeqNum)); |
669 TInt32(iLastPlayedSeqNum)); |
670 TRACE_PRN_N1(_L("JB-> [GET] PACKETS [%d]"), iPacketsInBuffer); |
670 TRACE_PRN_N1(_L("JB-> [GET] PACKETS [%d]"), iPacketsInBuffer); |
671 |
671 |
672 // Get next in order frame to play |
672 // Get next in order frame to play |
673 TJitterBufferElement& jbElement = iBuffer[iPacketsInBuffer - 1]; |
673 TJitterBufferElement& jbElement = iBuffer[iPacketsInBuffer - 1]; |
674 |
674 |
675 if (playBuffer.MaxLength() >= jbElement.iDataFrame->Data().Length()) |
675 if (playBuffer.MaxLength() >= |
|
676 jbElement.iDataFrame->Data().Length()) |
676 { |
677 { |
677 playBuffer.Copy(jbElement.iDataFrame->Data()); |
678 playBuffer.Copy(jbElement.iDataFrame->Data()); |
678 } |
679 } |
679 else |
680 else |
680 { |
681 { |
681 TRACE_PRN_N1(_L("JB-> [GET] ERROR: BUFFER TOO SMALL [%d]"), |
682 TRACE_PRN_N1(_L("JB-> [GET] ERROR: BUFFER TOO SMALL [%d]"), |
682 playBuffer.MaxLength()); |
683 playBuffer.MaxLength()); |
683 |
684 |
684 iCNGenerator->GenerateSidPacket(playBuffer, |
685 iCNGenerator->GenerateSidPacket(playBuffer, |
685 iDataBuffer->RequestSize()); |
686 iDataBuffer->RequestSize()); |
686 } |
687 } |
687 |
688 |
688 iLastPlayedSeqNum = jbElement.iSequenceNumber; |
689 iLastPlayedSeqNum = jbElement.iSequenceNumber; |
689 jbElement.iSequenceNumber = -1; |
690 jbElement.iSequenceNumber = -1; |
690 jbElement.iTimeStamp = -1; |
691 jbElement.iTimeStamp = -1; |
691 iPacketsInBuffer--; |
692 iPacketsInBuffer--; |
692 |
693 |
693 // Reset inactivity timeout timer |
694 // Reset inactivity timeout timer |
694 iInactivityTime = 0; |
695 iInactivityTime = 0; |
695 |
696 |
|
697 #ifdef __FEATURE_NOT_SUPPORTED__ |
696 // Try to lead new buffer to DTX period |
698 // Try to lead new buffer to DTX period |
697 iCNGenerator->DoDtxDecision(playBuffer); |
699 iCNGenerator->DoDtxDecision(playBuffer); |
698 } |
700 #endif //__FEATURE_NOT_SUPPORTED__ |
699 } |
701 } |
700 |
702 } |
|
703 |
701 return KErrNone; |
704 return KErrNone; |
702 } |
705 } |
703 |
706 |
704 // ----------------------------------------------------------------------------- |
707 // ----------------------------------------------------------------------------- |
705 // CVoIPJitterBufferImpl::FindLargestSeqNum |
708 // CVoIPJitterBufferImpl::FindLargestSeqNum |
730 // CVoIPJitterBufferImpl::InsertBufferElement |
733 // CVoIPJitterBufferImpl::InsertBufferElement |
731 // Insert Buffer Element |
734 // Insert Buffer Element |
732 // ----------------------------------------------------------------------------- |
735 // ----------------------------------------------------------------------------- |
733 // |
736 // |
734 void CVoIPJitterBufferImpl::InsertBufferElement(const TDesC8& aBuffer, |
737 void CVoIPJitterBufferImpl::InsertBufferElement(const TDesC8& aBuffer, |
735 TInt64 aLargestSeqNum) |
738 TInt64 aLargestSeqNum) |
736 { |
739 { |
737 // TRACE_PRN_FN_ENT; |
740 /* if (aBuffer.Length() == 0 || aBuffer.Length() > iFrameSize) |
738 |
|
739 /* if (aBuffer.Length() == 0 || aBuffer.Length() > iFrameSize) |
|
740 { |
741 { |
741 TRACE_PRN_N(_L("JB->INVALID DATA, IGNORING")); |
742 TRACE_PRN_N(_L("JB->INVALID DATA, IGNORING")); |
742 return; |
743 return; |
743 }*/ |
744 }*/ |
744 |
745 |
745 const TInt len(BufferLength()); |
746 const TInt len(BufferLength()); |
746 |
747 |
747 if (iIsWrappedAround) |
748 if (iIsWrappedAround) |
748 { |
749 { |
749 iBuffer[len-1].iDataFrame->Data().Copy(aBuffer); |
750 iBuffer[len - 1].iDataFrame->Data().Copy(aBuffer); |
750 iBuffer[len-1].iSequenceNumber = iCurrentSeqNum; |
751 iBuffer[len - 1].iSequenceNumber = iCurrentSeqNum; |
751 |
752 |
752 for (TInt i = 0; i < len; i++) |
753 for (TInt i = 0; i < len; i++) |
753 { |
754 { |
754 if (iBuffer[i].iTimeStamp > aLargestSeqNum) |
755 if (iBuffer[i].iTimeStamp > aLargestSeqNum) |
755 { |
756 { |
756 aLargestSeqNum = iBuffer[i].iTimeStamp; |
757 aLargestSeqNum = iBuffer[i].iTimeStamp; |
757 } |
758 } |
758 } |
759 } |
759 |
760 |
760 iBuffer[len-1].iTimeStamp = aLargestSeqNum + 1; |
761 iBuffer[len - 1].iTimeStamp = aLargestSeqNum + 1; |
761 iBuffer.Sort(iBufStampSorter); |
762 iBuffer.Sort(iBufStampSorter); |
762 iLastPlayedSeqNum = -1; |
763 iLastPlayedSeqNum = -1; |
763 } |
764 } |
764 else |
765 else |
765 { |
766 { |
766 iBuffer[len-1].iDataFrame->Data().Copy(aBuffer); |
767 iBuffer[len - 1].iDataFrame->Data().Copy(aBuffer); |
767 iBuffer[len-1].iSequenceNumber = iCurrentSeqNum; |
768 iBuffer[len - 1].iSequenceNumber = iCurrentSeqNum; |
768 iBuffer[len-1].iTimeStamp = iCurrentSeqNum - BufferLength(); |
769 iBuffer[len - 1].iTimeStamp = iCurrentSeqNum - BufferLength(); |
769 iBuffer.Sort(iBufSequenceSorter); |
770 iBuffer.Sort(iBufSequenceSorter); |
770 } |
771 } |
771 |
772 |
772 iPacketsInBuffer++; |
773 iPacketsInBuffer++; |
773 |
|
774 // TRACE_PRN_FN_EXT; |
|
775 } |
774 } |
776 |
775 |
777 // ----------------------------------------------------------------------------- |
776 // ----------------------------------------------------------------------------- |
778 // CVoIPJitterBufferImpl::BufferLength() |
777 // CVoIPJitterBufferImpl::BufferLength() |
779 // Return buffer length. |
778 // Return buffer length. |
782 TInt CVoIPJitterBufferImpl::BufferLength() const |
781 TInt CVoIPJitterBufferImpl::BufferLength() const |
783 { |
782 { |
784 return iBufferLength; |
783 return iBufferLength; |
785 } |
784 } |
786 |
785 |
|
786 #ifdef __FEATURE_NOT_SUPPORTED__ |
787 // ----------------------------------------------------------------------------- |
787 // ----------------------------------------------------------------------------- |
788 // CVoIPJitterBufferImpl::PacketCount() |
788 // CVoIPJitterBufferImpl::PacketCount() |
789 // Return number of packets that are currently in the buffer. |
789 // Return number of packets that are currently in the buffer. |
790 // ----------------------------------------------------------------------------- |
790 // ----------------------------------------------------------------------------- |
791 // |
791 // |
792 TInt CVoIPJitterBufferImpl::PacketCount() const |
792 TInt CVoIPJitterBufferImpl::PacketCount() const |
793 { |
793 { |
794 return iPacketsInBuffer; |
794 return iPacketsInBuffer; |
795 } |
795 } |
|
796 #endif //__FEATURE_NOT_SUPPORTED__ |
796 |
797 |
797 // ----------------------------------------------------------------------------- |
798 // ----------------------------------------------------------------------------- |
798 // CVoIPJitterBufferImpl::IsFull() |
799 // CVoIPJitterBufferImpl::IsFull() |
799 // Return: True if full |
800 // Return: True if full |
800 // False if not full |
801 // False if not full |
824 // This is because of network packet loss, where there might be gaps between |
825 // This is because of network packet loss, where there might be gaps between |
825 // frame sequence numbers. |
826 // frame sequence numbers. |
826 // ----------------------------------------------------------------------------- |
827 // ----------------------------------------------------------------------------- |
827 // |
828 // |
828 TBool CVoIPJitterBufferImpl::IsSeqNumWrappedAround(TInt64 aSeqNum1, |
829 TBool CVoIPJitterBufferImpl::IsSeqNumWrappedAround(TInt64 aSeqNum1, |
829 TInt64 aSeqNum2) const |
830 TInt64 aSeqNum2) const |
830 { |
831 { |
831 TBool status = EFalse; |
832 TBool status = EFalse; |
832 |
833 |
833 if (aSeqNum1 >= (KMaxSeqNumber - iSeqNumIncrement) && |
834 if (aSeqNum1 >= (KMaxSeqNumber - iSeqNumIncrement) && |
834 aSeqNum2 <= (iBufferLength * iSeqNumIncrement)) |
835 aSeqNum2 <= (iBufferLength * iSeqNumIncrement)) |
835 { |
836 { |
836 TRACE_PRN_N(_L("JB-> SEQUENCE WRAPPED-AROUND")); |
837 TRACE_PRN_N(_L("JB-> SEQUENCE WRAPPED-AROUND")); |
837 status = ETrue; |
838 status = ETrue; |
838 } |
839 } |
839 |
840 |
840 return status; |
841 return status; |
841 } |
842 } |
842 |
843 |
|
844 #ifdef __FEATURE_NOT_SUPPORTED__ |
843 // ----------------------------------------------------------------------------- |
845 // ----------------------------------------------------------------------------- |
844 // CVoIPJitterBufferImpl::GenerateStatistics |
846 // CVoIPJitterBufferImpl::GenerateStatistics |
845 // Generates the statistics from the jitterbuffer |
847 // Generates the statistics from the jitterbuffer |
846 // ----------------------------------------------------------------------------- |
848 // ----------------------------------------------------------------------------- |
847 // |
849 // |
848 void CVoIPJitterBufferImpl::GenerateStatistics(/*TJBStats& aStats*/) const |
850 void CVoIPJitterBufferImpl::GenerateStatistics(/*TJBStats& aStats*/) const |
849 {/* |
851 { |
850 aStats.iFramesReceived = iFramesReceived; |
852 aStats.iFramesReceived = iFramesReceived; |
851 aStats.iBufferLength = iBufferLength; |
853 aStats.iBufferLength = iBufferLength; |
852 aStats.iFramesInBuffer = iPacketsInBuffer; |
854 aStats.iFramesInBuffer = iPacketsInBuffer; |
853 aStats.iFrameLoss = iFramesLost; |
855 aStats.iFrameLoss = iFramesLost; |
854 aStats.iLateFrames = iNumOfLateFrames; |
856 aStats.iLateFrames = iNumOfLateFrames; |
855 aStats.iFramesRemoved = iFramesRemoved; |
857 aStats.iFramesRemoved = iFramesRemoved; |
856 aStats.iFramesPlayed = iFramesPlayed;*/ |
858 aStats.iFramesPlayed = iFramesPlayed; |
857 } |
859 } |
|
860 #endif //__FEATURE_NOT_SUPPORTED__ |
858 |
861 |
859 // ----------------------------------------------------------------------------- |
862 // ----------------------------------------------------------------------------- |
860 // CVoIPJitterBufferImpl::CheckThresholdBufferLength |
863 // CVoIPJitterBufferImpl::CheckThresholdBufferLength |
861 // ----------------------------------------------------------------------------- |
864 // ----------------------------------------------------------------------------- |
862 // |
865 // |
863 void CVoIPJitterBufferImpl::CheckThresholdBufferLength(TInt& aBufferLength, |
866 void CVoIPJitterBufferImpl::CheckThresholdBufferLength(TInt& aBufferLength, |
864 TInt aTreshhold) const |
867 TInt aTreshhold) const |
865 { |
868 { |
866 const TInt numTen = 10; |
869 const TInt numTen = 10; |
867 |
870 |
868 if ((aBufferLength - aTreshhold) < numTen) |
871 if ((aBufferLength - aTreshhold) < numTen) |
869 { |
872 { |
870 aBufferLength = aTreshhold + numTen; |
873 aBufferLength = aTreshhold + numTen; |
871 } |
874 } |
872 } |
875 } |
873 |
876 |
874 |
|
875 // End of File |
877 // End of File |
876 |
878 |