From 06abbd0eb7b1ec6e16821b7fa3567ea5c8c9d47d Mon Sep 17 00:00:00 2001 From: xiongguangjie Date: Sat, 2 Mar 2024 16:40:13 +0800 Subject: [PATCH] rtp send rtp g711 audio can config duration (#3325) optimization for this [issue](https://github.com/ZLMediaKit/ZLMediaKit/issues/3316) --- conf/config.ini | 4 ++++ ext-codec/G711Rtp.cpp | 28 +++++++++++++++++++++------- ext-codec/G711Rtp.h | 3 +++ src/Common/config.cpp | 2 ++ src/Common/config.h | 3 +++ src/Rtp/RawEncoder.cpp | 6 ++++++ src/Rtsp/RtpCodec.h | 11 +++++++++++ 7 files changed, 50 insertions(+), 7 deletions(-) diff --git a/conf/config.ini b/conf/config.ini index 4364ed99..a66de19f 100644 --- a/conf/config.ini +++ b/conf/config.ini @@ -329,6 +329,10 @@ opus_pt=100 #如果不调用startSendRtp相关接口,可以置0节省内存 gop_cache=1 +#国标发送g711 rtp 打包时,每个包的语音时长是多少,默认是100 ms,范围为20~180ms (gb28181-2016,c.2.4规定), +#最好为20 的倍数,程序自动向20的倍数取整 +rtp_g711_dur_ms = 100 + [rtc] #rtc播放推流、播放超时时间 timeoutSec=15 diff --git a/ext-codec/G711Rtp.cpp b/ext-codec/G711Rtp.cpp index 2760f8a6..ea07b767 100644 --- a/ext-codec/G711Rtp.cpp +++ b/ext-codec/G711Rtp.cpp @@ -8,13 +8,27 @@ G711RtpEncoder::G711RtpEncoder(CodecId codec, uint32_t channels){ _channels = channels; } +void G711RtpEncoder::setOpt(int opt, const toolkit::Any ¶m) { + if (opt == RTP_ENCODER_PKT_DUR_MS) { + if (param.is()) { + auto dur = param.get(); + if (dur < 20 || dur > 180) { + WarnL << "set g711 rtp encoder duration ms failed for " << dur; + return; + } + // 向上 20ms 取整 + _pkt_dur_ms = (dur + 19) / 20 * 20; + } + } +} + bool G711RtpEncoder::inputFrame(const Frame::Ptr &frame) { auto dur = (_cache_frame->size() - _cache_frame->prefixSize()) / (8 * _channels); auto next_pts = _cache_frame->pts() + dur; if (next_pts == 0) { _cache_frame->_pts = frame->pts(); } else { - if ((next_pts + 20) < frame->pts()) { // 有丢包超过20ms + if ((next_pts + _pkt_dur_ms) < frame->pts()) { // 有丢包超过20ms _cache_frame->_pts = frame->pts() - dur; } } @@ -24,9 +38,9 @@ bool G711RtpEncoder::inputFrame(const Frame::Ptr &frame) { auto ptr = _cache_frame->data() + _cache_frame->prefixSize(); auto len = _cache_frame->size() - _cache_frame->prefixSize(); auto remain_size = len; - auto max_size = 160 * _channels; // 20 ms per rtp - int n = 0; - bool mark = false; + auto max_size = 160 * _channels * _pkt_dur_ms / 20; // 20 ms per 160 byte + uint32_t n = 0; + bool mark = true; while (remain_size >= max_size) { size_t rtp_size; if (remain_size >= max_size) { @@ -35,13 +49,13 @@ bool G711RtpEncoder::inputFrame(const Frame::Ptr &frame) { break; } n++; - stamp += 20; - RtpCodec::inputRtp(getRtpInfo().makeRtp(TrackAudio, ptr, rtp_size, mark, stamp), false); + stamp += _pkt_dur_ms; + RtpCodec::inputRtp(getRtpInfo().makeRtp(TrackAudio, ptr, rtp_size, mark, stamp), true); ptr += rtp_size; remain_size -= rtp_size; } _cache_frame->_buffer.erase(0, n * max_size); - _cache_frame->_pts += 20 * n; + _cache_frame->_pts += (uint64_t)_pkt_dur_ms * n; return len > 0; } diff --git a/ext-codec/G711Rtp.h b/ext-codec/G711Rtp.h index 2d709e53..dab74f42 100644 --- a/ext-codec/G711Rtp.h +++ b/ext-codec/G711Rtp.h @@ -36,8 +36,11 @@ public: */ bool inputFrame(const Frame::Ptr &frame) override; + void setOpt(int opt, const toolkit::Any ¶m) override; + private: uint32_t _channels = 1; + uint32_t _pkt_dur_ms = 20; FrameImp::Ptr _cache_frame; }; diff --git a/src/Common/config.cpp b/src/Common/config.cpp index 357a9689..9a31b3e6 100644 --- a/src/Common/config.cpp +++ b/src/Common/config.cpp @@ -338,6 +338,7 @@ const string kH265PT = RTP_PROXY_FIELD "h265_pt"; const string kPSPT = RTP_PROXY_FIELD "ps_pt"; const string kOpusPT = RTP_PROXY_FIELD "opus_pt"; const string kGopCache = RTP_PROXY_FIELD "gop_cache"; +const string kRtpG711DurMs = RTP_PROXY_FIELD "rtp_g711_dur_ms"; static onceToken token([]() { mINI::Instance()[kDumpDir] = ""; @@ -348,6 +349,7 @@ static onceToken token([]() { mINI::Instance()[kPSPT] = 96; mINI::Instance()[kOpusPT] = 100; mINI::Instance()[kGopCache] = 1; + mINI::Instance()[kRtpG711DurMs] = 100; }); } // namespace RtpProxy diff --git a/src/Common/config.h b/src/Common/config.h index a6d7af4d..cd335ef4 100644 --- a/src/Common/config.h +++ b/src/Common/config.h @@ -382,6 +382,9 @@ extern const std::string kPSPT; extern const std::string kOpusPT; // RtpSender相关功能是否提前开启gop缓存优化级联秒开体验,默认开启 extern const std::string kGopCache; +//国标发送g711 rtp 打包时,每个包的语音时长是多少,默认是100 ms,范围为20~180ms (gb28181-2016,c.2.4规定), +//最好为20 的倍数,程序自动向20的倍数取整 +extern const std::string kRtpG711DurMs; } // namespace RtpProxy /** diff --git a/src/Rtp/RawEncoder.cpp b/src/Rtp/RawEncoder.cpp index 4bc17af7..c14254bd 100644 --- a/src/Rtp/RawEncoder.cpp +++ b/src/Rtp/RawEncoder.cpp @@ -34,6 +34,12 @@ bool RawEncoderImp::addTrack(const Track::Ptr &track) { auto ring = std::make_shared(); ring->setDelegate(std::make_shared([this](RtpPacket::Ptr rtp, bool is_key) { onRTP(std::move(rtp), true); })); _rtp_encoder->setRtpRing(std::move(ring)); + if (track->getCodecId() == CodecG711A || track->getCodecId() == CodecG711U) { + GET_CONFIG(uint32_t, dur_ms, RtpProxy::kRtpG711DurMs); + Any param; + param.set(dur_ms); + _rtp_encoder->setOpt(RtpCodec::RTP_ENCODER_PKT_DUR_MS, param); + } return true; } diff --git a/src/Rtsp/RtpCodec.h b/src/Rtsp/RtpCodec.h index d63f1962..9a8e3396 100644 --- a/src/Rtsp/RtpCodec.h +++ b/src/Rtsp/RtpCodec.h @@ -93,6 +93,17 @@ public: RtpInfo &getRtpInfo() { return *_rtp_info; } + enum { + RTP_ENCODER_PKT_DUR_MS = 1 // 主要应用于g711 rtp 打包器每个包的时间长度,option_value 为int*, option_len 为4 + }; + /** + * @brief 设置rtp打包器与解包器的相关参数,主要应用与g711 rtp 打包器,使用方法类似setsockopt + * + * @param opt 设置的选项 + * @param param 设置的参数 + */ + virtual void setOpt(int opt, const toolkit::Any ¶m) {}; + private: std::unique_ptr _rtp_info; };