Commit 82fb0dae authored by Eloi Bail's avatar Eloi Bail Committed by Guillaume Roguez
Browse files

media/video: use crf rather than bitrate

Dynamic quality change was done by increase/decreasing encoder bitrate.
It led to video artefact issues, specialy at low bitrates.
In addition, it does not make sence to use same bitrate with different
resolutions and fps. With high resolutions and fps, maximal bitrate
need to be higher.

It is possible for H264 and VP8 to set video quality using CRF.
This parameter solves video artefact issues and choose a different
output bitrate depending on input resolution and fps.

Tuleap: #80
Change-Id: I07d37175dfc335b5fc70cf54798f82eafe921ea9
parent 1474bf0a
......@@ -223,6 +223,9 @@ constexpr static const char FRAME_RATE [] = "CodecInfo.frameRate";
constexpr static const char BITRATE [] = "CodecInfo.bitrate";
constexpr static const char MIN_BITRATE [] = "CodecInfo.min_bitrate";
constexpr static const char MAX_BITRATE [] = "CodecInfo.max_bitrate";
constexpr static const char QUALITY [] = "CodecInfo.quality";
constexpr static const char MIN_QUALITY [] = "CodecInfo.min_quality";
constexpr static const char MAX_QUALITY [] = "CodecInfo.max_quality";
constexpr static const char CHANNEL_NUMBER [] = "CodecInfo.channelNumber";
} //namespace DRing::Account::ConfProperties::CodecInfo
......
......@@ -42,7 +42,10 @@ generateId()
SystemCodecInfo::SystemCodecInfo(unsigned avcodecId, const std::string name,
std::string libName,
MediaType mediaType, CodecType codecType,
unsigned bitrate, unsigned payloadType)
unsigned bitrate,
unsigned payloadType,
unsigned minQuality,
unsigned maxQuality)
: id(generateId())
, avcodecId(avcodecId)
, name(name)
......@@ -51,6 +54,8 @@ SystemCodecInfo::SystemCodecInfo(unsigned avcodecId, const std::string name,
, mediaType(mediaType)
, payloadType(payloadType)
, bitrate(bitrate)
, minQuality(minQuality)
, maxQuality(maxQuality)
{}
SystemCodecInfo::~SystemCodecInfo()
......@@ -94,11 +99,13 @@ SystemVideoCodecInfo::SystemVideoCodecInfo(unsigned m_avcodecId,
std::string m_libName,
CodecType m_type,
unsigned m_bitrate,
unsigned m_minQuality,
unsigned m_maxQuality,
unsigned m_payloadType,
unsigned m_frameRate,
unsigned m_profileId)
: SystemCodecInfo(m_avcodecId, m_name, m_libName, MEDIA_VIDEO,
m_type, m_bitrate, m_payloadType)
m_type, m_bitrate, m_payloadType, m_minQuality, m_maxQuality)
, frameRate(m_frameRate), profileId(m_profileId)
{}
......@@ -124,7 +131,10 @@ AccountCodecInfo::AccountCodecInfo(const SystemCodecInfo& sysCodecInfo)
, isActive(true)
, payloadType(sysCodecInfo.payloadType)
, bitrate(sysCodecInfo.bitrate)
{}
{
if (sysCodecInfo.minQuality != SystemCodecInfo::DEFAULT_NO_QUALITY)
quality = SystemCodecInfo::DEFAULT_CODEC_QUALITY;
}
AccountCodecInfo::~AccountCodecInfo()
{}
......@@ -187,6 +197,9 @@ AccountVideoCodecInfo::getCodecSpecifications()
{DRing::Account::ConfProperties::CodecInfo::BITRATE, to_string(bitrate)},
{DRing::Account::ConfProperties::CodecInfo::MAX_BITRATE, to_string(systemCodecInfo.maxBitrate)},
{DRing::Account::ConfProperties::CodecInfo::MIN_BITRATE, to_string(systemCodecInfo.minBitrate)},
{DRing::Account::ConfProperties::CodecInfo::QUALITY, to_string(quality)},
{DRing::Account::ConfProperties::CodecInfo::MAX_QUALITY, to_string(systemCodecInfo.maxQuality)},
{DRing::Account::ConfProperties::CodecInfo::MIN_QUALITY, to_string(systemCodecInfo.minQuality)},
{DRing::Account::ConfProperties::CodecInfo::FRAME_RATE, to_string(frameRate)}
};
}
......@@ -201,6 +214,10 @@ AccountVideoCodecInfo::setCodecSpecifications(const std::map<std::string, std::s
it = details.find(DRing::Account::ConfProperties::CodecInfo::FRAME_RATE);
if (it != details.end())
frameRate = ring::stoi(it->second);
it = details.find(DRing::Account::ConfProperties::CodecInfo::QUALITY);
if (it != details.end())
quality = ring::stoi(it->second);
}
AccountVideoCodecInfo::~AccountVideoCodecInfo()
......
......@@ -59,16 +59,29 @@ enum MediaType : unsigned {
*/
struct SystemCodecInfo
{
static constexpr unsigned DEFAULT_CODEC_QUALITY {35};
#ifdef RING_VIDEO
static constexpr unsigned DEFAULT_H264_MIN_QUALITY {50};
static constexpr unsigned DEFAULT_H264_MAX_QUALITY {25};
static constexpr unsigned DEFAULT_VP8_MIN_QUALITY {50};
static constexpr unsigned DEFAULT_VP8_MAX_QUALITY {20};
#endif
// 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 {2000};
SystemCodecInfo(unsigned avcodecId, const std::string name,
std::string libName, MediaType mediaType,
CodecType codecType = CODEC_NONE, unsigned bitrate = 0,
unsigned payloadType = 0);
unsigned payloadType = 0,
unsigned m_minQuality = DEFAULT_NO_QUALITY,
unsigned m_maxQuality = DEFAULT_NO_QUALITY);
virtual ~SystemCodecInfo();
static constexpr unsigned DEFAULT_MIN_BITRATE {250};
static constexpr unsigned DEFAULT_MAX_BITRATE {2000};
/* generic codec information */
unsigned id; /* id of the codec used with dbus */
unsigned avcodecId; /* read as AVCodecID libav codec identifier */
......@@ -82,6 +95,8 @@ struct SystemCodecInfo
unsigned bitrate;
unsigned minBitrate = DEFAULT_MIN_BITRATE;
unsigned maxBitrate = DEFAULT_MAX_BITRATE;
unsigned minQuality = DEFAULT_NO_QUALITY;
unsigned maxQuality = DEFAULT_NO_QUALITY;
};
/*
......@@ -114,7 +129,10 @@ struct SystemVideoCodecInfo : SystemCodecInfo
SystemVideoCodecInfo(unsigned avcodecId, const std::string name,
std::string libName, CodecType type = CODEC_NONE,
unsigned bitrate = 0,
unsigned payloadType = 0, unsigned frameRate = 0,
unsigned m_minQuality = 0,
unsigned m_maxQuality = 0,
unsigned payloadType = 0,
unsigned frameRate = 0,
unsigned profileId = 0);
~SystemVideoCodecInfo();
......@@ -142,6 +160,7 @@ struct AccountCodecInfo
/* account custom values */
unsigned payloadType;
unsigned bitrate;
unsigned quality;
std::map<std::string, std::string> getCodecSpecifications();
};
......
......@@ -2,6 +2,7 @@
* Copyright (C) 2013-2015 Savoir-faire Linux Inc.
*
* Author: Guillaume Roguez <Guillaume.Roguez@savoirfairelinux.com>
* Author: Eloi Bail <Eloi.Bail@savoirfairelinux.com>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
......@@ -75,6 +76,7 @@ void MediaEncoder::setOptions(const MediaDescription& args)
av_dict_set(&options_, "payload_type", ring::to_string(args.payload_type).c_str(), 0);
av_dict_set(&options_, "max_rate", ring::to_string(args.codec->bitrate).c_str(), 0);
av_dict_set(&options_, "crf", ring::to_string(args.codec->quality).c_str(), 0);
if (args.codec->systemCodecInfo.mediaType == MEDIA_AUDIO) {
auto accountAudioCodec = std::static_pointer_cast<AccountAudioCodecInfo>(args.codec);
......@@ -140,17 +142,30 @@ MediaEncoder::openOutput(const char *filename,
prepareEncoderContext(args.codec->systemCodecInfo.mediaType == MEDIA_VIDEO);
auto maxBitrate = 1000 * atoi(av_dict_get(options_, "max_rate", NULL, 0)->value);
encoderCtx_->rc_buffer_size = maxBitrate;
RING_DBG("Using max bitrate %d", maxBitrate );
auto crf = atoi(av_dict_get(options_, "crf", NULL, 0)->value);
/* let x264 preset override our encoder settings */
if (args.codec->systemCodecInfo.avcodecId == AV_CODEC_ID_H264) {
extractProfileLevelID(args.parameters, encoderCtx_);
forcePresetX264();
// For H264 : define max bitrate in rc_max_rate
encoderCtx_->rc_max_rate = maxBitrate;
// For H264 :
// 1- if quality is set use it
// 2- otherwise set rc_max_rate and rc_buffer_size
if (crf != SystemCodecInfo::DEFAULT_NO_QUALITY) {
av_opt_set(encoderCtx_->priv_data, "crf", av_dict_get(options_, "crf", NULL, 0)->value, 0);
RING_DBG("Using quality factor %d", crf);
} else {
encoderCtx_->rc_buffer_size = maxBitrate;
encoderCtx_->rc_max_rate = maxBitrate;
RING_DBG("Using max bitrate %d", maxBitrate );
}
} else if (args.codec->systemCodecInfo.avcodecId == AV_CODEC_ID_VP8) {
// For VP8 :
// 1- if quality is set use it
// bitrate need to be set. The target bitrate becomes the maximum allowed bitrate
// 2- otherwise set rc_max_rate and rc_buffer_size
// Using information given on this page:
// http://www.webmproject.org/docs/encoder-parameters/
av_opt_set(encoderCtx_->priv_data, "quality", "realtime", 0);
......@@ -161,11 +176,22 @@ MediaEncoder::openOutput(const char *filename,
encoderCtx_->qmin = 4;
encoderCtx_->qmax = 56;
encoderCtx_->gop_size = 999999;
// For VP8 : define max bitrate in bit_rate
encoderCtx_->rc_buffer_size = maxBitrate;
encoderCtx_->bit_rate = maxBitrate;
if (crf != SystemCodecInfo::DEFAULT_NO_QUALITY) {
av_opt_set(encoderCtx_->priv_data, "crf", av_dict_get(options_, "crf", NULL, 0)->value, 0);
RING_DBG("Using quality factor %d", crf);
} else {
RING_DBG("Using Max bitrate %d", maxBitrate);
}
} else if (args.codec->systemCodecInfo.avcodecId == AV_CODEC_ID_MPEG4) {
// For MPEG4 : define max bitrate in bit_rate
encoderCtx_->bit_rate = maxBitrate;
// For MPEG4 :
// No CRF avaiable.
// Use CBR (set bitrate)
encoderCtx_->rc_buffer_size = maxBitrate;
encoderCtx_->bit_rate = encoderCtx_->rc_min_rate = encoderCtx_->rc_max_rate = maxBitrate;
RING_DBG("Using Max bitrate %d", maxBitrate);
}
int ret;
......
......@@ -46,18 +46,28 @@ SystemCodecContainer::~SystemCodecContainer()
void
SystemCodecContainer::initCodecConfig()
{
#ifdef RING_VIDEO
auto minH264 = SystemCodecInfo::DEFAULT_H264_MIN_QUALITY;
auto maxH264 = SystemCodecInfo::DEFAULT_H264_MAX_QUALITY;
auto minVP8 = SystemCodecInfo::DEFAULT_VP8_MIN_QUALITY;
auto maxVP8 = SystemCodecInfo::DEFAULT_VP8_MAX_QUALITY;
#endif
availableCodecList_ = {
#ifdef RING_VIDEO
/* Define supported video codec*/
std::make_shared<SystemVideoCodecInfo>(AV_CODEC_ID_H264,
"H264", "libx264",
CODEC_ENCODER_DECODER,
DEFAULT_VIDEO_BITRATE),
DEFAULT_VIDEO_BITRATE,
minH264,
maxH264),
std::make_shared<SystemVideoCodecInfo>(AV_CODEC_ID_VP8,
"VP8", "libvpx",
CODEC_ENCODER_DECODER,
DEFAULT_VIDEO_BITRATE),
DEFAULT_VIDEO_BITRATE,
minVP8,
maxVP8),
std::make_shared<SystemVideoCodecInfo>(AV_CODEC_ID_MPEG4,
"MP4V-ES", "mpeg4",
......
......@@ -310,10 +310,44 @@ VideoRtpSession::checkPeerPacketLoss()
return NO_PACKET_LOSS_CALCULATED;
}
unsigned
VideoRtpSession::getLowerQuality()
{
// if lower quality was stored we return it
unsigned quality = videoBitrateInfo_.videoQualityCurrent;
while ( not histoQuality_.empty()) {
quality = histoQuality_.back();
histoQuality_.pop_back();
if (quality > videoBitrateInfo_.videoQualityCurrent)
return quality;
}
// if no appropriate quality found, calculate it with dichotomie
quality = (videoBitrateInfo_.videoQualityCurrent + videoBitrateInfo_.videoQualityMin) / 2;
return quality;
}
unsigned
VideoRtpSession::getLowerBitrate()
{
// if a lower bitrate was stored we return it
unsigned bitrate = videoBitrateInfo_.videoBitrateCurrent;
while ( not histoBitrate_.empty()) {
bitrate = histoBitrate_.back();
histoBitrate_.pop_back();
if (bitrate < videoBitrateInfo_.videoBitrateCurrent)
return bitrate;
}
// if no appropriate bitrate found, calculate it with dichotomie
bitrate = (videoBitrateInfo_.videoBitrateCurrent + videoBitrateInfo_.videoBitrateMin) / 2;
return bitrate;
}
void
VideoRtpSession::adaptBitrate()
VideoRtpSession::adaptQualityAndBitrate()
{
bool needToCheckBitrate = false;
bool needToCheckQuality = false;
bool mediaRestartNeeded = false;
float packetLostRate = 0.0;
......@@ -321,65 +355,87 @@ VideoRtpSession::adaptBitrate()
auto rtcpLongCheckTimer = std::chrono::duration_cast<std::chrono::seconds> (std::chrono::system_clock::now() - lastLongRTCPCheck_);
if (rtcpCheckTimer.count() >= RTCP_CHECKING_INTERVAL) {
needToCheckBitrate = true;
needToCheckQuality = true;
lastRTCPCheck_ = std::chrono::system_clock::now();
}
if (rtcpLongCheckTimer.count() >= RTCP_LONG_CHECKING_INTERVAL) {
needToCheckBitrate = true;
needToCheckQuality = true;
lastLongRTCPCheck_ = std::chrono::system_clock::now();
//we force iterative bitrate adaptation
// we force iterative bitrate adaptation
videoBitrateInfo_.cptBitrateChecking = 0;
}
if (needToCheckBitrate) {
if (needToCheckQuality) {
videoBitrateInfo_.cptBitrateChecking++;
auto oldBitrate = videoBitrateInfo_.videoBitrateCurrent;
//packetLostRate is not already available. Do nothing
// packetLostRate is not already available. Do nothing
if ((packetLostRate = checkPeerPacketLoss()) == NO_PACKET_LOSS_CALCULATED) {
//we force iterative bitrate adaptation
// we force iterative bitrate adaptation
videoBitrateInfo_.cptBitrateChecking = 0;
//too much packet lost : decrease bitrate
// too much packet lost : decrease quality and bitrate
} else if (packetLostRate >= videoBitrateInfo_.packetLostThreshold) {
//calculate new bitrate by dichotomie
videoBitrateInfo_.videoBitrateCurrent =
(videoBitrateInfo_.videoBitrateCurrent + videoBitrateInfo_.videoBitrateMin) / 2;
// 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;
//boundaries low
if (videoBitrateInfo_.videoBitrateCurrent < videoBitrateInfo_.videoBitrateMin)
videoBitrateInfo_.videoBitrateCurrent = videoBitrateInfo_.videoBitrateMin;
//we force iterative bitrate adaptation
// we force iterative bitrate and quality adaptation
videoBitrateInfo_.cptBitrateChecking = 0;
//asynchronous A/V media restart
if (videoBitrateInfo_.videoBitrateCurrent != oldBitrate)
// 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;
//no packet lost: increase bitrate
// no packet lost: increase quality and bitrate
} else if (videoBitrateInfo_.cptBitrateChecking <= videoBitrateInfo_.maxBitrateChecking) {
//calculate new bitrate by dichotomie
// 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
// 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
if (videoBitrateInfo_.videoBitrateCurrent != oldBitrate)
// 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();
} else {
//nothing we reach maximal tries
// nothing we reach maximal tries
}
}
......@@ -387,10 +443,11 @@ VideoRtpSession::adaptBitrate()
storeVideoBitrateInfo();
const auto& cid = callID_;
RING_WARN("[%u/%u] packetLostRate=%f -> change bitrate to %d",
RING_WARN("[%u/%u] packetLostRate=%f -> change quality to %d bitrate to %d",
videoBitrateInfo_.cptBitrateChecking,
videoBitrateInfo_.maxBitrateChecking,
packetLostRate,
videoBitrateInfo_.videoQualityCurrent,
videoBitrateInfo_.videoBitrateCurrent);
runOnMainThread([cid]{
......@@ -399,7 +456,6 @@ VideoRtpSession::adaptBitrate()
});
}
}
void
VideoRtpSession::getVideoBitrateInfo() {
auto codecVideo = std::static_pointer_cast<ring::AccountVideoCodecInfo>(send_.codec);
......@@ -408,12 +464,15 @@ VideoRtpSession::getVideoBitrateInfo() {
(unsigned)(ring::stoi(codecVideo->getCodecSpecifications()[DRing::Account::ConfProperties::CodecInfo::BITRATE])),
(unsigned)(ring::stoi(codecVideo->getCodecSpecifications()[DRing::Account::ConfProperties::CodecInfo::MIN_BITRATE])),
(unsigned)(ring::stoi(codecVideo->getCodecSpecifications()[DRing::Account::ConfProperties::CodecInfo::MAX_BITRATE])),
(unsigned)(ring::stoi(codecVideo->getCodecSpecifications()[DRing::Account::ConfProperties::CodecInfo::QUALITY])),
(unsigned)(ring::stoi(codecVideo->getCodecSpecifications()[DRing::Account::ConfProperties::CodecInfo::MIN_QUALITY])),
(unsigned)(ring::stoi(codecVideo->getCodecSpecifications()[DRing::Account::ConfProperties::CodecInfo::MAX_QUALITY])),
videoBitrateInfo_.cptBitrateChecking,
videoBitrateInfo_.maxBitrateChecking,
videoBitrateInfo_.packetLostThreshold,
};
} else {
videoBitrateInfo_ = {0,0,0,0,0,0};
videoBitrateInfo_ = {0,0,0,0,0,0,0,0,0};
}
}
......@@ -425,8 +484,21 @@ VideoRtpSession::storeVideoBitrateInfo() {
codecVideo->setCodecSpecifications({
{DRing::Account::ConfProperties::CodecInfo::BITRATE, ring::to_string(videoBitrateInfo_.videoBitrateCurrent)},
{DRing::Account::ConfProperties::CodecInfo::MIN_BITRATE, ring::to_string(videoBitrateInfo_.videoBitrateMin)},
{DRing::Account::ConfProperties::CodecInfo::MAX_BITRATE, ring::to_string(videoBitrateInfo_.videoBitrateMax)}
{DRing::Account::ConfProperties::CodecInfo::MAX_BITRATE, ring::to_string(videoBitrateInfo_.videoBitrateMax)},
{DRing::Account::ConfProperties::CodecInfo::QUALITY, ring::to_string(videoBitrateInfo_.videoQualityCurrent)},
{DRing::Account::ConfProperties::CodecInfo::MIN_QUALITY, ring::to_string(videoBitrateInfo_.videoQualityMin)},
{DRing::Account::ConfProperties::CodecInfo::MAX_QUALITY, ring::to_string(videoBitrateInfo_.videoQualityMax)}
});
if (histoQuality_.size() > MAX_SIZE_HISTO_QUALITY_)
histoQuality_.pop_front();
if (histoBitrate_.size() > MAX_SIZE_HISTO_BITRATE_)
histoBitrate_.pop_front();
histoQuality_.push_back(videoBitrateInfo_.videoQualityCurrent);
histoBitrate_.push_back(videoBitrateInfo_.videoBitrateCurrent);
}
}
bool
......@@ -439,7 +511,7 @@ VideoRtpSession::setupRtcpChecker()
void
VideoRtpSession::processRtcpChecker()
{
adaptBitrate();
adaptQualityAndBitrate();
rtcpCheckerThread_.wait_for(std::chrono::seconds(RTCP_CHECKING_INTERVAL));
}
......
......@@ -45,6 +45,9 @@ struct VideoBitrateInfo {
unsigned videoBitrateCurrent;
unsigned videoBitrateMin;
unsigned videoBitrateMax;
unsigned videoQualityCurrent;
unsigned videoQualityMin;
unsigned videoQualityMax;
unsigned cptBitrateChecking;
unsigned maxBitrateChecking;
float packetLostThreshold;
......@@ -92,19 +95,28 @@ private:
uint16_t initSeqVal_ = 0;
float checkPeerPacketLoss();
void adaptBitrate();
unsigned getLowerQuality();
unsigned getLowerBitrate();
void adaptQualityAndBitrate();
void storeVideoBitrateInfo();
void getVideoBitrateInfo();
//interval in seconds between RTCP checkings
// interval in seconds between RTCP checkings
const unsigned RTCP_CHECKING_INTERVAL {4};
//long interval in seconds between RTCP checkings
// long interval in seconds between RTCP checkings
const unsigned RTCP_LONG_CHECKING_INTERVAL {30};
//not packet loss can be calculated as no data in input
// no packet loss can be calculated as no data in input
static constexpr float NO_PACKET_LOSS_CALCULATED {-1.0};
//bitrate info struct
VideoBitrateInfo videoBitrateInfo_ = {0,0,0,0, MAX_ADAPTATIVE_BITRATE_ITERATION, PACKET_LOSS_THRESHOLD};
// bitrate and quality info struct
VideoBitrateInfo videoBitrateInfo_ = {0,0,0,0,0,0,0, MAX_ADAPTATIVE_BITRATE_ITERATION, PACKET_LOSS_THRESHOLD};
// previous quality and bitrate used if quality or bitrate need to be decreased
std::list<unsigned> histoQuality_ {};
std::list<unsigned> histoBitrate_ {};
// max size of quality and bitrate historic
static constexpr unsigned MAX_SIZE_HISTO_QUALITY_ {30};
static constexpr unsigned MAX_SIZE_HISTO_BITRATE_ {100};
//5 tries in a row
static constexpr unsigned MAX_ADAPTATIVE_BITRATE_ITERATION {5};
//packet loss threshold
......
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment