mirror of
https://github.com/ossrs/srs.git
synced 2025-03-09 15:49:59 +00:00
add twcc and replace auto method
This commit is contained in:
parent
a72dce494d
commit
9910151feb
3 changed files with 1176 additions and 661 deletions
1052
trunk/src/kernel/srs_kernel_rtc_rtcp.cpp
Normal file
1052
trunk/src/kernel/srs_kernel_rtc_rtcp.cpp
Normal file
File diff suppressed because it is too large
Load diff
|
@ -3,7 +3,7 @@
|
|||
#define SRS_KERNEL_RTCP_HPP
|
||||
|
||||
#include <srs_kernel_buffer.hpp>
|
||||
#include <srs_kernel_rtp.hpp>
|
||||
#include <srs_kernel_rtc_rtp.hpp>
|
||||
#include <vector>
|
||||
#include <set>
|
||||
|
||||
|
@ -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<uint16_t> packet_chucks_;
|
||||
std::vector<uint8_t> recv_deltas_;
|
||||
std::vector<uint16_t> encoded_chucks_;
|
||||
std::vector<uint16_t> pkt_deltas_;
|
||||
|
||||
std::map<uint16_t, srs_utime_t> recv_packes_;
|
||||
std::set<uint16_t, less_compare> 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<uint16_t> get_packet_chucks() const;
|
||||
const std::vector<uint8_t> get_recv_deltas() const;
|
||||
const std::vector<uint16_t> 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_;
|
|
@ -1,637 +0,0 @@
|
|||
|
||||
#include <srs_kernel_rtcp.hpp>
|
||||
#include <srs_kernel_error.hpp>
|
||||
#include <srs_kernel_log.hpp>
|
||||
|
||||
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<uint16_t> SrsRTCP_TWCC::get_packet_chucks() const
|
||||
{
|
||||
return packet_chucks_;
|
||||
}
|
||||
|
||||
const vector<uint8_t> 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<uint16_t> SrsRTCP_Nack::get_lost_sns() const
|
||||
{
|
||||
vector<uint16_t> 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<pid_blp_t*> 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<SrsRTCPCommon*>::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<SrsRTCPCommon*>::iterator it;
|
||||
for(it = rtcps_.begin(); it != rtcps_.end(); ++it) {
|
||||
SrsRTCPCommon *rtcp = *it;
|
||||
delete rtcp;
|
||||
rtcp = NULL;
|
||||
}
|
||||
rtcps_.clear();
|
||||
nb_bytes_ = 0;
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue