1
0
mirror of https://github.com/danog/libtgvoip.git synced 2024-11-30 04:39:03 +01:00

Fix packet count estimation

This commit is contained in:
Daniil Gentili 2020-01-29 19:12:12 +01:00
parent 4af8a89491
commit b6224112f0
Signed by: danog
GPG Key ID: 8C1BE3B34B230CA7
10 changed files with 94 additions and 57 deletions

View File

@ -572,7 +572,6 @@ private:
void handleReliablePackets();
void SetupOutgoingVideoStream();
bool WasOutgoingPacketAcknowledged(uint32_t seq, bool checkAll = true);
void NetworkPacketReceived(std::shared_ptr<NetworkPacket> packet);
void TrySendOutgoingPackets();
@ -607,6 +606,7 @@ private:
uint32_t packetsReceived = 0;
uint32_t recvLossCount = 0;
uint32_t prevSendLossCount = 0;
uint32_t prevSeq = 1;
uint32_t firstSentPing;
HistoricBuffer<double, 32> rttHistory;
bool waitingForAcks = false;

View File

@ -96,33 +96,29 @@ void AudioPacketSender::SendFrame(unsigned char *data, size_t len, unsigned char
//unsentStreamPackets++;
//PendingOutgoingPacket p{
// /*.seq=*/nextLocalSeq(),
// /*.type=*/PKT_STREAM_DATA,
// /*.len=*/pkt.GetLength(),
// /*.data=*/Buffer(move(pkt)),
// /*.endpoint=*/0,
//};
//conctl.PacketSent(p.seq, p.len);
//shared_ptr<VoIPController::Stream> outgoingAudioStream = GetStreamByType(STREAM_TYPE_AUDIO, false);
if (PeerVersion() < PROTOCOL_RELIABLE)
{
// Need to increase this anyway to go hand in hand with timestamp
packetManager.nextLocalSeq();
// packetManager.nextLocalSeq();
double rtt = LastRtt();
if (!packetLoss)
{
PendingOutgoingPacket p{
0,
PKT_STREAM_DATA,
pkt.GetLength(),
Buffer(move(pkt)),
0,
};
rtt = !rtt || rtt > 0.3 ? 0.5 : rtt; // Tweak this (a lot) later
uint32_t seq = SendPacket(std::move(p));
}
else
{
double retry = stream->frameDuration / (resendCount * 2.0);
double timeout = 0; //(outgoingAudioStream && outgoingAudioStream->jitterBuffer ? outgoingAudioStream->jitterBuffer->GetTimeoutWindow() : 0) - rtt;
LOGE("TIMEOUT %lf", timeout + rtt);
timeout = timeout <= 0 ? rtt : timeout;
SendPacketReliably(PKT_STREAM_DATA, pkt.GetBuffer(), pkt.GetLength(), rtt, timeout, 10); // Todo Optimize RTT
SendPacketReliably(PKT_STREAM_DATA, pkt.GetBuffer(), pkt.GetLength(), retry / 1000.0, (stream->frameDuration * 4) / 1000.0 , resendCount); // Todo Optimize RTT
}
}
else
{
@ -176,3 +172,31 @@ void AudioPacketSender::SendFrame(unsigned char *data, size_t len, unsigned char
}
#endif
}
double AudioPacketSender::setPacketLoss(double percent)
{
packetLoss = percent;
if (percent > 2)
{
resendCount = std::clamp(percent / 2, 0.0, 5.0);
}
/*else if (percent > 5)
{
resendCount = 1.5;
}
else if (percent > 2)
{
resendCount = 1.3;
}*/
else
{
resendCount = 1;
}
++resendCount;
double newLoss = percent / resendCount;
LOGE("Packet loss %lf / resend count %lf = new packet loss %lf", percent, resendCount, newLoss);
return newLoss;
}

View File

@ -41,6 +41,8 @@ public:
this->extraEcLevel = extraEcLevel;
}
double setPacketLoss(double percent);
private:
void SendFrame(unsigned char *data, size_t len, unsigned char *secondaryData, size_t secondaryLen);
@ -51,6 +53,10 @@ private:
bool shittyInternetMode = false;
uint8_t extraEcLevel = 0;
double packetLoss = 0.0;
double resendCount = 1.0;
std::deque<Buffer> ecAudioPackets;
BufferPool<1024, 32> outgoingAudioBufferPool;

View File

@ -96,7 +96,7 @@ void JitterBuffer::PutInternal(jitter_packet_t *pkt, bool overwriteExisting)
{
if (!slots[i].buffer.IsEmpty() && slots[i].timestamp == pkt->timestamp)
{
LOGV("Found existing packet for timestamp %u, overwrite %d", pkt->timestamp, overwriteExisting);
//LOGV("Found existing packet for timestamp %u, overwrite %d", pkt->timestamp, overwriteExisting);
if (overwriteExisting)
{
slots[i].buffer.CopyFrom(pkt->buffer, pkt->size);
@ -142,7 +142,7 @@ void JitterBuffer::PutInternal(jitter_packet_t *pkt, bool overwriteExisting)
if (expectNextAtTime != 0)
{
double dev = expectNextAtTime - time;
//LOGV("packet dev %f", dev);
LOGV("packet dev %f", dev);
deviationHistory.Add(dev);
expectNextAtTime += step / 1000.0;
}

View File

@ -60,10 +60,10 @@ private:
struct jitter_packet_t
{
Buffer buffer = Buffer();
size_t size;
uint32_t timestamp;
bool isEC;
double recvTimeDiff;
size_t size = 0;
uint32_t timestamp = 0;
bool isEC = 0;
double recvTimeDiff = 0.0;
};
void PutInternal(jitter_packet_t *pkt, bool overwriteExisting);
int GetInternal(jitter_packet_t *pkt, int offset, bool advance);
@ -72,7 +72,7 @@ private:
BufferPool<JITTER_SLOT_SIZE, JITTER_SLOT_COUNT> bufferPool;
Mutex mutex;
uint32_t step;
std::array<jitter_packet_t, JITTER_SLOT_COUNT> slots;
std::array<jitter_packet_t, JITTER_SLOT_COUNT> slots{0};
std::atomic<int64_t> nextFetchTimestamp = ATOMIC_VAR_INIT(0); // What frame to read next
double minDelay = 6;
uint32_t minMinDelay;

View File

@ -25,6 +25,7 @@ public:
{
return packetManager;
}
protected:
inline void SendExtra(Buffer &data, unsigned char type)
{
@ -87,6 +88,11 @@ protected:
return controller->receivedInitAck;
}
inline auto &GetConctl()
{
return controller->conctl;
}
inline const int32_t PeerVersion() const
{
return controller->peerVersion;

View File

@ -56,10 +56,10 @@ bool VoIPController::SendOrEnqueuePacket(PendingOutgoingPacket pkt, bool enqueue
BufferOutputStream out(1500);
uint8_t transportId = WritePacketHeader(pkt, out, source);
SendPacket(out.GetBuffer(), out.GetLength(), *endpoint, pkt.seq, pkt.type, transportId);
if (pkt.type == PKT_STREAM_DATA)
/*if (pkt.type == PKT_STREAM_DATA)
{
unsentStreamPackets--;
}
}*/
}
return true;
}

View File

@ -8,7 +8,11 @@ using namespace std;
PacketManager &VoIPController::getBestPacketManager()
{
#if PROTOCOL_VERSION == 9
return packetManager;
#else
return outgoingStreams.empty() ? packetManager : outgoingStreams[0]->packetSender->getPacketManager();
#endif
}
void VoIPController::ProcessIncomingPacket(NetworkPacket &packet, Endpoint &srcEndpoint)
@ -212,9 +216,9 @@ void VoIPController::ProcessIncomingPacket(NetworkPacket &packet, Endpoint &srcE
return;
}
#ifdef LOG_PACKETS
#ifdef LOG_PACKETS
LOGV("Received: from=%s:%u, seq=%u, length=%u, type=%s, transportId=%hhu", srcEndpoint.GetAddress().ToString().c_str(), srcEndpoint.port, pseq, (unsigned int)packet.data.Length(), GetPacketTypeString(type).c_str(), transportId);
#endif
#endif
// Extra data
if (pflags & XPFLAG_HAS_EXTRA)
@ -252,7 +256,7 @@ void VoIPController::ProcessIncomingPacket(NetworkPacket &packet, Endpoint &srcE
conctl.PacketAcknowledged(ackId);
manager->ackLocal(ackId, acks);
if (transportId != 0xFF && !incomingStreams.empty() && incomingStreams[transportId]->jitterBuffer)
{
// Technically I should be using the specific packet manager's rtt history but will separate later
@ -1071,7 +1075,7 @@ uint8_t VoIPController::WritePacketHeader(PendingOutgoingPacket &pkt, BufferOutp
s.WriteByte(static_cast<unsigned char>(currentExtras.size()));
for (auto &x : currentExtras)
{
LOGV("Writing extra into header: type %u, length %d", x.type, int(x.data.Length()));
//LOGV("Writing extra into header: type %u, length %d", x.type, int(x.data.Length()));
assert(x.data.Length() <= 254);
s.WriteByte(static_cast<unsigned char>(x.data.Length() + 1));
s.WriteByte(x.type);

View File

@ -6,8 +6,9 @@ using namespace std;
void VoIPController::SendPacketReliably(unsigned char type, unsigned char *data, size_t len, double retryInterval, double timeout, uint8_t tries)
{
ENFORCE_MSG_THREAD;
#ifdef LOG_PACKETS
LOGV("Send reliably, type=%u, len=%u, retry=%.3f, timeout=%.3f, tries=%hhu", type, unsigned(len), retryInterval, timeout, tries);
#endif
ReliableOutgoingPacket pkt;
if (data)
{
@ -36,13 +37,17 @@ void VoIPController::UpdateReliablePackets()
{
if (qp->timeout > 0 && qp->firstSentTime > 0 && GetCurrentTime() - qp->firstSentTime >= qp->timeout)
{
//#ifdef LOG_PACKETS
LOGD("Removing queued packet because of timeout");
//#endif
qp = reliablePackets.erase(qp);
continue;
}
if (!qp->tries--)
{
//#ifdef LOG_PACKETS
LOGD("Removing queued packet because of no more tries");
//#endif
qp = reliablePackets.erase(qp);
continue;
}
@ -52,7 +57,9 @@ void VoIPController::UpdateReliablePackets()
uint32_t seq = packetManager.nextLocalSeq();
qp->seqs.Add(seq);
qp->lastSentTime = GetCurrentTime();
//LOGD("Sending queued packet, seq=%u, type=%u, len=%u", seq, qp.type, qp.data.Length());
//#ifdef LOG_PACKETS
LOGD("Sending reliable queued packet, seq=%u, type=%u, len=%lu", seq, qp->type, qp->data.Length());
//#endif
Buffer buf(qp->data.Length());
if (qp->firstSentTime == 0)
qp->firstSentTime = qp->lastSentTime;
@ -80,7 +87,7 @@ void VoIPController::handleReliablePackets()
bool didAck = false;
for (uint8_t i = 0; i < qp.seqs.Size(); ++i)
{
if (!qp.seqs[i] || (didAck = WasOutgoingPacketAcknowledged(qp.seqs[i], false)))
if (!qp.seqs[i] || (didAck = packetManager.wasLocalAcked(qp.seqs[i])))
break;
}
if (didAck)
@ -91,18 +98,4 @@ void VoIPController::handleReliablePackets()
}
++it;
}
}
bool VoIPController::WasOutgoingPacketAcknowledged(uint32_t seq, bool checkAll)
{
bool res = packetManager.wasLocalAcked(seq);
if (res || !checkAll)
{
return res;
}
RecentOutgoingPacket *pkt = packetManager.GetRecentOutgoingPacket(seq);
if (!pkt)
return false;
return pkt->ackTime != 0.0;
}

View File

@ -149,7 +149,7 @@ void VoIPController::TickJitterBufferAndCongestionControl()
{
pkt.sender->PacketLost(pkt.seq, pkt.type, pkt.size);
}
else if (pkt.type == PKT_STREAM_DATA)
if (pkt.type == PKT_STREAM_DATA)
{
conctl.PacketLost(pkt.seq);
}
@ -157,7 +157,6 @@ void VoIPController::TickJitterBufferAndCongestionControl()
}
}
void VoIPController::UpdateRTT()
{
rttHistory.Add(GetAverageRTT());
@ -188,17 +187,22 @@ void VoIPController::UpdateCongestion()
uint32_t sendLossCount = conctl.GetSendLossCount();
sendLossCountHistory.Add(sendLossCount - prevSendLossCount);
prevSendLossCount = sendLossCount;
double packetsPerSec = 1000 / (double)outgoingStreams[0]->frameDuration;
uint32_t lastSentSeq = getBestPacketManager().getLastSentSeq();
double packetsPerSec = 1000 / (lastSentSeq - prevSeq);
prevSeq = lastSentSeq;
//double packetsPerSec = 1000 / (double)outgoingStreams[0]->frameDuration;
double avgSendLossCount = sendLossCountHistory.Average() / packetsPerSec;
//LOGV("avg send loss: %.3f%%", avgSendLossCount*100);
LOGE("avg send loss: %.3f%%", avgSendLossCount*100);
AudioPacketSender *sender = dynamic_cast<AudioPacketSender *>(GetStreamByType(STREAM_TYPE_AUDIO, true)->packetSender.get());
//avgSendLossCount = sender->setPacketLoss(avgSendLossCount * 100.0) / 100.0;
sender->setPacketLoss(avgSendLossCount * 100.0);
if (avgSendLossCount > packetLossToEnableExtraEC && networkType != NET_TYPE_GPRS && networkType != NET_TYPE_EDGE)
{
if (!sender->getShittyInternetMode())
{
// Shitty Internet Mode™. Redundant redundancy you can trust.
sender->setShittyInternetMode( true);
sender->setShittyInternetMode(true);
for (shared_ptr<Stream> &s : outgoingStreams)
{
if (s->type == STREAM_TYPE_AUDIO)