mirror of
https://github.com/ossrs/srs.git
synced 2025-02-15 04:42:04 +00:00
RTC: Parse TWCC SN fastly.
This commit is contained in:
parent
d184b5662c
commit
9a9efb8546
3 changed files with 65 additions and 8 deletions
|
@ -1132,19 +1132,12 @@ srs_error_t SrsRtcPublishStream::on_rtp(char* data, int nb_data)
|
||||||
|
|
||||||
// Decode the header first.
|
// Decode the header first.
|
||||||
if (twcc_id_) {
|
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:
|
// 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.
|
// 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.
|
// 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).
|
// so, we must parse the header before SRTP unprotect(which may fail and drop packet).
|
||||||
uint16_t twcc_sn = 0;
|
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) {
|
if((err = on_twcc(twcc_sn)) != srs_success) {
|
||||||
return srs_error_wrap(err, "on twcc");
|
return srs_error_wrap(err, "on twcc");
|
||||||
}
|
}
|
||||||
|
|
|
@ -70,6 +70,68 @@ uint8_t srs_rtp_fast_parse_pt(char* buf, int size)
|
||||||
}
|
}
|
||||||
return buf[1] & 0x7f;
|
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
|
// If value is newer than pre_value,return true; otherwise false
|
||||||
bool srs_seq_is_newer(uint16_t value, uint16_t pre_value)
|
bool srs_seq_is_newer(uint16_t value, uint16_t pre_value)
|
||||||
|
|
|
@ -57,10 +57,12 @@ class SrsBuffer;
|
||||||
class SrsRtpRawPayload;
|
class SrsRtpRawPayload;
|
||||||
class SrsRtpFUAPayload2;
|
class SrsRtpFUAPayload2;
|
||||||
class SrsSharedPtrMessage;
|
class SrsSharedPtrMessage;
|
||||||
|
class SrsRtpExtensionTypes;
|
||||||
|
|
||||||
// Fast parse the SSRC from RTP packet. Return 0 if invalid.
|
// Fast parse the SSRC from RTP packet. Return 0 if invalid.
|
||||||
uint32_t srs_rtp_fast_parse_ssrc(char* buf, int size);
|
uint32_t srs_rtp_fast_parse_ssrc(char* buf, int size);
|
||||||
uint8_t srs_rtp_fast_parse_pt(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:
|
// 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
|
// distance(prev_value=3, value=5) === (int16_t)(uint16_t)((uint16_t)3-(uint16_t)5) === -2
|
||||||
|
|
Loading…
Reference in a new issue