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: ...@@ -100,6 +100,8 @@ public:
const std::string& getAudioCodec() const { return audioCodec_; } const std::string& getAudioCodec() const { return audioCodec_; }
const std::string& getVideoCodec() const { return videoCodec_; } const std::string& getVideoCodec() const { return videoCodec_; }
void setBitrate(uint64_t br);
#ifdef RING_ACCEL #ifdef RING_ACCEL
void enableAccel(bool enableAccel); void enableAccel(bool enableAccel);
#endif #endif
...@@ -116,6 +118,9 @@ private: ...@@ -116,6 +118,9 @@ private:
int initStream(const SystemCodecInfo& systemCodecInfo, AVBufferRef* framesCtx); int initStream(const SystemCodecInfo& systemCodecInfo, AVBufferRef* framesCtx);
void openIOContext(); void openIOContext();
void startIO(); void startIO();
AVCodecContext* getCurrentVideoAVCtx();
void stopEncoder();
AVCodecContext* initCodec(AVMediaType mediaType, AVCodecID avcodecId, AVBufferRef* framesCtx, uint64_t br);
std::vector<AVCodecContext*> encoders_; std::vector<AVCodecContext*> encoders_;
AVFormatContext *outputCtx_ = nullptr; AVFormatContext *outputCtx_ = nullptr;
...@@ -124,6 +129,14 @@ private: ...@@ -124,6 +129,14 @@ private:
unsigned sent_samples = 0; unsigned sent_samples = 0;
bool initialized_ {false}; bool initialized_ {false};
bool fileIO_ {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 #ifdef ENABLE_VIDEO
video::VideoScaler scaler_; video::VideoScaler scaler_;
......
...@@ -46,8 +46,8 @@ namespace jami { namespace video { ...@@ -46,8 +46,8 @@ namespace jami { namespace video {
using std::string; using std::string;
constexpr auto DELAY_AFTER_RESTART = std::chrono::seconds(2); constexpr auto DELAY_AFTER_RESTART = std::chrono::milliseconds(1000);
constexpr auto EXPIRY_TIME_RTCP = std::chrono::milliseconds(2000); constexpr auto EXPIRY_TIME_RTCP = std::chrono::milliseconds(1000);
VideoRtpSession::VideoRtpSession(const string &callID, VideoRtpSession::VideoRtpSession(const string &callID,
const DeviceParams& localVideoParams) : const DeviceParams& localVideoParams) :
...@@ -401,16 +401,16 @@ VideoRtpSession::adaptQualityAndBitrate() ...@@ -401,16 +401,16 @@ VideoRtpSession::adaptQualityAndBitrate()
return; return;
} }
// If bitrate has changed, let time to receive fresh RTCP packets
auto now = clock::now(); auto now = clock::now();
auto restartTimer = now - lastMediaRestart_; auto restartTimer = now - lastMediaRestart_;
//Sleep 3 seconds while the media restart
if (restartTimer < DELAY_AFTER_RESTART) { if (restartTimer < DELAY_AFTER_RESTART) {
//JAMI_DBG("[AutoAdapt] Waiting for delay %ld ms", std::chrono::duration_cast<std::chrono::milliseconds>(restartTimer)); //JAMI_DBG("[AutoAdapt] Waiting for delay %ld ms", std::chrono::duration_cast<std::chrono::milliseconds>(restartTimer));
return; return;
} }
if (rtcpi.jitter > 5000) { if (rtcpi.jitter > 1000) {
JAMI_DBG("[AutoAdapt] Jitter too high"); //JAMI_DBG("[AutoAdapt] Jitter too high");
return; return;
} }
...@@ -419,11 +419,12 @@ VideoRtpSession::adaptQualityAndBitrate() ...@@ -419,11 +419,12 @@ VideoRtpSession::adaptQualityAndBitrate()
//Take action only when two successive drop superior to 1% are catched... //Take action only when two successive drop superior to 1% are catched...
//and when jitter is less than 5 seconds //and when jitter is less than 5 seconds
auto pondLoss = getPonderateLoss(rtcpi.packetLoss); 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) if(pondLoss >= 2.0f)
{ {
videoBitrateInfo_.videoBitrateCurrent = videoBitrateInfo_.videoBitrateCurrent / ((rtcpi.packetLoss / 20)+1); videoBitrateInfo_.videoBitrateCurrent = videoBitrateInfo_.videoBitrateCurrent * (1.0f - rtcpi.packetLoss/150.0f);
JAMI_WARN("[AutoAdapt] packet loss rate: %f%%, decrease bitrate from %d Kbps to %d Kbps", rtcpi.packetLoss, oldBitrate, videoBitrateInfo_.videoBitrateCurrent); 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); videoBitrateInfo_.videoBitrateCurrent = std::max(videoBitrateInfo_.videoBitrateCurrent, videoBitrateInfo_.videoBitrateMin);
...@@ -431,16 +432,10 @@ VideoRtpSession::adaptQualityAndBitrate() ...@@ -431,16 +432,10 @@ VideoRtpSession::adaptQualityAndBitrate()
if(oldBitrate != videoBitrateInfo_.videoBitrateCurrent) { if(oldBitrate != videoBitrateInfo_.videoBitrateCurrent) {
storeVideoBitrateInfo(); storeVideoBitrateInfo();
JAMI_DBG("[AutoAdapt] Restart media sender");
const auto& cid = callID_; // If encoder no longer exist do nothing
if(sender_->setBitrate(videoBitrateInfo_.videoBitrateCurrent) == 0)
runOnMainThread([cid]{ lastMediaRestart_ = now;
if (auto call = Manager::instance().callFactory.getCall(cid))
call->restartMediaSender();
});
lastMediaRestart_ = now;
} }
} }
...@@ -540,7 +535,7 @@ float ...@@ -540,7 +535,7 @@ float
VideoRtpSession::getPonderateLoss(float lastLoss) VideoRtpSession::getPonderateLoss(float lastLoss)
{ {
float pond = 0.0f, pondLoss = 0.0f, totalPond = 0.0f; 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; constexpr float coefficient_b = 1.0f;
auto now = clock::now(); auto now = clock::now();
...@@ -553,7 +548,7 @@ VideoRtpSession::getPonderateLoss(float lastLoss) ...@@ -553,7 +548,7 @@ VideoRtpSession::getPonderateLoss(float lastLoss)
//JAMI_WARN("now - it.first: %ld", std::chrono::duration_cast<std::chrono::milliseconds>(delay)); //JAMI_WARN("now - it.first: %ld", std::chrono::duration_cast<std::chrono::milliseconds>(delay));
// 1ms -> 100% // 1ms -> 100%
// 2000ms -> 1 // 1000ms -> 1
if(delay <= EXPIRY_TIME_RTCP) if(delay <= EXPIRY_TIME_RTCP)
{ {
pond = std::min(delay.count() * coefficient_a + coefficient_b, 1.0f); pond = std::min(delay.count() * coefficient_a + coefficient_b, 1.0f);
......
...@@ -141,4 +141,17 @@ VideoSender::setChangeOrientationCallback(std::function<void(int)> cb) ...@@ -141,4 +141,17 @@ VideoSender::setChangeOrientationCallback(std::function<void(int)> cb)
changeOrientationCallback_ = std::move(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 }} // namespace jami::video
...@@ -60,6 +60,7 @@ public: ...@@ -60,6 +60,7 @@ public:
uint16_t getLastSeqValue(); uint16_t getLastSeqValue();
void setChangeOrientationCallback(std::function<void(int)> cb); void setChangeOrientationCallback(std::function<void(int)> cb);
int setBitrate(uint64_t br);
private: private:
static constexpr int KEYFRAMES_AT_START {4}; // Number of keyframes to enforce at stream startup 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