1
0
mirror of https://github.com/danog/libtgvoip.git synced 2024-12-02 17:51:06 +01:00
libtgvoip/JitterBuffer.cpp

456 lines
12 KiB
C++
Raw Normal View History

2017-02-02 17:24:40 +01:00
//
// libtgvoip is free and unencumbered public domain software.
// For more information, see http://unlicense.org or the UNLICENSE file
// you should have received with this source code distribution.
//
2017-03-30 16:06:59 +02:00
#include "VoIPController.h"
2017-02-02 17:24:40 +01:00
#include "JitterBuffer.h"
#include "logging.h"
2017-03-30 16:06:59 +02:00
#include "VoIPServerConfig.h"
#include <math.h>
2017-02-02 17:24:40 +01:00
using namespace tgvoip;
JitterBuffer::JitterBuffer(MediaStreamItf *out, uint32_t step){
2017-02-02 17:24:40 +01:00
if(out)
out->SetCallback(JitterBuffer::CallbackOut, this);
2017-02-02 17:24:40 +01:00
this->step=step;
memset(slots, 0, sizeof(jitter_packet_t)*JITTER_SLOT_COUNT);
2017-03-30 16:06:59 +02:00
if(step<30){
minMinDelay=(uint32_t) ServerConfig::GetSharedInstance()->GetInt("jitter_min_delay_20", 6);
maxMinDelay=(uint32_t) ServerConfig::GetSharedInstance()->GetInt("jitter_max_delay_20", 25);
maxUsedSlots=(uint32_t) ServerConfig::GetSharedInstance()->GetInt("jitter_max_slots_20", 50);
2017-03-30 16:06:59 +02:00
}else if(step<50){
minMinDelay=(uint32_t) ServerConfig::GetSharedInstance()->GetInt("jitter_min_delay_40", 4);
maxMinDelay=(uint32_t) ServerConfig::GetSharedInstance()->GetInt("jitter_max_delay_40", 15);
maxUsedSlots=(uint32_t) ServerConfig::GetSharedInstance()->GetInt("jitter_max_slots_40", 30);
2017-03-30 16:06:59 +02:00
}else{
minMinDelay=(uint32_t) ServerConfig::GetSharedInstance()->GetInt("jitter_min_delay_60", 2);
maxMinDelay=(uint32_t) ServerConfig::GetSharedInstance()->GetInt("jitter_max_delay_60", 10);
maxUsedSlots=(uint32_t) ServerConfig::GetSharedInstance()->GetInt("jitter_max_slots_60", 20);
2017-03-30 16:06:59 +02:00
}
lossesToReset=(uint32_t) ServerConfig::GetSharedInstance()->GetInt("jitter_losses_to_reset", 20);
resyncThreshold=ServerConfig::GetSharedInstance()->GetDouble("jitter_resync_threshold", 1.0);
2018-05-15 20:23:46 +02:00
#ifdef TGVOIP_DUMP_JITTER_STATS
#ifdef TGVOIP_JITTER_DUMP_FILE
dump=fopen(TGVOIP_JITTER_DUMP_FILE, "w");
#elif defined(__ANDROID__)
dump=fopen("/sdcard/tgvoip_jitter_dump.txt", "w");
#else
dump=fopen("tgvoip_jitter_dump.txt", "w");
#endif
tgvoip_log_file_write_header(dump);
fprintf(dump, "PTS\tRTS\tNumInBuf\tAJitter\tADelay\tTDelay\n");
#endif
2017-02-02 17:24:40 +01:00
Reset();
}
JitterBuffer::~JitterBuffer(){
2017-02-02 17:24:40 +01:00
Reset();
}
void JitterBuffer::SetMinPacketCount(uint32_t count){
2018-11-10 02:05:47 +01:00
LOGI("jitter: set min packet count %u", count);
2017-02-02 17:24:40 +01:00
minDelay=count;
minMinDelay=count;
2018-06-04 21:37:43 +02:00
//Reset();
2017-02-02 17:24:40 +01:00
}
int JitterBuffer::GetMinPacketCount(){
return (int)minDelay;
2017-02-02 17:24:40 +01:00
}
size_t JitterBuffer::CallbackIn(unsigned char *data, size_t len, void *param){
//((JitterBuffer*)param)->HandleInput(data, len);
2017-02-02 17:24:40 +01:00
return 0;
}
size_t JitterBuffer::CallbackOut(unsigned char *data, size_t len, void *param){
return 0; //((JitterBuffer*)param)->HandleOutput(data, len, 0, NULL);
2017-02-02 17:24:40 +01:00
}
2018-06-04 21:37:43 +02:00
void JitterBuffer::HandleInput(unsigned char *data, size_t len, uint32_t timestamp, bool isEC){
MutexGuard m(mutex);
2017-02-02 17:24:40 +01:00
jitter_packet_t pkt;
pkt.size=len;
pkt.buffer=Buffer::Wrap(data, len, [](void*){}, [](void* a, size_t)->void*{return a;});
2017-02-02 17:24:40 +01:00
pkt.timestamp=timestamp;
2018-06-04 21:37:43 +02:00
pkt.isEC=isEC;
PutInternal(&pkt, !isEC);
//LOGV("in, ts=%d, ec=%d", timestamp, isEC);
2017-02-02 17:24:40 +01:00
}
void JitterBuffer::Reset(){
2017-02-02 17:24:40 +01:00
wasReset=true;
needBuffering=true;
lastPutTimestamp=0;
int i;
for(i=0;i<JITTER_SLOT_COUNT;i++){
if(!slots[i].buffer.IsEmpty()){
slots[i].buffer=Buffer();
2017-02-02 17:24:40 +01:00
}
}
delayHistory.Reset();
lateHistory.Reset();
2017-02-02 17:24:40 +01:00
adjustingDelay=false;
2017-03-30 16:06:59 +02:00
lostSinceReset=0;
gotSinceReset=0;
expectNextAtTime=0;
deviationHistory.Reset();
outstandingDelayChange=0;
dontChangeDelay=0;
2017-02-02 17:24:40 +01:00
}
2018-06-04 21:37:43 +02:00
size_t JitterBuffer::HandleOutput(unsigned char *buffer, size_t len, int offsetInSteps, bool advance, int& playbackScaledDuration, bool& isEC){
2017-02-02 17:24:40 +01:00
jitter_packet_t pkt;
pkt.buffer=Buffer::Wrap(buffer, len, [](void*){}, [](void* a, size_t)->void*{return a;});
2017-02-02 17:24:40 +01:00
pkt.size=len;
2018-05-15 20:23:46 +02:00
MutexGuard m(mutex);
if(first){
first=false;
unsigned int delay=GetCurrentDelay();
if(GetCurrentDelay()>5){
LOGW("jitter: delay too big upon start (%u), dropping packets", delay);
while(delay>GetMinPacketCount()){
for(int i=0;i<JITTER_SLOT_COUNT;i++){
if(slots[i].timestamp==nextTimestamp){
if(!slots[i].buffer.IsEmpty()){
slots[i].buffer=Buffer();
}
break;
}
}
Advance();
delay--;
}
}
}
2018-05-15 20:23:46 +02:00
int result=GetInternal(&pkt, offsetInSteps, advance);
2018-06-04 21:37:43 +02:00
if(outstandingDelayChange!=0){
if(outstandingDelayChange<0){
playbackScaledDuration=40;
outstandingDelayChange+=20;
}else{
2018-06-04 21:37:43 +02:00
playbackScaledDuration=80;
outstandingDelayChange-=20;
}
2018-06-04 21:37:43 +02:00
//LOGV("outstanding delay change: %d", outstandingDelayChange);
}else if(advance && GetCurrentDelay()==0){
//LOGV("stretching packet because the next one is late");
playbackScaledDuration=80;
}else{
playbackScaledDuration=60;
}
2017-02-02 17:24:40 +01:00
if(result==JR_OK){
2018-06-04 21:37:43 +02:00
isEC=pkt.isEC;
2017-02-02 17:24:40 +01:00
return pkt.size;
}else{
return 0;
}
}
2018-05-15 20:23:46 +02:00
int JitterBuffer::GetInternal(jitter_packet_t* pkt, int offset, bool advance){
2017-02-02 17:24:40 +01:00
/*if(needBuffering && lastPutTimestamp<nextTimestamp){
2017-04-19 15:39:27 +02:00
LOGV("jitter: don't have timestamp %lld, buffering", (long long int)nextTimestamp);
2017-02-02 17:24:40 +01:00
Advance();
return JR_BUFFERING;
}*/
//needBuffering=false;
int64_t timestampToGet=nextTimestamp+offset*(int32_t)step;
int i;
for(i=0;i<JITTER_SLOT_COUNT;i++){
if(!slots[i].buffer.IsEmpty() && slots[i].timestamp==timestampToGet){
2017-02-02 17:24:40 +01:00
break;
}
}
if(i<JITTER_SLOT_COUNT){
if(pkt && pkt->size<slots[i].size){
2017-04-19 15:39:27 +02:00
LOGE("jitter: packet won't fit into provided buffer of %d (need %d)", int(slots[i].size), int(pkt->size));
2017-02-02 17:24:40 +01:00
}else{
if(pkt) {
pkt->size = slots[i].size;
pkt->timestamp = slots[i].timestamp;
pkt->buffer.CopyFrom(slots[i].buffer, slots[i].size);
2018-06-04 21:37:43 +02:00
pkt->isEC=slots[i].isEC;
2017-02-02 17:24:40 +01:00
}
}
slots[i].buffer=Buffer();
2017-02-02 17:24:40 +01:00
if(offset==0)
Advance();
lostCount=0;
needBuffering=false;
return JR_OK;
}
LOGV("jitter: found no packet for timestamp %lld (last put = %d, lost = %d)", (long long int)timestampToGet, lastPutTimestamp, lostCount);
2017-02-02 17:24:40 +01:00
2018-05-15 20:23:46 +02:00
if(advance)
2017-02-02 17:24:40 +01:00
Advance();
if(!needBuffering){
lostCount++;
2017-03-30 16:06:59 +02:00
if(offset==0){
2017-02-02 17:24:40 +01:00
lostPackets++;
2017-03-30 16:06:59 +02:00
lostSinceReset++;
}
if(lostCount>=lossesToReset || (gotSinceReset>minDelay*25 && lostSinceReset>gotSinceReset/2)){
2017-02-02 17:24:40 +01:00
LOGW("jitter: lost %d packets in a row, resetting", lostCount);
//minDelay++;
dontIncMinDelay=16;
dontDecMinDelay+=128;
if(GetCurrentDelay()<minDelay)
nextTimestamp-=(int64_t)(minDelay-GetCurrentDelay());
2017-02-02 17:24:40 +01:00
lostCount=0;
Reset();
}
return JR_MISSING;
}
return JR_BUFFERING;
}
2018-06-04 21:37:43 +02:00
void JitterBuffer::PutInternal(jitter_packet_t* pkt, bool overwriteExisting){
2017-02-02 17:24:40 +01:00
if(pkt->size>JITTER_SLOT_SIZE){
LOGE("The packet is too big to fit into the jitter buffer");
return;
}
2018-06-04 21:37:43 +02:00
2017-02-02 17:24:40 +01:00
int i;
2018-06-04 21:37:43 +02:00
for(i=0;i<JITTER_SLOT_COUNT;i++){
if(!slots[i].buffer.IsEmpty() && slots[i].timestamp==pkt->timestamp){
2018-06-04 21:37:43 +02:00
//LOGV("Found existing packet for timestamp %u, overwrite %d", pkt->timestamp, overwriteExisting);
if(overwriteExisting){
slots[i].buffer.CopyFrom(pkt->buffer, pkt->size);
2018-06-04 21:37:43 +02:00
slots[i].size=pkt->size;
slots[i].isEC=pkt->isEC;
}
return;
}
}
gotSinceReset++;
2017-02-02 17:24:40 +01:00
if(wasReset){
wasReset=false;
outstandingDelayChange=0;
nextTimestamp=(int64_t)(((int64_t)pkt->timestamp)-step*minDelay);
first=true;
2018-06-04 21:37:43 +02:00
LOGI("jitter: resyncing, next timestamp = %lld (step=%d, minDelay=%f)", (long long int)nextTimestamp, step, minDelay);
2017-03-30 16:06:59 +02:00
}
for(i=0;i<JITTER_SLOT_COUNT;i++){
if(!slots[i].buffer.IsEmpty()){
2017-03-30 16:06:59 +02:00
if(slots[i].timestamp<nextTimestamp-1){
slots[i].buffer=Buffer();
2017-02-02 17:24:40 +01:00
}
}
}
2017-03-30 16:06:59 +02:00
/*double prevTime=0;
uint32_t closestTime=0;
for(i=0;i<JITTER_SLOT_COUNT;i++){
if(slots[i].buffer!=NULL && pkt->timestamp-slots[i].timestamp<pkt->timestamp-closestTime){
closestTime=slots[i].timestamp;
prevTime=slots[i].recvTime;
}
}*/
double time=VoIPController::GetCurrentTime();
2017-03-30 16:06:59 +02:00
if(expectNextAtTime!=0){
double dev=expectNextAtTime-time;
//LOGV("packet dev %f", dev);
deviationHistory.Add(dev);
2017-03-30 16:06:59 +02:00
expectNextAtTime+=step/1000.0;
}else{
expectNextAtTime=time+step/1000.0;
}
2017-02-02 17:24:40 +01:00
if(pkt->timestamp<nextTimestamp){
2018-05-15 20:23:46 +02:00
//LOGW("jitter: would drop packet with timestamp %d because it is late but not hopelessly", pkt->timestamp);
2017-02-02 17:24:40 +01:00
latePacketCount++;
lostPackets--;
}else if(pkt->timestamp<nextTimestamp-1){
2018-05-15 20:23:46 +02:00
//LOGW("jitter: dropping packet with timestamp %d because it is too late", pkt->timestamp);
2017-02-02 17:24:40 +01:00
latePacketCount++;
return;
}
if(pkt->timestamp>lastPutTimestamp)
lastPutTimestamp=pkt->timestamp;
for(i=0;i<JITTER_SLOT_COUNT;i++){
if(slots[i].buffer.IsEmpty())
2017-02-02 17:24:40 +01:00
break;
}
2017-03-30 16:06:59 +02:00
if(i==JITTER_SLOT_COUNT || GetCurrentDelay()>=maxUsedSlots){
2017-02-02 17:24:40 +01:00
int toRemove=JITTER_SLOT_COUNT;
uint32_t bestTimestamp=0xFFFFFFFF;
for(i=0;i<JITTER_SLOT_COUNT;i++){
if(!slots[i].buffer.IsEmpty() && slots[i].timestamp<bestTimestamp){
2017-02-02 17:24:40 +01:00
toRemove=i;
bestTimestamp=slots[i].timestamp;
}
}
2017-03-30 16:06:59 +02:00
Advance();
slots[toRemove].buffer=Buffer();
2017-02-02 17:24:40 +01:00
i=toRemove;
}
slots[i].timestamp=pkt->timestamp;
slots[i].size=pkt->size;
slots[i].buffer=bufferPool.Get();
2017-03-30 16:06:59 +02:00
slots[i].recvTimeDiff=time-prevRecvTime;
2018-06-04 21:37:43 +02:00
slots[i].isEC=pkt->isEC;
slots[i].buffer.CopyFrom(pkt->buffer, pkt->size);
2018-05-15 20:23:46 +02:00
#ifdef TGVOIP_DUMP_JITTER_STATS
fprintf(dump, "%u\t%.03f\t%d\t%.03f\t%.03f\t%.03f\n", pkt->timestamp, time, GetCurrentDelay(), lastMeasuredJitter, lastMeasuredDelay, minDelay);
#endif
2017-03-30 16:06:59 +02:00
prevRecvTime=time;
2017-02-02 17:24:40 +01:00
}
void JitterBuffer::Advance(){
2017-02-02 17:24:40 +01:00
nextTimestamp+=step;
}
2018-05-15 20:23:46 +02:00
unsigned int JitterBuffer::GetCurrentDelay(){
unsigned int delay=0;
2017-02-02 17:24:40 +01:00
int i;
for(i=0;i<JITTER_SLOT_COUNT;i++){
if(!slots[i].buffer.IsEmpty())
2017-02-02 17:24:40 +01:00
delay++;
}
return delay;
}
void JitterBuffer::Tick(){
2018-05-15 20:23:46 +02:00
MutexGuard m(mutex);
2017-02-02 17:24:40 +01:00
int i;
lateHistory.Add(latePacketCount);
2017-02-02 17:24:40 +01:00
latePacketCount=0;
bool absolutelyNoLatePackets=lateHistory.Max()==0;
2017-02-02 17:24:40 +01:00
double avgLate16=lateHistory.Average(16);
2017-02-02 17:24:40 +01:00
//LOGV("jitter: avg late=%.1f, %.1f, %.1f", avgLate16, avgLate32, avgLate64);
2017-03-30 16:06:59 +02:00
if(avgLate16>=resyncThreshold){
LOGV("resyncing: avgLate16=%f, resyncThreshold=%f", avgLate16, resyncThreshold);
2017-03-30 16:06:59 +02:00
wasReset=true;
}
if(absolutelyNoLatePackets){
if(dontDecMinDelay>0)
dontDecMinDelay--;
}
2017-02-02 17:24:40 +01:00
delayHistory.Add(GetCurrentDelay());
avgDelay=delayHistory.Average(32);
2017-03-30 16:06:59 +02:00
double stddev=0;
double avgdev=deviationHistory.Average();
2017-03-30 16:06:59 +02:00
for(i=0;i<64;i++){
double d=(deviationHistory[i]-avgdev);
stddev+=(d*d);
}
stddev=sqrt(stddev/64);
uint32_t stddevDelay=(uint32_t)ceil(stddev*2*1000/step);
if(stddevDelay<minMinDelay)
stddevDelay=minMinDelay;
if(stddevDelay>maxMinDelay)
stddevDelay=maxMinDelay;
if(stddevDelay!=minDelay){
int32_t diff=(int32_t)(stddevDelay-minDelay);
2017-03-30 16:06:59 +02:00
if(diff>0){
dontDecMinDelay=100;
}
if(diff<-1)
diff=-1;
if(diff>1)
diff=1;
if((diff>0 && dontIncMinDelay==0) || (diff<0 && dontDecMinDelay==0)){
//nextTimestamp+=diff*(int32_t)step;
2017-03-30 16:06:59 +02:00
minDelay+=diff;
outstandingDelayChange+=diff*60;
dontChangeDelay+=32;
//LOGD("new delay from stddev %f", minDelay);
2017-03-30 16:06:59 +02:00
if(diff<0){
dontDecMinDelay+=25;
}
if(diff>0){
dontIncMinDelay=25;
}
}
}
lastMeasuredJitter=stddev;
lastMeasuredDelay=stddevDelay;
2017-03-30 16:06:59 +02:00
//LOGV("stddev=%.3f, avg=%.3f, ndelay=%d, dontDec=%u", stddev, avgdev, stddevDelay, dontDecMinDelay);
if(dontChangeDelay==0){
if(avgDelay>minDelay+0.5){
outstandingDelayChange-=avgDelay>minDelay+2 ? 60 : 20;
dontChangeDelay+=10;
}else if(avgDelay<minDelay-0.3){
outstandingDelayChange+=20;
dontChangeDelay+=10;
}
}
if(dontChangeDelay>0)
dontChangeDelay--;
2017-03-30 16:06:59 +02:00
2017-02-02 17:24:40 +01:00
//LOGV("jitter: avg delay=%d, delay=%d, late16=%.1f, dontDecMinDelay=%d", avgDelay, delayHistory[0], avgLate16, dontDecMinDelay);
/*if(!adjustingDelay) {
if (((minDelay==1 ? (avgDelay>=3) : (avgDelay>=minDelay/2)) && delayHistory[0]>minDelay && avgLate16<=0.1 && absolutelyNoLatePackets && dontDecMinDelay<32 && min>minDelay)) {
2017-02-02 17:24:40 +01:00
LOGI("jitter: need adjust");
adjustingDelay=true;
}
}else{
if(!absolutelyNoLatePackets){
LOGI("jitter: done adjusting because we're losing packets");
adjustingDelay=false;
}else if(tickCount%5==0){
LOGD("jitter: removing a packet to reduce delay");
GetInternal(NULL, 0);
2017-03-30 16:06:59 +02:00
expectNextAtTime=0;
2017-02-02 17:24:40 +01:00
if(GetCurrentDelay()<=minDelay || min<=minDelay){
adjustingDelay = false;
LOGI("jitter: done adjusting");
}
}
}*/
2017-02-02 17:24:40 +01:00
tickCount++;
}
void JitterBuffer::GetAverageLateCount(double *out){
double avgLate64=lateHistory.Average(), avgLate32=lateHistory.Average(32), avgLate16=lateHistory.Average(16);
2017-02-02 17:24:40 +01:00
out[0]=avgLate16;
out[1]=avgLate32;
out[2]=avgLate64;
}
int JitterBuffer::GetAndResetLostPacketCount(){
2018-05-15 20:23:46 +02:00
MutexGuard m(mutex);
2017-02-02 17:24:40 +01:00
int r=lostPackets;
lostPackets=0;
return r;
}
double JitterBuffer::GetLastMeasuredJitter(){
return lastMeasuredJitter;
}
double JitterBuffer::GetLastMeasuredDelay(){
return lastMeasuredDelay;
}
double JitterBuffer::GetAverageDelay(){
return avgDelay;
}