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

autoadapt: change bitrate quickly

Change bitrate on the fly for supported codec, restart encoder only for other
(~10ms) instead of restart all pipeline

Change-Id: I1faad6e3cdc83f846d2279d9b8b997f1656f8596
parent bd855880
This diff is collapsed.
......@@ -100,6 +100,8 @@ public:
const std::string& getAudioCodec() const { return audioCodec_; }
const std::string& getVideoCodec() const { return videoCodec_; }
void setBitrate(uint64_t br);
#ifdef RING_ACCEL
void enableAccel(bool enableAccel);
#endif
......@@ -116,6 +118,9 @@ private:
int initStream(const SystemCodecInfo& systemCodecInfo, AVBufferRef* framesCtx);
void openIOContext();
void startIO();
AVCodecContext* getCurrentVideoAVCtx();
void stopEncoder();
AVCodecContext* initCodec(AVMediaType mediaType, AVCodecID avcodecId, AVBufferRef* framesCtx, uint64_t br);
std::vector<AVCodecContext*> encoders_;
AVFormatContext *outputCtx_ = nullptr;
......@@ -124,6 +129,14 @@ private:
unsigned sent_samples = 0;
bool initialized_ {false};
bool fileIO_ {false};
unsigned int currentVideoCodecID_ {0};
AVCodec* outputCodec_ = nullptr;
std::mutex encMutex_;
void initH264(AVCodecContext* encoderCtx, uint64_t br);
void initVP8(AVCodecContext* encoderCtx, uint64_t br);
void initMPEG4(AVCodecContext* encoderCtx, uint64_t br);
void initH263(AVCodecContext* encoderCtx, uint64_t br);
#ifdef ENABLE_VIDEO
video::VideoScaler scaler_;
......
......@@ -46,8 +46,8 @@ namespace jami { namespace video {
using std::string;
constexpr auto DELAY_AFTER_RESTART = std::chrono::seconds(2);
constexpr auto EXPIRY_TIME_RTCP = std::chrono::milliseconds(2000);
constexpr auto DELAY_AFTER_RESTART = std::chrono::milliseconds(1000);
constexpr auto EXPIRY_TIME_RTCP = std::chrono::milliseconds(1000);
VideoRtpSession::VideoRtpSession(const string &callID,
const DeviceParams& localVideoParams) :
......@@ -401,16 +401,16 @@ VideoRtpSession::adaptQualityAndBitrate()
return;
}
// If bitrate has changed, let time to receive fresh RTCP packets
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");
if (rtcpi.jitter > 1000) {
//JAMI_DBG("[AutoAdapt] Jitter too high");
return;
}
......@@ -419,11 +419,12 @@ VideoRtpSession::adaptQualityAndBitrate()
//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);
//JAMI_DBG("[AutoAdapt] Pondloss: %f%, last loss: %f%", pondLoss, rtcpi.packetLoss);
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);
videoBitrateInfo_.videoBitrateCurrent = videoBitrateInfo_.videoBitrateCurrent * (1.0f - rtcpi.packetLoss/150.0f);
JAMI_DBG("[AutoAdapt] pondLoss: %f%%, packet loss rate: %f%%, decrease bitrate from %d Kbps to %d Kbps, ratio %f", pondLoss, rtcpi.packetLoss, oldBitrate, videoBitrateInfo_.videoBitrateCurrent, (float) videoBitrateInfo_.videoBitrateCurrent / oldBitrate);
histoLoss_.clear();
}
videoBitrateInfo_.videoBitrateCurrent = std::max(videoBitrateInfo_.videoBitrateCurrent, videoBitrateInfo_.videoBitrateMin);
......@@ -431,16 +432,10 @@ VideoRtpSession::adaptQualityAndBitrate()
if(oldBitrate != videoBitrateInfo_.videoBitrateCurrent) {
storeVideoBitrateInfo();
JAMI_DBG("[AutoAdapt] Restart media sender");
const auto& cid = callID_;
runOnMainThread([cid]{
if (auto call = Manager::instance().callFactory.getCall(cid))
call->restartMediaSender();
});
lastMediaRestart_ = now;
// If encoder no longer exist do nothing
if(sender_->setBitrate(videoBitrateInfo_.videoBitrateCurrent) == 0)
lastMediaRestart_ = now;
}
}
......@@ -540,7 +535,7 @@ 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_a = -1/1000.0f;
constexpr float coefficient_b = 1.0f;
auto now = clock::now();
......@@ -553,7 +548,7 @@ VideoRtpSession::getPonderateLoss(float lastLoss)
//JAMI_WARN("now - it.first: %ld", std::chrono::duration_cast<std::chrono::milliseconds>(delay));
// 1ms -> 100%
// 2000ms -> 1
// 1000ms -> 1
if(delay <= EXPIRY_TIME_RTCP)
{
pond = std::min(delay.count() * coefficient_a + coefficient_b, 1.0f);
......
......@@ -141,4 +141,17 @@ VideoSender::setChangeOrientationCallback(std::function<void(int)> cb)
changeOrientationCallback_ = std::move(cb);
}
int
VideoSender::setBitrate(uint64_t br)
{
// The encoder may be destroy during a bitrate change
// when a codec parameter like auto quality change
if(!videoEncoder_)
return -1;
videoEncoder_->setBitrate(br);
return 0;
}
}} // namespace jami::video
......@@ -60,6 +60,7 @@ public:
uint16_t getLastSeqValue();
void setChangeOrientationCallback(std::function<void(int)> cb);
int setBitrate(uint64_t br);
private:
static constexpr int KEYFRAMES_AT_START {4}; // Number of keyframes to enforce at stream startup
......
Markdown is supported
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