From a72dce494d7a65cfdfeb5a7e2e4a0e2ba134efdb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=8E=AB=E6=88=98?= Date: Sat, 9 May 2020 10:51:57 +0800 Subject: [PATCH 1/2] add rtcp support --- trunk/configure | 2 +- trunk/src/kernel/srs_kernel_rtcp.cpp | 637 +++++++++++++++++++++++++++ trunk/src/kernel/srs_kernel_rtcp.hpp | 232 ++++++++++ trunk/src/kernel/srs_kernel_rtp.cpp | 50 +++ trunk/src/kernel/srs_kernel_rtp.hpp | 4 + 5 files changed, 924 insertions(+), 1 deletion(-) create mode 100644 trunk/src/kernel/srs_kernel_rtcp.cpp create mode 100644 trunk/src/kernel/srs_kernel_rtcp.hpp diff --git a/trunk/configure b/trunk/configure index 115e5f8d5..5bc40ce7b 100755 --- a/trunk/configure +++ b/trunk/configure @@ -213,7 +213,7 @@ MODULE_FILES=("srs_kernel_error" "srs_kernel_log" "srs_kernel_buffer" "srs_kernel_consts" "srs_kernel_aac" "srs_kernel_mp3" "srs_kernel_ts" "srs_kernel_stream" "srs_kernel_balance" "srs_kernel_mp4" "srs_kernel_file") if [[ $SRS_RTC == YES ]]; then - MODULE_FILES+=("srs_kernel_rtp") + MODULE_FILES+=("srs_kernel_rtp" "srs_kernel_rtcp") fi KERNEL_INCS="src/kernel"; MODULE_DIR=${KERNEL_INCS} . auto/modules.sh KERNEL_OBJS="${MODULE_OBJS[@]}" diff --git a/trunk/src/kernel/srs_kernel_rtcp.cpp b/trunk/src/kernel/srs_kernel_rtcp.cpp new file mode 100644 index 000000000..0d8762ff4 --- /dev/null +++ b/trunk/src/kernel/srs_kernel_rtcp.cpp @@ -0,0 +1,637 @@ + +#include +#include +#include + +using namespace std; + +SrsRTCPCommon::SrsRTCPCommon() +{ +} + +SrsRTCPCommon::~SrsRTCPCommon() +{ +} + +srs_error_t SrsRTCPCommon::decode_header(SrsBuffer *buffer) +{ + buffer->read_bytes((char*)(&header_), sizeof(srs_rtcp_header_t)); + header_.length = ntohs(header_.length); + return srs_success; +} + +srs_error_t SrsRTCPCommon::encode_header(SrsBuffer *buffer) +{ + header_.length = htons(header_.length); + buffer->write_bytes((char*)(&header_), sizeof(srs_rtcp_header_t)); + return srs_success; +} + +srs_error_t SrsRTCPCommon::decode(SrsBuffer *buffer) +{ + srs_error_t err = srs_success; + err = decode_header(buffer); + if(srs_success != err) { + return srs_error_wrap(err, "fail to parse rtcp header"); + } + payload_len_ = (header_.length + 1) * 4 - sizeof(srs_rtcp_header_t); + buffer->read_bytes((char *)payload_, payload_len_); + return srs_success; +} + +int SrsRTCPCommon::nb_bytes() +{ + return sizeof(srs_rtcp_header_t) + payload_len_; +} + +srs_error_t SrsRTCPCommon::encode(SrsBuffer *buffer) +{ + return srs_error_new(ERROR_RTC_RTCP, "not implement"); +} + +SrsRTCP_SR::SrsRTCP_SR() +{ + header_.padding = 0; + header_.type = RTCP_SR; + header_.rc = 0; + header_.version = kRtcpVersion; + header_.length = 6; +} + +SrsRTCP_SR::~SrsRTCP_SR() +{ + +} + +const uint32_t SrsRTCP_SR::get_sender_ssrc() const +{ + return sender_ssrc_; +} + +const uint64_t SrsRTCP_SR::get_ntp() const +{ + return ntp_; +} + +const uint32_t SrsRTCP_SR::get_rtp_ts() const +{ + return rtp_ts_; +} + +const uint32_t SrsRTCP_SR::get_rtp_send_packets() const +{ + return send_rtp_packets_; +} + +const uint32_t SrsRTCP_SR::get_rtp_send_bytes() const +{ + return send_rtp_bytes_; +} + +void SrsRTCP_SR::set_sender_ssrc(uint32_t ssrc) +{ + sender_ssrc_ = ssrc; +} + +void SrsRTCP_SR::set_ntp(uint64_t ntp) +{ + ntp_ = ntp; +} + +void SrsRTCP_SR::set_rtp_ts(uint32_t ts) +{ + rtp_ts_ = ts; +} + +void SrsRTCP_SR::set_rtp_send_packets(uint32_t packets) +{ + send_rtp_packets_ = packets; +} + +void SrsRTCP_SR::set_rtp_send_bytes(uint32_t bytes) +{ + send_rtp_bytes_ = bytes; +} + +srs_error_t SrsRTCP_SR::decode(SrsBuffer *buffer) +{ + srs_error_t err = srs_success; + err = decode_header(buffer); + if(srs_success != err) { + return srs_error_wrap(err, "fail to parse rtcp header"); + } + sender_ssrc_ = buffer->read_4bytes(); + ntp_ = buffer->read_8bytes(); + rtp_ts_ = buffer->read_4bytes(); + send_rtp_packets_ = buffer->read_4bytes(); + send_rtp_bytes_ = buffer->read_4bytes(); + if(header_.rc > 0) { + char buf[1500]; + buffer->read_bytes(buf, header_.rc * 24); + } + return err; +} + +int SrsRTCP_SR::nb_bytes() +{ + return (header_.length + 1) * 4; +} + +srs_error_t SrsRTCP_SR::encode(SrsBuffer *buffer) +{ + srs_error_t err = srs_success; + if(! buffer->require(nb_bytes())) { + return srs_error_new(ERROR_RTC_RTCP, + "the size of buffer is not enough. buffer:%d, required:%d", buffer->left(), nb_bytes()); + } + err = encode_header(buffer); + if(srs_success != err) { + return srs_error_wrap(err, "fail to encode rtcp header"); + } + buffer->write_4bytes(sender_ssrc_); + buffer->write_8bytes(ntp_); + buffer->write_4bytes(rtp_ts_); + buffer->write_4bytes(send_rtp_packets_); + buffer->write_4bytes(send_rtp_bytes_); + return err; +} + +SrsRTCP_RR::SrsRTCP_RR(uint32_t sender_ssrc/*=0*/): sender_ssrc_(sender_ssrc) +{ + header_.padding = 0; + header_.type = RTCP_RR; + header_.rc = 0; + header_.version = kRtcpVersion; + header_.length = 7; +} + +SrsRTCP_RR::~SrsRTCP_RR() +{ +} + +const uint32_t SrsRTCP_RR::get_rb_ssrc() const +{ + return rb_.ssrc; +} + +const float SrsRTCP_RR::get_lost_rate() const +{ + return rb_.fraction_lost / 256; +} + +const uint32_t SrsRTCP_RR::get_lost_packets() const +{ + return rb_.lost_packets; +} + +const uint32_t SrsRTCP_RR::get_highest_sn() const +{ + return rb_.highest_sn; +} + +const uint32_t SrsRTCP_RR::get_jitter() const +{ + return rb_.jitter; +} + +const uint32_t SrsRTCP_RR::get_lsr() const +{ + return rb_.lsr; +} + +const uint32_t SrsRTCP_RR::get_dlsr() const +{ + return rb_.dlsr; +} + +void SrsRTCP_RR::set_rb_ssrc(uint32_t ssrc) +{ + rb_.ssrc = ssrc; +} + +void SrsRTCP_RR::set_lost_rate(float rate) +{ + rb_.fraction_lost = rate * 256; +} + +void SrsRTCP_RR::set_lost_packets(uint32_t count) +{ + rb_.lost_packets = count; +} + +void SrsRTCP_RR::set_highest_sn(uint32_t sn) +{ + rb_.highest_sn = sn; +} + +void SrsRTCP_RR::set_jitter(uint32_t jitter) +{ + rb_.jitter = jitter; +} + +void SrsRTCP_RR::set_lsr(uint32_t lsr) +{ + rb_.lsr = lsr; +} + +void SrsRTCP_RR::set_dlsr(uint32_t dlsr) +{ + rb_.dlsr = dlsr; +} + +void SrsRTCP_RR::set_sender_ntp(uint64_t ntp) +{ + uint32_t lsr = (uint32_t)((ntp >> 16) & 0x00000000FFFFFFFF); + rb_.lsr = lsr; +} + +srs_error_t SrsRTCP_RR::decode(SrsBuffer *buffer) +{ + srs_error_t err = srs_success; + err = decode_header(buffer); + if(srs_success != err) { + return srs_error_wrap(err, "fail to parse rtcp header"); + } + sender_ssrc_ = buffer->read_4bytes(); + if(header_.rc < 1) { + return srs_success; + } + rb_.ssrc = buffer->read_4bytes(); + rb_.fraction_lost = buffer->read_1bytes(); + rb_.lost_packets = buffer->read_3bytes(); + rb_.highest_sn = buffer->read_4bytes(); + rb_.jitter = buffer->read_4bytes(); + rb_.lsr = buffer->read_4bytes(); + rb_.dlsr = buffer->read_4bytes(); + + if(header_.rc > 1) { + char buf[1500]; + buffer->read_bytes(buf, (header_.rc -1 ) * 24); + } + + return err; +} + +int SrsRTCP_RR::nb_bytes() +{ + return (header_.length + 1) * 4; +} + +srs_error_t SrsRTCP_RR::encode(SrsBuffer *buffer) +{ + srs_error_t err = srs_success; + if(! buffer->require(nb_bytes())) { + return srs_error_new(ERROR_RTC_RTCP, + "the size of buffer is not enough. buffer:%d, required:%d", buffer->left(), nb_bytes()); + } + + header_.rc = 1; + err = encode_header(buffer); + if(srs_success != err) { + return srs_error_wrap(err, "fail to encode rtcp header"); + } + buffer->write_4bytes(sender_ssrc_); + + buffer->write_4bytes(rb_.ssrc); + buffer->write_1bytes(rb_.fraction_lost); + buffer->write_3bytes(rb_.lost_packets); + buffer->write_4bytes(rb_.highest_sn); + buffer->write_4bytes(rb_.jitter); + buffer->write_4bytes(rb_.lsr); + buffer->write_4bytes(rb_.dlsr); + return err; +} + +SrsRTCP_TWCC::SrsRTCP_TWCC(uint32_t sender_ssrc/*=0*/) : sender_ssrc_(sender_ssrc) +{ + header_.padding = 0; + header_.type = RTCP_RTPFB; + header_.rc = 15; + header_.version = kRtcpVersion; +} + +SrsRTCP_TWCC::~SrsRTCP_TWCC() +{ +} + +const uint32_t SrsRTCP_TWCC::get_media_ssrc() const +{ + return media_ssrc_; +} +const uint16_t SrsRTCP_TWCC::get_base_sn() const +{ + return base_sn_; +} + +const uint32_t SrsRTCP_TWCC::get_reference_time() const +{ + return reference_time_; +} + +const uint8_t SrsRTCP_TWCC::get_feedback_count() const +{ + return fb_pkt_count_; +} + +const uint16_t SrsRTCP_TWCC::get_packet_status_count() const +{ + return recv_deltas_.size(); +} + +const vector SrsRTCP_TWCC::get_packet_chucks() const +{ + return packet_chucks_; +} + +const vector SrsRTCP_TWCC::get_recv_deltas() const +{ + return recv_deltas_; +} + +void SrsRTCP_TWCC::set_media_ssrc(uint32_t ssrc) +{ + media_ssrc_ = ssrc; +} +void SrsRTCP_TWCC::set_base_sn(uint16_t sn) +{ + base_sn_ = sn; +} + +void SrsRTCP_TWCC::set_reference_time(uint32_t time) +{ + reference_time_ = time; +} + +void SrsRTCP_TWCC::set_feedback_count(uint8_t count) +{ + fb_pkt_count_ = count; +} + +void SrsRTCP_TWCC::add_packet_chuck(uint16_t chunk) +{ + packet_chucks_.push_back(chunk); +} + +void SrsRTCP_TWCC::add_recv_delta(uint8_t delta) +{ + recv_deltas_.push_back(delta); +} + +srs_error_t SrsRTCP_TWCC::decode(SrsBuffer *buffer) +{ + srs_error_t err = srs_success; + + return err; +} + +int SrsRTCP_TWCC::nb_bytes() +{ + return kRtcpPacketSize; +} + +srs_error_t SrsRTCP_TWCC::encode(SrsBuffer *buffer) +{ + srs_error_t err = srs_success; + + return err; +} + +SrsRTCP_Nack::SrsRTCP_Nack(uint32_t sender_ssrc /*= 0*/): sender_ssrc_(sender_ssrc) +{ + header_.padding = 0; + header_.type = RTCP_RTPFB; + header_.rc = 1; + header_.version = kRtcpVersion; +} + +SrsRTCP_Nack::~SrsRTCP_Nack() +{ +} + +const uint32_t SrsRTCP_Nack::get_media_ssrc() const +{ + return media_ssrc_; +} + +const vector SrsRTCP_Nack::get_lost_sns() const +{ + vector sn; + for(auto it : lost_sns_) { + sn.push_back(it); + } + return sn; +} + +void SrsRTCP_Nack::set_media_ssrc(uint32_t ssrc) +{ + media_ssrc_ = ssrc; +} + +void SrsRTCP_Nack::add_lost_sn(uint16_t sn) +{ + lost_sns_.insert(sn); +} + +srs_error_t SrsRTCP_Nack::decode(SrsBuffer *buffer) +{ + srs_error_t err = srs_success; + err = decode_header(buffer); + if(srs_success != err) { + return srs_error_wrap(err, "fail to parse rtcp header"); + } + sender_ssrc_ = buffer->read_4bytes(); + media_ssrc_ = buffer->read_4bytes(); + char bitmask[20]; + for(int i = 0; i < (header_.length - 2); i++) { + uint16_t pid = buffer->read_2bytes(); + uint16_t blp = buffer->read_2bytes(); + lost_sns_.insert(pid); + memset(bitmask, 0, 20); + for(int j=0; j<16; j++) { + bitmask[j] = (blp & ( 1 << j )) >> j ? '1' : '0'; + if((blp & ( 1 << j )) >> j) + lost_sns_.insert(pid+j+1); + } + bitmask[16] = '\n'; + srs_info("[%d] %d / %s", i, pid, bitmask); + } + + return err; +} +int SrsRTCP_Nack::nb_bytes() +{ + return kRtcpPacketSize; +} + +srs_error_t SrsRTCP_Nack::encode(SrsBuffer *buffer) +{ + srs_error_t err = srs_success; + if(! buffer->require(nb_bytes())) { + return srs_error_new(ERROR_RTC_RTCP, + "the size of buffer is not enough. buffer:%d, required:%d", buffer->left(), nb_bytes()); + } + + vector chunks; + do { + pid_blp_t *chunk = NULL; + uint16_t pid = 0; + for(auto sn : lost_sns_) { + if(NULL == chunk) { + chunk = new pid_blp_t; + chunk->pid = sn; + chunk->blp = 0; + pid = sn; + continue; + } + if((sn - pid) < 1) { + srs_info("Skipping PID to NACK (%d already added)...\n", sn); + } else if( (sn - pid) > 16) { + // add new chunk + chunks.push_back(chunk); + chunk = NULL; + } else { + chunk->blp |= 1 << (sn-pid-1); + } + } + + header_.length = 2 + chunks.size(); + err = encode_header(buffer); + if(srs_success != err) { + err = srs_error_wrap(err, "fail to encode rtcp header"); + break; + } + buffer->write_4bytes(sender_ssrc_); + buffer->write_4bytes(media_ssrc_); + for(auto chunk : chunks) { + buffer->write_2bytes(chunk->pid); + buffer->write_2bytes(chunk->blp); + delete chunk; + chunk = NULL; + } + + } while(0); + + for(auto chunk : chunks) { + delete chunk; + chunk = NULL; + } + + return err; +} + +SrsRTCPCompound::SrsRTCPCompound(): nb_bytes_(0) +{ +} + +SrsRTCPCompound::~SrsRTCPCompound() +{ + clear(); +} + +SrsRTCPCommon* SrsRTCPCompound::get_next_rtcp() +{ + if(rtcps_.empty()) { + return NULL; + } + SrsRTCPCommon *rtcp = rtcps_.back(); + nb_bytes_ -= rtcp->nb_bytes(); + rtcps_.pop_back(); + return rtcp; +} + +srs_error_t SrsRTCPCompound::add_rtcp(SrsRTCPCommon *rtcp) +{ + int new_len = rtcp->nb_bytes(); + if((new_len + nb_bytes_) > kRtcpPacketSize) { + return srs_error_new(ERROR_RTC_RTCP, "exceed the rtcp max size. new rtcp: %d, current: %d", new_len, nb_bytes_); + } + nb_bytes_ += new_len; + rtcps_.push_back(rtcp); + + return srs_success; +} + +srs_error_t SrsRTCPCompound::decode(SrsBuffer *buffer) +{ + srs_error_t err = srs_success; + + while(0 != buffer->left()) { + srs_rtcp_header_t* header = (srs_rtcp_header_t *)(buffer->head()); + switch (header->type) + { + case RTCP_SR: + { + SrsRTCP_SR *rtcp = new SrsRTCP_SR; + err = rtcp->decode(buffer); + if(srs_success != err) { + return srs_error_wrap(err, "fail to decode rtcp sr"); + } + nb_bytes_ += rtcp->nb_bytes(); + rtcps_.push_back(rtcp); + break; + } + case RTCP_RR: + { + SrsRTCP_RR *rtcp = new SrsRTCP_RR; + err = rtcp->decode(buffer); + if(srs_success != err) { + return srs_error_wrap(err, "fail to decode rtcp rr"); + } + nb_bytes_ += rtcp->nb_bytes(); + rtcps_.push_back(rtcp); + break; + } + default: + { + SrsRTCPCommon *rtcp = new SrsRTCPCommon; + err = rtcp->decode(buffer); + if(srs_success != err) { + return srs_error_wrap(err, "fail to decode rtcp type:%d", header->type); + } + nb_bytes_ += rtcp->nb_bytes(); + rtcps_.push_back(rtcp); + break; + } + } + } + + return err; +} + +int SrsRTCPCompound::nb_bytes() +{ + return nb_bytes_; +} + +srs_error_t SrsRTCPCompound::encode(SrsBuffer *buffer) +{ + srs_error_t err = srs_success; + if(false == buffer->require(nb_bytes_)) { + return srs_error_new(ERROR_RTC_RTCP, + "the left size of buffer is not enough. buffer:%d, required:%d", buffer->left(), nb_bytes_); + } + + vector::iterator it; + for(it = rtcps_.begin(); it != rtcps_.end(); ++it) { + SrsRTCPCommon *rtcp = *it; + err = rtcp->encode(buffer); + if(err != srs_success) { + return srs_error_wrap(err, "fail to encode rtcp compound. type:%d", rtcp->type()); + } + } + + clear(); + return err; +} + +void SrsRTCPCompound::clear() +{ + vector::iterator it; + for(it = rtcps_.begin(); it != rtcps_.end(); ++it) { + SrsRTCPCommon *rtcp = *it; + delete rtcp; + rtcp = NULL; + } + rtcps_.clear(); + nb_bytes_ = 0; +} diff --git a/trunk/src/kernel/srs_kernel_rtcp.hpp b/trunk/src/kernel/srs_kernel_rtcp.hpp new file mode 100644 index 000000000..11e4ab213 --- /dev/null +++ b/trunk/src/kernel/srs_kernel_rtcp.hpp @@ -0,0 +1,232 @@ + +#ifndef SRS_KERNEL_RTCP_HPP +#define SRS_KERNEL_RTCP_HPP + +#include +#include +#include +#include + +const int kRtcpPacketSize = 1500; +const uint8_t kRtcpVersion = 0x2; + +/*! \brief RTCP Packet Types (http://www.networksorcery.com/enp/protocol/rtcp.htm) */ +typedef enum { + RTCP_FIR = 192, + RTCP_SR = 200, + RTCP_RR = 201, + RTCP_SDES = 202, + RTCP_BYE = 203, + RTCP_APP = 204, + RTCP_RTPFB = 205, + RTCP_PSFB = 206, + RTCP_XR = 207, +} srs_rtcp_type_t; + + +/*! \brief RTCP Header (http://tools.ietf.org/html/rfc3550#section-6.1) */ +typedef struct srs_rtcp_header_s +{ + uint16_t rc:5; + uint16_t padding:1; + uint16_t version:2; + uint16_t type:8; + + uint16_t length:16; +} srs_rtcp_header_t; + +class SrsRTCPCommon: public ISrsCodec +{ +protected: + srs_rtcp_header_t header_; + uint8_t payload_[kRtcpPacketSize]; + int payload_len_; + +protected: + srs_error_t decode_header(SrsBuffer *buffer); + srs_error_t encode_header(SrsBuffer *buffer); +public: + SrsRTCPCommon(); + virtual ~SrsRTCPCommon(); + virtual const uint8_t type() const { return header_.type; } + +public: + // ISrsCodec + virtual srs_error_t decode(SrsBuffer *buffer); + virtual int nb_bytes(); + virtual srs_error_t encode(SrsBuffer *buffer); +}; + +typedef struct srs_rtcp_report_block_s { + uint32_t ssrc; + uint8_t fraction_lost; + uint32_t lost_packets; + uint32_t highest_sn; + uint32_t jitter; + uint32_t lsr; + uint32_t dlsr; +}srs_rtcp_rb_t; + +class SrsRTCP_SR : public SrsRTCPCommon +{ +private: + uint32_t sender_ssrc_; + uint64_t ntp_; + uint32_t rtp_ts_; + uint32_t send_rtp_packets_; + uint32_t send_rtp_bytes_; +public: + SrsRTCP_SR(); + virtual ~SrsRTCP_SR(); + + const uint8_t get_rc() const { return header_.rc; } + // overload SrsRTCPCommon + virtual const uint8_t type() const { return RTCP_SR; } + const uint32_t get_sender_ssrc() const; + const uint64_t get_ntp() const; + const uint32_t get_rtp_ts() const; + const uint32_t get_rtp_send_packets() const; + const uint32_t get_rtp_send_bytes() const; + + void set_sender_ssrc(uint32_t ssrc); + void set_ntp(uint64_t ntp); + void set_rtp_ts(uint32_t ts); + void set_rtp_send_packets(uint32_t packets); + void set_rtp_send_bytes(uint32_t bytes); + +public: + // ISrsCodec + virtual srs_error_t decode(SrsBuffer *buffer); + virtual int nb_bytes(); + virtual srs_error_t encode(SrsBuffer *buffer); +}; + +class SrsRTCP_RR : public SrsRTCPCommon +{ +private: + uint32_t sender_ssrc_; + srs_rtcp_rb_t rb_; +public: + SrsRTCP_RR(uint32_t sender_ssrc = 0); + virtual ~SrsRTCP_RR(); + + // overload SrsRTCPCommon + virtual const uint8_t type() const { return RTCP_RR; } + + const uint32_t get_rb_ssrc() const; + const float get_lost_rate() const; + const uint32_t get_lost_packets() const; + const uint32_t get_highest_sn() const; + const uint32_t get_jitter() const; + const uint32_t get_lsr() const; + const uint32_t get_dlsr() const; + + void set_rb_ssrc(uint32_t ssrc); + void set_lost_rate(float rate); + void set_lost_packets(uint32_t count); + void set_highest_sn(uint32_t sn); + void set_jitter(uint32_t jitter); + void set_lsr(uint32_t lsr); + void set_dlsr(uint32_t dlsr); + void set_sender_ntp(uint64_t ntp); + +public: + // ISrsCodec + virtual srs_error_t decode(SrsBuffer *buffer); + virtual int nb_bytes(); + virtual srs_error_t encode(SrsBuffer *buffer); + +}; + +class SrsRTCP_TWCC : public SrsRTCPCommon +{ +private: + uint32_t sender_ssrc_; + uint32_t media_ssrc_; + uint16_t base_sn_; + uint32_t reference_time_; + uint8_t fb_pkt_count_; + std::vector packet_chucks_; + std::vector recv_deltas_; +public: + SrsRTCP_TWCC(uint32_t sender_ssrc = 0); + virtual ~SrsRTCP_TWCC(); + + const uint32_t get_media_ssrc() const; + const uint16_t get_base_sn() const; + const uint32_t get_reference_time() const; + const uint8_t get_feedback_count() const; + const uint16_t get_packet_status_count() const; + const std::vector get_packet_chucks() const; + const std::vector get_recv_deltas() const; + + void set_media_ssrc(uint32_t ssrc); + void set_base_sn(uint16_t sn); + void set_reference_time(uint32_t time); + void set_feedback_count(uint8_t count); + void add_packet_chuck(uint16_t chuck); + void add_recv_delta(uint8_t delta); + +public: + // ISrsCodec + virtual srs_error_t decode(SrsBuffer *buffer); + virtual int nb_bytes(); + virtual srs_error_t encode(SrsBuffer *buffer); + +}; + +struct less_compare { + bool operator()(const uint16_t &lhs, const uint16_t &rhs) const { + return SnCompare(rhs, lhs); + } +}; +class SrsRTCP_Nack : public SrsRTCPCommon +{ +private: + typedef struct pid_blp_s { + uint16_t pid; + uint16_t blp; + }pid_blp_t; + + uint32_t sender_ssrc_; + uint32_t media_ssrc_; + std::set lost_sns_; +public: + SrsRTCP_Nack(uint32_t sender_ssrc = 0); + virtual ~SrsRTCP_Nack(); + + const uint32_t get_media_ssrc() const; + const std::vector get_lost_sns() const; + + void set_media_ssrc(uint32_t ssrc); + void add_lost_sn(uint16_t sn); + +public: + // ISrsCodec + virtual srs_error_t decode(SrsBuffer *buffer); + virtual int nb_bytes(); + virtual srs_error_t encode(SrsBuffer *buffer); +}; + + +class SrsRTCPCompound : public ISrsCodec +{ +private: + std::vector rtcps_; + int nb_bytes_; +public: + SrsRTCPCompound(); + virtual ~SrsRTCPCompound(); + + SrsRTCPCommon* get_next_rtcp(); + srs_error_t add_rtcp(SrsRTCPCommon *rtcp); + void clear(); + +public: + // ISrsCodec + virtual srs_error_t decode(SrsBuffer *buffer); + virtual int nb_bytes(); + virtual srs_error_t encode(SrsBuffer *buffer); +}; + +#endif diff --git a/trunk/src/kernel/srs_kernel_rtp.cpp b/trunk/src/kernel/srs_kernel_rtp.cpp index bcaac2145..eaaed6695 100644 --- a/trunk/src/kernel/srs_kernel_rtp.cpp +++ b/trunk/src/kernel/srs_kernel_rtp.cpp @@ -32,6 +32,56 @@ using namespace std; #include #include +//sn comparison,if current_sn is more than last_sn,return true,else return false +bool SnCompare(uint16_t current_sn, uint16_t last_sn) { + if(current_sn > last_sn) { + //current_sn 65533 last_sn 5 + if(current_sn - last_sn > 0x8000) { + return false; + } else { + return true; + } + } else { + //current_sn 2 last_sn 65535 + if(current_sn - last_sn < -0x8000) { + return true; + } else { + return false; + } + } +} + +bool SnRollback(uint16_t current_sn, uint16_t last_sn) +{ + if(SnCompare(current_sn, last_sn)) { + if((last_sn > current_sn)) { + return true; + } + } + return false; +} + +// caculate the difference between sn. If current_sn is more then last_sn, return positive difference, else return negative difference. +int32_t SnDiff(uint16_t current_sn, uint16_t last_sn) { + if(current_sn > last_sn) { + //current_sn 65535 last_sn 0 + if(current_sn - last_sn > 0x8000) { + return (current_sn - last_sn - 1 - 65535); + } else { + return (current_sn - last_sn); + } + } else { + //current_sn 0 last_sn 65535 + if(current_sn - last_sn < -0x8000) { + return (current_sn - last_sn + 65535 + 1); + } else { + return (current_sn - last_sn); + // current_sn 15039 last_sn 15042 + //return last_sn - current_sn; + } + } +} + SrsRtpHeader::SrsRtpHeader() { padding = false; diff --git a/trunk/src/kernel/srs_kernel_rtp.hpp b/trunk/src/kernel/srs_kernel_rtp.hpp index 9651edd55..4badf4977 100644 --- a/trunk/src/kernel/srs_kernel_rtp.hpp +++ b/trunk/src/kernel/srs_kernel_rtp.hpp @@ -54,6 +54,10 @@ class SrsBuffer; class SrsRtpRawPayload; class SrsRtpFUAPayload2; +bool SnCompare(uint16_t current_sn, uint16_t last_sn); +bool SnRollback(uint16_t current_sn, uint16_t last_sn); +int32_t SnDiff(uint16_t current_sn, uint16_t last_sn); + class SrsRtpHeader { private: From 9910151feb63cb0cc4c86d4db6ec441a44b2ece7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=8E=AB=E6=88=98?= Date: Fri, 15 May 2020 09:55:15 +0800 Subject: [PATCH 2/2] add twcc and replace auto method --- trunk/src/kernel/srs_kernel_rtc_rtcp.cpp | 1052 +++++++++++++++++ ...ernel_rtcp.hpp => srs_kernel_rtc_rtcp.hpp} | 148 ++- trunk/src/kernel/srs_kernel_rtcp.cpp | 637 ---------- 3 files changed, 1176 insertions(+), 661 deletions(-) create mode 100644 trunk/src/kernel/srs_kernel_rtc_rtcp.cpp rename trunk/src/kernel/{srs_kernel_rtcp.hpp => srs_kernel_rtc_rtcp.hpp} (51%) delete mode 100644 trunk/src/kernel/srs_kernel_rtcp.cpp diff --git a/trunk/src/kernel/srs_kernel_rtc_rtcp.cpp b/trunk/src/kernel/srs_kernel_rtc_rtcp.cpp new file mode 100644 index 000000000..55e4b9840 --- /dev/null +++ b/trunk/src/kernel/srs_kernel_rtc_rtcp.cpp @@ -0,0 +1,1052 @@ + +#include +#include +#include + +using namespace std; + +SrsRTCPCommon::SrsRTCPCommon() +{ +} + +SrsRTCPCommon::~SrsRTCPCommon() +{ +} + +srs_error_t SrsRTCPCommon::decode_header(SrsBuffer *buffer) +{ + buffer->read_bytes((char*)(&header_), sizeof(srs_rtcp_header_t)); + header_.length = ntohs(header_.length); + return srs_success; +} + +srs_error_t SrsRTCPCommon::encode_header(SrsBuffer *buffer) +{ + header_.length = htons(header_.length); + buffer->write_bytes((char*)(&header_), sizeof(srs_rtcp_header_t)); + return srs_success; +} + +srs_error_t SrsRTCPCommon::decode(SrsBuffer *buffer) +{ + srs_error_t err = srs_success; + err = decode_header(buffer); + if(srs_success != err) { + return srs_error_wrap(err, "fail to parse rtcp header"); + } + payload_len_ = (header_.length + 1) * 4 - sizeof(srs_rtcp_header_t); + buffer->read_bytes((char *)payload_, payload_len_); + return srs_success; +} + +int SrsRTCPCommon::nb_bytes() +{ + return sizeof(srs_rtcp_header_t) + payload_len_; +} + +srs_error_t SrsRTCPCommon::encode(SrsBuffer *buffer) +{ + return srs_error_new(ERROR_RTC_RTCP, "not implement"); +} + +SrsRTCP_App::SrsRTCP_App():ssrc_(0) +{ +} + +SrsRTCP_App::~SrsRTCP_App() +{ +} + +const uint32_t SrsRTCP_App::get_ssrc() const +{ + return ssrc_; +} + +const uint8_t SrsRTCP_App::get_subtype() const +{ + return header_.rc; +} + +const string SrsRTCP_App::get_name() const +{ + return string((char*)name_); +} + +const srs_error_t SrsRTCP_App::get_payload(uint8_t*& payload, int& len) +{ + len = payload_len_; + payload = payload_; + return srs_success; +} + +srs_error_t SrsRTCP_App::set_subtype(uint8_t type) +{ + if(31 < type) { + return srs_error_new(ERROR_RTC_RTCP, "subtype is out of range. type:%d", type); + } + header_.rc = type; + return srs_success; +} + +srs_error_t SrsRTCP_App::set_name(std::string name) +{ + if(name.length() > 4) { + return srs_error_new(ERROR_RTC_RTCP, "length of name is more than 4. len:%d", name.length()); + } + memset(name_, 0, sizeof(name_)); + memcpy(name_, name.c_str(), name.length()); + return srs_success; +} + +srs_error_t SrsRTCP_App::set_payload(uint8_t* payload, int len) +{ + if(len > (kRtcpPacketSize - 12)) { + return srs_error_new(ERROR_RTC_RTCP, "length of payload is more than 1488. len:%d", len); + } + payload_len_ = len; + memcpy(payload_, payload, len); + return srs_success; +} + +void SrsRTCP_App::set_ssrc(uint32_t ssrc) +{ + ssrc_ = ssrc; +} + +srs_error_t SrsRTCP_App::decode(SrsBuffer *buffer) +{ + srs_error_t err = srs_success; + err = decode_header(buffer); + if(srs_success != err) { + return srs_error_wrap(err, "fail to parse rtcp header"); + } + ssrc_ = buffer->read_4bytes(); + buffer->read_bytes((char *)name_, sizeof(name_)); + payload_len_ = (header_.length + 1) * 4 - sizeof(srs_rtcp_header_t) - sizeof(name_) - sizeof(ssrc_); + buffer->read_bytes((char *)payload_, payload_len_); + return srs_success; +} + +int SrsRTCP_App::nb_bytes() +{ + return sizeof(srs_rtcp_header_t) + sizeof(ssrc_) + sizeof(name_) + payload_len_; +} + +srs_error_t SrsRTCP_App::encode(SrsBuffer *buffer) +{ + srs_error_t err = srs_success; + if(! buffer->require(nb_bytes())) { + return srs_error_new(ERROR_RTC_RTCP, + "the size of buffer is not enough. buffer:%d, required:%d", buffer->left(), nb_bytes()); + } + err = encode_header(buffer); + if(srs_success != err) { + return srs_error_wrap(err, "fail to encode rtcp header"); + } + buffer->write_4bytes(ssrc_); + buffer->write_bytes((char*)name_, sizeof(name_)); + buffer->write_bytes((char*)payload_, payload_len_); + + return srs_success; +} + +SrsRTCP_SR::SrsRTCP_SR() +{ + header_.padding = 0; + header_.type = srs_rtcp_type_sr; + header_.rc = 0; + header_.version = kRtcpVersion; + header_.length = 6; +} + +SrsRTCP_SR::~SrsRTCP_SR() +{ + +} + +const uint32_t SrsRTCP_SR::get_sender_ssrc() const +{ + return sender_ssrc_; +} + +const uint64_t SrsRTCP_SR::get_ntp() const +{ + return ntp_; +} + +const uint32_t SrsRTCP_SR::get_rtp_ts() const +{ + return rtp_ts_; +} + +const uint32_t SrsRTCP_SR::get_rtp_send_packets() const +{ + return send_rtp_packets_; +} + +const uint32_t SrsRTCP_SR::get_rtp_send_bytes() const +{ + return send_rtp_bytes_; +} + +void SrsRTCP_SR::set_sender_ssrc(uint32_t ssrc) +{ + sender_ssrc_ = ssrc; +} + +void SrsRTCP_SR::set_ntp(uint64_t ntp) +{ + ntp_ = ntp; +} + +void SrsRTCP_SR::set_rtp_ts(uint32_t ts) +{ + rtp_ts_ = ts; +} + +void SrsRTCP_SR::set_rtp_send_packets(uint32_t packets) +{ + send_rtp_packets_ = packets; +} + +void SrsRTCP_SR::set_rtp_send_bytes(uint32_t bytes) +{ + send_rtp_bytes_ = bytes; +} + +srs_error_t SrsRTCP_SR::decode(SrsBuffer *buffer) +{ + srs_error_t err = srs_success; + err = decode_header(buffer); + if(srs_success != err) { + return srs_error_wrap(err, "fail to parse rtcp header"); + } + sender_ssrc_ = buffer->read_4bytes(); + ntp_ = buffer->read_8bytes(); + rtp_ts_ = buffer->read_4bytes(); + send_rtp_packets_ = buffer->read_4bytes(); + send_rtp_bytes_ = buffer->read_4bytes(); + if(header_.rc > 0) { + char buf[1500]; + buffer->read_bytes(buf, header_.rc * 24); + } + return err; +} + +int SrsRTCP_SR::nb_bytes() +{ + return (header_.length + 1) * 4; +} + +srs_error_t SrsRTCP_SR::encode(SrsBuffer *buffer) +{ + srs_error_t err = srs_success; + if(! buffer->require(nb_bytes())) { + return srs_error_new(ERROR_RTC_RTCP, + "the size of buffer is not enough. buffer:%d, required:%d", buffer->left(), nb_bytes()); + } + err = encode_header(buffer); + if(srs_success != err) { + return srs_error_wrap(err, "fail to encode rtcp header"); + } + buffer->write_4bytes(sender_ssrc_); + buffer->write_8bytes(ntp_); + buffer->write_4bytes(rtp_ts_); + buffer->write_4bytes(send_rtp_packets_); + buffer->write_4bytes(send_rtp_bytes_); + return err; +} + +SrsRTCP_RR::SrsRTCP_RR(uint32_t sender_ssrc/*=0*/): sender_ssrc_(sender_ssrc) +{ + header_.padding = 0; + header_.type = srs_rtcp_type_rr; + header_.rc = 0; + header_.version = kRtcpVersion; + header_.length = 7; +} + +SrsRTCP_RR::~SrsRTCP_RR() +{ +} + +const uint32_t SrsRTCP_RR::get_rb_ssrc() const +{ + return rb_.ssrc; +} + +const float SrsRTCP_RR::get_lost_rate() const +{ + return rb_.fraction_lost / 256; +} + +const uint32_t SrsRTCP_RR::get_lost_packets() const +{ + return rb_.lost_packets; +} + +const uint32_t SrsRTCP_RR::get_highest_sn() const +{ + return rb_.highest_sn; +} + +const uint32_t SrsRTCP_RR::get_jitter() const +{ + return rb_.jitter; +} + +const uint32_t SrsRTCP_RR::get_lsr() const +{ + return rb_.lsr; +} + +const uint32_t SrsRTCP_RR::get_dlsr() const +{ + return rb_.dlsr; +} + +void SrsRTCP_RR::set_rb_ssrc(uint32_t ssrc) +{ + rb_.ssrc = ssrc; +} + +void SrsRTCP_RR::set_lost_rate(float rate) +{ + rb_.fraction_lost = rate * 256; +} + +void SrsRTCP_RR::set_lost_packets(uint32_t count) +{ + rb_.lost_packets = count; +} + +void SrsRTCP_RR::set_highest_sn(uint32_t sn) +{ + rb_.highest_sn = sn; +} + +void SrsRTCP_RR::set_jitter(uint32_t jitter) +{ + rb_.jitter = jitter; +} + +void SrsRTCP_RR::set_lsr(uint32_t lsr) +{ + rb_.lsr = lsr; +} + +void SrsRTCP_RR::set_dlsr(uint32_t dlsr) +{ + rb_.dlsr = dlsr; +} + +void SrsRTCP_RR::set_sender_ntp(uint64_t ntp) +{ + uint32_t lsr = (uint32_t)((ntp >> 16) & 0x00000000FFFFFFFF); + rb_.lsr = lsr; +} + +srs_error_t SrsRTCP_RR::decode(SrsBuffer *buffer) +{ + srs_error_t err = srs_success; + err = decode_header(buffer); + if(srs_success != err) { + return srs_error_wrap(err, "fail to parse rtcp header"); + } + sender_ssrc_ = buffer->read_4bytes(); + if(header_.rc < 1) { + return srs_success; + } + rb_.ssrc = buffer->read_4bytes(); + rb_.fraction_lost = buffer->read_1bytes(); + rb_.lost_packets = buffer->read_3bytes(); + rb_.highest_sn = buffer->read_4bytes(); + rb_.jitter = buffer->read_4bytes(); + rb_.lsr = buffer->read_4bytes(); + rb_.dlsr = buffer->read_4bytes(); + + if(header_.rc > 1) { + char buf[1500]; + buffer->read_bytes(buf, (header_.rc -1 ) * 24); + } + + return err; +} + +int SrsRTCP_RR::nb_bytes() +{ + return (header_.length + 1) * 4; +} + +srs_error_t SrsRTCP_RR::encode(SrsBuffer *buffer) +{ + srs_error_t err = srs_success; + if(! buffer->require(nb_bytes())) { + return srs_error_new(ERROR_RTC_RTCP, + "the size of buffer is not enough. buffer:%d, required:%d", buffer->left(), nb_bytes()); + } + + header_.rc = 1; + err = encode_header(buffer); + if(srs_success != err) { + return srs_error_wrap(err, "fail to encode rtcp header"); + } + buffer->write_4bytes(sender_ssrc_); + + buffer->write_4bytes(rb_.ssrc); + buffer->write_1bytes(rb_.fraction_lost); + buffer->write_3bytes(rb_.lost_packets); + buffer->write_4bytes(rb_.highest_sn); + buffer->write_4bytes(rb_.jitter); + buffer->write_4bytes(rb_.lsr); + buffer->write_4bytes(rb_.dlsr); + return err; +} + +SrsRTCP_TWCC::SrsRTCP_TWCC(uint32_t sender_ssrc/*=0*/) : sender_ssrc_(sender_ssrc), pkt_len(0) +{ + header_.padding = 0; + header_.type = srs_rtcp_type_rtpfb; + header_.rc = 15; + header_.version = kRtcpVersion; +} + +SrsRTCP_TWCC::~SrsRTCP_TWCC() +{ +} + +void SrsRTCP_TWCC::clear() +{ + encoded_chucks_.clear(); + pkt_deltas_.clear(); + recv_packes_.clear(); + recv_sns_.clear(); +} + +const uint32_t SrsRTCP_TWCC::get_media_ssrc() const +{ + return media_ssrc_; +} +const uint16_t SrsRTCP_TWCC::get_base_sn() const +{ + return base_sn_; +} + +const uint32_t SrsRTCP_TWCC::get_reference_time() const +{ + return reference_time_; +} + +const uint8_t SrsRTCP_TWCC::get_feedback_count() const +{ + return fb_pkt_count_; +} + +const uint16_t SrsRTCP_TWCC::get_packet_status_count() const +{ + return packet_count_; +} + +const vector SrsRTCP_TWCC::get_packet_chucks() const +{ + return encoded_chucks_; +} + +const vector SrsRTCP_TWCC::get_recv_deltas() const +{ + return pkt_deltas_; +} + +void SrsRTCP_TWCC::set_media_ssrc(uint32_t ssrc) +{ + media_ssrc_ = ssrc; +} +void SrsRTCP_TWCC::set_base_sn(uint16_t sn) +{ + base_sn_ = sn; +} + +void SrsRTCP_TWCC::set_packet_status_count(uint16_t count) +{ + packet_count_ = count; +} + +void SrsRTCP_TWCC::set_reference_time(uint32_t time) +{ + reference_time_ = time; +} + +void SrsRTCP_TWCC::set_feedback_count(uint8_t count) +{ + fb_pkt_count_ = count; +} + +void SrsRTCP_TWCC::add_packet_chuck(uint16_t chunk) +{ + encoded_chucks_.push_back(chunk); +} + +void SrsRTCP_TWCC::add_recv_delta(uint16_t delta) +{ + pkt_deltas_.push_back(delta); +} + +srs_error_t SrsRTCP_TWCC::recv_packet(uint16_t sn, srs_utime_t ts) +{ + map::iterator it = recv_packes_.find(sn); + if(it != recv_packes_.end()) { + return srs_error_new(ERROR_RTC_RTCP, "twcc: recv duplicated sn:%d", sn); + } + recv_packes_[sn] = ts; + recv_sns_.insert(sn); + return srs_success; +} + +srs_error_t SrsRTCP_TWCC::decode(SrsBuffer *buffer) +{ + srs_error_t err = srs_success; + + return err; +} + +int SrsRTCP_TWCC::nb_bytes() +{ + return kRtcpPacketSize; +} + +srs_utime_t SrsRTCP_TWCC::calculate_delta_us(srs_utime_t ts, srs_utime_t last) +{ + int64_t divisor = kTwccFbReferenceTimeDivisor; + int64_t delta_us = (ts - last) % divisor; + + if (delta_us > (divisor >> 1)) + delta_us -= divisor; + + delta_us += (delta_us < 0) ? (-kTwccFbDeltaUnit / 2) : (kTwccFbDeltaUnit / 2); + delta_us /= kTwccFbDeltaUnit; + + return delta_us; +} + +bool SrsRTCP_TWCC::can_add_to_chunk(SrsRTCP_TWCC::srs_rtcp_twcc_chunk_t& chunk, int delta_size) +{ + srs_verbose("can_add %d chunk->size %u delta_sizes %d %d %d %d %d %d %d %d %d %d %d %d %d %d" + " all_same %d has_large_delta %d", + delta_size, + chunk.size, + chunk.delta_sizes[0], chunk.delta_sizes[1], chunk.delta_sizes[2], + chunk.delta_sizes[3], chunk.delta_sizes[4], chunk.delta_sizes[5], + chunk.delta_sizes[6], chunk.delta_sizes[7], chunk.delta_sizes[8], + chunk.delta_sizes[9], chunk.delta_sizes[10], chunk.delta_sizes[11], + chunk.delta_sizes[12], chunk.delta_sizes[13], + (int)chunk.all_same, + (int)chunk.has_large_delta + ); + + if (chunk.size < kTwccFbTwoBitElements) + return true; + + + if (chunk.size < kTwccFbOneBitElements && !chunk.has_large_delta && delta_size != kTwccFbLargeRecvDeltaBytes) + return true; + + + if (chunk.size < kTwccFbMaxRunLength && chunk.all_same && chunk.delta_sizes[0] == delta_size) { + srs_verbose("< 8191 && all_same && delta_size[0] %d == %d", + chunk.delta_sizes[0], delta_size); + return true; + } + + return false; +} + +void SrsRTCP_TWCC::add_to_chunk(SrsRTCP_TWCC::srs_rtcp_twcc_chunk_t& chunk, int delta_size) +{ + if (chunk.size < kTwccFbMaxBitElements) + chunk.delta_sizes[chunk.size] = delta_size; + chunk.size += 1; + chunk.all_same = chunk.all_same && delta_size == chunk.delta_sizes[0]; + chunk.has_large_delta = chunk.has_large_delta || delta_size >= kTwccFbLargeRecvDeltaBytes; +} + +srs_error_t SrsRTCP_TWCC::encode_chunk_run_length(SrsRTCP_TWCC::srs_rtcp_twcc_chunk_t& chunk) +{ + if (!chunk.all_same || chunk.size > kTwccFbMaxRunLength) + return srs_error_new(ERROR_RTC_RTCP, "cannot encode by run length. all_same:%d, size:%d", chunk.all_same, chunk.size); + + uint16_t encoded_chunk = (chunk.delta_sizes[0] << 13) | chunk.size; + + encoded_chucks_.push_back(encoded_chunk); + pkt_len += sizeof(encoded_chunk); + + return 0; +} + +srs_error_t SrsRTCP_TWCC::encode_chunk_one_bit(SrsRTCP_TWCC::srs_rtcp_twcc_chunk_t& chunk) +{ + int i = 0; + if (chunk.has_large_delta) + return srs_error_new(ERROR_RTC_RTCP, "it's large delta, cannot encode by one bit moe"); + uint16_t encoded_chunk = 0x8000; + for (i = 0; i < chunk.size; ++i) { + encoded_chunk |= (chunk.delta_sizes[i] << (kTwccFbOneBitElements - 1 - i)); + } + + encoded_chucks_.push_back(encoded_chunk); + pkt_len += sizeof(encoded_chunk); + + /* 1 0 symbol_list */ + return srs_success; +} + +srs_error_t SrsRTCP_TWCC::encode_chunk_two_bit(SrsRTCP_TWCC::srs_rtcp_twcc_chunk_t& chunk, size_t size, bool shift) +{ + unsigned int i = 0; + uint8_t delta_size = 0; + + uint16_t encoded_chunk = 0xc000; + /* 1 1 symbol_list */ + for (i = 0; i < size; ++i) { + encoded_chunk |= (chunk.delta_sizes[i] << (2 * (kTwccFbTwoBitElements - 1 - i))); + } + encoded_chucks_.push_back(encoded_chunk); + pkt_len += sizeof(encoded_chunk); + + if (shift) { + chunk.all_same = true; + chunk.has_large_delta = false; + for (i = size; i < chunk.size; ++i) { + delta_size = chunk.delta_sizes[i]; + chunk.delta_sizes[i - size] = delta_size; + chunk.all_same = (chunk.all_same && delta_size == chunk.delta_sizes[0]); + chunk.has_large_delta = chunk.has_large_delta || delta_size == kTwccFbLargeRecvDeltaBytes; + } + // JANUS_LOG(LOG_INFO, "ccc->size %u size %u B\n", ccc->size, size); + chunk.size -= size; + // JANUS_LOG(LOG_INFO, "ccc->size %u shift %d A\n", ccc->size, shift); + } + + return srs_success; +} + +void SrsRTCP_TWCC::reset_chunk(SrsRTCP_TWCC::srs_rtcp_twcc_chunk_t& chunk) +{ + chunk.size = 0; + + chunk.all_same = true; + chunk.has_large_delta = false; +} + +srs_error_t SrsRTCP_TWCC::encode_chunk(SrsRTCP_TWCC::srs_rtcp_twcc_chunk_t& chunk) +{ + srs_error_t err = srs_success; + + if (can_add_to_chunk(chunk, 0) && can_add_to_chunk(chunk, 1) && + can_add_to_chunk(chunk, 2)) + return srs_error_new(ERROR_RTC_RTCP, "it should be added to chunk, not encode"); + + if (chunk.all_same) { + if ((err = encode_chunk_run_length(chunk)) != srs_success) + return srs_error_wrap(err, "fail to encode chunk by run length mode"); + reset_chunk(chunk); + return err; + } + + if (chunk.size == kTwccFbOneBitElements) { + if ((err = encode_chunk_one_bit(chunk)) != srs_success) + return srs_error_wrap(err, "fail to encode chunk by one bit mode"); + reset_chunk(chunk); + return err; + } + + if ((err =encode_chunk_two_bit(chunk, kTwccFbTwoBitElements, true)) != srs_success) + return srs_error_wrap(err, "fail to encode chunk by two bit mode"); + + return err; +} + +srs_error_t SrsRTCP_TWCC::encode_remaining_chunk(SrsRTCP_TWCC::srs_rtcp_twcc_chunk_t& chunk) +{ + if (chunk.all_same) { + return encode_chunk_run_length(chunk); + } else if (chunk.size <= kTwccFbTwoBitElements) { + // FIXME, TRUE or FALSE + return encode_chunk_two_bit(chunk, chunk.size, false); + } + return encode_chunk_one_bit(chunk); +} + +srs_error_t SrsRTCP_TWCC::process_pkt_chunk(SrsRTCP_TWCC::srs_rtcp_twcc_chunk_t& chunk, int delta_size) +{ + srs_error_t err = srs_success; + + size_t needed_chunk_size = chunk.size == 0 ? kTwccFbChunkBytes : 0; + + size_t might_occupied = pkt_len + needed_chunk_size + delta_size; + if (might_occupied > kRtcpPacketSize) { + return srs_error_new(ERROR_RTC_RTCP, "might_occupied %zu", might_occupied); + } + + if (can_add_to_chunk(chunk, delta_size)) { + //pkt_len += needed_chunk_size; + add_to_chunk(chunk, delta_size); + return err; + } +/* + if (pkt_len + delta_size + kTwccFbChunkBytes > kRtcpPacketSize) { + JANUS_LOG(LOG_INFO, "chunk_can_not_add, delta_size %u\n", delta_size); + return -1; + } +*/ + if ((err = encode_chunk(chunk)) != srs_success) { + return srs_error_new(ERROR_RTC_RTCP, "chunk can not be encoded, delta_size %u", delta_size); + } +/* + ccf->encoded_chunks = g_list_append(ccf->encoded_chunks, ((gpointer) (glong) (chunk))); + ccf->size_bytes += sizeof(chunk); + */ + add_to_chunk(chunk, delta_size); + return err; +} + +srs_error_t SrsRTCP_TWCC::encode(SrsBuffer *buffer) +{ + srs_error_t err = srs_success; + if(! buffer->require(nb_bytes())) { + return srs_error_new(ERROR_RTC_RTCP, + "the size of buffer is not enough. buffer:%d, required:%d", buffer->left(), nb_bytes()); + } + pkt_len = kTwccFbPktHeaderSize; + set::iterator it_sn = recv_sns_.begin(); + base_sn_ = *it_sn; + map::iterator it_ts = recv_packes_.find(base_sn_); + srs_utime_t ts = it_ts->second; + reference_time_ = (ts % kTwccFbReferenceTimeDivisor) / kTwccFbTimeMultiplier; + srs_utime_t last_ts = (srs_utime_t)(reference_time_) * kTwccFbTimeMultiplier; + uint16_t last_sn = base_sn_; + packet_count_ = recv_packes_.size(); + do { + // encode chunk + SrsRTCP_TWCC::srs_rtcp_twcc_chunk_t chunk; + for(; it_sn != recv_sns_.end(); ++it_sn) { + uint16_t current_sn = *it_sn; + // calculate delta + it_ts = recv_packes_.find(current_sn); + srs_utime_t delta_us = calculate_delta_us(it_ts->second, last_ts); + uint16_t delta = delta_us; + if(delta != delta_us) { + return srs_error_new(ERROR_RTC_RTCP, "twcc: delta:%lld, exceeds the 16-bit base receive delta", delta_us); + } + + if(current_sn > (last_sn + 1)) { + // lost packet + for(uint16_t lost_sn = last_sn + 1; lost_sn < current_sn; ++lost_sn) { + process_pkt_chunk(chunk, 0); + packet_count_++; + } + + } + + // FIXME 24-bit base receive delta not supported + int recv_delta_size = (delta >= 0 && delta <= 0xff) ? 1 : 2; + /* pakcet received, small delta 1 + * packet received, large or negative delta 2 + * */ + if ((err = process_pkt_chunk(chunk, recv_delta_size)) != srs_success) { + return srs_error_new(ERROR_RTC_RTCP, "delta_size %d, failed to append_recv_delta\n", recv_delta_size); + } + + pkt_deltas_.push_back(delta); + last_ts += delta * kTwccFbDeltaUnit; + pkt_len += recv_delta_size; + last_sn = current_sn; + } + + if(0 < chunk.size) { + if((err = encode_remaining_chunk(chunk)) != srs_success) { + return srs_error_wrap(err, "fail to encode remaining chunk"); + } + } + + // encode rtcp twcc packet + if((pkt_len % 4) == 0) { + header_.length = pkt_len / 4; + } else { + header_.length = (pkt_len + 4 - (pkt_len%4)) / 4; + } + header_.length -= 1; + + err = encode_header(buffer); + if(srs_success != err) { + err = srs_error_wrap(err, "fail to encode rtcp header"); + break; + } + buffer->write_4bytes(sender_ssrc_); + buffer->write_4bytes(media_ssrc_); + buffer->write_2bytes(base_sn_); + buffer->write_2bytes(packet_count_); + buffer->write_3bytes(reference_time_); + buffer->write_1bytes(fb_pkt_count_); + + for(vector::iterator it = encoded_chucks_.begin(); it != encoded_chucks_.end(); ++it) { + buffer->write_2bytes(*it); + } + for(vector::iterator it = pkt_deltas_.begin(); it != pkt_deltas_.end(); ++it) { + if(0 <= *it && 0xFF >= *it) { + // small delta + uint8_t delta = *it; + buffer->write_1bytes(delta); + } else { + // large or negative delta + buffer->write_2bytes(*it); + } + } + while((pkt_len % 4) != 0) { + buffer->write_1bytes(0); + pkt_len++; + } + + } while(0); + + clear(); + + return err; +} + +SrsRTCP_Nack::SrsRTCP_Nack(uint32_t sender_ssrc /*= 0*/): sender_ssrc_(sender_ssrc) +{ + header_.padding = 0; + header_.type = srs_rtcp_type_rtpfb; + header_.rc = 1; + header_.version = kRtcpVersion; +} + +SrsRTCP_Nack::~SrsRTCP_Nack() +{ +} + +const uint32_t SrsRTCP_Nack::get_media_ssrc() const +{ + return media_ssrc_; +} + +const vector SrsRTCP_Nack::get_lost_sns() const +{ + vector sn; + for(set::iterator it = lost_sns_.begin(); it != lost_sns_.end(); ++it) { + sn.push_back(*it); + } + return sn; +} + +void SrsRTCP_Nack::set_media_ssrc(uint32_t ssrc) +{ + media_ssrc_ = ssrc; +} + +void SrsRTCP_Nack::add_lost_sn(uint16_t sn) +{ + lost_sns_.insert(sn); +} + +srs_error_t SrsRTCP_Nack::decode(SrsBuffer *buffer) +{ + srs_error_t err = srs_success; + err = decode_header(buffer); + if(srs_success != err) { + return srs_error_wrap(err, "fail to parse rtcp header"); + } + sender_ssrc_ = buffer->read_4bytes(); + media_ssrc_ = buffer->read_4bytes(); + char bitmask[20]; + for(int i = 0; i < (header_.length - 2); i++) { + uint16_t pid = buffer->read_2bytes(); + uint16_t blp = buffer->read_2bytes(); + lost_sns_.insert(pid); + memset(bitmask, 0, 20); + for(int j=0; j<16; j++) { + bitmask[j] = (blp & ( 1 << j )) >> j ? '1' : '0'; + if((blp & ( 1 << j )) >> j) + lost_sns_.insert(pid+j+1); + } + bitmask[16] = '\n'; + srs_info("[%d] %d / %s", i, pid, bitmask); + } + + return err; +} +int SrsRTCP_Nack::nb_bytes() +{ + return kRtcpPacketSize; +} + +srs_error_t SrsRTCP_Nack::encode(SrsBuffer *buffer) +{ + srs_error_t err = srs_success; + if(! buffer->require(nb_bytes())) { + return srs_error_new(ERROR_RTC_RTCP, + "the size of buffer is not enough. buffer:%d, required:%d", buffer->left(), nb_bytes()); + } + + vector chunks; + do { + pid_blp_t chunk; + chunk.in_use = false; + uint16_t pid = 0; + for(set::iterator it = lost_sns_.begin(); it != lost_sns_.end(); ++it) { + uint16_t sn = *it; + if(!chunk.in_use) { + chunk.pid = sn; + chunk.blp = 0; + chunk.in_use = true; + pid = sn; + continue; + } + if((sn - pid) < 1) { + srs_info("Skipping PID to NACK (%d already added)...\n", sn); + } else if( (sn - pid) > 16) { + // add new chunk + chunks.push_back(chunk); + chunk.in_use = false; + } else { + chunk.blp |= 1 << (sn-pid-1); + } + } + if(chunk.in_use) { + chunks.push_back(chunk); + } + + header_.length = 2 + chunks.size(); + err = encode_header(buffer); + if(srs_success != err) { + err = srs_error_wrap(err, "fail to encode rtcp header"); + break; + } + buffer->write_4bytes(sender_ssrc_); + buffer->write_4bytes(media_ssrc_); + for(vector::iterator it_chunk = chunks.begin(); it_chunk != chunks.end(); it_chunk++) { + buffer->write_2bytes(it_chunk->pid); + buffer->write_2bytes(it_chunk->blp); + } + + } while(0); + + return err; +} + +SrsRTCPCompound::SrsRTCPCompound(): nb_bytes_(0) +{ +} + +SrsRTCPCompound::~SrsRTCPCompound() +{ + clear(); +} + +SrsRTCPCommon* SrsRTCPCompound::get_next_rtcp() +{ + if(rtcps_.empty()) { + return NULL; + } + SrsRTCPCommon *rtcp = rtcps_.back(); + nb_bytes_ -= rtcp->nb_bytes(); + rtcps_.pop_back(); + return rtcp; +} + +srs_error_t SrsRTCPCompound::add_rtcp(SrsRTCPCommon *rtcp) +{ + int new_len = rtcp->nb_bytes(); + if((new_len + nb_bytes_) > kRtcpPacketSize) { + return srs_error_new(ERROR_RTC_RTCP, "exceed the rtcp max size. new rtcp: %d, current: %d", new_len, nb_bytes_); + } + nb_bytes_ += new_len; + rtcps_.push_back(rtcp); + + return srs_success; +} + +srs_error_t SrsRTCPCompound::decode(SrsBuffer *buffer) +{ + srs_error_t err = srs_success; + + while(0 != buffer->left()) { + srs_rtcp_header_t* header = (srs_rtcp_header_t *)(buffer->head()); + switch (header->type) + { + case srs_rtcp_type_sr: + { + SrsRTCP_SR *rtcp = new SrsRTCP_SR; + err = rtcp->decode(buffer); + if(srs_success != err) { + return srs_error_wrap(err, "fail to decode rtcp sr"); + } + nb_bytes_ += rtcp->nb_bytes(); + rtcps_.push_back(rtcp); + break; + } + case srs_rtcp_type_rr: + { + SrsRTCP_RR *rtcp = new SrsRTCP_RR; + err = rtcp->decode(buffer); + if(srs_success != err) { + return srs_error_wrap(err, "fail to decode rtcp rr"); + } + nb_bytes_ += rtcp->nb_bytes(); + rtcps_.push_back(rtcp); + break; + } + default: + { + SrsRTCPCommon *rtcp = new SrsRTCPCommon; + err = rtcp->decode(buffer); + if(srs_success != err) { + return srs_error_wrap(err, "fail to decode rtcp type:%d", header->type); + } + nb_bytes_ += rtcp->nb_bytes(); + rtcps_.push_back(rtcp); + break; + } + } + } + + return err; +} + +int SrsRTCPCompound::nb_bytes() +{ + return nb_bytes_; +} + +srs_error_t SrsRTCPCompound::encode(SrsBuffer *buffer) +{ + srs_error_t err = srs_success; + if(false == buffer->require(nb_bytes_)) { + return srs_error_new(ERROR_RTC_RTCP, + "the left size of buffer is not enough. buffer:%d, required:%d", buffer->left(), nb_bytes_); + } + + vector::iterator it; + for(it = rtcps_.begin(); it != rtcps_.end(); ++it) { + SrsRTCPCommon *rtcp = *it; + err = rtcp->encode(buffer); + if(err != srs_success) { + return srs_error_wrap(err, "fail to encode rtcp compound. type:%d", rtcp->type()); + } + } + + clear(); + return err; +} + +void SrsRTCPCompound::clear() +{ + vector::iterator it; + for(it = rtcps_.begin(); it != rtcps_.end(); ++it) { + SrsRTCPCommon *rtcp = *it; + delete rtcp; + rtcp = NULL; + } + rtcps_.clear(); + nb_bytes_ = 0; +} diff --git a/trunk/src/kernel/srs_kernel_rtcp.hpp b/trunk/src/kernel/srs_kernel_rtc_rtcp.hpp similarity index 51% rename from trunk/src/kernel/srs_kernel_rtcp.hpp rename to trunk/src/kernel/srs_kernel_rtc_rtcp.hpp index 11e4ab213..9f03d944a 100644 --- a/trunk/src/kernel/srs_kernel_rtcp.hpp +++ b/trunk/src/kernel/srs_kernel_rtc_rtcp.hpp @@ -3,7 +3,7 @@ #define SRS_KERNEL_RTCP_HPP #include -#include +#include #include #include @@ -12,16 +12,16 @@ const uint8_t kRtcpVersion = 0x2; /*! \brief RTCP Packet Types (http://www.networksorcery.com/enp/protocol/rtcp.htm) */ typedef enum { - RTCP_FIR = 192, - RTCP_SR = 200, - RTCP_RR = 201, - RTCP_SDES = 202, - RTCP_BYE = 203, - RTCP_APP = 204, - RTCP_RTPFB = 205, - RTCP_PSFB = 206, - RTCP_XR = 207, -} srs_rtcp_type_t; + srs_rtcp_type_fir = 192, + srs_rtcp_type_sr = 200, + srs_rtcp_type_rr = 201, + srs_rtcp_type_sdes = 202, + srs_rtcp_type_bye = 203, + srs_rtcp_type_app = 204, + srs_rtcp_type_rtpfb = 205, + srs_rtcp_type_psfb = 206, + srs_rtcp_type_xr = 207, +} srs_rtcp_type; /*! \brief RTCP Header (http://tools.ietf.org/html/rfc3550#section-6.1) */ @@ -35,6 +35,12 @@ typedef struct srs_rtcp_header_s uint16_t length:16; } srs_rtcp_header_t; +struct less_compare { + bool operator()(const uint16_t &lhs, const uint16_t &rhs) const { + return SnCompare(rhs, lhs); + } +}; + class SrsRTCPCommon: public ISrsCodec { protected: @@ -57,6 +63,35 @@ public: virtual srs_error_t encode(SrsBuffer *buffer); }; +class SrsRTCP_App : public SrsRTCPCommon +{ + srs_rtcp_header_t header_; + uint32_t ssrc_; + uint8_t name_[4]; + uint8_t payload_[kRtcpPacketSize]; + int payload_len_; +public: + SrsRTCP_App(); + virtual ~SrsRTCP_App(); + + virtual const uint8_t type() const { return srs_rtcp_type_app; } + + const uint32_t get_ssrc() const; + const uint8_t get_subtype() const; + const std::string get_name() const; + const srs_error_t get_payload(uint8_t*& payload, int& len); + + void set_ssrc(uint32_t ssrc); + srs_error_t set_subtype(uint8_t type); + srs_error_t set_name(std::string name); + srs_error_t set_payload(uint8_t* payload, int len); +public: + // ISrsCodec + virtual srs_error_t decode(SrsBuffer *buffer); + virtual int nb_bytes(); + virtual srs_error_t encode(SrsBuffer *buffer); +}; + typedef struct srs_rtcp_report_block_s { uint32_t ssrc; uint8_t fraction_lost; @@ -81,7 +116,7 @@ public: const uint8_t get_rc() const { return header_.rc; } // overload SrsRTCPCommon - virtual const uint8_t type() const { return RTCP_SR; } + virtual const uint8_t type() const { return srs_rtcp_type_sr; } const uint32_t get_sender_ssrc() const; const uint64_t get_ntp() const; const uint32_t get_rtp_ts() const; @@ -111,7 +146,7 @@ public: virtual ~SrsRTCP_RR(); // overload SrsRTCPCommon - virtual const uint8_t type() const { return RTCP_RR; } + virtual const uint8_t type() const { return srs_rtcp_type_rr; } const uint32_t get_rb_ssrc() const; const float get_lost_rate() const; @@ -138,34 +173,103 @@ public: }; +/* + 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 + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + |V=2|P| FMT=15 | PT=205 | length | + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + | SSRC of packet sender | + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + | SSRC of media source | + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + | base sequence number | packet status count | + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + | reference time | fb pkt. count | + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + | packet chunk | packet chunk | + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + . . + . . + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + | packet chunk | recv delta | recv delta | + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + . . +*/ +#define kTwccFbPktHeaderSize (4 + 8 + 8) +#define kTwccFbChunkBytes (2) +#define kTwccFbPktFormat (15) +#define kTwccFbPayloadType (205) +#define kTwccFbMaxPktStatusCount (0xffff) +//#define kTwccFbMaxPktLength (4 + (1 << 16)) +#define kTwccFbDeltaUnit (250) // multiple of 250us +#define kTwccFbTimeMultiplier (kTwccFbDeltaUnit * (1 << 8)) // multiplicand multiplier/* 250us -> 64ms (1 << 8) */ +#define kTwccFbReferenceTimeDivisor ((1ll<<24) * kTwccFbTimeMultiplier) // dividend divisor + +#define kTwccFbMaxRunLength 0x1fff +#define kTwccFbOneBitElements 14 +#define kTwccFbTwoBitElements 7 +#define kTwccFbLargeRecvDeltaBytes 2 +#define kTwccFbMaxBitElements kTwccFbOneBitElements + class SrsRTCP_TWCC : public SrsRTCPCommon { private: uint32_t sender_ssrc_; uint32_t media_ssrc_; uint16_t base_sn_; - uint32_t reference_time_; + uint16_t packet_count_; + int32_t reference_time_; uint8_t fb_pkt_count_; - std::vector packet_chucks_; - std::vector recv_deltas_; + std::vector encoded_chucks_; + std::vector pkt_deltas_; + + std::map recv_packes_; + std::set recv_sns_; + + typedef struct srs_rtcp_twcc_chunk { + uint8_t delta_sizes[kTwccFbMaxBitElements]; + uint16_t size; + bool all_same; + bool has_large_delta; + }srs_rtcp_twcc_chunk_t; + + int pkt_len; + +private: + void clear(); + srs_utime_t calculate_delta_us(srs_utime_t ts, srs_utime_t last); + srs_error_t process_pkt_chunk(srs_rtcp_twcc_chunk_t& chunk, int delta_size); + bool can_add_to_chunk(srs_rtcp_twcc_chunk_t& chunk, int delta_size); + void add_to_chunk(srs_rtcp_twcc_chunk_t& chunk, int delta_size); + srs_error_t encode_chunk(srs_rtcp_twcc_chunk_t& chunk); + srs_error_t encode_chunk_run_length(srs_rtcp_twcc_chunk_t& chunk); + srs_error_t encode_chunk_one_bit(srs_rtcp_twcc_chunk_t& chunk); + srs_error_t encode_chunk_two_bit(srs_rtcp_twcc_chunk_t& chunk, size_t size, bool shift); + void reset_chunk(srs_rtcp_twcc_chunk_t& chunk); + srs_error_t encode_remaining_chunk(srs_rtcp_twcc_chunk_t& chunk); + public: SrsRTCP_TWCC(uint32_t sender_ssrc = 0); virtual ~SrsRTCP_TWCC(); const uint32_t get_media_ssrc() const; const uint16_t get_base_sn() const; + const uint16_t get_packet_status_count() const; const uint32_t get_reference_time() const; const uint8_t get_feedback_count() const; - const uint16_t get_packet_status_count() const; const std::vector get_packet_chucks() const; - const std::vector get_recv_deltas() const; + const std::vector get_recv_deltas() const; void set_media_ssrc(uint32_t ssrc); void set_base_sn(uint16_t sn); + void set_packet_status_count(uint16_t count); void set_reference_time(uint32_t time); void set_feedback_count(uint8_t count); void add_packet_chuck(uint16_t chuck); - void add_recv_delta(uint8_t delta); + void add_recv_delta(uint16_t delta); + + srs_error_t recv_packet(uint16_t sn, srs_utime_t ts); public: // ISrsCodec @@ -175,17 +279,13 @@ public: }; -struct less_compare { - bool operator()(const uint16_t &lhs, const uint16_t &rhs) const { - return SnCompare(rhs, lhs); - } -}; class SrsRTCP_Nack : public SrsRTCPCommon { private: typedef struct pid_blp_s { uint16_t pid; uint16_t blp; + bool in_use; }pid_blp_t; uint32_t sender_ssrc_; diff --git a/trunk/src/kernel/srs_kernel_rtcp.cpp b/trunk/src/kernel/srs_kernel_rtcp.cpp deleted file mode 100644 index 0d8762ff4..000000000 --- a/trunk/src/kernel/srs_kernel_rtcp.cpp +++ /dev/null @@ -1,637 +0,0 @@ - -#include -#include -#include - -using namespace std; - -SrsRTCPCommon::SrsRTCPCommon() -{ -} - -SrsRTCPCommon::~SrsRTCPCommon() -{ -} - -srs_error_t SrsRTCPCommon::decode_header(SrsBuffer *buffer) -{ - buffer->read_bytes((char*)(&header_), sizeof(srs_rtcp_header_t)); - header_.length = ntohs(header_.length); - return srs_success; -} - -srs_error_t SrsRTCPCommon::encode_header(SrsBuffer *buffer) -{ - header_.length = htons(header_.length); - buffer->write_bytes((char*)(&header_), sizeof(srs_rtcp_header_t)); - return srs_success; -} - -srs_error_t SrsRTCPCommon::decode(SrsBuffer *buffer) -{ - srs_error_t err = srs_success; - err = decode_header(buffer); - if(srs_success != err) { - return srs_error_wrap(err, "fail to parse rtcp header"); - } - payload_len_ = (header_.length + 1) * 4 - sizeof(srs_rtcp_header_t); - buffer->read_bytes((char *)payload_, payload_len_); - return srs_success; -} - -int SrsRTCPCommon::nb_bytes() -{ - return sizeof(srs_rtcp_header_t) + payload_len_; -} - -srs_error_t SrsRTCPCommon::encode(SrsBuffer *buffer) -{ - return srs_error_new(ERROR_RTC_RTCP, "not implement"); -} - -SrsRTCP_SR::SrsRTCP_SR() -{ - header_.padding = 0; - header_.type = RTCP_SR; - header_.rc = 0; - header_.version = kRtcpVersion; - header_.length = 6; -} - -SrsRTCP_SR::~SrsRTCP_SR() -{ - -} - -const uint32_t SrsRTCP_SR::get_sender_ssrc() const -{ - return sender_ssrc_; -} - -const uint64_t SrsRTCP_SR::get_ntp() const -{ - return ntp_; -} - -const uint32_t SrsRTCP_SR::get_rtp_ts() const -{ - return rtp_ts_; -} - -const uint32_t SrsRTCP_SR::get_rtp_send_packets() const -{ - return send_rtp_packets_; -} - -const uint32_t SrsRTCP_SR::get_rtp_send_bytes() const -{ - return send_rtp_bytes_; -} - -void SrsRTCP_SR::set_sender_ssrc(uint32_t ssrc) -{ - sender_ssrc_ = ssrc; -} - -void SrsRTCP_SR::set_ntp(uint64_t ntp) -{ - ntp_ = ntp; -} - -void SrsRTCP_SR::set_rtp_ts(uint32_t ts) -{ - rtp_ts_ = ts; -} - -void SrsRTCP_SR::set_rtp_send_packets(uint32_t packets) -{ - send_rtp_packets_ = packets; -} - -void SrsRTCP_SR::set_rtp_send_bytes(uint32_t bytes) -{ - send_rtp_bytes_ = bytes; -} - -srs_error_t SrsRTCP_SR::decode(SrsBuffer *buffer) -{ - srs_error_t err = srs_success; - err = decode_header(buffer); - if(srs_success != err) { - return srs_error_wrap(err, "fail to parse rtcp header"); - } - sender_ssrc_ = buffer->read_4bytes(); - ntp_ = buffer->read_8bytes(); - rtp_ts_ = buffer->read_4bytes(); - send_rtp_packets_ = buffer->read_4bytes(); - send_rtp_bytes_ = buffer->read_4bytes(); - if(header_.rc > 0) { - char buf[1500]; - buffer->read_bytes(buf, header_.rc * 24); - } - return err; -} - -int SrsRTCP_SR::nb_bytes() -{ - return (header_.length + 1) * 4; -} - -srs_error_t SrsRTCP_SR::encode(SrsBuffer *buffer) -{ - srs_error_t err = srs_success; - if(! buffer->require(nb_bytes())) { - return srs_error_new(ERROR_RTC_RTCP, - "the size of buffer is not enough. buffer:%d, required:%d", buffer->left(), nb_bytes()); - } - err = encode_header(buffer); - if(srs_success != err) { - return srs_error_wrap(err, "fail to encode rtcp header"); - } - buffer->write_4bytes(sender_ssrc_); - buffer->write_8bytes(ntp_); - buffer->write_4bytes(rtp_ts_); - buffer->write_4bytes(send_rtp_packets_); - buffer->write_4bytes(send_rtp_bytes_); - return err; -} - -SrsRTCP_RR::SrsRTCP_RR(uint32_t sender_ssrc/*=0*/): sender_ssrc_(sender_ssrc) -{ - header_.padding = 0; - header_.type = RTCP_RR; - header_.rc = 0; - header_.version = kRtcpVersion; - header_.length = 7; -} - -SrsRTCP_RR::~SrsRTCP_RR() -{ -} - -const uint32_t SrsRTCP_RR::get_rb_ssrc() const -{ - return rb_.ssrc; -} - -const float SrsRTCP_RR::get_lost_rate() const -{ - return rb_.fraction_lost / 256; -} - -const uint32_t SrsRTCP_RR::get_lost_packets() const -{ - return rb_.lost_packets; -} - -const uint32_t SrsRTCP_RR::get_highest_sn() const -{ - return rb_.highest_sn; -} - -const uint32_t SrsRTCP_RR::get_jitter() const -{ - return rb_.jitter; -} - -const uint32_t SrsRTCP_RR::get_lsr() const -{ - return rb_.lsr; -} - -const uint32_t SrsRTCP_RR::get_dlsr() const -{ - return rb_.dlsr; -} - -void SrsRTCP_RR::set_rb_ssrc(uint32_t ssrc) -{ - rb_.ssrc = ssrc; -} - -void SrsRTCP_RR::set_lost_rate(float rate) -{ - rb_.fraction_lost = rate * 256; -} - -void SrsRTCP_RR::set_lost_packets(uint32_t count) -{ - rb_.lost_packets = count; -} - -void SrsRTCP_RR::set_highest_sn(uint32_t sn) -{ - rb_.highest_sn = sn; -} - -void SrsRTCP_RR::set_jitter(uint32_t jitter) -{ - rb_.jitter = jitter; -} - -void SrsRTCP_RR::set_lsr(uint32_t lsr) -{ - rb_.lsr = lsr; -} - -void SrsRTCP_RR::set_dlsr(uint32_t dlsr) -{ - rb_.dlsr = dlsr; -} - -void SrsRTCP_RR::set_sender_ntp(uint64_t ntp) -{ - uint32_t lsr = (uint32_t)((ntp >> 16) & 0x00000000FFFFFFFF); - rb_.lsr = lsr; -} - -srs_error_t SrsRTCP_RR::decode(SrsBuffer *buffer) -{ - srs_error_t err = srs_success; - err = decode_header(buffer); - if(srs_success != err) { - return srs_error_wrap(err, "fail to parse rtcp header"); - } - sender_ssrc_ = buffer->read_4bytes(); - if(header_.rc < 1) { - return srs_success; - } - rb_.ssrc = buffer->read_4bytes(); - rb_.fraction_lost = buffer->read_1bytes(); - rb_.lost_packets = buffer->read_3bytes(); - rb_.highest_sn = buffer->read_4bytes(); - rb_.jitter = buffer->read_4bytes(); - rb_.lsr = buffer->read_4bytes(); - rb_.dlsr = buffer->read_4bytes(); - - if(header_.rc > 1) { - char buf[1500]; - buffer->read_bytes(buf, (header_.rc -1 ) * 24); - } - - return err; -} - -int SrsRTCP_RR::nb_bytes() -{ - return (header_.length + 1) * 4; -} - -srs_error_t SrsRTCP_RR::encode(SrsBuffer *buffer) -{ - srs_error_t err = srs_success; - if(! buffer->require(nb_bytes())) { - return srs_error_new(ERROR_RTC_RTCP, - "the size of buffer is not enough. buffer:%d, required:%d", buffer->left(), nb_bytes()); - } - - header_.rc = 1; - err = encode_header(buffer); - if(srs_success != err) { - return srs_error_wrap(err, "fail to encode rtcp header"); - } - buffer->write_4bytes(sender_ssrc_); - - buffer->write_4bytes(rb_.ssrc); - buffer->write_1bytes(rb_.fraction_lost); - buffer->write_3bytes(rb_.lost_packets); - buffer->write_4bytes(rb_.highest_sn); - buffer->write_4bytes(rb_.jitter); - buffer->write_4bytes(rb_.lsr); - buffer->write_4bytes(rb_.dlsr); - return err; -} - -SrsRTCP_TWCC::SrsRTCP_TWCC(uint32_t sender_ssrc/*=0*/) : sender_ssrc_(sender_ssrc) -{ - header_.padding = 0; - header_.type = RTCP_RTPFB; - header_.rc = 15; - header_.version = kRtcpVersion; -} - -SrsRTCP_TWCC::~SrsRTCP_TWCC() -{ -} - -const uint32_t SrsRTCP_TWCC::get_media_ssrc() const -{ - return media_ssrc_; -} -const uint16_t SrsRTCP_TWCC::get_base_sn() const -{ - return base_sn_; -} - -const uint32_t SrsRTCP_TWCC::get_reference_time() const -{ - return reference_time_; -} - -const uint8_t SrsRTCP_TWCC::get_feedback_count() const -{ - return fb_pkt_count_; -} - -const uint16_t SrsRTCP_TWCC::get_packet_status_count() const -{ - return recv_deltas_.size(); -} - -const vector SrsRTCP_TWCC::get_packet_chucks() const -{ - return packet_chucks_; -} - -const vector SrsRTCP_TWCC::get_recv_deltas() const -{ - return recv_deltas_; -} - -void SrsRTCP_TWCC::set_media_ssrc(uint32_t ssrc) -{ - media_ssrc_ = ssrc; -} -void SrsRTCP_TWCC::set_base_sn(uint16_t sn) -{ - base_sn_ = sn; -} - -void SrsRTCP_TWCC::set_reference_time(uint32_t time) -{ - reference_time_ = time; -} - -void SrsRTCP_TWCC::set_feedback_count(uint8_t count) -{ - fb_pkt_count_ = count; -} - -void SrsRTCP_TWCC::add_packet_chuck(uint16_t chunk) -{ - packet_chucks_.push_back(chunk); -} - -void SrsRTCP_TWCC::add_recv_delta(uint8_t delta) -{ - recv_deltas_.push_back(delta); -} - -srs_error_t SrsRTCP_TWCC::decode(SrsBuffer *buffer) -{ - srs_error_t err = srs_success; - - return err; -} - -int SrsRTCP_TWCC::nb_bytes() -{ - return kRtcpPacketSize; -} - -srs_error_t SrsRTCP_TWCC::encode(SrsBuffer *buffer) -{ - srs_error_t err = srs_success; - - return err; -} - -SrsRTCP_Nack::SrsRTCP_Nack(uint32_t sender_ssrc /*= 0*/): sender_ssrc_(sender_ssrc) -{ - header_.padding = 0; - header_.type = RTCP_RTPFB; - header_.rc = 1; - header_.version = kRtcpVersion; -} - -SrsRTCP_Nack::~SrsRTCP_Nack() -{ -} - -const uint32_t SrsRTCP_Nack::get_media_ssrc() const -{ - return media_ssrc_; -} - -const vector SrsRTCP_Nack::get_lost_sns() const -{ - vector sn; - for(auto it : lost_sns_) { - sn.push_back(it); - } - return sn; -} - -void SrsRTCP_Nack::set_media_ssrc(uint32_t ssrc) -{ - media_ssrc_ = ssrc; -} - -void SrsRTCP_Nack::add_lost_sn(uint16_t sn) -{ - lost_sns_.insert(sn); -} - -srs_error_t SrsRTCP_Nack::decode(SrsBuffer *buffer) -{ - srs_error_t err = srs_success; - err = decode_header(buffer); - if(srs_success != err) { - return srs_error_wrap(err, "fail to parse rtcp header"); - } - sender_ssrc_ = buffer->read_4bytes(); - media_ssrc_ = buffer->read_4bytes(); - char bitmask[20]; - for(int i = 0; i < (header_.length - 2); i++) { - uint16_t pid = buffer->read_2bytes(); - uint16_t blp = buffer->read_2bytes(); - lost_sns_.insert(pid); - memset(bitmask, 0, 20); - for(int j=0; j<16; j++) { - bitmask[j] = (blp & ( 1 << j )) >> j ? '1' : '0'; - if((blp & ( 1 << j )) >> j) - lost_sns_.insert(pid+j+1); - } - bitmask[16] = '\n'; - srs_info("[%d] %d / %s", i, pid, bitmask); - } - - return err; -} -int SrsRTCP_Nack::nb_bytes() -{ - return kRtcpPacketSize; -} - -srs_error_t SrsRTCP_Nack::encode(SrsBuffer *buffer) -{ - srs_error_t err = srs_success; - if(! buffer->require(nb_bytes())) { - return srs_error_new(ERROR_RTC_RTCP, - "the size of buffer is not enough. buffer:%d, required:%d", buffer->left(), nb_bytes()); - } - - vector chunks; - do { - pid_blp_t *chunk = NULL; - uint16_t pid = 0; - for(auto sn : lost_sns_) { - if(NULL == chunk) { - chunk = new pid_blp_t; - chunk->pid = sn; - chunk->blp = 0; - pid = sn; - continue; - } - if((sn - pid) < 1) { - srs_info("Skipping PID to NACK (%d already added)...\n", sn); - } else if( (sn - pid) > 16) { - // add new chunk - chunks.push_back(chunk); - chunk = NULL; - } else { - chunk->blp |= 1 << (sn-pid-1); - } - } - - header_.length = 2 + chunks.size(); - err = encode_header(buffer); - if(srs_success != err) { - err = srs_error_wrap(err, "fail to encode rtcp header"); - break; - } - buffer->write_4bytes(sender_ssrc_); - buffer->write_4bytes(media_ssrc_); - for(auto chunk : chunks) { - buffer->write_2bytes(chunk->pid); - buffer->write_2bytes(chunk->blp); - delete chunk; - chunk = NULL; - } - - } while(0); - - for(auto chunk : chunks) { - delete chunk; - chunk = NULL; - } - - return err; -} - -SrsRTCPCompound::SrsRTCPCompound(): nb_bytes_(0) -{ -} - -SrsRTCPCompound::~SrsRTCPCompound() -{ - clear(); -} - -SrsRTCPCommon* SrsRTCPCompound::get_next_rtcp() -{ - if(rtcps_.empty()) { - return NULL; - } - SrsRTCPCommon *rtcp = rtcps_.back(); - nb_bytes_ -= rtcp->nb_bytes(); - rtcps_.pop_back(); - return rtcp; -} - -srs_error_t SrsRTCPCompound::add_rtcp(SrsRTCPCommon *rtcp) -{ - int new_len = rtcp->nb_bytes(); - if((new_len + nb_bytes_) > kRtcpPacketSize) { - return srs_error_new(ERROR_RTC_RTCP, "exceed the rtcp max size. new rtcp: %d, current: %d", new_len, nb_bytes_); - } - nb_bytes_ += new_len; - rtcps_.push_back(rtcp); - - return srs_success; -} - -srs_error_t SrsRTCPCompound::decode(SrsBuffer *buffer) -{ - srs_error_t err = srs_success; - - while(0 != buffer->left()) { - srs_rtcp_header_t* header = (srs_rtcp_header_t *)(buffer->head()); - switch (header->type) - { - case RTCP_SR: - { - SrsRTCP_SR *rtcp = new SrsRTCP_SR; - err = rtcp->decode(buffer); - if(srs_success != err) { - return srs_error_wrap(err, "fail to decode rtcp sr"); - } - nb_bytes_ += rtcp->nb_bytes(); - rtcps_.push_back(rtcp); - break; - } - case RTCP_RR: - { - SrsRTCP_RR *rtcp = new SrsRTCP_RR; - err = rtcp->decode(buffer); - if(srs_success != err) { - return srs_error_wrap(err, "fail to decode rtcp rr"); - } - nb_bytes_ += rtcp->nb_bytes(); - rtcps_.push_back(rtcp); - break; - } - default: - { - SrsRTCPCommon *rtcp = new SrsRTCPCommon; - err = rtcp->decode(buffer); - if(srs_success != err) { - return srs_error_wrap(err, "fail to decode rtcp type:%d", header->type); - } - nb_bytes_ += rtcp->nb_bytes(); - rtcps_.push_back(rtcp); - break; - } - } - } - - return err; -} - -int SrsRTCPCompound::nb_bytes() -{ - return nb_bytes_; -} - -srs_error_t SrsRTCPCompound::encode(SrsBuffer *buffer) -{ - srs_error_t err = srs_success; - if(false == buffer->require(nb_bytes_)) { - return srs_error_new(ERROR_RTC_RTCP, - "the left size of buffer is not enough. buffer:%d, required:%d", buffer->left(), nb_bytes_); - } - - vector::iterator it; - for(it = rtcps_.begin(); it != rtcps_.end(); ++it) { - SrsRTCPCommon *rtcp = *it; - err = rtcp->encode(buffer); - if(err != srs_success) { - return srs_error_wrap(err, "fail to encode rtcp compound. type:%d", rtcp->type()); - } - } - - clear(); - return err; -} - -void SrsRTCPCompound::clear() -{ - vector::iterator it; - for(it = rtcps_.begin(); it != rtcps_.end(); ++it) { - SrsRTCPCommon *rtcp = *it; - delete rtcp; - rtcp = NULL; - } - rtcps_.clear(); - nb_bytes_ = 0; -}