Skip to content
Snippets Groups Projects
Commit 8fc78c4b authored by Pierre Lespagnol's avatar Pierre Lespagnol Committed by Adrien Béraud
Browse files

media/encoder: add CBR rate mode for autoadapt

Change-Id: Ida76ac6be3f33a15df7942afb40d21c5594781c5
parent 5839f47a
Branches
Tags
No related merge requests found
......@@ -278,6 +278,7 @@ struct MediaDescription {
/** Video parameters */
std::string parameters {};
bool auto_quality {false};
/** Crypto parameters */
CryptoAttribute crypto {};
......
......@@ -118,6 +118,8 @@ MediaEncoder::setOptions(const MediaDescription& args)
if (not args.parameters.empty())
libav_utils::setDictValue(&options_, "parameters", args.parameters);
auto_quality = args.auto_quality;
}
void
......@@ -552,7 +554,7 @@ MediaEncoder::prepareEncoderContext(AVCodec* outputCodec, bool is_video)
void
MediaEncoder::forcePresetX264(AVCodecContext* encoderCtx)
{
const char *speedPreset = "ultrafast";
const char *speedPreset = "veryfast";
if (av_opt_set(encoderCtx, "preset", speedPreset, AV_OPT_SEARCH_CHILDREN))
JAMI_WARN("Failed to set x264 preset '%s'", speedPreset);
const char *tune = "zerolatency";
......@@ -739,32 +741,41 @@ MediaEncoder::setBitrate(uint64_t br)
else if(codecId == AV_CODEC_ID_MPEG4)
initMPEG4(encoderCtx, br);
else {
stopEncoder();
encoderCtx = initCodec(codecType, codecId, NULL, br);
if (avcodec_open2(encoderCtx, outputCodec_, &options_) < 0)
throw MediaEncoderException("Could not open encoder");
// restart encoder on runtime doesn't work for VP8
// stopEncoder();
// encoderCtx = initCodec(codecType, codecId, NULL, br);
// if (avcodec_open2(encoderCtx, outputCodec_, &options_) < 0)
// throw MediaEncoderException("Could not open encoder");
}
}
void
MediaEncoder::initH264(AVCodecContext* encoderCtx, uint64_t br)
{
// If auto quality disabled use CRF mode
if(not auto_quality) {
uint64_t maxBitrate = 1000 * br;
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;
#ifdef RING_ACCEL
if (accel_) {
bufSize = 2 * maxBitrate;
encoderCtx->bit_rate = maxBitrate;
}
#endif
uint64_t bufSize = maxBitrate * 2;
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;
av_opt_set_int(encoderCtx, "b", maxBitrate, AV_OPT_SEARCH_CHILDREN);
av_opt_set_int(encoderCtx, "maxrate", maxBitrate, AV_OPT_SEARCH_CHILDREN);
av_opt_set_int(encoderCtx, "minrate", -1, AV_OPT_SEARCH_CHILDREN);
av_opt_set_int(encoderCtx, "bufsize", bufSize, AV_OPT_SEARCH_CHILDREN);
JAMI_DBG("H264 encoder setup: crf=%u, maxrate=%lu, bufsize=%lu", crf, maxBitrate, bufSize);
}
// If auto quality enabled use CRB mode
else {
av_opt_set_int(encoderCtx, "b", br * 1000, AV_OPT_SEARCH_CHILDREN);
av_opt_set_int(encoderCtx, "maxrate", br * 1000, AV_OPT_SEARCH_CHILDREN);
av_opt_set_int(encoderCtx, "minrate", br * 1000, AV_OPT_SEARCH_CHILDREN);
av_opt_set_int(encoderCtx, "bufsize", br * 500, AV_OPT_SEARCH_CHILDREN);
av_opt_set_int(encoderCtx, "crf", -1, AV_OPT_SEARCH_CHILDREN);
JAMI_DBG("H264 encoder setup cbr: bitrate=%lu kbit/s", br);
}
}
void
MediaEncoder::initVP8(AVCodecContext* encoderCtx, uint64_t br)
......
......@@ -132,6 +132,7 @@ private:
unsigned int currentVideoCodecID_ {0};
AVCodec* outputCodec_ = nullptr;
std::mutex encMutex_;
bool auto_quality {false};
void initH264(AVCodecContext* encoderCtx, uint64_t br);
void initVP8(AVCodecContext* encoderCtx, uint64_t br);
......
......@@ -128,6 +128,12 @@ void VideoRtpSession::startSender()
// be sure to not send any packets before saving last RTP seq value
socketPair_->stopSendOp();
auto codecVideo = std::static_pointer_cast<jami::AccountVideoCodecInfo>(send_.codec);
auto autoQuality = codecVideo->isAutoQualityEnabled;
send_.auto_quality = autoQuality;
if (sender_)
initSeqVal_ = sender_->getLastSeqValue() + 10; // Skip a few sequences to make nvenc happy on a sender restart
try {
......@@ -145,8 +151,6 @@ void VideoRtpSession::startSender()
lastMediaRestart_ = clock::now();
last_REMB_inc_ = clock::now();
last_REMB_dec_ = clock::now();
auto codecVideo = std::static_pointer_cast<jami::AccountVideoCodecInfo>(send_.codec);
auto autoQuality = codecVideo->isAutoQualityEnabled;
if (autoQuality and not rtcpCheckerThread_.isRunning())
rtcpCheckerThread_.start();
else if (not autoQuality and rtcpCheckerThread_.isRunning())
......@@ -517,7 +521,7 @@ VideoRtpSession::setNewBitrate(unsigned int newBR)
#if __ANDROID__
auto input_device = std::static_pointer_cast<VideoInput>(videoLocal_);
emitSignal<DRing::VideoSignal::SetBitrate>(input_device->getParams().name, (int)videoBitrateInfo_.videoBitrateCurrent);
emitSignal<DRing::VideoSignal::SetBitrate>(input_device->getParams().name, (int)newBR);
#endif
// If encoder no longer exist do nothing
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment