mirror of
https://github.com/ossrs/srs.git
synced 2025-02-13 11:51:57 +00:00
For #307, support padding for GSO
This commit is contained in:
parent
6869ccca50
commit
bbdd2d7eed
5 changed files with 68 additions and 17 deletions
|
@ -443,6 +443,10 @@ rtc_server {
|
||||||
# @remark Linux 4.18+ only, for other OS always disabled.
|
# @remark Linux 4.18+ only, for other OS always disabled.
|
||||||
# default: on
|
# default: on
|
||||||
gso on;
|
gso on;
|
||||||
|
# Whether pad first packet for GSO for padding bytes.
|
||||||
|
# If 0, disable padding for GSO.
|
||||||
|
# default: 0
|
||||||
|
padding 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
vhost rtc.vhost.srs.com {
|
vhost rtc.vhost.srs.com {
|
||||||
|
|
|
@ -3618,7 +3618,8 @@ srs_error_t SrsConfig::check_normal_config()
|
||||||
for (int i = 0; conf && i < (int)conf->directives.size(); i++) {
|
for (int i = 0; conf && i < (int)conf->directives.size(); i++) {
|
||||||
string n = conf->at(i)->name;
|
string n = conf->at(i)->name;
|
||||||
if (n != "enabled" && n != "listen" && n != "dir" && n != "candidate" && n != "ecdsa"
|
if (n != "enabled" && n != "listen" && n != "dir" && n != "candidate" && n != "ecdsa"
|
||||||
&& n != "sendmmsg" && n != "encrypt" && n != "reuseport" && n != "gso" && n != "merge_nalus") {
|
&& n != "sendmmsg" && n != "encrypt" && n != "reuseport" && n != "gso" && n != "merge_nalus"
|
||||||
|
&& n != "padding") {
|
||||||
return srs_error_new(ERROR_SYSTEM_CONFIG_INVALID, "illegal rtc_server.%s", n.c_str());
|
return srs_error_new(ERROR_SYSTEM_CONFIG_INVALID, "illegal rtc_server.%s", n.c_str());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -4840,6 +4841,23 @@ bool SrsConfig::get_rtc_server_gso2()
|
||||||
return SRS_CONF_PERFER_TRUE(conf->arg0());
|
return SRS_CONF_PERFER_TRUE(conf->arg0());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int SrsConfig::get_rtc_server_padding()
|
||||||
|
{
|
||||||
|
static int DEFAULT = 0;
|
||||||
|
|
||||||
|
SrsConfDirective* conf = root->get("rtc_server");
|
||||||
|
if (!conf) {
|
||||||
|
return DEFAULT;
|
||||||
|
}
|
||||||
|
|
||||||
|
conf = conf->get("padding");
|
||||||
|
if (!conf || conf->arg0().empty()) {
|
||||||
|
return DEFAULT;
|
||||||
|
}
|
||||||
|
|
||||||
|
return srs_min(16, ::atoi(conf->arg0().c_str()));
|
||||||
|
}
|
||||||
|
|
||||||
SrsConfDirective* SrsConfig::get_rtc(string vhost)
|
SrsConfDirective* SrsConfig::get_rtc(string vhost)
|
||||||
{
|
{
|
||||||
SrsConfDirective* conf = get_vhost(vhost);
|
SrsConfDirective* conf = get_vhost(vhost);
|
||||||
|
|
|
@ -535,6 +535,9 @@ public:
|
||||||
virtual bool get_rtc_server_gso();
|
virtual bool get_rtc_server_gso();
|
||||||
private:
|
private:
|
||||||
virtual bool get_rtc_server_gso2();
|
virtual bool get_rtc_server_gso2();
|
||||||
|
public:
|
||||||
|
virtual int get_rtc_server_padding();
|
||||||
|
|
||||||
public:
|
public:
|
||||||
SrsConfDirective* get_rtc(std::string vhost);
|
SrsConfDirective* get_rtc(std::string vhost);
|
||||||
bool get_rtc_enabled(std::string vhost);
|
bool get_rtc_enabled(std::string vhost);
|
||||||
|
|
|
@ -468,6 +468,7 @@ SrsRtcPackets::SrsRtcPackets(bool gso, bool merge_nalus)
|
||||||
nn_rtp_pkts = 0;
|
nn_rtp_pkts = 0;
|
||||||
nn_audios = nn_extras = 0;
|
nn_audios = nn_extras = 0;
|
||||||
nn_videos = nn_samples = 0;
|
nn_videos = nn_samples = 0;
|
||||||
|
nn_paddings = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
SrsRtcPackets::~SrsRtcPackets()
|
SrsRtcPackets::~SrsRtcPackets()
|
||||||
|
@ -490,6 +491,7 @@ SrsRtcSenderThread::SrsRtcSenderThread(SrsRtcSession* s, SrsUdpMuxSocket* u, int
|
||||||
sendonly_ukt = u->copy_sendonly();
|
sendonly_ukt = u->copy_sendonly();
|
||||||
gso = false;
|
gso = false;
|
||||||
merge_nalus = false;
|
merge_nalus = false;
|
||||||
|
max_padding = 0;
|
||||||
|
|
||||||
audio_timestamp = 0;
|
audio_timestamp = 0;
|
||||||
audio_sequence = 0;
|
audio_sequence = 0;
|
||||||
|
@ -519,8 +521,9 @@ srs_error_t SrsRtcSenderThread::initialize(const uint32_t& vssrc, const uint32_t
|
||||||
|
|
||||||
gso = _srs_config->get_rtc_server_gso();
|
gso = _srs_config->get_rtc_server_gso();
|
||||||
merge_nalus = _srs_config->get_rtc_server_merge_nalus();
|
merge_nalus = _srs_config->get_rtc_server_merge_nalus();
|
||||||
srs_trace("RTC sender video(ssrc=%d, pt=%d), audio(ssrc=%d, pt=%d), package(gso=%d, merge_nalus=%d)",
|
max_padding = _srs_config->get_rtc_server_padding();
|
||||||
video_ssrc, video_payload_type, audio_ssrc, audio_payload_type, gso, merge_nalus);
|
srs_trace("RTC sender video(ssrc=%d, pt=%d), audio(ssrc=%d, pt=%d), package(gso=%d, merge_nalus=%d), padding=%d",
|
||||||
|
video_ssrc, video_payload_type, audio_ssrc, audio_payload_type, gso, merge_nalus, max_padding);
|
||||||
|
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
|
@ -543,6 +546,14 @@ srs_error_t SrsRtcSenderThread::on_reload_rtc_server()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (true) {
|
||||||
|
bool v = _srs_config->get_rtc_server_padding();
|
||||||
|
if (max_padding != v) {
|
||||||
|
srs_trace("Reload padding %d=>%d", max_padding, v);
|
||||||
|
max_padding = v;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return srs_success;
|
return srs_success;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -665,7 +676,7 @@ srs_error_t SrsRtcSenderThread::cycle()
|
||||||
// Stat the RTP packets going into kernel.
|
// Stat the RTP packets going into kernel.
|
||||||
stat->perf_on_gso_packets(pkts.nn_rtp_pkts);
|
stat->perf_on_gso_packets(pkts.nn_rtp_pkts);
|
||||||
#if defined(SRS_DEBUG)
|
#if defined(SRS_DEBUG)
|
||||||
srs_trace("RTC PLAY packets, msgs %d/%d, rtp %d, gso %d, %d audios, %d extras, %d videos, %d samples, %d bytes",
|
srs_trace("RTC PLAY done, msgs %d/%d, rtp %d, gso %d, %d audios, %d extras, %d videos, %d samples, %d bytes",
|
||||||
msg_count, nn_rtc_packets, pkts.packets.size(), pkts.nn_rtp_pkts, pkts.nn_audios, pkts.nn_extras, pkts.nn_videos,
|
msg_count, nn_rtc_packets, pkts.packets.size(), pkts.nn_rtp_pkts, pkts.nn_audios, pkts.nn_extras, pkts.nn_videos,
|
||||||
pkts.nn_samples, pkts.nn_bytes);
|
pkts.nn_samples, pkts.nn_bytes);
|
||||||
#endif
|
#endif
|
||||||
|
@ -673,9 +684,9 @@ srs_error_t SrsRtcSenderThread::cycle()
|
||||||
pprint->elapse();
|
pprint->elapse();
|
||||||
if (pprint->can_print()) {
|
if (pprint->can_print()) {
|
||||||
// TODO: FIXME: Print stat like frame/s, packet/s, loss_packets.
|
// TODO: FIXME: Print stat like frame/s, packet/s, loss_packets.
|
||||||
srs_trace("-> RTC PLAY %d msgs, %d/%d packets, %d audios, %d extras, %d videos, %d samples, %d bytes",
|
srs_trace("-> RTC PLAY %d msgs, %d/%d packets, %d audios, %d extras, %d videos, %d samples, %d bytes, %d pad",
|
||||||
msg_count, pkts.packets.size(), pkts.nn_rtp_pkts, pkts.nn_audios, pkts.nn_extras, pkts.nn_videos,
|
msg_count, pkts.packets.size(), pkts.nn_rtp_pkts, pkts.nn_audios, pkts.nn_extras, pkts.nn_videos,
|
||||||
pkts.nn_samples, pkts.nn_bytes);
|
pkts.nn_samples, pkts.nn_bytes, pkts.nn_paddings);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -862,13 +873,28 @@ srs_error_t SrsRtcSenderThread::send_packets_gso(SrsUdpMuxSocket* skt, SrsRtcPac
|
||||||
int nn_packets = (int)packets.packets.size();
|
int nn_packets = (int)packets.packets.size();
|
||||||
for (int i = 0; i < nn_packets; i++) {
|
for (int i = 0; i < nn_packets; i++) {
|
||||||
SrsRtpPacket2* packet = packets.packets[i];
|
SrsRtpPacket2* packet = packets.packets[i];
|
||||||
|
|
||||||
// The handler to send message.
|
|
||||||
mmsghdr* mhdr = NULL;
|
|
||||||
|
|
||||||
// Check whether we can use GSO to send it.
|
|
||||||
int nn_packet = packet->nb_bytes();
|
int nn_packet = packet->nb_bytes();
|
||||||
|
|
||||||
|
SrsRtpPacket2* next_packet = NULL;
|
||||||
|
int nn_next_packet = 0;
|
||||||
|
if (i < nn_packets - 1) {
|
||||||
|
next_packet = (i < nn_packets - 1)? packets.packets[i + 1]:NULL;
|
||||||
|
nn_next_packet = next_packet? next_packet->nb_bytes() : 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Padding the first packet if size is similar to the next one.
|
||||||
|
if (i == 0 && max_padding > 0 && next_packet && nn_packet < nn_next_packet && nn_next_packet - nn_packet < max_padding) {
|
||||||
|
#if defined(SRS_DEBUG)
|
||||||
|
srs_trace("Padding %d bytes %d=>%d, packets %d, max_padding %d", nn_next_packet - nn_packet,
|
||||||
|
nn_packet, nn_next_packet, nn_packets, max_padding);
|
||||||
|
#endif
|
||||||
|
packet->set_padding(nn_next_packet - nn_packet);
|
||||||
|
nn_packet = nn_next_packet;
|
||||||
|
packets.nn_paddings++;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check whether we can use GSO to send it.
|
||||||
|
mmsghdr* mhdr = NULL;
|
||||||
if ((gso_size && gso_size == nn_packet) || (use_gso && !gso_final)) {
|
if ((gso_size && gso_size == nn_packet) || (use_gso && !gso_final)) {
|
||||||
use_gso = true;
|
use_gso = true;
|
||||||
gso_final = (gso_size && gso_size != nn_packet);
|
gso_final = (gso_size && gso_size != nn_packet);
|
||||||
|
@ -893,10 +919,7 @@ srs_error_t SrsRtcSenderThread::send_packets_gso(SrsUdpMuxSocket* skt, SrsRtcPac
|
||||||
}
|
}
|
||||||
|
|
||||||
// Change the state according to the next packet.
|
// Change the state according to the next packet.
|
||||||
if (i < nn_packets - 1) {
|
if (next_packet) {
|
||||||
SrsRtpPacket2* next_packet = (i < nn_packets - 1)? packets.packets[i + 1]:NULL;
|
|
||||||
int nn_next_packet = next_packet? next_packet->nb_bytes() : 0;
|
|
||||||
|
|
||||||
// If GSO, but next is bigger than this one, we must enter the final state.
|
// If GSO, but next is bigger than this one, we must enter the final state.
|
||||||
if (use_gso && !gso_final) {
|
if (use_gso && !gso_final) {
|
||||||
gso_final = (nn_packet < nn_next_packet);
|
gso_final = (nn_packet < nn_next_packet);
|
||||||
|
@ -1025,8 +1048,8 @@ srs_error_t SrsRtcSenderThread::send_packets_gso(SrsUdpMuxSocket* skt, SrsRtcPac
|
||||||
}
|
}
|
||||||
|
|
||||||
#if defined(SRS_DEBUG)
|
#if defined(SRS_DEBUG)
|
||||||
srs_trace("RTC PLAY summary, rtp %d/%d, videos %d/%d, audios %d/%d", packets.packets.size(),
|
srs_trace("RTC PLAY summary, rtp %d/%d, videos %d/%d, audios %d/%d, pad %d", packets.packets.size(), packets.nn_rtp_pkts,
|
||||||
packets.nn_rtp_pkts, packets.nn_videos, packets.nn_samples, packets.nn_audios, packets.nn_extras);
|
packets.nn_videos, packets.nn_samples, packets.nn_audios, packets.nn_extras, packets.nn_paddings);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
return err;
|
return err;
|
||||||
|
|
|
@ -138,6 +138,8 @@ public:
|
||||||
int nn_audios;
|
int nn_audios;
|
||||||
// The original video messages.
|
// The original video messages.
|
||||||
int nn_videos;
|
int nn_videos;
|
||||||
|
// The number of padded packet.
|
||||||
|
int nn_paddings;
|
||||||
public:
|
public:
|
||||||
std::vector<SrsRtpPacket2*> packets;
|
std::vector<SrsRtpPacket2*> packets;
|
||||||
public:
|
public:
|
||||||
|
@ -166,6 +168,7 @@ public:
|
||||||
SrsUdpMuxSocket* sendonly_ukt;
|
SrsUdpMuxSocket* sendonly_ukt;
|
||||||
bool merge_nalus;
|
bool merge_nalus;
|
||||||
bool gso;
|
bool gso;
|
||||||
|
int max_padding;
|
||||||
public:
|
public:
|
||||||
SrsRtcSenderThread(SrsRtcSession* s, SrsUdpMuxSocket* u, int parent_cid);
|
SrsRtcSenderThread(SrsRtcSession* s, SrsUdpMuxSocket* u, int parent_cid);
|
||||||
virtual ~SrsRtcSenderThread();
|
virtual ~SrsRtcSenderThread();
|
||||||
|
|
Loading…
Reference in a new issue