From 9a9efb854659420a83b4e9d52f1b0c8011aa5d12 Mon Sep 17 00:00:00 2001 From: winlin Date: Sun, 7 Feb 2021 15:48:46 +0800 Subject: [PATCH] RTC: Parse TWCC SN fastly. --- trunk/src/app/srs_app_rtc_conn.cpp | 9 +--- trunk/src/kernel/srs_kernel_rtc_rtp.cpp | 62 +++++++++++++++++++++++++ trunk/src/kernel/srs_kernel_rtc_rtp.hpp | 2 + 3 files changed, 65 insertions(+), 8 deletions(-) diff --git a/trunk/src/app/srs_app_rtc_conn.cpp b/trunk/src/app/srs_app_rtc_conn.cpp index 103a53319..5ec60865e 100644 --- a/trunk/src/app/srs_app_rtc_conn.cpp +++ b/trunk/src/app/srs_app_rtc_conn.cpp @@ -1132,19 +1132,12 @@ srs_error_t SrsRtcPublishStream::on_rtp(char* data, int nb_data) // Decode the header first. if (twcc_id_) { - SrsRtpHeader h; - 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). uint16_t twcc_sn = 0; - if ((err = h.get_twcc_sequence_number(twcc_sn)) == srs_success) { + if ((err = srs_rtp_fast_parse_twcc(data, nb_data, &extension_types_, twcc_sn)) == srs_success) { if((err = on_twcc(twcc_sn)) != srs_success) { return srs_error_wrap(err, "on twcc"); } diff --git a/trunk/src/kernel/srs_kernel_rtc_rtp.cpp b/trunk/src/kernel/srs_kernel_rtc_rtp.cpp index 355b02c61..04a17d154 100644 --- a/trunk/src/kernel/srs_kernel_rtc_rtp.cpp +++ b/trunk/src/kernel/srs_kernel_rtc_rtp.cpp @@ -70,6 +70,68 @@ uint8_t srs_rtp_fast_parse_pt(char* buf, int size) } return buf[1] & 0x7f; } +srs_error_t srs_rtp_fast_parse_twcc(char* buf, int size, SrsRtpExtensionTypes* ext_types, uint16_t& twcc_sn) +{ + srs_error_t err = srs_success; + + int need_size = 12 /*rtp head fix len*/ + 4 /* extension header len*/ + 3 /* twcc extension len*/; + if(size < (need_size)) { + return srs_error_new(ERROR_RTC_RTP_MUXER, "required %d bytes, actual %d", need_size, size); + } + + uint8_t first = buf[0]; + bool extension = (first & 0x10); + uint8_t cc = (first & 0x0F); + + if(!extension) { + return srs_error_new(ERROR_RTC_RTP, "no extension in rtp"); + } + + need_size += cc * 4; // csrc size + if(size < (need_size)) { + return srs_error_new(ERROR_RTC_RTP_MUXER, "required %d bytes, actual %d", need_size, size); + } + buf += 12 + 4*cc; + + uint16_t value = *((uint16_t*)buf); + value = ntohs(value); + if(0xBEDE != value) { + return srs_error_new(ERROR_RTC_RTP_MUXER, "no support this type(0x%02x) extension", value); + } + buf += 2; + + uint16_t extension_length = ntohs(*((uint16_t*)buf)); + buf += 2; + extension_length *= 4; + need_size += extension_length; // entension size + if(size < (need_size)) { + return srs_error_new(ERROR_RTC_RTP_MUXER, "required %d bytes, actual %d", need_size, size); + } + + while(extension_length > 0) { + uint8_t v = buf[0]; + buf++; + extension_length--; + if(0 == v) { + continue; + } + + uint8_t id = (v & 0xF0) >>4; + uint8_t len = (v & 0x0F) + 1; + + SrsRtpExtensionType xtype = ext_types->get_type(id); + if(xtype == kRtpExtensionTransportSequenceNumber) { + twcc_sn = ntohs(*((uint16_t*)buf)); + return err; + } else { + buf += len; + extension_length -= len; + } + } + + + return err; +} // If value is newer than pre_value,return true; otherwise false bool srs_seq_is_newer(uint16_t value, uint16_t pre_value) diff --git a/trunk/src/kernel/srs_kernel_rtc_rtp.hpp b/trunk/src/kernel/srs_kernel_rtc_rtp.hpp index 4b5761b4a..b843dc201 100644 --- a/trunk/src/kernel/srs_kernel_rtc_rtp.hpp +++ b/trunk/src/kernel/srs_kernel_rtc_rtp.hpp @@ -57,10 +57,12 @@ class SrsBuffer; class SrsRtpRawPayload; class SrsRtpFUAPayload2; class SrsSharedPtrMessage; +class SrsRtpExtensionTypes; // Fast parse the SSRC from RTP packet. Return 0 if invalid. uint32_t srs_rtp_fast_parse_ssrc(char* buf, int size); uint8_t srs_rtp_fast_parse_pt(char* buf, int size); +srs_error_t srs_rtp_fast_parse_twcc(char* buf, int size, SrsRtpExtensionTypes* types, uint16_t& twcc_sn); // The "distance" between two uint16 number, for example: // distance(prev_value=3, value=5) === (int16_t)(uint16_t)((uint16_t)3-(uint16_t)5) === -2