From 998791a36d7cb974b356ad9ca8cd8b1977ee972a Mon Sep 17 00:00:00 2001 From: Philip-Dylan Gleonec <philip-dylan.gleonec@savoirfairelinux.com> Date: Fri, 15 Jan 2021 16:01:16 +0100 Subject: [PATCH] media_encoder: add setPacketLoss method Add a setPacketLoss method to enable setting a new packet loss estimation in the codec. This method follows the model of setBitrate and requires the implementation of getCurrentAudioAVCtx and isDynPacketLossSupported, which are also included in this patch. Issue: #5157 Change-Id: I62f5246df1df0dc0867649299c6bbf6c12db43a2 --- src/media/media_encoder.cpp | 41 +++++++++++++++++++++++++++++++++++++ src/media/media_encoder.h | 3 +++ 2 files changed, 44 insertions(+) diff --git a/src/media/media_encoder.cpp b/src/media/media_encoder.cpp index f985b1763e..50e8a21317 100644 --- a/src/media/media_encoder.cpp +++ b/src/media/media_encoder.cpp @@ -823,6 +823,28 @@ MediaEncoder::setBitrate(uint64_t br) return 1; // OK } +int +MediaEncoder::setPacketLoss(uint64_t pl) +{ + std::lock_guard<std::mutex> lk(encMutex_); + AVCodecContext* encoderCtx = getCurrentAudioAVCtx(); + if (not encoderCtx) + return -1; // NOK + + AVCodecID codecId = encoderCtx->codec_id; + + if (not isDynPacketLossSupported(codecId)) + return 0; // Restart needed + + // Cap between 0 and 100 + pl = std::clamp((int) pl, 0, 100); + + // Change parameters on the fly + if (codecId == AV_CODEC_ID_OPUS) + av_opt_set_int(encoderCtx, "packet_loss", (int64_t) pl, AV_OPT_SEARCH_CHILDREN); + return 1; // OK +} + void MediaEncoder::initH264(AVCodecContext* encoderCtx, uint64_t br) { @@ -997,6 +1019,16 @@ MediaEncoder::getCurrentVideoAVCtx() return nullptr; } +AVCodecContext* +MediaEncoder::getCurrentAudioAVCtx() +{ + for (auto it : encoders_) { + if (it->codec_type == AVMEDIA_TYPE_AUDIO) + return it; + } + return nullptr; +} + void MediaEncoder::stopEncoder() { @@ -1027,6 +1059,15 @@ MediaEncoder::isDynBitrateSupported(AVCodecID codecid) return false; } +bool +MediaEncoder::isDynPacketLossSupported(AVCodecID codecid) +{ + if (codecid == AV_CODEC_ID_OPUS) + return true; + + return false; +} + void MediaEncoder::readConfig(AVCodecContext* encoderCtx) { diff --git a/src/media/media_encoder.h b/src/media/media_encoder.h index 52c76a32c6..14e8268c76 100644 --- a/src/media/media_encoder.h +++ b/src/media/media_encoder.h @@ -105,6 +105,7 @@ public: const std::string& getVideoCodec() const { return videoCodec_; } int setBitrate(uint64_t br); + int setPacketLoss(uint64_t pl); #ifdef RING_ACCEL void enableAccel(bool enableAccel); @@ -125,6 +126,7 @@ private: void openIOContext(); void startIO(); AVCodecContext* getCurrentVideoAVCtx(); + AVCodecContext* getCurrentAudioAVCtx(); void stopEncoder(); AVCodecContext* initCodec(AVMediaType mediaType, AVCodecID avcodecId, uint64_t br); void initH264(AVCodecContext* encoderCtx, uint64_t br); @@ -134,6 +136,7 @@ private: void initH263(AVCodecContext* encoderCtx, uint64_t br); void initOpus(AVCodecContext* encoderCtx); bool isDynBitrateSupported(AVCodecID codecid); + bool isDynPacketLossSupported(AVCodecID codecid); void initAccel(AVCodecContext* encoderCtx, uint64_t br); int getHWFrame(const std::shared_ptr<VideoFrame>& input, std::shared_ptr<VideoFrame>& output); std::shared_ptr<VideoFrame> getUnlinkedHWFrame(const VideoFrame& input); -- GitLab