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:
parent
62b70943d4
commit
5cc0f70f62
4 changed files with 305 additions and 117 deletions
|
@ -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);
|
||||||
|
|
||||||
|
|
|
@ -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();
|
||||||
|
|
|
@ -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()
|
||||||
|
|
|
@ -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();
|
||||||
|
|
Loading…
Reference in a new issue