📄 jitter.cxx
字号:
lastWriteTimestamp = 0;
lastWriteTick = 0;
return TRUE;
}
// Detatch oldest packet from the list, put into parking space
currentDepth--;
#if PTRACING && !defined(NO_ANALYSER)
analyser->Out(oldestTimestamp, currentDepth, timestamp >= oldestTimestamp ? "" : "Late");
#endif
currentWriteFrame = oldestFrame;
oldestFrame = currentWriteFrame->next;
currentWriteFrame->next = NULL;
// Calculate the jitter contribution of this frame
// - don't count if start of a talk burst
if (currentWriteFrame->GetMarker()) {
lastWriteTimestamp = 0;
lastWriteTick = 0;
}
if (lastWriteTimestamp != 0 && lastWriteTick !=0) {
int thisJitter = 0;
if (currentWriteFrame->GetTimestamp() < lastWriteTimestamp) {
//Not too sure how to handle this situation...
thisJitter = 0;
}
else if (currentWriteFrame->tick < lastWriteTick) {
//Not too sure how to handle this situation either!
thisJitter = 0;
}
else {
thisJitter = (currentWriteFrame->tick -
lastWriteTick).GetInterval()*timeUnits +
lastWriteTimestamp -
currentWriteFrame->GetTimestamp();
}
if (thisJitter < 0) thisJitter *=(-1);
thisJitter *=2; //currentJitterTime needs to be at least TWICE the maximum jitter
if (thisJitter > (int) currentJitterTime * LOWER_JITTER_MAX_PCNT / 100) {
targetJitterTime = currentJitterTime;
PTRACE(3, "RTP\tJitter buffer target realigned to current jitter buffer");
consecutiveEarlyPacketStartTime = PTimer::Tick();
jitterCalcPacketCount = 0;
jitterCalc = 0;
}
else {
if (thisJitter > (int) jitterCalc)
jitterCalc = thisJitter;
jitterCalcPacketCount++;
//If it's bigger than the target we're currently trying to set, adapt that target.
//Note: this will never make targetJitterTime larger than currentJitterTime due to
//previous if condition
if (thisJitter > (int) targetJitterTime * LOWER_JITTER_MAX_PCNT / 100) {
targetJitterTime = thisJitter * 100 / LOWER_JITTER_MAX_PCNT;
PTRACE(3, "RTP\tJitter buffer target size increased to "
<< targetJitterTime << " (" << (targetJitterTime/timeUnits) << "ms)");
}
}
}
lastWriteTimestamp = currentWriteFrame->GetTimestamp();
lastWriteTick = currentWriteFrame->tick;
if (oldestFrame == NULL)
newestFrame = NULL;
else {
oldestFrame->prev = NULL;
// If exceeded current jitter buffer time delay:
if ((newestTimestamp - currentWriteFrame->GetTimestamp()) > currentJitterTime) {
PTRACE(4, "RTP\tJitter buffer length exceeded");
consecutiveEarlyPacketStartTime = PTimer::Tick();
jitterCalcPacketCount = 0;
jitterCalc = 0;
lastWriteTimestamp = 0;
lastWriteTick = 0;
// If we haven't yet written a frame, we get one free overrun
if (!doneFirstWrite) {
PTRACE(4, "RTP\tJitter buffer length exceed was prior to first write. Not increasing buffer size");
while ((newestTimestamp - currentWriteFrame->GetTimestamp()) > currentJitterTime) {
Entry * wastedFrame = currentWriteFrame;
currentWriteFrame = oldestFrame;
oldestFrame = oldestFrame->next;
currentDepth--;
currentWriteFrame->next = NULL; //currentWriteFrame should never be able to be NULL
wastedFrame->next = freeFrames;
if (freeFrames != NULL)
freeFrames->prev = wastedFrame;
freeFrames = wastedFrame;
if (oldestFrame == NULL) {
newestFrame = NULL;
break;
}
oldestFrame->prev = NULL;
}
doneFirstWrite = TRUE;
frame = *currentWriteFrame;
return TRUE;
}
// See if exceeded maximum jitter buffer time delay, waste them if so
while ((newestFrame->GetTimestamp() - currentWriteFrame->GetTimestamp()) > maxJitterTime) {
PTRACE(4, "RTP\tJitter buffer oldest packet ("
<< oldestFrame->GetTimestamp() << " < "
<< (newestTimestamp - maxJitterTime)
<< ") too late, throwing away");
currentJitterTime = maxJitterTime;
//Throw away the oldest frame and move everything up
Entry * wastedFrame = currentWriteFrame;
currentWriteFrame = oldestFrame;
oldestFrame = oldestFrame->next;
currentDepth--;
currentWriteFrame->next = NULL; //currentWriteFrame should never be able to be NULL
wastedFrame->next = freeFrames;
if (freeFrames != NULL)
freeFrames->prev = wastedFrame;
freeFrames = wastedFrame;
if (oldestFrame == NULL) {
newestFrame = NULL;
break;
}
}
// Now change the jitter time to cope with the new size
// unless already set to maxJitterTime
if (newestTimestamp - currentWriteFrame->GetTimestamp() > currentJitterTime)
currentJitterTime = newestTimestamp - currentWriteFrame->GetTimestamp();
targetJitterTime = currentJitterTime;
PTRACE(3, "RTP\tJitter buffer size increased to "
<< currentJitterTime << " (" << (currentJitterTime/timeUnits) << "ms)");
}
}
if ((PTimer::Tick() - consecutiveEarlyPacketStartTime).GetInterval() > DECREASE_JITTER_PERIOD &&
jitterCalcPacketCount >= DECREASE_JITTER_MIN_PACKETS){
jitterCalc = jitterCalc * 100 / LOWER_JITTER_MAX_PCNT;
if (jitterCalc < targetJitterTime / 2) jitterCalc = targetJitterTime / 2;
if (jitterCalc < minJitterTime) jitterCalc = minJitterTime;
targetJitterTime = jitterCalc;
PTRACE(3, "RTP\tJitter buffer target size decreased to "
<< targetJitterTime << " (" << (targetJitterTime/timeUnits) << "ms)");
jitterCalc = 0;
jitterCalcPacketCount = 0;
consecutiveEarlyPacketStartTime = PTimer::Tick();
}
/* If using immediate jitter reduction (rather than waiting for silence opportunities)
then trash oldest frames as necessary to reduce the size of the jitter buffer */
if (targetJitterTime < currentJitterTime &&
doJitterReductionImmediately &&
newestFrame != NULL) {
while ((newestFrame->GetTimestamp() - currentWriteFrame->GetTimestamp()) > targetJitterTime){
// Throw away the newest entries
Entry * wastedFrame = newestFrame;
newestFrame = newestFrame->prev;
if (newestFrame != NULL)
newestFrame->next = NULL;
wastedFrame->prev = NULL;
// Put thrown away frame on free list
wastedFrame->next = freeFrames;
if (freeFrames != NULL)
freeFrames->prev = wastedFrame;
freeFrames = wastedFrame;
// Reset jitter calculation baseline
lastWriteTimestamp = 0;
lastWriteTick = 0;
currentDepth--;
if (newestFrame == NULL)
{
oldestFrame = NULL;
break;
}
}
currentJitterTime = targetJitterTime;
PTRACE(3, "RTP\tJitter buffer size decreased to "
<< currentJitterTime << " (" << (currentJitterTime/timeUnits) << "ms)");
}
doneFirstWrite = TRUE;
frame = *currentWriteFrame;
return TRUE;
}
#if PTRACING && !defined(NO_ANALYSER)
RTP_JitterBufferAnalyser::RTP_JitterBufferAnalyser()
{
inPos = outPos = 1;
in[0].time = out[0].time = 0;
in[0].tick = out[0].tick = PTimer::Tick();
in[0].depth = out[0].depth = 0;
}
void RTP_JitterBufferAnalyser::In(DWORD time, unsigned depth, const char * extra)
{
if (inPos < PARRAYSIZE(in)) {
in[inPos].tick = PTimer::Tick();
in[inPos].time = time;
in[inPos].depth = depth;
in[inPos++].extra = extra;
}
}
void RTP_JitterBufferAnalyser::Out(DWORD time, unsigned depth, const char * extra)
{
if (outPos < PARRAYSIZE(out)) {
out[outPos].tick = PTimer::Tick();
if (time == 0 && outPos > 0)
out[outPos].time = out[outPos-1].time;
else
out[outPos].time = time;
out[outPos].depth = depth;
out[outPos++].extra = extra;
}
}
void RTP_JitterBufferAnalyser::PrintOn(ostream & strm) const
{
strm << "Input samples: " << inPos << " Output samples: " << outPos << "\n"
"Dir\tRTPTime\tInDiff\tOutDiff\tInMode\tOutMode\t"
"InDepth\tOutDep\tInTick\tInDelay\tOutTick\tOutDel\tIODelay\n";
PINDEX ix = 1;
PINDEX ox = 1;
while (ix < inPos || ox < outPos) {
while (ix < inPos && (ox >= outPos || in[ix].time < out[ox].time)) {
strm << "In\t"
<< in[ix].time << '\t'
<< (in[ix].time - in[ix-1].time) << "\t"
"\t"
<< in[ix].extra << "\t"
"\t"
<< in[ix].depth << "\t"
"\t"
<< (in[ix].tick - in[0].tick) << '\t'
<< (in[ix].tick - in[ix-1].tick) << "\t"
"\t"
"\t"
"\n";
ix++;
}
while (ox < outPos && (ix >= inPos || out[ox].time < in[ix].time)) {
strm << "Out\t"
<< out[ox].time << "\t"
"\t"
<< (out[ox].time - out[ox-1].time) << "\t"
"\t"
<< out[ox].extra << "\t"
"\t"
<< out[ox].depth << "\t"
"\t"
"\t"
<< (out[ox].tick - out[0].tick) << '\t'
<< (out[ox].tick - out[ox-1].tick) << "\t"
"\n";
ox++;
}
while (ix < inPos && ox < outPos && in[ix].time == out[ox].time) {
strm << "I/O\t"
<< in[ix].time << '\t'
<< (in[ix].time - in[ix-1].time) << '\t'
<< (out[ox].time - out[ox-1].time) << '\t'
<< in[ix].extra << '\t'
<< out[ox].extra << '\t'
<< in[ix].depth << '\t'
<< out[ox].depth << '\t'
<< (in[ix].tick - in[0].tick) << '\t'
<< (in[ix].tick - in[ix-1].tick) << '\t'
<< (out[ox].tick - out[0].tick) << '\t'
<< (out[ox].tick - out[ox-1].tick) << '\t'
<< (out[ox].tick - in[ix].tick)
<< '\n';
ox++;
ix++;
}
}
}
#endif
/////////////////////////////////////////////////////////////////////////////
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -