Commit e522de96 authored by Pierre Lespagnol's avatar Pierre Lespagnol Committed by Adrien Béraud

improve video quality

Change-Id: I5692497489f2df3e0b94737651e6d1d1ba44012f
parent 5458eb86
......@@ -60,7 +60,7 @@ struct SystemCodecInfo
{
static constexpr unsigned DEFAULT_CODEC_QUALITY {30};
#ifdef ENABLE_VIDEO
static constexpr unsigned DEFAULT_H264_MIN_QUALITY {35};
static constexpr unsigned DEFAULT_H264_MIN_QUALITY {40};
static constexpr unsigned DEFAULT_H264_MAX_QUALITY {20};
static constexpr unsigned DEFAULT_VP8_MIN_QUALITY {50};
static constexpr unsigned DEFAULT_VP8_MAX_QUALITY {20};
......@@ -70,8 +70,8 @@ struct SystemCodecInfo
// indicates that the codec does not use quality factor
static constexpr unsigned DEFAULT_NO_QUALITY {0};
static constexpr unsigned DEFAULT_MIN_BITRATE {250};
static constexpr unsigned DEFAULT_MAX_BITRATE {3000};
static constexpr unsigned DEFAULT_MIN_BITRATE {220};
static constexpr unsigned DEFAULT_MAX_BITRATE {6000};
SystemCodecInfo(unsigned avcodecId, const std::string& name,
const std::string& libName, MediaType mediaType,
......
......@@ -52,6 +52,9 @@ extern "C" {
namespace jami {
constexpr double LOGREG_PARAM_A {114.40432};
constexpr double LOGREG_PARAM_B {-6.049181};
MediaEncoder::MediaEncoder()
: outputCtx_(avformat_alloc_context())
{}
......@@ -218,9 +221,9 @@ MediaEncoder::initStream(const SystemCodecInfo& systemCodecInfo, AVBufferRef* fr
}
#endif
auto maxBitrate = 1000 * std::atoi(libav_utils::getDictValue(options_, "max_rate"));
auto bufSize = 2 * maxBitrate; // as recommended (TODO: make it customizable)
auto crf = std::atoi(libav_utils::getDictValue(options_, "crf"));
uint64_t maxBitrate = 1000 * std::atoi(libav_utils::getDictValue(options_, "max_rate"));
uint8_t crf = (uint8_t) std::round(LOGREG_PARAM_A + log(pow(maxBitrate, LOGREG_PARAM_B))); // CRF = A + B*ln(maxBitrate)
uint64_t bufSize = 2 * maxBitrate;
/* let x264 preset override our encoder settings */
if (systemCodecInfo.avcodecId == AV_CODEC_ID_H264) {
......@@ -245,7 +248,7 @@ MediaEncoder::initStream(const SystemCodecInfo& systemCodecInfo, AVBufferRef* fr
if (crf == SystemCodecInfo::DEFAULT_NO_QUALITY)
crf = 30; // good value for H264-720p@30
JAMI_DBG("H264 encoder setup: crf=%u, maxrate=%u, bufsize=%u", crf, maxBitrate, bufSize);
libav_utils::setDictValue(&options_, "crf", std::to_string(crf));
av_opt_set_int(encoderCtx, "crf", crf, AV_OPT_SEARCH_CHILDREN);
encoderCtx->rc_buffer_size = bufSize;
encoderCtx->rc_max_rate = maxBitrate;
......@@ -651,7 +654,7 @@ MediaEncoder::extractProfileLevelID(const std::string &parameters,
// From RFC3984:
// If no profile-level-id is present, the Baseline Profile without
// additional constraints at Level 1 MUST be implied.
ctx->profile = FF_PROFILE_H264_BASELINE;
ctx->profile = FF_PROFILE_H264_CONSTRAINED_BASELINE;
ctx->level = 0x0d;
// ctx->level = 0x0d; // => 13 aka 1.3
if (parameters.empty())
......
......@@ -59,6 +59,24 @@ extern "C" {
#include <fcntl.h>
#endif
// Swap 2 byte, 16 bit values:
#define Swap2Bytes(val) \
( (((val) >> 8) & 0x00FF) | (((val) << 8) & 0xFF00) )
// Swap 4 byte, 32 bit values:
#define Swap4Bytes(val) \
( (((val) >> 24) & 0x000000FF) | (((val) >> 8) & 0x0000FF00) | \
(((val) << 8) & 0x00FF0000) | (((val) << 24) & 0xFF000000) )
// Swap 8 byte, 64 bit values:
#define Swap8Bytes(val) \
( (((val) >> 56) & 0x00000000000000FF) | (((val) >> 40) & 0x000000000000FF00) | \
(((val) >> 24) & 0x0000000000FF0000) | (((val) >> 8) & 0x00000000FF000000) | \
(((val) << 8) & 0x000000FF00000000) | (((val) << 24) & 0x0000FF0000000000) | \
(((val) << 40) & 0x00FF000000000000) | (((val) << 56) & 0xFF00000000000000) )
namespace jami {
static constexpr int NET_POLL_TIMEOUT = 100; /* poll() timeout in ms */
......@@ -195,6 +213,15 @@ SocketPair::~SocketPair()
closeSockets();
}
bool
SocketPair::waitForRTCP(std::chrono::seconds interval)
{
std::unique_lock<std::mutex> lock(rtcpInfo_mutex_);
return cvRtcpPacketReadyToRead_.wait_for(lock, interval, [this]{
return interrupted_ or not listRtcpHeader_.empty();
});
}
void
SocketPair::saveRtcpPacket(uint8_t* buf, size_t len)
{
......@@ -212,19 +239,15 @@ SocketPair::saveRtcpPacket(uint8_t* buf, size_t len)
}
listRtcpHeader_.push_back(*header);
cvRtcpPacketReadyToRead_.notify_one();
}
std::vector<rtcpRRHeader>
std::list<rtcpRRHeader>
SocketPair::getRtcpInfo()
{
decltype(listRtcpHeader_) l;
{
std::lock_guard<std::mutex> lock(rtcpInfo_mutex_);
if (listRtcpHeader_.empty())
return {};
l = std::move(listRtcpHeader_);
}
return {std::make_move_iterator(l.begin()), std::make_move_iterator(l.end())};
std::lock_guard<std::mutex> lock(rtcpInfo_mutex_);
return std::move(listRtcpHeader_);
}
void
......@@ -406,6 +429,14 @@ SocketPair::readCallback(uint8_t* buf, int buf_size)
int len = 0;
bool fromRTCP = false;
auto header = reinterpret_cast<rtcpRRHeader*>(buf);
if(header->pt == 201) //201 = RR PT
{
lastDLSR_ = Swap4Bytes(header->dlsr);
//JAMI_WARN("Read RR, lastDLSR : %d", lastDLSR_);
lastRR_time = std::chrono::steady_clock::now();
}
// Priority to RTCP as its less invasive in bandwidth
if (datatype & static_cast<int>(DataType::RTCP)) {
len = readRtcpData(buf, buf_size);
......@@ -478,6 +509,8 @@ SocketPair::writeCallback(uint8_t* buf, int buf_size)
{
int ret;
bool isRTCP = RTP_PT_IS_RTCP(buf[1]);
unsigned int ts_LSB, ts_MSB;
double currentSRTS, currentLatency;
// Encrypt?
if (not isRTCP and srtpContext_ and srtpContext_->srtp_out.aes) {
......@@ -505,15 +538,46 @@ SocketPair::writeCallback(uint8_t* buf, int buf_size)
ret = writeData(buf, buf_size);
} while (ret < 0 and errno == EAGAIN);
if(buf[1] == 200) //Sender Report
{
auto header = reinterpret_cast<rtcpSRHeader*>(buf);
ts_LSB = Swap4Bytes(header->timestampLSB);
ts_MSB = Swap4Bytes(header->timestampMSB);
currentSRTS = ts_MSB + (ts_LSB / pow(2,32));
if(lastSRTS_ != 0 && lastDLSR_ != 0)
{
if (histoLatency_.size() >= MAX_LIST_SIZE)
histoLatency_.pop_front();
currentLatency = (currentSRTS - lastSRTS_) / 2;
//JAMI_WARN("Current Latency : %f from sender %X", currentLatency, header->ssrc);
histoLatency_.push_back(currentLatency);
}
lastSRTS_ = currentSRTS;
// JAMI_WARN("SENDING NEW RTCP SR !! ");
}
else if(buf[1] == 201) //Receiver Report
{
//auto header = reinterpret_cast<rtcpRRHeader*>(buf);
//JAMI_WARN("SENDING NEW RTCP RR !! ");
}
return ret < 0 ? -errno : ret;
}
bool
SocketPair::rtcpPacketLossDetected() const
double
SocketPair::getLastLatency()
{
// set to false on checking packet loss to avoid burst of keyframe requests
bool b = true;
return rtcpPacketLoss_.compare_exchange_strong(b, false);
if(not histoLatency_.empty())
return histoLatency_.back();
else
return -1;
}
} // namespace jami
......@@ -66,12 +66,37 @@ typedef struct {
uint32_t pt:8; /* payload type */
uint32_t len:16; /* length of RTCP packet */
uint32_t ssrc; /* synchronization source identifier of packet send */
uint32_t ssrc_1; /* synchronization source identifier of first source */
uint32_t fraction_lost; /* 8 bits of fraction, 24 bits of total packets lost */
uint32_t last_seq; /*last sequence number */
uint32_t jitter; /*jitter */
uint32_t id; /* synchronization source identifier of first source */
uint32_t fraction_lost:8; /* 8 bits of fraction, 24 bits of total packets lost */
uint32_t cum_lost_packet:24; /* cumulative number packet lost */
uint32_t ext_high; /* Extended highest sequence number received */
uint32_t jitter; /* jitter */
uint32_t lsr; /* last SR timestamp */
uint32_t dlsr; /* Delay since last SR timestamp */
} rtcpRRHeader;
typedef struct {
#ifdef WORDS_BIGENDIAN
uint32_t version:2; /* protocol version */
uint32_t p:1; /* padding flag */
uint32_t rc:5; /* reception report count must be 201 for report */
#else
uint32_t rc:5; /* reception report count must be 201 for report */
uint32_t p:1; /* padding flag */
uint32_t version:2; /* protocol version */
#endif
uint32_t pt:8; /* payload type */
uint32_t len:16; /* length of RTCP packet */
uint32_t ssrc; /* synchronization source identifier of packet send */
uint32_t timestampMSB; /* timestamp MSB */
uint32_t timestampLSB; /* timestamp LSB */
uint32_t timestampRTP; /* RTP timestamp */
uint32_t spc; /* Sender's packet count */
uint32_t soc; /* Sender's octet count */
} rtcpSRHeader;
class SocketPair {
public:
SocketPair(const char* uri, int localPort);
......@@ -106,8 +131,10 @@ class SocketPair {
const char* in_suite, const char* in_params);
void stopSendOp(bool state = true);
std::vector<rtcpRRHeader> getRtcpInfo();
bool rtcpPacketLossDetected() const;
std::list<rtcpRRHeader> getRtcpInfo();
bool waitForRTCP(std::chrono::seconds interval);
double getLastLatency();
private:
NON_COPYABLE(SocketPair);
......@@ -139,12 +166,17 @@ class SocketPair {
std::list<rtcpRRHeader> listRtcpHeader_;
std::mutex rtcpInfo_mutex_;
static constexpr unsigned MAX_LIST_SIZE {20};
std::condition_variable cvRtcpPacketReadyToRead_;
static constexpr unsigned MAX_LIST_SIZE {10};
mutable std::atomic_bool rtcpPacketLoss_ {false};
};
double lastSRTS_;
uint32_t lastDLSR_;
std::list<double> histoLatency_;
std::chrono::steady_clock::time_point lastRR_time;
};
} // namespace jami
......@@ -40,6 +40,8 @@ namespace jami { namespace video {
using std::string;
constexpr auto MS_BETWEEN_2_KEYFRAME_REQUEST = std::chrono::milliseconds(500);
VideoReceiveThread::VideoReceiveThread(const std::string& id,
const std::string &sdp,
uint16_t mtu) :
......@@ -199,7 +201,14 @@ bool VideoReceiveThread::decodeFrame()
case MediaDecoder::Status::DecodeError:
JAMI_WARN("video decoding failure");
if (requestKeyFrameCallback_)
requestKeyFrameCallback_();
{
auto keyFrameCheckTimer = std::chrono::steady_clock::now() - lastKeyFrameTime_;
if (keyFrameCheckTimer >= MS_BETWEEN_2_KEYFRAME_REQUEST)
{
lastKeyFrameTime_ = std::chrono::steady_clock::now();
requestKeyFrameCallback_();
}
}
break;
case MediaDecoder::Status::ReadError:
......
......@@ -90,6 +90,7 @@ private:
uint16_t mtu_;
int rotation_;
std::shared_ptr<AVBufferRef> displayMatrix_;
std::chrono::steady_clock::time_point lastKeyFrameTime_;
std::function<void(void)> requestKeyFrameCallback_;
void openDecoder();
......
......@@ -45,21 +45,16 @@ namespace jami { namespace video {
using std::string;
// how long (in seconds) to wait before rechecking for packet loss
static constexpr auto RTCP_PACKET_LOSS_INTERVAL = std::chrono::milliseconds(1000);
constexpr auto DELAY_AFTER_RESTART = std::chrono::seconds(2);
constexpr auto EXPIRY_TIME_RTCP = std::chrono::milliseconds(2000);
VideoRtpSession::VideoRtpSession(const string &callID,
const DeviceParams& localVideoParams) :
RtpSession(callID), localVideoParams_(localVideoParams)
, lastRTCPCheck_(std::chrono::system_clock::now())
, lastLongRTCPCheck_(std::chrono::system_clock::now())
, videoBitrateInfo_ {}
, rtcpCheckerThread_([] { return true; },
[this]{ processRtcpChecker(); },
[]{})
, packetLossThread_([] { return true; },
[this]{ processPacketLoss(); },
[]{})
{
setupVideoBitrateInfo(); // reset bitrate
}
......@@ -133,6 +128,7 @@ void VideoRtpSession::startSender()
JAMI_ERR("%s", e.what());
send_.enabled = false;
}
lastMediaRestart_ = clock::now();
auto codecVideo = std::static_pointer_cast<jami::AccountVideoCodecInfo>(send_.codec);
auto autoQuality = codecVideo->isAutoQualityEnabled;
if (autoQuality and not rtcpCheckerThread_.isRunning())
......@@ -168,13 +164,11 @@ void VideoRtpSession::startReceiver()
receiveThread_->setRequestKeyFrameCallback(requestKeyFrameCallback_);
receiveThread_->addIOContext(*socketPair_);
receiveThread_->startLoop();
packetLossThread_.start();
} else {
JAMI_DBG("Video receiving disabled");
if (receiveThread_)
receiveThread_->detach(videoMixer_.get());
receiveThread_.reset();
packetLossThread_.join();
}
}
......@@ -214,8 +208,6 @@ void VideoRtpSession::start(std::unique_ptr<IceSocket> rtp_sock,
void VideoRtpSession::stop()
{
std::lock_guard<std::recursive_mutex> lock(mutex_);
rtcpCheckerThread_.join();
packetLossThread_.join();
if (videoLocal_)
videoLocal_->detach(sender_.get());
......@@ -228,6 +220,8 @@ void VideoRtpSession::stop()
if (socketPair_)
socketPair_->interrupt();
rtcpCheckerThread_.join();
// reset default video quality if exist
if (videoBitrateInfo_.videoQualityCurrent != SystemCodecInfo::DEFAULT_NO_QUALITY)
videoBitrateInfo_.videoQualityCurrent = SystemCodecInfo::DEFAULT_CODEC_QUALITY;
......@@ -336,23 +330,29 @@ void VideoRtpSession::exitConference()
conference_ = nullptr;
}
float
VideoRtpSession::checkPeerPacketLoss()
bool
VideoRtpSession::checkMediumRCTPInfo(RTCPInfo& rtcpi)
{
auto rtcpInfoVect = socketPair_->getRtcpInfo();
unsigned totalLost = 0;
unsigned fract = 0;
unsigned totalJitter = 0;
unsigned nbDropNotNull = 0;
auto vectSize = rtcpInfoVect.size();
for (const auto& it : rtcpInfoVect) {
fract = (ntohl(it.fraction_lost) & 0xff000000) >> 24;
totalLost += fract;
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;
rtcpi.jitter = totalJitter / vectSize / 16; // millisecond
rtcpi.nb_sample = vectSize;
rtcpi.latency = socketPair_->getLastLatency();
return true;
}
if (vectSize != 0)
return (float)( 100 * totalLost) / (256.0 * vectSize);
else
return NO_PACKET_LOSS_CALCULATED;
return false;
}
unsigned
......@@ -392,117 +392,54 @@ VideoRtpSession::getLowerBitrate()
void
VideoRtpSession::adaptQualityAndBitrate()
{
bool needToCheckQuality = false;
bool mediaRestartNeeded = false;
float packetLostRate = 0.0;
auto rtcpCheckTimer = std::chrono::duration_cast<std::chrono::seconds> (std::chrono::system_clock::now() - lastRTCPCheck_);
auto rtcpLongCheckTimer = std::chrono::duration_cast<std::chrono::seconds> (std::chrono::system_clock::now() - lastLongRTCPCheck_);
setupVideoBitrateInfo();
if (rtcpCheckTimer.count() >= RTCP_CHECKING_INTERVAL) {
needToCheckQuality = true;
lastRTCPCheck_ = std::chrono::system_clock::now();
RTCPInfo rtcpi {};
if (not checkMediumRCTPInfo(rtcpi)) {
JAMI_DBG("[AutoAdapt] Sample not ready");
return;
}
if (rtcpLongCheckTimer.count() >= RTCP_LONG_CHECKING_INTERVAL) {
needToCheckQuality = true;
hasReachMaxQuality_ = false;
lastLongRTCPCheck_ = std::chrono::system_clock::now();
// we force iterative bitrate adaptation
videoBitrateInfo_.cptBitrateChecking = 0;
auto now = clock::now();
auto restartTimer = now - lastMediaRestart_;
//Sleep 3 seconds while the media restart
if (restartTimer < DELAY_AFTER_RESTART) {
//JAMI_DBG("[AutoAdapt] Waiting for delay %ld ms", std::chrono::duration_cast<std::chrono::milliseconds>(restartTimer));
return;
}
if (rtcpi.jitter > 5000) {
JAMI_DBG("[AutoAdapt] Jitter too high");
return;
}
if (needToCheckQuality) {
videoBitrateInfo_.cptBitrateChecking++;
// packetLostRate is not already available. Do nothing
if ((packetLostRate = checkPeerPacketLoss()) == NO_PACKET_LOSS_CALCULATED) {
// we force iterative bitrate adaptation
videoBitrateInfo_.cptBitrateChecking = 0;
// too much packet lost : decrease quality and bitrate
} else if (packetLostRate >= videoBitrateInfo_.packetLostThreshold) {
// calculate new quality by dichotomie
videoBitrateInfo_.videoQualityCurrent = getLowerQuality();
// calculate new bitrate by dichotomie
videoBitrateInfo_.videoBitrateCurrent = getLowerBitrate();
// boundaries low
if (videoBitrateInfo_.videoQualityCurrent > videoBitrateInfo_.videoQualityMin)
videoBitrateInfo_.videoQualityCurrent = videoBitrateInfo_.videoQualityMin;
if (videoBitrateInfo_.videoBitrateCurrent < videoBitrateInfo_.videoBitrateMin)
videoBitrateInfo_.videoBitrateCurrent = videoBitrateInfo_.videoBitrateMin;
// we force iterative bitrate and quality adaptation
videoBitrateInfo_.cptBitrateChecking = 0;
// asynchronous A/V media restart
// we give priority to quality
if (((videoBitrateInfo_.videoQualityCurrent != SystemCodecInfo::DEFAULT_NO_QUALITY) &&
(videoBitrateInfo_.videoQualityCurrent != (histoQuality_.empty() ? 0 : histoQuality_.back()))) ||
((videoBitrateInfo_.videoQualityCurrent == SystemCodecInfo::DEFAULT_NO_QUALITY) &&
(videoBitrateInfo_.videoBitrateCurrent != (histoBitrate_.empty() ? 0 : histoBitrate_.back())))) {
mediaRestartNeeded = true;
hasReachMaxQuality_ = true;
}
// no packet lost: increase quality and bitrate
} else if ((videoBitrateInfo_.cptBitrateChecking <= videoBitrateInfo_.maxBitrateChecking)
and not hasReachMaxQuality_) {
// calculate new quality by dichotomie
videoBitrateInfo_.videoQualityCurrent =
(videoBitrateInfo_.videoQualityCurrent + videoBitrateInfo_.videoQualityMax) / 2;
// calculate new bitrate by dichotomie
videoBitrateInfo_.videoBitrateCurrent =
( videoBitrateInfo_.videoBitrateCurrent + videoBitrateInfo_.videoBitrateMax) / 2;
// boundaries high
if (videoBitrateInfo_.videoQualityCurrent < videoBitrateInfo_.videoQualityMax)
videoBitrateInfo_.videoQualityCurrent = videoBitrateInfo_.videoQualityMax;
if (videoBitrateInfo_.videoBitrateCurrent > videoBitrateInfo_.videoBitrateMax)
videoBitrateInfo_.videoBitrateCurrent = videoBitrateInfo_.videoBitrateMax;
// asynchronous A/V media restart
// we give priority to quality
if (((videoBitrateInfo_.videoQualityCurrent != SystemCodecInfo::DEFAULT_NO_QUALITY) &&
(videoBitrateInfo_.videoQualityCurrent != (histoQuality_.empty() ? 0 : histoQuality_.back()))) ||
((videoBitrateInfo_.videoQualityCurrent == SystemCodecInfo::DEFAULT_NO_QUALITY) &&
(videoBitrateInfo_.videoBitrateCurrent != (histoBitrate_.empty() ? 0 : histoBitrate_.back()))))
mediaRestartNeeded = true;
if (videoBitrateInfo_.cptBitrateChecking == videoBitrateInfo_.maxBitrateChecking)
lastLongRTCPCheck_ = std::chrono::system_clock::now();
auto oldBitrate = videoBitrateInfo_.videoBitrateCurrent;
} else {
// nothing we reach maximal tries
}
//Take action only when two successive drop superior to 1% are catched...
//and when jitter is less than 5 seconds
auto pondLoss = getPonderateLoss(rtcpi.packetLoss);
//JAMI_DBG("[AutoAdapt] Ponderate packet loss rate: %f%, Last packet loss rate: %f%, Medium Jitter: %dms" , pondLoss, rtcpi.packetLoss, rtcpi.jitter);
if(pondLoss >= 2.0f)
{
videoBitrateInfo_.videoBitrateCurrent = videoBitrateInfo_.videoBitrateCurrent / ((rtcpi.packetLoss / 20)+1);
JAMI_WARN("[AutoAdapt] packet loss rate: %f%%, decrease bitrate from %d Kbps to %d Kbps", rtcpi.packetLoss, oldBitrate, videoBitrateInfo_.videoBitrateCurrent);
}
if (mediaRestartNeeded) {
videoBitrateInfo_.videoBitrateCurrent = std::max(videoBitrateInfo_.videoBitrateCurrent, videoBitrateInfo_.videoBitrateMin);
videoBitrateInfo_.videoBitrateCurrent = std::min(videoBitrateInfo_.videoBitrateCurrent, videoBitrateInfo_.videoBitrateMax);
if(oldBitrate != videoBitrateInfo_.videoBitrateCurrent) {
storeVideoBitrateInfo();
const auto& cid = callID_;
JAMI_DBG("[AutoAdapt] Restart media sender");
JAMI_WARN("[%u/%u] packetLostRate=%f -> change quality to %d bitrate to %d",
videoBitrateInfo_.cptBitrateChecking,
videoBitrateInfo_.maxBitrateChecking,
packetLostRate,
videoBitrateInfo_.videoQualityCurrent,
videoBitrateInfo_.videoBitrateCurrent);
const auto& cid = callID_;
runOnMainThread([cid]{
if (auto call = Manager::instance().callFactory.getCall(cid))
call->restartMediaSender();
});
lastMediaRestart_ = now;
}
}
......@@ -550,7 +487,6 @@ VideoRtpSession::storeVideoBitrateInfo() {
histoQuality_.push_back(videoBitrateInfo_.videoQualityCurrent);
histoBitrate_.push_back(videoBitrateInfo_.videoBitrateCurrent);
}
}
......@@ -558,17 +494,7 @@ void
VideoRtpSession::processRtcpChecker()
{
adaptQualityAndBitrate();
rtcpCheckerThread_.wait_for(std::chrono::seconds(RTCP_CHECKING_INTERVAL));
}
void
VideoRtpSession::processPacketLoss()
{
if (packetLossThread_.wait_for(RTCP_PACKET_LOSS_INTERVAL,
[this]{return socketPair_->rtcpPacketLossDetected();})) {
if (requestKeyFrameCallback_)
requestKeyFrameCallback_();
}
socketPair_->waitForRTCP(std::chrono::seconds(rtcp_checking_interval));
}
void
......@@ -607,4 +533,39 @@ VideoRtpSession::setChangeOrientationCallback(std::function<void(int)> cb)
changeOrientationCallback_ = std::move(cb);
}
float
VideoRtpSession::getPonderateLoss(float lastLoss)
{
float pond = 0.0f, pondLoss = 0.0f, totalPond = 0.0f;
constexpr float coefficient_a = -1/2000.0f;
constexpr float coefficient_b = 1.0f;
auto now = clock::now();
histoLoss_.emplace_back(now, lastLoss);
//for(auto& it : histoLoss_)
for (auto it = histoLoss_.begin(); it != histoLoss_.end();) {
auto delay = now - it->first;
//JAMI_WARN("now - it.first: %ld", std::chrono::duration_cast<std::chrono::milliseconds>(delay));
// 1ms -> 100%
// 2000ms -> 1
if(delay <= EXPIRY_TIME_RTCP)