mirror of
https://github.com/danog/libtgvoip.git
synced 2024-11-26 20:24:38 +01:00
Fix packet count estimation
This commit is contained in:
parent
4af8a89491
commit
b6224112f0
@ -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;
|
||||
|
@ -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;
|
||||
}
|
@ -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;
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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);
|
||||
|
@ -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;
|
||||
}
|
@ -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)
|
||||
|
Loading…
Reference in New Issue
Block a user