2020-05-15 03:50:59 +00:00
|
|
|
/**
|
|
|
|
* The MIT License (MIT)
|
|
|
|
*
|
|
|
|
* Copyright (c) 2013-2020 LiPeng
|
|
|
|
*
|
|
|
|
* Permission is hereby granted, free of charge, to any person obtaining a copy of
|
|
|
|
* this software and associated documentation files (the "Software"), to deal in
|
|
|
|
* the Software without restriction, including without limitation the rights to
|
|
|
|
* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
|
|
|
|
* the Software, and to permit persons to whom the Software is furnished to do so,
|
|
|
|
* subject to the following conditions:
|
|
|
|
*
|
|
|
|
* The above copyright notice and this permission notice shall be included in all
|
|
|
|
* copies or substantial portions of the Software.
|
|
|
|
*
|
|
|
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
|
|
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
|
|
|
* FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
|
|
|
* COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
|
|
|
* IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
|
|
|
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
|
|
|
*/
|
2020-05-15 01:55:15 +00:00
|
|
|
|
|
|
|
#include <srs_kernel_rtc_rtcp.hpp>
|
2020-05-15 03:50:59 +00:00
|
|
|
|
2020-05-15 01:55:15 +00:00
|
|
|
#include <srs_kernel_error.hpp>
|
|
|
|
#include <srs_kernel_log.hpp>
|
|
|
|
|
2020-05-30 09:52:11 +00:00
|
|
|
#include <arpa/inet.h>
|
2020-05-15 01:55:15 +00:00
|
|
|
using namespace std;
|
|
|
|
|
2020-05-15 04:03:43 +00:00
|
|
|
SrsRtcpCommon::SrsRtcpCommon()
|
2020-05-15 01:55:15 +00:00
|
|
|
{
|
|
|
|
}
|
|
|
|
|
2020-05-15 04:03:43 +00:00
|
|
|
SrsRtcpCommon::~SrsRtcpCommon()
|
2020-05-15 01:55:15 +00:00
|
|
|
{
|
|
|
|
}
|
|
|
|
|
2020-05-19 09:49:34 +00:00
|
|
|
const uint8_t SrsRtcpCommon::type() const
|
|
|
|
{
|
|
|
|
return header_.type;
|
|
|
|
}
|
|
|
|
|
2020-05-15 04:03:43 +00:00
|
|
|
srs_error_t SrsRtcpCommon::decode_header(SrsBuffer *buffer)
|
2020-05-15 01:55:15 +00:00
|
|
|
{
|
2020-05-15 04:03:43 +00:00
|
|
|
buffer->read_bytes((char*)(&header_), sizeof(SrsRtcpHeader));
|
2020-05-15 01:55:15 +00:00
|
|
|
header_.length = ntohs(header_.length);
|
2020-05-15 10:06:25 +00:00
|
|
|
|
2020-05-15 01:55:15 +00:00
|
|
|
return srs_success;
|
|
|
|
}
|
|
|
|
|
2020-05-15 04:03:43 +00:00
|
|
|
srs_error_t SrsRtcpCommon::encode_header(SrsBuffer *buffer)
|
2020-05-15 01:55:15 +00:00
|
|
|
{
|
|
|
|
header_.length = htons(header_.length);
|
2020-05-15 04:03:43 +00:00
|
|
|
buffer->write_bytes((char*)(&header_), sizeof(SrsRtcpHeader));
|
2020-05-15 10:06:25 +00:00
|
|
|
|
2020-05-15 01:55:15 +00:00
|
|
|
return srs_success;
|
|
|
|
}
|
|
|
|
|
2020-05-15 04:03:43 +00:00
|
|
|
srs_error_t SrsRtcpCommon::decode(SrsBuffer *buffer)
|
2020-05-15 01:55:15 +00:00
|
|
|
{
|
|
|
|
srs_error_t err = srs_success;
|
2020-05-15 10:06:25 +00:00
|
|
|
|
|
|
|
if(srs_success != (err = decode_header(buffer))) {
|
|
|
|
return srs_error_wrap(err, "decode header");
|
2020-05-15 01:55:15 +00:00
|
|
|
}
|
2020-05-15 10:06:25 +00:00
|
|
|
|
2020-05-15 04:03:43 +00:00
|
|
|
payload_len_ = (header_.length + 1) * 4 - sizeof(SrsRtcpHeader);
|
2020-05-15 01:55:15 +00:00
|
|
|
buffer->read_bytes((char *)payload_, payload_len_);
|
2020-05-15 10:06:25 +00:00
|
|
|
|
|
|
|
return err;
|
2020-05-15 01:55:15 +00:00
|
|
|
}
|
|
|
|
|
2020-05-15 04:03:43 +00:00
|
|
|
int SrsRtcpCommon::nb_bytes()
|
2020-05-15 01:55:15 +00:00
|
|
|
{
|
2020-05-15 04:03:43 +00:00
|
|
|
return sizeof(SrsRtcpHeader) + payload_len_;
|
2020-05-15 01:55:15 +00:00
|
|
|
}
|
|
|
|
|
2020-05-15 04:03:43 +00:00
|
|
|
srs_error_t SrsRtcpCommon::encode(SrsBuffer *buffer)
|
2020-05-15 01:55:15 +00:00
|
|
|
{
|
|
|
|
return srs_error_new(ERROR_RTC_RTCP, "not implement");
|
|
|
|
}
|
|
|
|
|
2020-05-15 04:03:43 +00:00
|
|
|
SrsRtcpApp::SrsRtcpApp():ssrc_(0)
|
2020-05-15 01:55:15 +00:00
|
|
|
{
|
|
|
|
}
|
|
|
|
|
2020-05-15 04:03:43 +00:00
|
|
|
SrsRtcpApp::~SrsRtcpApp()
|
2020-05-15 01:55:15 +00:00
|
|
|
{
|
|
|
|
}
|
|
|
|
|
2020-05-19 09:49:34 +00:00
|
|
|
const uint8_t SrsRtcpApp::type() const
|
|
|
|
{
|
|
|
|
return SrsRtcpType_app;
|
|
|
|
}
|
|
|
|
|
2020-05-15 04:03:43 +00:00
|
|
|
const uint32_t SrsRtcpApp::get_ssrc() const
|
2020-05-15 01:55:15 +00:00
|
|
|
{
|
|
|
|
return ssrc_;
|
|
|
|
}
|
|
|
|
|
2020-05-15 04:03:43 +00:00
|
|
|
const uint8_t SrsRtcpApp::get_subtype() const
|
2020-05-15 01:55:15 +00:00
|
|
|
{
|
|
|
|
return header_.rc;
|
|
|
|
}
|
|
|
|
|
2020-05-15 04:03:43 +00:00
|
|
|
const string SrsRtcpApp::get_name() const
|
2020-05-15 01:55:15 +00:00
|
|
|
{
|
|
|
|
return string((char*)name_);
|
|
|
|
}
|
|
|
|
|
2020-05-15 04:03:43 +00:00
|
|
|
const srs_error_t SrsRtcpApp::get_payload(uint8_t*& payload, int& len)
|
2020-05-15 01:55:15 +00:00
|
|
|
{
|
|
|
|
len = payload_len_;
|
|
|
|
payload = payload_;
|
2020-05-15 10:06:25 +00:00
|
|
|
|
2020-05-15 01:55:15 +00:00
|
|
|
return srs_success;
|
|
|
|
}
|
|
|
|
|
2020-05-15 04:03:43 +00:00
|
|
|
srs_error_t SrsRtcpApp::set_subtype(uint8_t type)
|
2020-05-15 01:55:15 +00:00
|
|
|
{
|
|
|
|
if(31 < type) {
|
2020-05-15 10:06:25 +00:00
|
|
|
return srs_error_new(ERROR_RTC_RTCP, "invalid type: %d", type);
|
2020-05-15 01:55:15 +00:00
|
|
|
}
|
2020-05-15 10:06:25 +00:00
|
|
|
|
2020-05-15 01:55:15 +00:00
|
|
|
header_.rc = type;
|
2020-05-15 10:06:25 +00:00
|
|
|
|
2020-05-15 01:55:15 +00:00
|
|
|
return srs_success;
|
|
|
|
}
|
|
|
|
|
2020-05-15 04:03:43 +00:00
|
|
|
srs_error_t SrsRtcpApp::set_name(std::string name)
|
2020-05-15 01:55:15 +00:00
|
|
|
{
|
|
|
|
if(name.length() > 4) {
|
2020-05-15 10:06:25 +00:00
|
|
|
return srs_error_new(ERROR_RTC_RTCP, "invalid name length %d", name.length());
|
2020-05-15 01:55:15 +00:00
|
|
|
}
|
2020-05-15 10:06:25 +00:00
|
|
|
|
2020-05-15 01:55:15 +00:00
|
|
|
memset(name_, 0, sizeof(name_));
|
|
|
|
memcpy(name_, name.c_str(), name.length());
|
2020-05-15 10:06:25 +00:00
|
|
|
|
2020-05-15 01:55:15 +00:00
|
|
|
return srs_success;
|
|
|
|
}
|
|
|
|
|
2020-05-15 04:03:43 +00:00
|
|
|
srs_error_t SrsRtcpApp::set_payload(uint8_t* payload, int len)
|
2020-05-15 01:55:15 +00:00
|
|
|
{
|
|
|
|
if(len > (kRtcpPacketSize - 12)) {
|
2020-05-15 10:06:25 +00:00
|
|
|
return srs_error_new(ERROR_RTC_RTCP, "invalid payload length %d", len);
|
2020-05-15 01:55:15 +00:00
|
|
|
}
|
2020-05-15 10:06:25 +00:00
|
|
|
|
2020-05-15 01:55:15 +00:00
|
|
|
payload_len_ = len;
|
|
|
|
memcpy(payload_, payload, len);
|
2020-05-15 10:06:25 +00:00
|
|
|
|
2020-05-15 01:55:15 +00:00
|
|
|
return srs_success;
|
|
|
|
}
|
|
|
|
|
2020-05-15 04:03:43 +00:00
|
|
|
void SrsRtcpApp::set_ssrc(uint32_t ssrc)
|
2020-05-15 01:55:15 +00:00
|
|
|
{
|
|
|
|
ssrc_ = ssrc;
|
|
|
|
}
|
|
|
|
|
2020-05-15 04:03:43 +00:00
|
|
|
srs_error_t SrsRtcpApp::decode(SrsBuffer *buffer)
|
2020-05-15 01:55:15 +00:00
|
|
|
{
|
|
|
|
srs_error_t err = srs_success;
|
2020-05-15 10:06:25 +00:00
|
|
|
|
|
|
|
if(srs_success != (err = decode_header(buffer))) {
|
|
|
|
return srs_error_wrap(err, "decode header");
|
2020-05-15 01:55:15 +00:00
|
|
|
}
|
2020-05-15 10:06:25 +00:00
|
|
|
|
2020-05-15 01:55:15 +00:00
|
|
|
ssrc_ = buffer->read_4bytes();
|
|
|
|
buffer->read_bytes((char *)name_, sizeof(name_));
|
2020-05-15 10:06:25 +00:00
|
|
|
|
|
|
|
// TODO: FIXME: Should check size?
|
2020-05-15 04:03:43 +00:00
|
|
|
payload_len_ = (header_.length + 1) * 4 - sizeof(SrsRtcpHeader) - sizeof(name_) - sizeof(ssrc_);
|
2020-05-15 01:55:15 +00:00
|
|
|
buffer->read_bytes((char *)payload_, payload_len_);
|
2020-05-15 10:06:25 +00:00
|
|
|
|
2020-05-15 01:55:15 +00:00
|
|
|
return srs_success;
|
|
|
|
}
|
|
|
|
|
2020-05-15 04:03:43 +00:00
|
|
|
int SrsRtcpApp::nb_bytes()
|
2020-05-15 01:55:15 +00:00
|
|
|
{
|
2020-05-15 04:03:43 +00:00
|
|
|
return sizeof(SrsRtcpHeader) + sizeof(ssrc_) + sizeof(name_) + payload_len_;
|
2020-05-15 01:55:15 +00:00
|
|
|
}
|
|
|
|
|
2020-05-15 04:03:43 +00:00
|
|
|
srs_error_t SrsRtcpApp::encode(SrsBuffer *buffer)
|
2020-05-15 01:55:15 +00:00
|
|
|
{
|
|
|
|
srs_error_t err = srs_success;
|
2020-05-15 10:06:25 +00:00
|
|
|
|
|
|
|
if(!buffer->require(nb_bytes())) {
|
|
|
|
return srs_error_new(ERROR_RTC_RTCP, "requires %d bytes", nb_bytes());
|
2020-05-15 01:55:15 +00:00
|
|
|
}
|
2020-05-15 10:06:25 +00:00
|
|
|
|
|
|
|
if(srs_success != (err = encode_header(buffer))) {
|
|
|
|
return srs_error_wrap(err, "encode header");
|
2020-05-15 01:55:15 +00:00
|
|
|
}
|
2020-05-15 10:06:25 +00:00
|
|
|
|
2020-05-15 01:55:15 +00:00
|
|
|
buffer->write_4bytes(ssrc_);
|
|
|
|
buffer->write_bytes((char*)name_, sizeof(name_));
|
|
|
|
buffer->write_bytes((char*)payload_, payload_len_);
|
|
|
|
|
|
|
|
return srs_success;
|
|
|
|
}
|
|
|
|
|
2020-05-15 04:03:43 +00:00
|
|
|
SrsRtcpSR::SrsRtcpSR()
|
2020-05-15 01:55:15 +00:00
|
|
|
{
|
|
|
|
header_.padding = 0;
|
2020-05-15 04:03:43 +00:00
|
|
|
header_.type = SrsRtcpType_sr;
|
2020-05-15 01:55:15 +00:00
|
|
|
header_.rc = 0;
|
|
|
|
header_.version = kRtcpVersion;
|
|
|
|
header_.length = 6;
|
|
|
|
}
|
|
|
|
|
2020-05-15 04:03:43 +00:00
|
|
|
SrsRtcpSR::~SrsRtcpSR()
|
2020-05-15 01:55:15 +00:00
|
|
|
{
|
2020-05-19 09:49:34 +00:00
|
|
|
}
|
2020-05-15 01:55:15 +00:00
|
|
|
|
2020-05-19 09:49:34 +00:00
|
|
|
const uint8_t SrsRtcpSR::get_rc() const
|
|
|
|
{
|
|
|
|
return header_.rc;
|
|
|
|
}
|
|
|
|
|
|
|
|
const uint8_t SrsRtcpSR::type() const
|
|
|
|
{
|
|
|
|
return SrsRtcpType_sr;
|
2020-05-15 01:55:15 +00:00
|
|
|
}
|
|
|
|
|
2020-05-15 04:03:43 +00:00
|
|
|
const uint32_t SrsRtcpSR::get_sender_ssrc() const
|
2020-05-15 01:55:15 +00:00
|
|
|
{
|
|
|
|
return sender_ssrc_;
|
|
|
|
}
|
|
|
|
|
2020-05-15 04:03:43 +00:00
|
|
|
const uint64_t SrsRtcpSR::get_ntp() const
|
2020-05-15 01:55:15 +00:00
|
|
|
{
|
|
|
|
return ntp_;
|
|
|
|
}
|
|
|
|
|
2020-05-15 04:03:43 +00:00
|
|
|
const uint32_t SrsRtcpSR::get_rtp_ts() const
|
2020-05-15 01:55:15 +00:00
|
|
|
{
|
|
|
|
return rtp_ts_;
|
|
|
|
}
|
|
|
|
|
2020-05-15 04:03:43 +00:00
|
|
|
const uint32_t SrsRtcpSR::get_rtp_send_packets() const
|
2020-05-15 01:55:15 +00:00
|
|
|
{
|
|
|
|
return send_rtp_packets_;
|
|
|
|
}
|
|
|
|
|
2020-05-15 04:03:43 +00:00
|
|
|
const uint32_t SrsRtcpSR::get_rtp_send_bytes() const
|
2020-05-15 01:55:15 +00:00
|
|
|
{
|
|
|
|
return send_rtp_bytes_;
|
|
|
|
}
|
|
|
|
|
2020-05-15 04:03:43 +00:00
|
|
|
void SrsRtcpSR::set_sender_ssrc(uint32_t ssrc)
|
2020-05-15 01:55:15 +00:00
|
|
|
{
|
|
|
|
sender_ssrc_ = ssrc;
|
|
|
|
}
|
|
|
|
|
2020-05-15 04:03:43 +00:00
|
|
|
void SrsRtcpSR::set_ntp(uint64_t ntp)
|
2020-05-15 01:55:15 +00:00
|
|
|
{
|
|
|
|
ntp_ = ntp;
|
|
|
|
}
|
|
|
|
|
2020-05-15 04:03:43 +00:00
|
|
|
void SrsRtcpSR::set_rtp_ts(uint32_t ts)
|
2020-05-15 01:55:15 +00:00
|
|
|
{
|
|
|
|
rtp_ts_ = ts;
|
|
|
|
}
|
|
|
|
|
2020-05-15 04:03:43 +00:00
|
|
|
void SrsRtcpSR::set_rtp_send_packets(uint32_t packets)
|
2020-05-15 01:55:15 +00:00
|
|
|
{
|
|
|
|
send_rtp_packets_ = packets;
|
|
|
|
}
|
|
|
|
|
2020-05-15 04:03:43 +00:00
|
|
|
void SrsRtcpSR::set_rtp_send_bytes(uint32_t bytes)
|
2020-05-15 01:55:15 +00:00
|
|
|
{
|
|
|
|
send_rtp_bytes_ = bytes;
|
|
|
|
}
|
|
|
|
|
2020-05-15 04:03:43 +00:00
|
|
|
srs_error_t SrsRtcpSR::decode(SrsBuffer *buffer)
|
2020-05-15 01:55:15 +00:00
|
|
|
{
|
|
|
|
srs_error_t err = srs_success;
|
2020-05-15 10:06:25 +00:00
|
|
|
|
|
|
|
if(srs_success != (err = decode_header(buffer))) {
|
|
|
|
return srs_error_wrap(err, "decode header");
|
2020-05-15 01:55:15 +00:00
|
|
|
}
|
2020-05-15 10:06:25 +00:00
|
|
|
|
2020-05-15 01:55:15 +00:00
|
|
|
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();
|
2020-05-15 10:06:25 +00:00
|
|
|
|
2020-05-15 01:55:15 +00:00
|
|
|
if(header_.rc > 0) {
|
|
|
|
char buf[1500];
|
|
|
|
buffer->read_bytes(buf, header_.rc * 24);
|
|
|
|
}
|
2020-05-15 10:06:25 +00:00
|
|
|
|
2020-05-15 01:55:15 +00:00
|
|
|
return err;
|
|
|
|
}
|
|
|
|
|
2020-05-15 04:03:43 +00:00
|
|
|
int SrsRtcpSR::nb_bytes()
|
2020-05-15 01:55:15 +00:00
|
|
|
{
|
|
|
|
return (header_.length + 1) * 4;
|
|
|
|
}
|
|
|
|
|
2020-05-15 04:03:43 +00:00
|
|
|
srs_error_t SrsRtcpSR::encode(SrsBuffer *buffer)
|
2020-05-15 01:55:15 +00:00
|
|
|
{
|
|
|
|
srs_error_t err = srs_success;
|
2020-05-15 10:06:25 +00:00
|
|
|
|
|
|
|
if(!buffer->require(nb_bytes())) {
|
|
|
|
return srs_error_new(ERROR_RTC_RTCP, "requires %d bytes", nb_bytes());
|
2020-05-15 01:55:15 +00:00
|
|
|
}
|
2020-05-15 10:06:25 +00:00
|
|
|
|
|
|
|
if(srs_success != (err = encode_header(buffer))) {
|
|
|
|
return srs_error_wrap(err, "encode header");
|
2020-05-15 01:55:15 +00:00
|
|
|
}
|
2020-05-15 10:06:25 +00:00
|
|
|
|
2020-05-15 01:55:15 +00:00
|
|
|
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_);
|
2020-05-15 10:06:25 +00:00
|
|
|
|
2020-05-15 01:55:15 +00:00
|
|
|
return err;
|
|
|
|
}
|
|
|
|
|
2020-05-15 04:07:11 +00:00
|
|
|
SrsRtcpRR::SrsRtcpRR(uint32_t sender_ssrc): sender_ssrc_(sender_ssrc)
|
2020-05-15 01:55:15 +00:00
|
|
|
{
|
|
|
|
header_.padding = 0;
|
2020-05-15 04:03:43 +00:00
|
|
|
header_.type = SrsRtcpType_rr;
|
2020-05-15 01:55:15 +00:00
|
|
|
header_.rc = 0;
|
|
|
|
header_.version = kRtcpVersion;
|
|
|
|
header_.length = 7;
|
|
|
|
}
|
|
|
|
|
2020-05-15 04:03:43 +00:00
|
|
|
SrsRtcpRR::~SrsRtcpRR()
|
2020-05-15 01:55:15 +00:00
|
|
|
{
|
|
|
|
}
|
|
|
|
|
2020-05-19 09:49:34 +00:00
|
|
|
const uint8_t SrsRtcpRR::type() const
|
|
|
|
{
|
|
|
|
return SrsRtcpType_rr;
|
|
|
|
}
|
|
|
|
|
2020-05-15 04:03:43 +00:00
|
|
|
const uint32_t SrsRtcpRR::get_rb_ssrc() const
|
2020-05-15 01:55:15 +00:00
|
|
|
{
|
|
|
|
return rb_.ssrc;
|
|
|
|
}
|
|
|
|
|
2020-05-15 04:03:43 +00:00
|
|
|
const float SrsRtcpRR::get_lost_rate() const
|
2020-05-15 01:55:15 +00:00
|
|
|
{
|
|
|
|
return rb_.fraction_lost / 256;
|
|
|
|
}
|
|
|
|
|
2020-05-15 04:03:43 +00:00
|
|
|
const uint32_t SrsRtcpRR::get_lost_packets() const
|
2020-05-15 01:55:15 +00:00
|
|
|
{
|
|
|
|
return rb_.lost_packets;
|
|
|
|
}
|
|
|
|
|
2020-05-15 04:03:43 +00:00
|
|
|
const uint32_t SrsRtcpRR::get_highest_sn() const
|
2020-05-15 01:55:15 +00:00
|
|
|
{
|
|
|
|
return rb_.highest_sn;
|
|
|
|
}
|
|
|
|
|
2020-05-15 04:03:43 +00:00
|
|
|
const uint32_t SrsRtcpRR::get_jitter() const
|
2020-05-15 01:55:15 +00:00
|
|
|
{
|
|
|
|
return rb_.jitter;
|
|
|
|
}
|
|
|
|
|
2020-05-15 04:03:43 +00:00
|
|
|
const uint32_t SrsRtcpRR::get_lsr() const
|
2020-05-15 01:55:15 +00:00
|
|
|
{
|
|
|
|
return rb_.lsr;
|
|
|
|
}
|
|
|
|
|
2020-05-15 04:03:43 +00:00
|
|
|
const uint32_t SrsRtcpRR::get_dlsr() const
|
2020-05-15 01:55:15 +00:00
|
|
|
{
|
|
|
|
return rb_.dlsr;
|
|
|
|
}
|
|
|
|
|
2020-05-15 04:03:43 +00:00
|
|
|
void SrsRtcpRR::set_rb_ssrc(uint32_t ssrc)
|
2020-05-15 01:55:15 +00:00
|
|
|
{
|
|
|
|
rb_.ssrc = ssrc;
|
|
|
|
}
|
|
|
|
|
2020-05-15 04:03:43 +00:00
|
|
|
void SrsRtcpRR::set_lost_rate(float rate)
|
2020-05-15 01:55:15 +00:00
|
|
|
{
|
|
|
|
rb_.fraction_lost = rate * 256;
|
|
|
|
}
|
|
|
|
|
2020-05-15 04:03:43 +00:00
|
|
|
void SrsRtcpRR::set_lost_packets(uint32_t count)
|
2020-05-15 01:55:15 +00:00
|
|
|
{
|
|
|
|
rb_.lost_packets = count;
|
|
|
|
}
|
|
|
|
|
2020-05-15 04:03:43 +00:00
|
|
|
void SrsRtcpRR::set_highest_sn(uint32_t sn)
|
2020-05-15 01:55:15 +00:00
|
|
|
{
|
|
|
|
rb_.highest_sn = sn;
|
|
|
|
}
|
|
|
|
|
2020-05-15 04:03:43 +00:00
|
|
|
void SrsRtcpRR::set_jitter(uint32_t jitter)
|
2020-05-15 01:55:15 +00:00
|
|
|
{
|
|
|
|
rb_.jitter = jitter;
|
|
|
|
}
|
|
|
|
|
2020-05-15 04:03:43 +00:00
|
|
|
void SrsRtcpRR::set_lsr(uint32_t lsr)
|
2020-05-15 01:55:15 +00:00
|
|
|
{
|
|
|
|
rb_.lsr = lsr;
|
|
|
|
}
|
|
|
|
|
2020-05-15 04:03:43 +00:00
|
|
|
void SrsRtcpRR::set_dlsr(uint32_t dlsr)
|
2020-05-15 01:55:15 +00:00
|
|
|
{
|
|
|
|
rb_.dlsr = dlsr;
|
|
|
|
}
|
|
|
|
|
2020-05-15 04:03:43 +00:00
|
|
|
void SrsRtcpRR::set_sender_ntp(uint64_t ntp)
|
2020-05-15 01:55:15 +00:00
|
|
|
{
|
|
|
|
uint32_t lsr = (uint32_t)((ntp >> 16) & 0x00000000FFFFFFFF);
|
|
|
|
rb_.lsr = lsr;
|
|
|
|
}
|
|
|
|
|
2020-05-15 04:03:43 +00:00
|
|
|
srs_error_t SrsRtcpRR::decode(SrsBuffer *buffer)
|
2020-05-15 01:55:15 +00:00
|
|
|
{
|
|
|
|
srs_error_t err = srs_success;
|
2020-05-15 10:06:25 +00:00
|
|
|
|
|
|
|
if(srs_success != (err = decode_header(buffer))) {
|
|
|
|
return srs_error_wrap(err, "decode header");
|
2020-05-15 01:55:15 +00:00
|
|
|
}
|
2020-05-15 10:06:25 +00:00
|
|
|
|
2020-05-15 01:55:15 +00:00
|
|
|
sender_ssrc_ = buffer->read_4bytes();
|
|
|
|
if(header_.rc < 1) {
|
2020-05-15 10:06:25 +00:00
|
|
|
return err;
|
2020-05-15 01:55:15 +00:00
|
|
|
}
|
|
|
|
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;
|
|
|
|
}
|
|
|
|
|
2020-05-15 04:03:43 +00:00
|
|
|
int SrsRtcpRR::nb_bytes()
|
2020-05-15 01:55:15 +00:00
|
|
|
{
|
|
|
|
return (header_.length + 1) * 4;
|
|
|
|
}
|
|
|
|
|
2020-05-15 04:03:43 +00:00
|
|
|
srs_error_t SrsRtcpRR::encode(SrsBuffer *buffer)
|
2020-05-15 01:55:15 +00:00
|
|
|
{
|
|
|
|
srs_error_t err = srs_success;
|
2020-05-15 10:06:25 +00:00
|
|
|
|
|
|
|
if(!buffer->require(nb_bytes())) {
|
|
|
|
return srs_error_new(ERROR_RTC_RTCP, "requires %d bytes", nb_bytes());
|
2020-05-15 01:55:15 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
header_.rc = 1;
|
2020-05-15 10:06:25 +00:00
|
|
|
if(srs_success != (err = encode_header(buffer))) {
|
|
|
|
return srs_error_wrap(err, "encode header");
|
2020-05-15 01:55:15 +00:00
|
|
|
}
|
|
|
|
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);
|
2020-05-15 10:06:25 +00:00
|
|
|
|
2020-05-15 01:55:15 +00:00
|
|
|
return err;
|
|
|
|
}
|
|
|
|
|
2020-05-15 04:07:11 +00:00
|
|
|
SrsRtcpTWCC::SrsRtcpTWCC(uint32_t sender_ssrc) : sender_ssrc_(sender_ssrc), pkt_len(0)
|
2020-05-15 01:55:15 +00:00
|
|
|
{
|
|
|
|
header_.padding = 0;
|
2020-05-15 04:03:43 +00:00
|
|
|
header_.type = SrsRtcpType_rtpfb;
|
2020-05-15 01:55:15 +00:00
|
|
|
header_.rc = 15;
|
|
|
|
header_.version = kRtcpVersion;
|
|
|
|
}
|
|
|
|
|
2020-05-15 04:03:43 +00:00
|
|
|
SrsRtcpTWCC::~SrsRtcpTWCC()
|
2020-05-15 01:55:15 +00:00
|
|
|
{
|
|
|
|
}
|
|
|
|
|
2020-05-15 04:03:43 +00:00
|
|
|
void SrsRtcpTWCC::clear()
|
2020-05-15 01:55:15 +00:00
|
|
|
{
|
|
|
|
encoded_chucks_.clear();
|
|
|
|
pkt_deltas_.clear();
|
|
|
|
recv_packes_.clear();
|
|
|
|
recv_sns_.clear();
|
|
|
|
}
|
|
|
|
|
2020-05-15 04:03:43 +00:00
|
|
|
const uint32_t SrsRtcpTWCC::get_media_ssrc() const
|
2020-05-15 01:55:15 +00:00
|
|
|
{
|
|
|
|
return media_ssrc_;
|
|
|
|
}
|
2020-05-15 04:03:43 +00:00
|
|
|
const uint16_t SrsRtcpTWCC::get_base_sn() const
|
2020-05-15 01:55:15 +00:00
|
|
|
{
|
|
|
|
return base_sn_;
|
|
|
|
}
|
|
|
|
|
2020-05-15 04:03:43 +00:00
|
|
|
const uint32_t SrsRtcpTWCC::get_reference_time() const
|
2020-05-15 01:55:15 +00:00
|
|
|
{
|
|
|
|
return reference_time_;
|
|
|
|
}
|
|
|
|
|
2020-05-15 04:03:43 +00:00
|
|
|
const uint8_t SrsRtcpTWCC::get_feedback_count() const
|
2020-05-15 01:55:15 +00:00
|
|
|
{
|
|
|
|
return fb_pkt_count_;
|
|
|
|
}
|
|
|
|
|
2020-05-15 04:03:43 +00:00
|
|
|
const uint16_t SrsRtcpTWCC::get_packet_status_count() const
|
2020-05-15 01:55:15 +00:00
|
|
|
{
|
|
|
|
return packet_count_;
|
|
|
|
}
|
|
|
|
|
2020-05-15 04:03:43 +00:00
|
|
|
const vector<uint16_t> SrsRtcpTWCC::get_packet_chucks() const
|
2020-05-15 01:55:15 +00:00
|
|
|
{
|
|
|
|
return encoded_chucks_;
|
|
|
|
}
|
|
|
|
|
2020-05-15 04:03:43 +00:00
|
|
|
const vector<uint16_t> SrsRtcpTWCC::get_recv_deltas() const
|
2020-05-15 01:55:15 +00:00
|
|
|
{
|
|
|
|
return pkt_deltas_;
|
|
|
|
}
|
|
|
|
|
2020-05-15 04:03:43 +00:00
|
|
|
void SrsRtcpTWCC::set_media_ssrc(uint32_t ssrc)
|
2020-05-15 01:55:15 +00:00
|
|
|
{
|
|
|
|
media_ssrc_ = ssrc;
|
|
|
|
}
|
2020-05-15 04:03:43 +00:00
|
|
|
void SrsRtcpTWCC::set_base_sn(uint16_t sn)
|
2020-05-15 01:55:15 +00:00
|
|
|
{
|
|
|
|
base_sn_ = sn;
|
|
|
|
}
|
|
|
|
|
2020-05-15 04:03:43 +00:00
|
|
|
void SrsRtcpTWCC::set_packet_status_count(uint16_t count)
|
2020-05-15 01:55:15 +00:00
|
|
|
{
|
|
|
|
packet_count_ = count;
|
|
|
|
}
|
|
|
|
|
2020-05-15 04:03:43 +00:00
|
|
|
void SrsRtcpTWCC::set_reference_time(uint32_t time)
|
2020-05-15 01:55:15 +00:00
|
|
|
{
|
|
|
|
reference_time_ = time;
|
|
|
|
}
|
|
|
|
|
2020-05-15 04:03:43 +00:00
|
|
|
void SrsRtcpTWCC::set_feedback_count(uint8_t count)
|
2020-05-15 01:55:15 +00:00
|
|
|
{
|
|
|
|
fb_pkt_count_ = count;
|
|
|
|
}
|
|
|
|
|
2020-05-15 04:03:43 +00:00
|
|
|
void SrsRtcpTWCC::add_packet_chuck(uint16_t chunk)
|
2020-05-15 01:55:15 +00:00
|
|
|
{
|
|
|
|
encoded_chucks_.push_back(chunk);
|
|
|
|
}
|
|
|
|
|
2020-05-15 04:03:43 +00:00
|
|
|
void SrsRtcpTWCC::add_recv_delta(uint16_t delta)
|
2020-05-15 01:55:15 +00:00
|
|
|
{
|
|
|
|
pkt_deltas_.push_back(delta);
|
|
|
|
}
|
|
|
|
|
2020-05-15 04:03:43 +00:00
|
|
|
srs_error_t SrsRtcpTWCC::recv_packet(uint16_t sn, srs_utime_t ts)
|
2020-05-15 01:55:15 +00:00
|
|
|
{
|
|
|
|
map<uint16_t, srs_utime_t>::iterator it = recv_packes_.find(sn);
|
|
|
|
if(it != recv_packes_.end()) {
|
2020-05-15 10:06:25 +00:00
|
|
|
return srs_error_new(ERROR_RTC_RTCP, "TWCC dup seq: %d", sn);
|
2020-05-15 01:55:15 +00:00
|
|
|
}
|
2020-05-15 10:06:25 +00:00
|
|
|
|
2020-05-15 01:55:15 +00:00
|
|
|
recv_packes_[sn] = ts;
|
|
|
|
recv_sns_.insert(sn);
|
2020-05-15 10:06:25 +00:00
|
|
|
|
2020-05-15 01:55:15 +00:00
|
|
|
return srs_success;
|
|
|
|
}
|
|
|
|
|
2020-05-15 04:03:43 +00:00
|
|
|
srs_error_t SrsRtcpTWCC::decode(SrsBuffer *buffer)
|
2020-05-15 01:55:15 +00:00
|
|
|
{
|
|
|
|
srs_error_t err = srs_success;
|
|
|
|
|
|
|
|
return err;
|
|
|
|
}
|
|
|
|
|
2020-05-15 04:03:43 +00:00
|
|
|
int SrsRtcpTWCC::nb_bytes()
|
2020-05-15 01:55:15 +00:00
|
|
|
{
|
|
|
|
return kRtcpPacketSize;
|
|
|
|
}
|
|
|
|
|
2020-05-15 04:03:43 +00:00
|
|
|
srs_utime_t SrsRtcpTWCC::calculate_delta_us(srs_utime_t ts, srs_utime_t last)
|
2020-05-15 01:55:15 +00:00
|
|
|
{
|
|
|
|
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;
|
|
|
|
}
|
|
|
|
|
2020-05-17 12:23:57 +00:00
|
|
|
bool SrsRtcpTWCC::can_add_to_chunk(SrsRtcpTWCC::SrsRtcpTWCCChunk& chunk, int delta_size)
|
2020-05-15 01:55:15 +00:00
|
|
|
{
|
2020-05-15 10:06:25 +00:00
|
|
|
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);
|
2020-05-15 01:55:15 +00:00
|
|
|
|
2020-05-15 10:06:25 +00:00
|
|
|
if (chunk.size < kTwccFbTwoBitElements) {
|
2020-05-15 01:55:15 +00:00
|
|
|
return true;
|
2020-05-15 10:06:25 +00:00
|
|
|
}
|
2020-05-15 01:55:15 +00:00
|
|
|
|
2020-05-15 10:06:25 +00:00
|
|
|
if (chunk.size < kTwccFbOneBitElements && !chunk.has_large_delta && delta_size != kTwccFbLargeRecvDeltaBytes) {
|
|
|
|
return true;
|
|
|
|
}
|
2020-05-15 01:55:15 +00:00
|
|
|
|
|
|
|
if (chunk.size < kTwccFbMaxRunLength && chunk.all_same && chunk.delta_sizes[0] == delta_size) {
|
2020-05-15 10:06:25 +00:00
|
|
|
srs_verbose("< %d && all_same && delta_size[0] %d == %d", kTwccFbMaxRunLength, chunk.delta_sizes[0], delta_size);
|
2020-05-15 01:55:15 +00:00
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2020-05-17 12:23:57 +00:00
|
|
|
void SrsRtcpTWCC::add_to_chunk(SrsRtcpTWCC::SrsRtcpTWCCChunk& chunk, int delta_size)
|
2020-05-15 01:55:15 +00:00
|
|
|
{
|
2020-05-15 10:06:25 +00:00
|
|
|
if (chunk.size < kTwccFbMaxBitElements) {
|
2020-05-15 01:55:15 +00:00
|
|
|
chunk.delta_sizes[chunk.size] = delta_size;
|
2020-05-15 10:06:25 +00:00
|
|
|
}
|
|
|
|
|
2020-05-15 01:55:15 +00:00
|
|
|
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;
|
|
|
|
}
|
|
|
|
|
2020-05-17 12:23:57 +00:00
|
|
|
srs_error_t SrsRtcpTWCC::encode_chunk_run_length(SrsRtcpTWCC::SrsRtcpTWCCChunk& chunk)
|
2020-05-15 01:55:15 +00:00
|
|
|
{
|
2020-05-15 10:06:25 +00:00
|
|
|
if (!chunk.all_same || chunk.size > kTwccFbMaxRunLength) {
|
|
|
|
return srs_error_new(ERROR_RTC_RTCP, "invalid run all_same:%d, size:%d", chunk.all_same, chunk.size);
|
|
|
|
}
|
2020-05-15 01:55:15 +00:00
|
|
|
|
|
|
|
uint16_t encoded_chunk = (chunk.delta_sizes[0] << 13) | chunk.size;
|
|
|
|
|
|
|
|
encoded_chucks_.push_back(encoded_chunk);
|
|
|
|
pkt_len += sizeof(encoded_chunk);
|
|
|
|
|
2020-05-15 10:06:25 +00:00
|
|
|
return srs_success;
|
2020-05-15 01:55:15 +00:00
|
|
|
}
|
|
|
|
|
2020-05-17 12:23:57 +00:00
|
|
|
srs_error_t SrsRtcpTWCC::encode_chunk_one_bit(SrsRtcpTWCC::SrsRtcpTWCCChunk& chunk)
|
2020-05-15 01:55:15 +00:00
|
|
|
{
|
|
|
|
int i = 0;
|
2020-05-15 10:06:25 +00:00
|
|
|
if (chunk.has_large_delta) {
|
|
|
|
return srs_error_new(ERROR_RTC_RTCP, "invalid large delta");
|
|
|
|
}
|
|
|
|
|
2020-05-15 01:55:15 +00:00
|
|
|
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);
|
|
|
|
|
2020-05-15 04:07:11 +00:00
|
|
|
// 1 0 symbol_list
|
2020-05-15 01:55:15 +00:00
|
|
|
return srs_success;
|
|
|
|
}
|
|
|
|
|
2020-05-17 12:23:57 +00:00
|
|
|
srs_error_t SrsRtcpTWCC::encode_chunk_two_bit(SrsRtcpTWCC::SrsRtcpTWCCChunk& chunk, size_t size, bool shift)
|
2020-05-15 01:55:15 +00:00
|
|
|
{
|
|
|
|
unsigned int i = 0;
|
|
|
|
uint8_t delta_size = 0;
|
|
|
|
|
|
|
|
uint16_t encoded_chunk = 0xc000;
|
2020-05-15 04:07:11 +00:00
|
|
|
// 1 1 symbol_list
|
2020-05-15 01:55:15 +00:00
|
|
|
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;
|
|
|
|
}
|
|
|
|
chunk.size -= size;
|
|
|
|
}
|
|
|
|
|
|
|
|
return srs_success;
|
|
|
|
}
|
|
|
|
|
2020-05-17 12:23:57 +00:00
|
|
|
void SrsRtcpTWCC::reset_chunk(SrsRtcpTWCC::SrsRtcpTWCCChunk& chunk)
|
2020-05-15 01:55:15 +00:00
|
|
|
{
|
|
|
|
chunk.size = 0;
|
|
|
|
|
|
|
|
chunk.all_same = true;
|
|
|
|
chunk.has_large_delta = false;
|
|
|
|
}
|
|
|
|
|
2020-05-17 12:23:57 +00:00
|
|
|
srs_error_t SrsRtcpTWCC::encode_chunk(SrsRtcpTWCC::SrsRtcpTWCCChunk& chunk)
|
2020-05-15 01:55:15 +00:00
|
|
|
{
|
|
|
|
srs_error_t err = srs_success;
|
|
|
|
|
2020-05-15 10:06:25 +00:00
|
|
|
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, "TWCC chunk");
|
|
|
|
}
|
2020-05-15 01:55:15 +00:00
|
|
|
|
|
|
|
if (chunk.all_same) {
|
2020-05-15 10:06:25 +00:00
|
|
|
if ((err = encode_chunk_run_length(chunk)) != srs_success) {
|
|
|
|
return srs_error_wrap(err, "encode run");
|
|
|
|
}
|
2020-05-15 01:55:15 +00:00
|
|
|
reset_chunk(chunk);
|
|
|
|
return err;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (chunk.size == kTwccFbOneBitElements) {
|
2020-05-15 10:06:25 +00:00
|
|
|
if ((err = encode_chunk_one_bit(chunk)) != srs_success) {
|
|
|
|
return srs_error_wrap(err, "encode chunk");
|
|
|
|
}
|
2020-05-15 01:55:15 +00:00
|
|
|
reset_chunk(chunk);
|
|
|
|
return err;
|
|
|
|
}
|
|
|
|
|
2020-05-15 10:06:25 +00:00
|
|
|
if ((err = encode_chunk_two_bit(chunk, kTwccFbTwoBitElements, true)) != srs_success) {
|
|
|
|
return srs_error_wrap(err, "encode chunk");
|
|
|
|
}
|
2020-05-15 01:55:15 +00:00
|
|
|
|
|
|
|
return err;
|
|
|
|
}
|
|
|
|
|
2020-05-17 12:23:57 +00:00
|
|
|
srs_error_t SrsRtcpTWCC::encode_remaining_chunk(SrsRtcpTWCC::SrsRtcpTWCCChunk& chunk)
|
2020-05-15 01:55:15 +00:00
|
|
|
{
|
|
|
|
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);
|
|
|
|
}
|
|
|
|
|
2020-05-17 12:23:57 +00:00
|
|
|
srs_error_t SrsRtcpTWCC::process_pkt_chunk(SrsRtcpTWCC::SrsRtcpTWCCChunk& chunk, int delta_size)
|
2020-05-15 01:55:15 +00:00
|
|
|
{
|
|
|
|
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 ((err = encode_chunk(chunk)) != srs_success) {
|
2020-05-15 10:06:25 +00:00
|
|
|
return srs_error_new(ERROR_RTC_RTCP, "encode chunk, delta_size %u", delta_size);
|
2020-05-15 01:55:15 +00:00
|
|
|
}
|
|
|
|
add_to_chunk(chunk, delta_size);
|
|
|
|
return err;
|
|
|
|
}
|
|
|
|
|
2020-05-15 04:03:43 +00:00
|
|
|
srs_error_t SrsRtcpTWCC::encode(SrsBuffer *buffer)
|
2020-05-15 01:55:15 +00:00
|
|
|
{
|
|
|
|
srs_error_t err = srs_success;
|
2020-05-15 10:06:25 +00:00
|
|
|
|
|
|
|
if(!buffer->require(nb_bytes())) {
|
|
|
|
return srs_error_new(ERROR_RTC_RTCP, "requires %d bytes", nb_bytes());
|
2020-05-15 01:55:15 +00:00
|
|
|
}
|
2020-05-15 10:06:25 +00:00
|
|
|
|
2020-05-15 01:55:15 +00:00
|
|
|
pkt_len = kTwccFbPktHeaderSize;
|
2020-05-15 04:03:43 +00:00
|
|
|
set<uint16_t, SrsSeqCompareLess>::iterator it_sn = recv_sns_.begin();
|
2020-05-15 01:55:15 +00:00
|
|
|
base_sn_ = *it_sn;
|
|
|
|
map<uint16_t, srs_utime_t>::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();
|
2020-05-15 10:06:25 +00:00
|
|
|
|
2020-05-15 01:55:15 +00:00
|
|
|
do {
|
|
|
|
// encode chunk
|
2020-05-17 12:23:57 +00:00
|
|
|
SrsRtcpTWCC::SrsRtcpTWCCChunk chunk;
|
2020-05-15 01:55:15 +00:00
|
|
|
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;
|
|
|
|
if ((err = process_pkt_chunk(chunk, recv_delta_size)) != srs_success) {
|
2020-05-15 10:06:25 +00:00
|
|
|
return srs_error_new(ERROR_RTC_RTCP, "delta_size %d, failed to append_recv_delta", recv_delta_size);
|
2020-05-15 01:55:15 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
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) {
|
2020-05-15 10:06:25 +00:00
|
|
|
return srs_error_wrap(err, "encode chunk");
|
2020-05-15 01:55:15 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// 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;
|
|
|
|
|
2020-05-15 10:06:25 +00:00
|
|
|
if(srs_success != (err = encode_header(buffer))) {
|
|
|
|
err = srs_error_wrap(err, "encode header");
|
2020-05-15 01:55:15 +00:00
|
|
|
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<uint16_t>::iterator it = encoded_chucks_.begin(); it != encoded_chucks_.end(); ++it) {
|
|
|
|
buffer->write_2bytes(*it);
|
|
|
|
}
|
|
|
|
for(vector<uint16_t>::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;
|
|
|
|
}
|
|
|
|
|
2020-05-15 04:07:11 +00:00
|
|
|
SrsRtcpNack::SrsRtcpNack(uint32_t sender_ssrc): sender_ssrc_(sender_ssrc)
|
2020-05-15 01:55:15 +00:00
|
|
|
{
|
|
|
|
header_.padding = 0;
|
2020-05-15 04:03:43 +00:00
|
|
|
header_.type = SrsRtcpType_rtpfb;
|
2020-05-15 01:55:15 +00:00
|
|
|
header_.rc = 1;
|
|
|
|
header_.version = kRtcpVersion;
|
|
|
|
}
|
|
|
|
|
2020-05-15 04:03:43 +00:00
|
|
|
SrsRtcpNack::~SrsRtcpNack()
|
2020-05-15 01:55:15 +00:00
|
|
|
{
|
|
|
|
}
|
|
|
|
|
2020-05-15 04:03:43 +00:00
|
|
|
const uint32_t SrsRtcpNack::get_media_ssrc() const
|
2020-05-15 01:55:15 +00:00
|
|
|
{
|
|
|
|
return media_ssrc_;
|
|
|
|
}
|
|
|
|
|
2020-05-15 04:03:43 +00:00
|
|
|
const vector<uint16_t> SrsRtcpNack::get_lost_sns() const
|
2020-05-15 01:55:15 +00:00
|
|
|
{
|
|
|
|
vector<uint16_t> sn;
|
2020-05-15 04:03:43 +00:00
|
|
|
for(set<uint16_t, SrsSeqCompareLess>::iterator it = lost_sns_.begin(); it != lost_sns_.end(); ++it) {
|
2020-05-15 01:55:15 +00:00
|
|
|
sn.push_back(*it);
|
|
|
|
}
|
|
|
|
return sn;
|
|
|
|
}
|
|
|
|
|
2020-05-15 04:03:43 +00:00
|
|
|
void SrsRtcpNack::set_media_ssrc(uint32_t ssrc)
|
2020-05-15 01:55:15 +00:00
|
|
|
{
|
|
|
|
media_ssrc_ = ssrc;
|
|
|
|
}
|
|
|
|
|
2020-05-15 04:03:43 +00:00
|
|
|
void SrsRtcpNack::add_lost_sn(uint16_t sn)
|
2020-05-15 01:55:15 +00:00
|
|
|
{
|
|
|
|
lost_sns_.insert(sn);
|
|
|
|
}
|
|
|
|
|
2020-05-15 04:03:43 +00:00
|
|
|
srs_error_t SrsRtcpNack::decode(SrsBuffer *buffer)
|
2020-05-15 01:55:15 +00:00
|
|
|
{
|
|
|
|
srs_error_t err = srs_success;
|
2020-05-15 10:06:25 +00:00
|
|
|
|
|
|
|
if(srs_success != (err = decode_header(buffer))) {
|
|
|
|
return srs_error_wrap(err, "decode header");
|
2020-05-15 01:55:15 +00:00
|
|
|
}
|
2020-05-15 10:06:25 +00:00
|
|
|
|
2020-05-15 01:55:15 +00:00
|
|
|
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;
|
|
|
|
}
|
2020-05-15 04:03:43 +00:00
|
|
|
int SrsRtcpNack::nb_bytes()
|
2020-05-15 01:55:15 +00:00
|
|
|
{
|
|
|
|
return kRtcpPacketSize;
|
|
|
|
}
|
|
|
|
|
2020-05-15 04:03:43 +00:00
|
|
|
srs_error_t SrsRtcpNack::encode(SrsBuffer *buffer)
|
2020-05-15 01:55:15 +00:00
|
|
|
{
|
|
|
|
srs_error_t err = srs_success;
|
2020-05-15 10:06:25 +00:00
|
|
|
if(!buffer->require(nb_bytes())) {
|
|
|
|
return srs_error_new(ERROR_RTC_RTCP, "requires %d bytes", nb_bytes());
|
2020-05-15 01:55:15 +00:00
|
|
|
}
|
|
|
|
|
2020-05-17 12:23:57 +00:00
|
|
|
vector<SrsPidBlp> chunks;
|
2020-05-15 01:55:15 +00:00
|
|
|
do {
|
2020-05-17 12:23:57 +00:00
|
|
|
SrsPidBlp chunk;
|
2020-05-15 01:55:15 +00:00
|
|
|
chunk.in_use = false;
|
|
|
|
uint16_t pid = 0;
|
2020-05-15 04:03:43 +00:00
|
|
|
for(set<uint16_t, SrsSeqCompareLess>::iterator it = lost_sns_.begin(); it != lost_sns_.end(); ++it) {
|
2020-05-15 01:55:15 +00:00
|
|
|
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) {
|
2020-05-15 10:06:25 +00:00
|
|
|
srs_info("skip seq %d", sn);
|
2020-05-15 01:55:15 +00:00
|
|
|
} 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();
|
2020-05-15 10:06:25 +00:00
|
|
|
if(srs_success != (err = encode_header(buffer))) {
|
|
|
|
err = srs_error_wrap(err, "encode header");
|
2020-05-15 01:55:15 +00:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
buffer->write_4bytes(sender_ssrc_);
|
|
|
|
buffer->write_4bytes(media_ssrc_);
|
2020-05-17 12:23:57 +00:00
|
|
|
for(vector<SrsPidBlp>::iterator it_chunk = chunks.begin(); it_chunk != chunks.end(); it_chunk++) {
|
2020-05-15 01:55:15 +00:00
|
|
|
buffer->write_2bytes(it_chunk->pid);
|
|
|
|
buffer->write_2bytes(it_chunk->blp);
|
|
|
|
}
|
|
|
|
} while(0);
|
|
|
|
|
|
|
|
return err;
|
|
|
|
}
|
|
|
|
|
2020-05-15 04:03:43 +00:00
|
|
|
SrsRtcpCompound::SrsRtcpCompound(): nb_bytes_(0)
|
2020-05-15 01:55:15 +00:00
|
|
|
{
|
|
|
|
}
|
|
|
|
|
2020-05-15 04:03:43 +00:00
|
|
|
SrsRtcpCompound::~SrsRtcpCompound()
|
2020-05-15 01:55:15 +00:00
|
|
|
{
|
|
|
|
clear();
|
|
|
|
}
|
|
|
|
|
2020-05-15 04:03:43 +00:00
|
|
|
SrsRtcpCommon* SrsRtcpCompound::get_next_rtcp()
|
2020-05-15 01:55:15 +00:00
|
|
|
{
|
|
|
|
if(rtcps_.empty()) {
|
|
|
|
return NULL;
|
|
|
|
}
|
2020-05-15 04:03:43 +00:00
|
|
|
SrsRtcpCommon *rtcp = rtcps_.back();
|
2020-05-15 01:55:15 +00:00
|
|
|
nb_bytes_ -= rtcp->nb_bytes();
|
|
|
|
rtcps_.pop_back();
|
|
|
|
return rtcp;
|
|
|
|
}
|
|
|
|
|
2020-05-15 04:03:43 +00:00
|
|
|
srs_error_t SrsRtcpCompound::add_rtcp(SrsRtcpCommon *rtcp)
|
2020-05-15 01:55:15 +00:00
|
|
|
{
|
|
|
|
int new_len = rtcp->nb_bytes();
|
|
|
|
if((new_len + nb_bytes_) > kRtcpPacketSize) {
|
2020-05-15 10:06:25 +00:00
|
|
|
return srs_error_new(ERROR_RTC_RTCP, "overflow, new rtcp: %d, current: %d", new_len, nb_bytes_);
|
2020-05-15 01:55:15 +00:00
|
|
|
}
|
|
|
|
nb_bytes_ += new_len;
|
|
|
|
rtcps_.push_back(rtcp);
|
|
|
|
|
|
|
|
return srs_success;
|
|
|
|
}
|
|
|
|
|
2020-05-15 04:03:43 +00:00
|
|
|
srs_error_t SrsRtcpCompound::decode(SrsBuffer *buffer)
|
2020-05-15 01:55:15 +00:00
|
|
|
{
|
|
|
|
srs_error_t err = srs_success;
|
|
|
|
|
2020-05-15 10:06:25 +00:00
|
|
|
while (buffer->empty()) {
|
|
|
|
SrsRtcpHeader* header = (SrsRtcpHeader*)(buffer->head());
|
|
|
|
if (header->type == SrsRtcpType_sr) {
|
2020-05-15 04:03:43 +00:00
|
|
|
SrsRtcpSR *rtcp = new SrsRtcpSR;
|
2020-05-15 10:06:25 +00:00
|
|
|
if(srs_success != (err = rtcp->decode(buffer))) {
|
|
|
|
return srs_error_wrap(err, "decode sr");
|
2020-05-15 01:55:15 +00:00
|
|
|
}
|
|
|
|
nb_bytes_ += rtcp->nb_bytes();
|
|
|
|
rtcps_.push_back(rtcp);
|
2020-05-15 10:06:25 +00:00
|
|
|
} else if (header->type == SrsRtcpType_rr) {
|
2020-05-15 04:03:43 +00:00
|
|
|
SrsRtcpRR *rtcp = new SrsRtcpRR;
|
2020-05-15 10:06:25 +00:00
|
|
|
if(srs_success != (err = rtcp->decode(buffer))) {
|
|
|
|
return srs_error_wrap(err, "decode rr");
|
2020-05-15 01:55:15 +00:00
|
|
|
}
|
|
|
|
nb_bytes_ += rtcp->nb_bytes();
|
|
|
|
rtcps_.push_back(rtcp);
|
2020-05-15 10:06:25 +00:00
|
|
|
} else {
|
2020-05-15 04:03:43 +00:00
|
|
|
SrsRtcpCommon *rtcp = new SrsRtcpCommon;
|
2020-05-15 10:06:25 +00:00
|
|
|
if(srs_success != (err = rtcp->decode(buffer))) {
|
|
|
|
return srs_error_wrap(err, "decode type: %#x", header->type);
|
2020-05-15 01:55:15 +00:00
|
|
|
}
|
|
|
|
nb_bytes_ += rtcp->nb_bytes();
|
|
|
|
rtcps_.push_back(rtcp);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return err;
|
|
|
|
}
|
|
|
|
|
2020-05-15 04:03:43 +00:00
|
|
|
int SrsRtcpCompound::nb_bytes()
|
2020-05-15 01:55:15 +00:00
|
|
|
{
|
|
|
|
return nb_bytes_;
|
|
|
|
}
|
|
|
|
|
2020-05-15 04:03:43 +00:00
|
|
|
srs_error_t SrsRtcpCompound::encode(SrsBuffer *buffer)
|
2020-05-15 01:55:15 +00:00
|
|
|
{
|
|
|
|
srs_error_t err = srs_success;
|
2020-05-15 10:06:25 +00:00
|
|
|
if(!buffer->require(nb_bytes_)) {
|
|
|
|
return srs_error_new(ERROR_RTC_RTCP, "requires %d bytes", nb_bytes_);
|
2020-05-15 01:55:15 +00:00
|
|
|
}
|
|
|
|
|
2020-05-15 04:03:43 +00:00
|
|
|
vector<SrsRtcpCommon*>::iterator it;
|
2020-05-15 01:55:15 +00:00
|
|
|
for(it = rtcps_.begin(); it != rtcps_.end(); ++it) {
|
2020-05-15 04:03:43 +00:00
|
|
|
SrsRtcpCommon *rtcp = *it;
|
2020-05-15 10:06:25 +00:00
|
|
|
if((err = rtcp->encode(buffer)) != srs_success) {
|
|
|
|
return srs_error_wrap(err, "encode compound type:%d", rtcp->type());
|
2020-05-15 01:55:15 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
clear();
|
|
|
|
return err;
|
|
|
|
}
|
|
|
|
|
2020-05-15 04:03:43 +00:00
|
|
|
void SrsRtcpCompound::clear()
|
2020-05-15 01:55:15 +00:00
|
|
|
{
|
2020-05-15 04:03:43 +00:00
|
|
|
vector<SrsRtcpCommon*>::iterator it;
|
2020-05-15 01:55:15 +00:00
|
|
|
for(it = rtcps_.begin(); it != rtcps_.end(); ++it) {
|
2020-05-15 04:03:43 +00:00
|
|
|
SrsRtcpCommon *rtcp = *it;
|
2020-05-15 01:55:15 +00:00
|
|
|
delete rtcp;
|
|
|
|
rtcp = NULL;
|
|
|
|
}
|
|
|
|
rtcps_.clear();
|
|
|
|
nb_bytes_ = 0;
|
|
|
|
}
|