新增配置项指定H264 rtp打包是否优先采用stap-a模式 (#2582)

H264 rtp打包模式是否采用stap-a模式(为了在老版本浏览器上兼容webrtc)还是采用Single NAL unit packet
per H.264 模式 有些老的rtsp设备不支持stap-a rtp,设置此配置为0可提高兼容性
This commit is contained in:
夏楚 2023-06-26 10:04:16 +08:00 committed by GitHub
parent 24d210f61d
commit db8e9182cc
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 32 additions and 10 deletions

View File

@ -281,6 +281,9 @@ videoMtuSize=1400
rtpMaxSize=10 rtpMaxSize=10
# rtp 打包时低延迟开关默认关闭为0h264存在一帧多个sliceNAL的情况在这种情况下如果开启可能会导致画面花屏 # rtp 打包时低延迟开关默认关闭为0h264存在一帧多个sliceNAL的情况在这种情况下如果开启可能会导致画面花屏
lowLatency=0 lowLatency=0
# H264 rtp打包模式是否采用stap-a模式(为了在老版本浏览器上兼容webrtc)还是采用Single NAL unit packet per H.264 模式
# 有些老的rtsp设备不支持stap-a rtp设置此配置为0可提高兼容性
h264_stap_a=1
[rtp_proxy] [rtp_proxy]
#导出调试数据(包括rtp/ps/h264)至该目录,置空则关闭数据导出 #导出调试数据(包括rtp/ps/h264)至该目录,置空则关闭数据导出

View File

@ -244,15 +244,15 @@ const string kVideoMtuSize = RTP_FIELD "videoMtuSize";
const string kAudioMtuSize = RTP_FIELD "audioMtuSize"; const string kAudioMtuSize = RTP_FIELD "audioMtuSize";
// rtp包最大长度限制单位是KB // rtp包最大长度限制单位是KB
const string kRtpMaxSize = RTP_FIELD "rtpMaxSize"; const string kRtpMaxSize = RTP_FIELD "rtpMaxSize";
const string kLowLatency = RTP_FIELD "lowLatency"; const string kLowLatency = RTP_FIELD "lowLatency";
const string kH264StapA = RTP_FIELD "h264_stap_a";
static onceToken token([]() { static onceToken token([]() {
mINI::Instance()[kVideoMtuSize] = 1400; mINI::Instance()[kVideoMtuSize] = 1400;
mINI::Instance()[kAudioMtuSize] = 600; mINI::Instance()[kAudioMtuSize] = 600;
mINI::Instance()[kRtpMaxSize] = 10; mINI::Instance()[kRtpMaxSize] = 10;
mINI::Instance()[kLowLatency] = 0; mINI::Instance()[kLowLatency] = 0;
mINI::Instance()[kH264StapA] = 1;
}); });
} // namespace Rtp } // namespace Rtp

View File

@ -298,6 +298,8 @@ extern const std::string kAudioMtuSize;
extern const std::string kRtpMaxSize; extern const std::string kRtpMaxSize;
// rtp 打包时低延迟开关默认关闭为0h264存在一帧多个sliceNAL的情况在这种情况下如果开启可能会导致画面花屏 // rtp 打包时低延迟开关默认关闭为0h264存在一帧多个sliceNAL的情况在这种情况下如果开启可能会导致画面花屏
extern const std::string kLowLatency; extern const std::string kLowLatency;
//H264 rtp打包模式是否采用stap-a模式(为了在老版本浏览器上兼容webrtc)还是采用Single NAL unit packet per H.264 模式
extern const std::string kH264StapA;
} // namespace Rtp } // namespace Rtp
////////////组播配置/////////// ////////////组播配置///////////

View File

@ -209,8 +209,8 @@ void H264RtpEncoder::insertConfigFrame(uint64_t pts){
void H264RtpEncoder::packRtp(const char *ptr, size_t len, uint64_t pts, bool is_mark, bool gop_pos){ void H264RtpEncoder::packRtp(const char *ptr, size_t len, uint64_t pts, bool is_mark, bool gop_pos){
if (len + 3 <= getMaxSize()) { if (len + 3 <= getMaxSize()) {
//STAP-A模式打包小于MTU // 采用STAP-A/Single NAL unit packet per H.264 模式
packRtpStapA(ptr, len, pts, is_mark, gop_pos); packRtpSmallFrame(ptr, len, pts, is_mark, gop_pos);
} else { } else {
//STAP-A模式打包会大于MTU,所以采用FU-A模式 //STAP-A模式打包会大于MTU,所以采用FU-A模式
packRtpFu(ptr, len, pts, is_mark, gop_pos); packRtpFu(ptr, len, pts, is_mark, gop_pos);
@ -220,8 +220,8 @@ void H264RtpEncoder::packRtp(const char *ptr, size_t len, uint64_t pts, bool is_
void H264RtpEncoder::packRtpFu(const char *ptr, size_t len, uint64_t pts, bool is_mark, bool gop_pos){ void H264RtpEncoder::packRtpFu(const char *ptr, size_t len, uint64_t pts, bool is_mark, bool gop_pos){
auto packet_size = getMaxSize() - 2; auto packet_size = getMaxSize() - 2;
if (len <= packet_size + 1) { if (len <= packet_size + 1) {
//小于FU-A打包最小字节长度要求采用STAP-A模式 // 小于FU-A打包最小字节长度要求采用STAP-A/Single NAL unit packet per H.264 模式
packRtpStapA(ptr, len, pts, is_mark, gop_pos); packRtpSmallFrame(ptr, len, pts, is_mark, gop_pos);
return; return;
} }
@ -257,8 +257,17 @@ void H264RtpEncoder::packRtpFu(const char *ptr, size_t len, uint64_t pts, bool i
} }
} }
void H264RtpEncoder::packRtpSmallFrame(const char *data, size_t len, uint64_t pts, bool is_mark, bool gop_pos) {
GET_CONFIG(bool, h264_stap_a, Rtp::kH264StapA);
if (h264_stap_a) {
packRtpStapA(data, len, pts, is_mark, gop_pos);
} else {
packRtpSingleNalu(data, len, pts, is_mark, gop_pos);
}
}
void H264RtpEncoder::packRtpStapA(const char *ptr, size_t len, uint64_t pts, bool is_mark, bool gop_pos){ void H264RtpEncoder::packRtpStapA(const char *ptr, size_t len, uint64_t pts, bool is_mark, bool gop_pos){
//如果帧长度不超过mtu,为了兼容性 webrtc采用STAP-A模式打包 // 如果帧长度不超过mtu,为了兼容性 webrtc采用STAP-A模式打包
auto rtp = makeRtp(getTrackType(), nullptr, len + 3, is_mark, pts); auto rtp = makeRtp(getTrackType(), nullptr, len + 3, is_mark, pts);
uint8_t *payload = rtp->getPayload(); uint8_t *payload = rtp->getPayload();
//STAP-A //STAP-A
@ -270,6 +279,11 @@ void H264RtpEncoder::packRtpStapA(const char *ptr, size_t len, uint64_t pts, boo
RtpCodec::inputRtp(rtp, gop_pos); RtpCodec::inputRtp(rtp, gop_pos);
} }
void H264RtpEncoder::packRtpSingleNalu(const char *data, size_t len, uint64_t pts, bool is_mark, bool gop_pos) {
// Single NAL unit packet per H.264 模式
RtpCodec::inputRtp(makeRtp(getTrackType(), data, len, is_mark, pts), gop_pos);
}
bool H264RtpEncoder::inputFrame(const Frame::Ptr &frame) { bool H264RtpEncoder::inputFrame(const Frame::Ptr &frame) {
auto ptr = frame->data() + frame->prefixSize(); auto ptr = frame->data() + frame->prefixSize();
switch (H264_TYPE(ptr[0])) { switch (H264_TYPE(ptr[0])) {

View File

@ -28,7 +28,7 @@ public:
using Ptr = std::shared_ptr<H264RtpDecoder>; using Ptr = std::shared_ptr<H264RtpDecoder>;
H264RtpDecoder(); H264RtpDecoder();
~H264RtpDecoder() {} ~H264RtpDecoder() override = default;
/** /**
* 264 rtp包 * 264 rtp包
@ -77,9 +77,10 @@ public:
uint32_t sample_rate = 90000, uint32_t sample_rate = 90000,
uint8_t pt = 96, uint8_t pt = 96,
uint8_t interleaved = TrackVideo * 2); uint8_t interleaved = TrackVideo * 2);
~H264RtpEncoder() {}
/** ~H264RtpEncoder() override = default;
/**
* 264 * 264
* @param frame * @param frame
*/ */
@ -96,6 +97,8 @@ private:
void packRtp(const char *data, size_t len, uint64_t pts, bool is_mark, bool gop_pos); void packRtp(const char *data, size_t len, uint64_t pts, bool is_mark, bool gop_pos);
void packRtpFu(const char *data, size_t len, uint64_t pts, bool is_mark, bool gop_pos); void packRtpFu(const char *data, size_t len, uint64_t pts, bool is_mark, bool gop_pos);
void packRtpStapA(const char *data, size_t len, uint64_t pts, bool is_mark, bool gop_pos); void packRtpStapA(const char *data, size_t len, uint64_t pts, bool is_mark, bool gop_pos);
void packRtpSingleNalu(const char *data, size_t len, uint64_t pts, bool is_mark, bool gop_pos);
void packRtpSmallFrame(const char *data, size_t len, uint64_t pts, bool is_mark, bool gop_pos);
private: private:
Frame::Ptr _sps; Frame::Ptr _sps;