rtp send rtp g711 audio can config duration (#3325)

optimization for this
[issue](https://github.com/ZLMediaKit/ZLMediaKit/issues/3316)
This commit is contained in:
xiongguangjie 2024-03-02 16:40:13 +08:00 committed by GitHub
parent 87cb488b04
commit 06abbd0eb7
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
7 changed files with 50 additions and 7 deletions

View File

@ -329,6 +329,10 @@ opus_pt=100
#如果不调用startSendRtp相关接口可以置0节省内存 #如果不调用startSendRtp相关接口可以置0节省内存
gop_cache=1 gop_cache=1
#国标发送g711 rtp 打包时每个包的语音时长是多少默认是100 ms范围为20~180ms (gb28181-2016c.2.4规定)
#最好为20 的倍数程序自动向20的倍数取整
rtp_g711_dur_ms = 100
[rtc] [rtc]
#rtc播放推流、播放超时时间 #rtc播放推流、播放超时时间
timeoutSec=15 timeoutSec=15

View File

@ -8,13 +8,27 @@ G711RtpEncoder::G711RtpEncoder(CodecId codec, uint32_t channels){
_channels = channels; _channels = channels;
} }
void G711RtpEncoder::setOpt(int opt, const toolkit::Any &param) {
if (opt == RTP_ENCODER_PKT_DUR_MS) {
if (param.is<uint32_t>()) {
auto dur = param.get<uint32_t>();
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) { bool G711RtpEncoder::inputFrame(const Frame::Ptr &frame) {
auto dur = (_cache_frame->size() - _cache_frame->prefixSize()) / (8 * _channels); auto dur = (_cache_frame->size() - _cache_frame->prefixSize()) / (8 * _channels);
auto next_pts = _cache_frame->pts() + dur; auto next_pts = _cache_frame->pts() + dur;
if (next_pts == 0) { if (next_pts == 0) {
_cache_frame->_pts = frame->pts(); _cache_frame->_pts = frame->pts();
} else { } else {
if ((next_pts + 20) < frame->pts()) { // 有丢包超过20ms if ((next_pts + _pkt_dur_ms) < frame->pts()) { // 有丢包超过20ms
_cache_frame->_pts = frame->pts() - dur; _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 ptr = _cache_frame->data() + _cache_frame->prefixSize();
auto len = _cache_frame->size() - _cache_frame->prefixSize(); auto len = _cache_frame->size() - _cache_frame->prefixSize();
auto remain_size = len; auto remain_size = len;
auto max_size = 160 * _channels; // 20 ms per rtp auto max_size = 160 * _channels * _pkt_dur_ms / 20; // 20 ms per 160 byte
int n = 0; uint32_t n = 0;
bool mark = false; bool mark = true;
while (remain_size >= max_size) { while (remain_size >= max_size) {
size_t rtp_size; size_t rtp_size;
if (remain_size >= max_size) { if (remain_size >= max_size) {
@ -35,13 +49,13 @@ bool G711RtpEncoder::inputFrame(const Frame::Ptr &frame) {
break; break;
} }
n++; n++;
stamp += 20; stamp += _pkt_dur_ms;
RtpCodec::inputRtp(getRtpInfo().makeRtp(TrackAudio, ptr, rtp_size, mark, stamp), false); RtpCodec::inputRtp(getRtpInfo().makeRtp(TrackAudio, ptr, rtp_size, mark, stamp), true);
ptr += rtp_size; ptr += rtp_size;
remain_size -= rtp_size; remain_size -= rtp_size;
} }
_cache_frame->_buffer.erase(0, n * max_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; return len > 0;
} }

View File

@ -36,8 +36,11 @@ public:
*/ */
bool inputFrame(const Frame::Ptr &frame) override; bool inputFrame(const Frame::Ptr &frame) override;
void setOpt(int opt, const toolkit::Any &param) override;
private: private:
uint32_t _channels = 1; uint32_t _channels = 1;
uint32_t _pkt_dur_ms = 20;
FrameImp::Ptr _cache_frame; FrameImp::Ptr _cache_frame;
}; };

View File

@ -338,6 +338,7 @@ const string kH265PT = RTP_PROXY_FIELD "h265_pt";
const string kPSPT = RTP_PROXY_FIELD "ps_pt"; const string kPSPT = RTP_PROXY_FIELD "ps_pt";
const string kOpusPT = RTP_PROXY_FIELD "opus_pt"; const string kOpusPT = RTP_PROXY_FIELD "opus_pt";
const string kGopCache = RTP_PROXY_FIELD "gop_cache"; const string kGopCache = RTP_PROXY_FIELD "gop_cache";
const string kRtpG711DurMs = RTP_PROXY_FIELD "rtp_g711_dur_ms";
static onceToken token([]() { static onceToken token([]() {
mINI::Instance()[kDumpDir] = ""; mINI::Instance()[kDumpDir] = "";
@ -348,6 +349,7 @@ static onceToken token([]() {
mINI::Instance()[kPSPT] = 96; mINI::Instance()[kPSPT] = 96;
mINI::Instance()[kOpusPT] = 100; mINI::Instance()[kOpusPT] = 100;
mINI::Instance()[kGopCache] = 1; mINI::Instance()[kGopCache] = 1;
mINI::Instance()[kRtpG711DurMs] = 100;
}); });
} // namespace RtpProxy } // namespace RtpProxy

View File

@ -382,6 +382,9 @@ extern const std::string kPSPT;
extern const std::string kOpusPT; extern const std::string kOpusPT;
// RtpSender相关功能是否提前开启gop缓存优化级联秒开体验默认开启 // RtpSender相关功能是否提前开启gop缓存优化级联秒开体验默认开启
extern const std::string kGopCache; extern const std::string kGopCache;
//国标发送g711 rtp 打包时每个包的语音时长是多少默认是100 ms范围为20~180ms (gb28181-2016c.2.4规定)
//最好为20 的倍数程序自动向20的倍数取整
extern const std::string kRtpG711DurMs;
} // namespace RtpProxy } // namespace RtpProxy
/** /**

View File

@ -34,6 +34,12 @@ bool RawEncoderImp::addTrack(const Track::Ptr &track) {
auto ring = std::make_shared<RtpRing::RingType>(); auto ring = std::make_shared<RtpRing::RingType>();
ring->setDelegate(std::make_shared<RingDelegateHelper>([this](RtpPacket::Ptr rtp, bool is_key) { onRTP(std::move(rtp), true); })); ring->setDelegate(std::make_shared<RingDelegateHelper>([this](RtpPacket::Ptr rtp, bool is_key) { onRTP(std::move(rtp), true); }));
_rtp_encoder->setRtpRing(std::move(ring)); _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<uint32_t>(dur_ms);
_rtp_encoder->setOpt(RtpCodec::RTP_ENCODER_PKT_DUR_MS, param);
}
return true; return true;
} }

View File

@ -93,6 +93,17 @@ public:
RtpInfo &getRtpInfo() { return *_rtp_info; } 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 &param) {};
private: private:
std::unique_ptr<RtpInfo> _rtp_info; std::unique_ptr<RtpInfo> _rtp_info;
}; };