Skip to content
Snippets Groups Projects
Commit 1367f46a authored by Philip-Dylan Gleonec's avatar Philip-Dylan Gleonec Committed by Pierre Lespagnol
Browse files

audio_rtp_session: add RTCP packet loss control

Add a rtcpCheckerThread to get packet loss estimation from the RTCP RR
packets, and send this information to the audio encoder.
This packet loss estimation is capped between 0 and 100.
When the new packet loss is higher than present estimation, the value
in the codec is set to the new value, in order to react to a quick
network quality drop.
When the new packet loss estimation is lower than present estimation,
the new value goes through a basic filter to avoid reducing the packet
loss estimation too fast.

Issue: #5157
Change-Id: Ibc1d3d6f6935e3b73c362bd212ef997cfd7b8d2f
parent 764c9cb0
No related branches found
No related tags found
No related merge requests found
......@@ -50,6 +50,7 @@ namespace jami {
AudioRtpSession::AudioRtpSession(const std::string& id)
: RtpSession(id)
, rtcpCheckerThread_([] { return true; }, [this] { processRtcpChecker(); }, [] {})
{
// don't move this into the initializer list or Cthulus will emerge
ringbuffer_ = Manager::instance().getRingBufferPool().createRingBuffer(callID_);
......@@ -105,6 +106,9 @@ AudioRtpSession::startSender()
JAMI_ERR("%s", e.what());
send_.enabled = false;
}
if (not rtcpCheckerThread_.isRunning())
rtcpCheckerThread_.start();
}
void
......@@ -181,6 +185,8 @@ AudioRtpSession::stop()
if (socketPair_)
socketPair_->interrupt();
rtcpCheckerThread_.join();
receiveThread_.reset();
sender_.reset();
socketPair_.reset();
......@@ -197,6 +203,85 @@ AudioRtpSession::setMuted(bool isMuted)
}
}
bool
AudioRtpSession::check_RCTP_Info_RR(RTCPInfo& rtcpi)
{
auto rtcpInfoVect = socketPair_->getRtcpRR();
unsigned totalLost = 0;
unsigned totalJitter = 0;
unsigned nbDropNotNull = 0;
auto vectSize = rtcpInfoVect.size();
if (vectSize != 0) {
for (const auto& it : rtcpInfoVect) {
if (it.fraction_lost != 0) // Exclude null drop
nbDropNotNull++;
totalLost += it.fraction_lost;
totalJitter += ntohl(it.jitter);
}
rtcpi.packetLoss = nbDropNotNull ? (float) (100 * totalLost) / (256.0 * nbDropNotNull) : 0;
// Jitter is expressed in timestamp unit -> convert to milliseconds
// https://stackoverflow.com/questions/51956520/convert-jitter-from-rtp-timestamp-unit-to-millisseconds
rtcpi.jitter = (totalJitter / vectSize / 90000.0f) * 1000;
rtcpi.nb_sample = vectSize;
rtcpi.latency = socketPair_->getLastLatency();
return true;
}
return false;
}
void
AudioRtpSession::adaptQualityAndBitrate()
{
RTCPInfo rtcpi {};
if (check_RCTP_Info_RR(rtcpi)) {
dropProcessing(&rtcpi);
}
}
void
AudioRtpSession::dropProcessing(RTCPInfo* rtcpi)
{
auto pondLoss = getPonderateLoss(rtcpi->packetLoss);
setNewPacketLoss(pondLoss);
}
void
AudioRtpSession::setNewPacketLoss(unsigned int newPL)
{
newPL = std::clamp((int) newPL, 0, 100);
if (newPL != packetLoss_) {
if (sender_) {
auto ret = sender_->setPacketLoss(newPL);
packetLoss_ = newPL;
if (ret == -1)
JAMI_ERR("Fail to access the encoder");
} else {
JAMI_ERR("Fail to access the sender");
}
}
}
float
AudioRtpSession::getPonderateLoss(float lastLoss)
{
static float pond = 10.0f;
pond = floor(0.5 * lastLoss + 0.5 * pond);
if (lastLoss > pond) {
return lastLoss;
} else {
return pond;
}
}
void
AudioRtpSession::processRtcpChecker()
{
adaptQualityAndBitrate();
socketPair_->waitForRTCP(std::chrono::seconds(rtcp_checking_interval));
}
void
AudioRtpSession::initRecorder(std::shared_ptr<MediaRecorder>& rec)
{
......
......@@ -25,6 +25,8 @@
#include "media_device.h"
#include "rtp_session.h"
#include "threadloop.h"
#include <string>
#include <memory>
......@@ -37,6 +39,14 @@ class IceSocket;
class MediaRecorder;
class RingBuffer;
struct RTCPInfo
{
float packetLoss;
unsigned int jitter;
unsigned int nb_sample;
float latency;
};
class AudioRtpSession : public RtpSession
{
public:
......@@ -57,6 +67,11 @@ public:
private:
void startSender();
void startReceiver();
bool check_RCTP_Info_RR(RTCPInfo& rtcpi);
void adaptQualityAndBitrate();
void dropProcessing(RTCPInfo* rtcpi);
void setNewPacketLoss(unsigned int newPL);
float getPonderateLoss(float lastLoss);
std::unique_ptr<AudioSender> sender_;
std::unique_ptr<AudioReceiveThread> receiveThread_;
......@@ -64,7 +79,14 @@ private:
std::shared_ptr<RingBuffer> ringbuffer_;
uint16_t initSeqVal_ = 0;
bool muteState_ = false;
int packetLoss_ = 10;
DeviceParams localAudioParams_;
InterruptedThreadLoop rtcpCheckerThread_;
void processRtcpChecker();
// interval in seconds between RTCP checkings
std::chrono::seconds rtcp_checking_interval {4};
};
} // namespace jami
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment