diff --git a/trunk/conf/full.conf b/trunk/conf/full.conf index 037b3fea3..e12ee39fc 100644 --- a/trunk/conf/full.conf +++ b/trunk/conf/full.conf @@ -497,6 +497,9 @@ vhost rtc.vhost.srs.com { # The version of dtls, support dtls1.0, dtls1.2, and auto # default: auto dtls_version auto; + # Drop the packet with the pt(payload type), 0 never drop. + # default: 0 + drop_for_pt 0; } # whether enable min delay mode for vhost. # default: on, for RTC. diff --git a/trunk/src/app/srs_app_config.cpp b/trunk/src/app/srs_app_config.cpp index 4bbcff951..11b4d93c3 100644 --- a/trunk/src/app/srs_app_config.cpp +++ b/trunk/src/app/srs_app_config.cpp @@ -3935,7 +3935,7 @@ srs_error_t SrsConfig::check_normal_config() for (int j = 0; j < (int)conf->directives.size(); j++) { string m = conf->at(j)->name; if (m != "enabled" && m != "bframe" && m != "aac" && m != "stun_timeout" && m != "stun_strict_check" - && m != "dtls_role" && m != "dtls_version") { + && m != "dtls_role" && m != "dtls_version" && m != "drop_for_pt") { return srs_error_new(ERROR_SYSTEM_CONFIG_INVALID, "illegal vhost.rtc.%s of %s", m.c_str(), vhost->arg0().c_str()); } } @@ -5056,6 +5056,23 @@ std::string SrsConfig::get_rtc_dtls_version(string vhost) return conf->arg0(); } +int SrsConfig::get_rtc_drop_for_pt(string vhost) +{ + static int DEFAULT = 0; + + SrsConfDirective* conf = get_vhost(vhost); + if (!conf) { + return DEFAULT; + } + + conf = conf->get("drop_for_pt"); + if (!conf || conf->arg0().empty()) { + return DEFAULT; + } + + return ::atoi(conf->arg0().c_str()); +} + bool SrsConfig::get_rtc_nack_enabled(string vhost) { static bool DEFAULT = true; diff --git a/trunk/src/app/srs_app_config.hpp b/trunk/src/app/srs_app_config.hpp index 0f6bbba29..5b083784a 100644 --- a/trunk/src/app/srs_app_config.hpp +++ b/trunk/src/app/srs_app_config.hpp @@ -546,6 +546,7 @@ public: bool get_rtc_stun_strict_check(std::string vhost); std::string get_rtc_dtls_role(std::string vhost); std::string get_rtc_dtls_version(std::string vhost); + int get_rtc_drop_for_pt(std::string vhost); bool get_rtc_nack_enabled(std::string vhost); bool get_rtc_twcc_enabled(std::string vhost); diff --git a/trunk/src/app/srs_app_rtc_conn.cpp b/trunk/src/app/srs_app_rtc_conn.cpp index 16fa7531d..e4251e7d3 100644 --- a/trunk/src/app/srs_app_rtc_conn.cpp +++ b/trunk/src/app/srs_app_rtc_conn.cpp @@ -855,6 +855,7 @@ SrsRtcPublisher::SrsRtcPublisher(SrsRtcSession* session) source = NULL; nn_simulate_nack_drop = 0; nack_enabled_ = false; + pt_to_drop_ = 0; nn_audio_frames = 0; twcc_ext_id_ = 0; @@ -892,9 +893,10 @@ srs_error_t SrsRtcPublisher::initialize(uint32_t vssrc, uint32_t assrc, uint8_t } // TODO: FIXME: Support reload. nack_enabled_ = _srs_config->get_rtc_nack_enabled(session_->req->vhost); + pt_to_drop_ = (uint16_t)_srs_config->get_rtc_drop_for_pt(session_->req->vhost); - srs_trace("RTC publisher video(ssrc=%u), audio(ssrc=%u), nack=%d", - video_ssrc, audio_ssrc, nack_enabled_); + srs_trace("RTC publisher video(ssrc=%u), audio(ssrc=%u), nack=%d, pt-drop=%u", + video_ssrc, audio_ssrc, nack_enabled_, pt_to_drop_); if ((err = report_timer->tick(0 * SRS_UTIME_MILLISECONDS)) != srs_success) { return srs_error_wrap(err, "hourglass tick"); @@ -1133,6 +1135,7 @@ srs_error_t SrsRtcPublisher::on_twcc(uint16_t sn) { srs_utime_t now = srs_get_system_time(); return rtcp_twcc_.recv_packet(sn, now); } + srs_error_t SrsRtcPublisher::on_rtp(char* data, int nb_data) { srs_error_t err = srs_success; @@ -1144,18 +1147,21 @@ srs_error_t SrsRtcPublisher::on_rtp(char* data, int nb_data) return err; } - // We must parse the TWCC from RTP header before SRTP unprotect, because: - // 1. Client may send some padding packets with invalid SequenceNumber, which causes the SRTP fail. - // 2. Server may send multiple duplicated NACK to client, and got more than one ARQ packet, which also fail SRTP. - // so, we must parse the header before SRTP unprotect(which may fail and drop packet). - if (0 != twcc_ext_id_) { - SrsBuffer b(data, nb_data); SrsRtpHeader h; - h.ignore_padding(true); - h.set_extensions(&extension_types_); + // Decode the header first. + SrsRtpHeader h; + if (pt_to_drop_ && twcc_ext_id_) { + SrsBuffer b(data, nb_data); + h.ignore_padding(true); h.set_extensions(&extension_types_); if ((err = h.decode(&b)) != srs_success) { return srs_error_wrap(err, "twcc decode header"); } + } + // We must parse the TWCC from RTP header before SRTP unprotect, because: + // 1. Client may send some padding packets with invalid SequenceNumber, which causes the SRTP fail. + // 2. Server may send multiple duplicated NACK to client, and got more than one ARQ packet, which also fail SRTP. + // so, we must parse the header before SRTP unprotect(which may fail and drop packet). + if (twcc_ext_id_) { uint16_t twcc_sn = 0; if ((err = h.get_twcc_sequence_number(twcc_sn)) == srs_success) { if((err = on_twcc(twcc_sn)) != srs_success) { @@ -1166,6 +1172,11 @@ srs_error_t SrsRtcPublisher::on_rtp(char* data, int nb_data) } } + // If payload type is configed to drop, ignore this packet. + if (pt_to_drop_ && pt_to_drop_ == h.get_payload_type()) { + return err; + } + // Decrypt the cipher to plaintext RTP data. int nb_unprotected_buf = nb_data; char* unprotected_buf = new char[kRtpPacketSize]; diff --git a/trunk/src/app/srs_app_rtc_conn.hpp b/trunk/src/app/srs_app_rtc_conn.hpp index abb64bc2e..96d6ccdd6 100644 --- a/trunk/src/app/srs_app_rtc_conn.hpp +++ b/trunk/src/app/srs_app_rtc_conn.hpp @@ -251,6 +251,9 @@ private: SrsRtcSession* session_; uint32_t video_ssrc; uint32_t audio_ssrc; + uint16_t pt_to_drop_; + // Whether enabled nack. + bool nack_enabled_; private: bool request_keyframe_; SrsRtpRingBuffer* video_queue_; @@ -260,8 +263,6 @@ private: private: SrsRequest* req; SrsRtcSource* source; - // Whether enabled nack. - bool nack_enabled_; // Simulators. int nn_simulate_nack_drop; private: