diff --git a/src/dring/account_const.h b/src/dring/account_const.h index 379b4d4b4914a003cd41f9c4b293c18d9d1cb0ad..cce6bc96795cc9a54ec11642a66386fcbbbbd23f 100644 --- a/src/dring/account_const.h +++ b/src/dring/account_const.h @@ -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 diff --git a/src/media/media_codec.cpp b/src/media/media_codec.cpp index d34075377168e55ee804b046acc2fe76f69d3f5c..b1939b204c34a76aaccdfb28ead5380b2a7df54c 100644 --- a/src/media/media_codec.cpp +++ b/src/media/media_codec.cpp @@ -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() diff --git a/src/media/media_codec.h b/src/media/media_codec.h index 5f2d6a3f36b89264a85e921a1542ef3f3befcd9c..46ed7896ea7211bc3ebdfa0fc6deb1ce49b19660 100644 --- a/src/media/media_codec.h +++ b/src/media/media_codec.h @@ -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(); }; diff --git a/src/media/media_encoder.cpp b/src/media/media_encoder.cpp index 6705bdeac1221f96b2a659404c0fec3f6550e875..ea93b19bf9d8324e15371fa92a7165ea2d4bb31b 100644 --- a/src/media/media_encoder.cpp +++ b/src/media/media_encoder.cpp @@ -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; diff --git a/src/media/system_codec_container.cpp b/src/media/system_codec_container.cpp index 3a8a0ae2585fe3fb450c87ab478db126b310b308..ec23e5d92b261408cd93d253fbff801ab146efdb 100644 --- a/src/media/system_codec_container.cpp +++ b/src/media/system_codec_container.cpp @@ -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", diff --git a/src/media/video/video_rtp_session.cpp b/src/media/video/video_rtp_session.cpp index 219d4da360f4e515154c1e0530c1e59c07c5c825..0727065548e33801efa1ae256bbc6b2be42e2e64 100644 --- a/src/media/video/video_rtp_session.cpp +++ b/src/media/video/video_rtp_session.cpp @@ -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)); } diff --git a/src/media/video/video_rtp_session.h b/src/media/video/video_rtp_session.h index ca469b828f203d49ac2bc65f1ceee19f9bd53392..5010cb62f46d9c2ebab71a21237b9ce399fb7faa 100644 --- a/src/media/video/video_rtp_session.h +++ b/src/media/video/video_rtp_session.h @@ -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