diff --git a/src/media/media_codec.h b/src/media/media_codec.h index ea6a6680d69745d243b5c19b8f9021c65168e1c1..19f845ec3b76056c99284ac48fb074e0e7e56d86 100644 --- a/src/media/media_codec.h +++ b/src/media/media_codec.h @@ -278,6 +278,7 @@ struct MediaDescription { /** Video parameters */ std::string parameters {}; + bool auto_quality {false}; /** Crypto parameters */ CryptoAttribute crypto {}; diff --git a/src/media/media_encoder.cpp b/src/media/media_encoder.cpp index 0ec2230ae3daaeaba2b5d914dc7cd4196c3ab701..f5f46d7a5abadeb7d1c41482c106c8da3b557be5 100644 --- a/src/media/media_encoder.cpp +++ b/src/media/media_encoder.cpp @@ -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,31 +741,40 @@ 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) { - 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; + // 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 = maxBitrate * 2; + + av_opt_set_int(encoderCtx, "crf", crf, AV_OPT_SEARCH_CHILDREN); + 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); } -#endif + // 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); - 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; - JAMI_DBG("H264 encoder setup: crf=%u, maxrate=%lu, bufsize=%lu", crf, maxBitrate, bufSize); + JAMI_DBG("H264 encoder setup cbr: bitrate=%lu kbit/s", br); + } } void diff --git a/src/media/media_encoder.h b/src/media/media_encoder.h index 800ec4bc955fced8035156a4b8af11ef828e1daa..0b978589aeb2fef99a97b471bffeae586aed4e8f 100644 --- a/src/media/media_encoder.h +++ b/src/media/media_encoder.h @@ -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); diff --git a/src/media/video/video_rtp_session.cpp b/src/media/video/video_rtp_session.cpp index 2aad2cc5ea4e6ad01a5d5495f830a0e10346e3ac..14fd9df8300e7df176dd3d1e9901a3ebf210550e 100644 --- a/src/media/video/video_rtp_session.cpp +++ b/src/media/video/video_rtp_session.cpp @@ -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