1
0
Fork 0
mirror of https://github.com/ossrs/srs.git synced 2025-02-15 04:42:04 +00:00

RTC: Refine the extensions for RTP.

This commit is contained in:
winlin 2020-06-26 15:24:37 +08:00
parent 62b70943d4
commit 5cc0f70f62
4 changed files with 305 additions and 117 deletions

View file

@ -917,7 +917,7 @@ srs_error_t SrsRtcPublisher::initialize(uint32_t vssrc, uint32_t assrc, uint8_t
req = r; req = r;
if (twcc_ext_id_ != 0) { if (twcc_ext_id_ != 0) {
extension_map_.register_by_uri(twcc_ext_id_, kTWCCExt); extension_types_.register_by_uri(twcc_ext_id_, kTWCCExt);
} }
// TODO: FIXME: Support reload. // TODO: FIXME: Support reload.
nack_enabled_ = _srs_config->get_rtc_nack_enabled(session_->req->vhost); nack_enabled_ = _srs_config->get_rtc_nack_enabled(session_->req->vhost);
@ -1224,7 +1224,7 @@ srs_error_t SrsRtcPublisher::on_rtp(char* data, int nb_data)
if (true) { if (true) {
pkt->set_decode_handler(this); pkt->set_decode_handler(this);
pkt->set_rtp_header_extensions(&extension_map_); pkt->set_extension_types(&extension_types_);
pkt->shared_msg = new SrsSharedPtrMessage(); pkt->shared_msg = new SrsSharedPtrMessage();
pkt->shared_msg->wrap(buf, nb_buf); pkt->shared_msg->wrap(buf, nb_buf);

View file

@ -277,7 +277,7 @@ private:
uint8_t twcc_ext_id_; uint8_t twcc_ext_id_;
uint8_t twcc_fb_count_; uint8_t twcc_fb_count_;
SrsRtcpTWCC rtcp_twcc_; SrsRtcpTWCC rtcp_twcc_;
SrsRtpHeaderExtensionMap extension_map_; SrsRtpExtensionTypes extension_types_;
public: public:
SrsRtcPublisher(SrsRtcSession* session); SrsRtcPublisher(SrsRtcSession* session);
virtual ~SrsRtcPublisher(); virtual ~SrsRtcPublisher();

View file

@ -53,15 +53,15 @@ int32_t srs_seq_distance(uint16_t value, uint16_t pre_value)
return srs_rtp_seq_distance(pre_value, value); return srs_rtp_seq_distance(pre_value, value);
} }
SrsRtpHeaderExtensionMap::SrsRtpHeaderExtensionMap() SrsRtpExtensionTypes::SrsRtpExtensionTypes()
{ {
} }
SrsRtpHeaderExtensionMap::~SrsRtpHeaderExtensionMap() SrsRtpExtensionTypes::~SrsRtpExtensionTypes()
{ {
} }
bool SrsRtpHeaderExtensionMap::register_by_uri(int id, std::string uri) bool SrsRtpExtensionTypes::register_by_uri(int id, std::string uri)
{ {
for (int i = 0; i < (int)sizeof(kExtensions); ++i) { for (int i = 0; i < (int)sizeof(kExtensions); ++i) {
if (kExtensions[i].uri == uri) { if (kExtensions[i].uri == uri) {
@ -71,7 +71,7 @@ bool SrsRtpHeaderExtensionMap::register_by_uri(int id, std::string uri)
return false; return false;
} }
bool SrsRtpHeaderExtensionMap::register_id(int id, SrsRtpExtensionType type, std::string uri) bool SrsRtpExtensionTypes::register_id(int id, SrsRtpExtensionType type, std::string uri)
{ {
if (id < 1 || id > 255) { if (id < 1 || id > 255) {
return false; return false;
@ -81,7 +81,7 @@ bool SrsRtpHeaderExtensionMap::register_id(int id, SrsRtpExtensionType type, std
return true; return true;
} }
SrsRtpExtensionType SrsRtpHeaderExtensionMap::get_type(int id) const SrsRtpExtensionType SrsRtpExtensionTypes::get_type(int id) const
{ {
for (int type = kRtpExtensionNone + 1; type < kRtpExtensionNumberOfExtensions; ++type) { for (int type = kRtpExtensionNone + 1; type < kRtpExtensionNumberOfExtensions; ++type) {
if (ids_[type] == id) { if (ids_[type] == id) {
@ -91,50 +91,148 @@ SrsRtpExtensionType SrsRtpHeaderExtensionMap::get_type(int id) const
return kInvalidType; return kInvalidType;
} }
SrsRtpHeaderExtension::SrsRtpHeaderExtension()
{
has_transport_sequence_number = false;
transport_sequence_number = 0;
transport_cc_ext_id = 0;
}
SrsRtpHeaderExtension::~SrsRtpHeaderExtension()
SrsRtpExtensionTwcc::SrsRtpExtensionTwcc(): has_twcc_(false), id_(0), sn_(0)
{ {
} }
SrsRtpHeader::SrsRtpHeader() SrsRtpExtensionTwcc::~SrsRtpExtensionTwcc()
{
padding_length = 0;
extension = false;
cc = 0;
marker = false;
payload_type = 0;
sequence = 0;
timestamp = 0;
ssrc = 0;
extension_length = 0;
}
SrsRtpHeader::~SrsRtpHeader()
{ {
} }
srs_error_t SrsRtpHeader::parse_extension(SrsBuffer* buf) { bool SrsRtpExtensionTwcc::has_twcc_ext()
{
return has_twcc_;
}
srs_error_t SrsRtpExtensionTwcc::decode(SrsBuffer* buf)
{
srs_error_t err = srs_success; srs_error_t err = srs_success;
// 0 1 2
// 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3
// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
// | ID | L=1 |transport wide sequence number |
// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
if (!buf->require(1)) {
return srs_error_new(ERROR_RTC_RTP_MUXER, "requires %d bytes", 1);
}
uint8_t v = buf->read_1bytes();
id_ = (v & 0xF0) >> 4;
uint8_t len = (v & 0x0F);
if(!id_ || len != 1) {
return srs_error_new(ERROR_RTC_RTP, "invalid twcc id=%d, len=%d", id_, len);
}
if (!buf->require(3)) {
return srs_error_new(ERROR_RTC_RTP_MUXER, "requires %d bytes", 3);
}
sn_ = buf->read_2bytes();
buf->read_1bytes();
has_twcc_ = true;
return err;
}
int SrsRtpExtensionTwcc::nb_bytes()
{
return 4;
}
srs_error_t SrsRtpExtensionTwcc::encode(SrsBuffer* buf)
{
srs_error_t err = srs_success;
uint8_t id_len = (id_ & 0x0F)<< 4| 0x01;
buf->write_1bytes(id_len);
buf->write_2bytes(sn_);
buf->write_1bytes(0x00);
return err;
}
uint8_t SrsRtpExtensionTwcc::get_id()
{
return id_;
}
void SrsRtpExtensionTwcc::set_id(uint8_t id)
{
id_ = id;
has_twcc_ = true;
}
uint16_t SrsRtpExtensionTwcc::get_sn()
{
return sn_;
}
void SrsRtpExtensionTwcc::set_sn(uint16_t sn)
{
sn_ = sn;
has_twcc_ = true;
}
SrsRtpExtensions::SrsRtpExtensions() : has_ext_(false)
{
}
SrsRtpExtensions::~SrsRtpExtensions()
{
}
srs_error_t SrsRtpExtensions::decode(SrsBuffer* buf)
{
srs_error_t err = srs_success;
/* @see https://tools.ietf.org/html/rfc3550#section-5.3.1
0 1 2 3
0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| defined by profile | length |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| header extension |
| .... |
*/
if (!buf->require(4)) {
return srs_error_new(ERROR_RTC_RTP_MUXER, "requires 4 bytes");
}
uint16_t profile_id = buf->read_2bytes(); uint16_t profile_id = buf->read_2bytes();
extension_length = buf->read_2bytes(); uint16_t extension_length = buf->read_2bytes();
// @see: https://tools.ietf.org/html/rfc5285#section-4.2 // @see: https://tools.ietf.org/html/rfc5285#section-4.2
if (profile_id == 0xBEDE) { if (profile_id == 0xBEDE) {
uint32_t xlen = extension_length * 4; SrsBuffer xbuf(buf->head(), extension_length * 4);
while (xlen > 0) { buf->skip(extension_length * 4);
// parse id and len return decode_0xbede(&xbuf);
uint8_t id_len = buf->read_1bytes(); } else if (profile_id == 0x1000) {
xlen--; buf->skip(extension_length * 4);
if(id_len == 0) { } else {
// padding, ignore return srs_error_new(ERROR_RTC_RTP_MUXER, "fail to parse extension");
}
return err;
}
srs_error_t SrsRtpExtensions::decode_0xbede(SrsBuffer* buf)
{
srs_error_t err = srs_success;
while (!buf->empty()) {
// The first byte maybe padding or id+len.
if (!buf->require(1)) {
return srs_error_new(ERROR_RTC_RTP_MUXER, "requires %d bytes", 1);
}
uint8_t v = *((uint8_t*)buf->head());
// Padding, ignore
if(v == 0) {
buf->skip(1);
continue; continue;
} }
// 0 // 0
// 0 1 2 3 4 5 6 7 // 0 1 2 3 4 5 6 7
// +-+-+-+-+-+-+-+-+ // +-+-+-+-+-+-+-+-+
@ -142,34 +240,91 @@ srs_error_t SrsRtpHeader::parse_extension(SrsBuffer* buf) {
// +-+-+-+-+-+-+-+-+ // +-+-+-+-+-+-+-+-+
// Note that 'len' is the header extension element length, which is the // Note that 'len' is the header extension element length, which is the
// number of bytes - 1. // number of bytes - 1.
uint8_t id = (id_len & 0xF0) >> 4; uint8_t id = (v & 0xF0) >> 4;
uint8_t len = (id_len & 0x0F); uint8_t len = (v & 0x0F);
SrsRtpExtensionType xtype = extension_map_.get_type(id); SrsRtpExtensionType xtype = types_.get_type(id);
if (xtype == kRtpExtensionTransportSequenceNumber) { if (xtype == kRtpExtensionTransportSequenceNumber) {
// 0 1 2 if(srs_success != (err = twcc_.decode(buf))) {
// 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 return srs_error_wrap(err, "decode twcc extension");
// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
// | ID | L=1 |transport wide sequence number |
// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
header_extension.has_transport_sequence_number = true;
header_extension.transport_sequence_number = buf->read_2bytes();
header_extension.transport_cc_ext_id = id;
xlen -= 2;
} else {
buf->skip(len + 1);
xlen -= len + 1;
} }
} has_ext_ = true;
} else if (profile_id == 0x1000) {
buf->skip(extension_length * 4);
} else { } else {
return srs_error_new(ERROR_RTC_RTP_MUXER, "fail to parse extension"); buf->skip(1 + (len + 1));
}
} }
return err; return err;
} }
int SrsRtpExtensions::nb_bytes()
{
return 4 + (twcc_.has_twcc_ext() ? twcc_.nb_bytes() : 0);
}
srs_error_t SrsRtpExtensions::encode(SrsBuffer* buf)
{
srs_error_t err = srs_success;
buf->write_2bytes(0xBEDE);
int len = 0;
//TODO: When add new rtp extension, it should add the extension length into len
if(twcc_.has_twcc_ext()) {
len += twcc_.nb_bytes();
}
buf->write_2bytes(len / 4);
if(twcc_.has_twcc_ext()) {
if(srs_success != (err = twcc_.encode(buf))) {
return srs_error_wrap(err, "encode twcc extension");
}
}
return err;
}
bool SrsRtpExtensions::exists()
{
return has_ext_;
}
void SrsRtpExtensions::set_types_(const SrsRtpExtensionTypes* types)
{
if(types) {
types_ = *types;
}
}
srs_error_t SrsRtpExtensions::get_twcc_sequence_number(uint16_t& twcc_sn)
{
if(twcc_.has_twcc_ext()) {
twcc_sn = twcc_.get_sn();
return srs_success;
}
return srs_error_new(ERROR_RTC_RTP_MUXER, "not find twcc sequence number");
}
srs_error_t SrsRtpExtensions::set_twcc_sequence_number(uint8_t id, uint16_t sn)
{
has_ext_ = true;
twcc_.set_id(id);
twcc_.set_sn(sn);
return srs_success;
}
SrsRtpHeader::SrsRtpHeader()
{
padding_length = 0;
cc = 0;
marker = false;
payload_type = 0;
sequence = 0;
timestamp = 0;
ssrc = 0;
}
SrsRtpHeader::~SrsRtpHeader()
{
}
srs_error_t SrsRtpHeader::decode(SrsBuffer* buf) srs_error_t SrsRtpHeader::decode(SrsBuffer* buf)
{ {
srs_error_t err = srs_success; srs_error_t err = srs_success;
@ -178,7 +333,7 @@ srs_error_t SrsRtpHeader::decode(SrsBuffer* buf)
return srs_error_new(ERROR_RTC_RTP_MUXER, "requires %d+ bytes", kRtpHeaderFixedSize); return srs_error_new(ERROR_RTC_RTP_MUXER, "requires %d+ bytes", kRtpHeaderFixedSize);
} }
/* /* @see https://tools.ietf.org/html/rfc1889#section-5.1
0 1 2 3 0 1 2 3
0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
@ -195,7 +350,7 @@ srs_error_t SrsRtpHeader::decode(SrsBuffer* buf)
uint8_t first = buf->read_1bytes(); uint8_t first = buf->read_1bytes();
bool padding = (first & 0x20); bool padding = (first & 0x20);
extension = (first & 0x10); bool extension = (first & 0x10);
cc = (first & 0x0F); cc = (first & 0x0F);
uint8_t second = buf->read_1bytes(); uint8_t second = buf->read_1bytes();
@ -216,16 +371,7 @@ srs_error_t SrsRtpHeader::decode(SrsBuffer* buf)
} }
if (extension) { if (extension) {
/* RTP header extension, RFC 3550. if ((err = parse_extensions(buf)) != srs_success) {
0 1 2 3
0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| defined by profile | length |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| header extension |
| .... |
*/
if ((err = parse_extension(buf)) != srs_success) {
return srs_error_wrap(err, "fail to parse extension"); return srs_error_wrap(err, "fail to parse extension");
} }
} }
@ -240,6 +386,16 @@ srs_error_t SrsRtpHeader::decode(SrsBuffer* buf)
return err; return err;
} }
srs_error_t SrsRtpHeader::parse_extensions(SrsBuffer* buf) {
srs_error_t err = srs_success;
if(srs_success != (err = extensions_.decode(buf))) {
return srs_error_wrap(err, "decode rtp extension");
}
return err;
}
srs_error_t SrsRtpHeader::encode(SrsBuffer* buf) srs_error_t SrsRtpHeader::encode(SrsBuffer* buf)
{ {
srs_error_t err = srs_success; srs_error_t err = srs_success;
@ -251,7 +407,7 @@ srs_error_t SrsRtpHeader::encode(SrsBuffer* buf)
if (padding_length > 0) { if (padding_length > 0) {
v |= 0x20; v |= 0x20;
} }
if (extension) { if (extensions_.exists()) {
v |= 0x10; v |= 0x10;
} }
buf->write_1bytes(v); buf->write_1bytes(v);
@ -277,40 +433,37 @@ srs_error_t SrsRtpHeader::encode(SrsBuffer* buf)
buf->write_4bytes(csrc[i]); buf->write_4bytes(csrc[i]);
} }
if (extension) { if (extensions_.exists()) {
buf->write_2bytes(0xBEDE); if(srs_success != (err = extensions_.encode(buf))) {
// TODO: FIXME: extension_length should caculate by extension length return srs_error_wrap(err, "encode rtp extension");
buf->write_2bytes(extension_length);
if (header_extension.has_transport_sequence_number) {
uint8_t id_len = (header_extension.transport_cc_ext_id & 0x0F)<< 4| 0x01;
buf->write_1bytes(id_len);
buf->write_2bytes(header_extension.transport_sequence_number);
buf->write_1bytes(0x00);
} }
} }
return err; return err;
} }
void SrsRtpHeader::set_extensions(const SrsRtpHeaderExtensionMap* extmap) void SrsRtpHeader::set_extensions(const SrsRtpExtensionTypes* extmap)
{ {
if (extmap) { if (extmap) {
extension_map_ = *extmap; extensions_.set_types_(extmap);
} }
} }
srs_error_t SrsRtpHeader::get_twcc_sequence_number(uint16_t& twcc_sn) srs_error_t SrsRtpHeader::get_twcc_sequence_number(uint16_t& twcc_sn)
{ {
if (header_extension.has_transport_sequence_number == true) { if (extensions_.exists()) {
twcc_sn = header_extension.transport_sequence_number; return extensions_.get_twcc_sequence_number(twcc_sn);
return srs_success;
} }
return srs_error_new(ERROR_RTC_RTP_MUXER, "not find twcc sequence number"); return srs_error_new(ERROR_RTC_RTP_MUXER, "no rtp extension");
}
srs_error_t SrsRtpHeader::set_twcc_sequence_number(uint8_t id, uint16_t sn)
{
return extensions_.set_twcc_sequence_number(id, sn);
} }
int SrsRtpHeader::nb_bytes() int SrsRtpHeader::nb_bytes()
{ {
return kRtpHeaderFixedSize + cc * 4 + (extension ? (extension_length + 1) * 4 : 0); return kRtpHeaderFixedSize + cc * 4 + (extensions_.exists() ? extensions_.nb_bytes() : 0);
} }
void SrsRtpHeader::set_marker(bool v) void SrsRtpHeader::set_marker(bool v)
@ -449,9 +602,9 @@ SrsRtpPacket2* SrsRtpPacket2::copy()
return cp; return cp;
} }
void SrsRtpPacket2::set_rtp_header_extensions(const SrsRtpHeaderExtensionMap* extmap) void SrsRtpPacket2::set_extension_types(const SrsRtpExtensionTypes* v)
{ {
return header.set_extensions(extmap); return header.set_extensions(v);
} }
int SrsRtpPacket2::nb_bytes() int SrsRtpPacket2::nb_bytes()

View file

@ -99,7 +99,7 @@ const SrsExtensionInfo kExtensions[] = {
{kRtpExtensionTransportSequenceNumber, std::string("http://www.ietf.org/id/draft-holmer-rmcat-transport-wide-cc-extensions-01")} {kRtpExtensionTransportSequenceNumber, std::string("http://www.ietf.org/id/draft-holmer-rmcat-transport-wide-cc-extensions-01")}
}; };
class SrsRtpHeaderExtensionMap class SrsRtpExtensionTypes
{ {
public: public:
static const SrsRtpExtensionType kInvalidType = kRtpExtensionNone; static const SrsRtpExtensionType kInvalidType = kRtpExtensionNone;
@ -108,30 +108,65 @@ public:
bool register_by_uri(int id, std::string uri); bool register_by_uri(int id, std::string uri);
SrsRtpExtensionType get_type(int id) const; SrsRtpExtensionType get_type(int id) const;
public: public:
SrsRtpHeaderExtensionMap(); SrsRtpExtensionTypes();
virtual ~SrsRtpHeaderExtensionMap(); virtual ~SrsRtpExtensionTypes();
private: private:
bool register_id(int id, SrsRtpExtensionType type, std::string uri); bool register_id(int id, SrsRtpExtensionType type, std::string uri);
private: private:
uint8_t ids_[kRtpExtensionNumberOfExtensions]; uint8_t ids_[kRtpExtensionNumberOfExtensions];
}; };
class SrsRtpHeaderExtension class SrsRtpExtensionTwcc : public ISrsCodec
{ {
bool has_twcc_;
uint8_t id_;
uint16_t sn_;
public: public:
bool has_transport_sequence_number; SrsRtpExtensionTwcc();
uint16_t transport_sequence_number; virtual ~SrsRtpExtensionTwcc();
uint8_t transport_cc_ext_id;
bool has_twcc_ext();
uint8_t get_id();
void set_id(uint8_t id);
uint16_t get_sn();
void set_sn(uint16_t sn);
public: public:
SrsRtpHeaderExtension(); // ISrsCodec
virtual ~SrsRtpHeaderExtension(); virtual srs_error_t decode(SrsBuffer* buf);
virtual srs_error_t encode(SrsBuffer* buf);
virtual int nb_bytes();
}; };
class SrsRtpHeader class SrsRtpExtensions : public ISrsCodec
{
private:
bool has_ext_;
SrsRtpExtensionTypes types_;
SrsRtpExtensionTwcc twcc_;
public:
SrsRtpExtensions();
virtual ~SrsRtpExtensions();
bool exists();
void set_types_(const SrsRtpExtensionTypes* types);
srs_error_t get_twcc_sequence_number(uint16_t& twcc_sn);
srs_error_t set_twcc_sequence_number(uint8_t id, uint16_t sn);
// ISrsCodec
public:
virtual srs_error_t decode(SrsBuffer* buf);
private:
srs_error_t decode_0xbede(SrsBuffer* buf);
public:
virtual srs_error_t encode(SrsBuffer* buf);
virtual int nb_bytes();
};
class SrsRtpHeader : public ISrsCodec
{ {
private: private:
uint8_t padding_length; uint8_t padding_length;
bool extension;
uint8_t cc; uint8_t cc;
bool marker; bool marker;
uint8_t payload_type; uint8_t payload_type;
@ -139,16 +174,15 @@ private:
uint32_t timestamp; uint32_t timestamp;
uint32_t ssrc; uint32_t ssrc;
uint32_t csrc[15]; uint32_t csrc[15];
uint16_t extension_length; SrsRtpExtensions extensions_;
SrsRtpHeaderExtensionMap extension_map_;
SrsRtpHeaderExtension header_extension;
public: public:
SrsRtpHeader(); SrsRtpHeader();
virtual ~SrsRtpHeader(); virtual ~SrsRtpHeader();
private:
srs_error_t parse_extension(SrsBuffer* buf);
public: public:
virtual srs_error_t decode(SrsBuffer* buf); virtual srs_error_t decode(SrsBuffer* buf);
private:
srs_error_t parse_extensions(SrsBuffer* buf);
public:
virtual srs_error_t encode(SrsBuffer* buf); virtual srs_error_t encode(SrsBuffer* buf);
virtual int nb_bytes(); virtual int nb_bytes();
public: public:
@ -164,8 +198,9 @@ public:
uint32_t get_ssrc() const; uint32_t get_ssrc() const;
void set_padding(uint8_t v); void set_padding(uint8_t v);
uint8_t get_padding() const; uint8_t get_padding() const;
void set_extensions(const SrsRtpHeaderExtensionMap* extmap); void set_extensions(const SrsRtpExtensionTypes* extmap);
srs_error_t get_twcc_sequence_number(uint16_t& twcc_sn); srs_error_t get_twcc_sequence_number(uint16_t& twcc_sn);
srs_error_t set_twcc_sequence_number(uint8_t id, uint16_t sn);
}; };
class ISrsRtpPayloader : public ISrsCodec class ISrsRtpPayloader : public ISrsCodec
@ -222,7 +257,7 @@ public:
// Copy the RTP packet. // Copy the RTP packet.
SrsRtpPacket2* copy(); SrsRtpPacket2* copy();
// Set RTP header extensions for encoding or decoding header extension // Set RTP header extensions for encoding or decoding header extension
void set_rtp_header_extensions(const SrsRtpHeaderExtensionMap* extmap); void set_extension_types(const SrsRtpExtensionTypes* v);
// interface ISrsEncoder // interface ISrsEncoder
public: public:
virtual int nb_bytes(); virtual int nb_bytes();