rtcp: Move SR and RR construction to rtcp packets module
This commit is contained in:
parent
473b7abf0b
commit
a08d92e848
|
|
@ -122,7 +122,7 @@ void receiver_hook(uvgrtp::frame::rtcp_receiver_report *frame)
|
||||||
std::cout << "last_seq: " << block.last_seq << std::endl;
|
std::cout << "last_seq: " << block.last_seq << std::endl;
|
||||||
std::cout << "jitter: " << block.jitter << std::endl;
|
std::cout << "jitter: " << block.jitter << std::endl;
|
||||||
std::cout << "lsr: " << block.lsr << std::endl;
|
std::cout << "lsr: " << block.lsr << std::endl;
|
||||||
std::cout << "dlsr (ms): " << uvgrtp::clock::jiffies_to_ms(block.dlsr)
|
std::cout << "dlsr (jiffies): " << uvgrtp::clock::jiffies_to_ms(block.dlsr)
|
||||||
<< std::endl << std::endl;
|
<< std::endl << std::endl;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -147,7 +147,7 @@ void sender_hook(uvgrtp::frame::rtcp_sender_report *frame)
|
||||||
std::cout << "last_seq: " << block.last_seq << std::endl;
|
std::cout << "last_seq: " << block.last_seq << std::endl;
|
||||||
std::cout << "jitter: " << block.jitter << std::endl;
|
std::cout << "jitter: " << block.jitter << std::endl;
|
||||||
std::cout << "lsr: " << block.lsr << std::endl;
|
std::cout << "lsr: " << block.lsr << std::endl;
|
||||||
std::cout << "dlsr (ms): " << uvgrtp::clock::jiffies_to_ms(block.dlsr)
|
std::cout << "dlsr (jiffies): " << uvgrtp::clock::jiffies_to_ms(block.dlsr)
|
||||||
<< std::endl << std::endl;
|
<< std::endl << std::endl;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -39,7 +39,7 @@ namespace uvgrtp {
|
||||||
uint32_t received_bytes = 0; /* Number of bytes received excluding RTP Header */
|
uint32_t received_bytes = 0; /* Number of bytes received excluding RTP Header */
|
||||||
bool received_rtp_packet = false; // since last report
|
bool received_rtp_packet = false; // since last report
|
||||||
|
|
||||||
float jitter = 0; /* The estimation of jitter (see RFC 3550 A.8) */
|
double jitter = 0; /* The estimation of jitter (see RFC 3550 A.8) */
|
||||||
uint32_t transit = 0; /* TODO: */
|
uint32_t transit = 0; /* TODO: */
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -54,7 +54,7 @@ namespace uvgrtp {
|
||||||
uint16_t max_seq = 0; /* Highest sequence number received */
|
uint16_t max_seq = 0; /* Highest sequence number received */
|
||||||
uint32_t base_seq = 0; /* First sequence number received */
|
uint32_t base_seq = 0; /* First sequence number received */
|
||||||
uint32_t bad_seq = 0; /* TODO: */
|
uint32_t bad_seq = 0; /* TODO: */
|
||||||
uint32_t cycles = 0; /* Number of sequence cycles */
|
uint16_t cycles = 0; /* Number of sequence cycles */
|
||||||
};
|
};
|
||||||
|
|
||||||
struct rtcp_participant {
|
struct rtcp_participant {
|
||||||
|
|
|
||||||
|
|
@ -82,7 +82,7 @@ uint64_t uvgrtp::clock::hrc::diff_now_us(hrc_t& then)
|
||||||
|
|
||||||
uint64_t uvgrtp::clock::ms_to_jiffies(uint64_t ms)
|
uint64_t uvgrtp::clock::ms_to_jiffies(uint64_t ms)
|
||||||
{
|
{
|
||||||
return (uint64_t)(((double)ms / 1000) * 65536);
|
return (uint64_t)(((double)ms/1000)* 65536);
|
||||||
}
|
}
|
||||||
|
|
||||||
uint64_t uvgrtp::clock::jiffies_to_ms(uint64_t jiffies)
|
uint64_t uvgrtp::clock::jiffies_to_ms(uint64_t jiffies)
|
||||||
|
|
|
||||||
37
src/rtcp.cc
37
src/rtcp.cc
|
|
@ -786,7 +786,7 @@ rtp_error_t uvgrtp::rtcp::update_participant_seq(uint32_t ssrc, uint16_t seq)
|
||||||
if (seq < p->stats.max_seq)
|
if (seq < p->stats.max_seq)
|
||||||
{
|
{
|
||||||
/* Sequence number wrapped - count another 64K cycle. */
|
/* Sequence number wrapped - count another 64K cycle. */
|
||||||
p->stats.cycles += RTP_SEQ_MOD;
|
p->stats.cycles += 1;
|
||||||
}
|
}
|
||||||
p->stats.max_seq = seq;
|
p->stats.max_seq = seq;
|
||||||
} else if (udelta <= RTP_SEQ_MOD - MAX_MISORDER) {
|
} else if (udelta <= RTP_SEQ_MOD - MAX_MISORDER) {
|
||||||
|
|
@ -1395,23 +1395,21 @@ rtp_error_t uvgrtp::rtcp::generate_report()
|
||||||
memset(frame, 0, rtcp_packet_size);
|
memset(frame, 0, rtcp_packet_size);
|
||||||
construct_rtcp_header(frame, ptr, rtcp_packet_size, reports, uvgrtp::frame::RTCP_FT_SR, ssrc_);
|
construct_rtcp_header(frame, ptr, rtcp_packet_size, reports, uvgrtp::frame::RTCP_FT_SR, ssrc_);
|
||||||
|
|
||||||
// add sender info to packet
|
/* TODO: The clock would be better to start with first sent RTP packet.
|
||||||
|
* In reality it should be provided by user which I think is implemented? */
|
||||||
if (clock_start_ == 0)
|
if (clock_start_ == 0)
|
||||||
{
|
{
|
||||||
clock_start_ = uvgrtp::clock::ntp::now();
|
clock_start_ = uvgrtp::clock::ntp::now();
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Sender information */
|
/* TODO: The RTP timestamp should be from an actual RTP packet and NTP timestamp should be the one
|
||||||
|
corresponding to it. */
|
||||||
uint64_t ntp_ts = uvgrtp::clock::ntp::now();
|
uint64_t ntp_ts = uvgrtp::clock::ntp::now();
|
||||||
|
|
||||||
uint64_t rtp_ts = rtp_ts_start_ + (uvgrtp::clock::ntp::diff(clock_start_, ntp_ts))
|
uint64_t rtp_ts = rtp_ts_start_ + (uvgrtp::clock::ntp::diff(clock_start_, ntp_ts))
|
||||||
* float(clock_rate_ / 1000);
|
* float(clock_rate_ / 1000);
|
||||||
|
|
||||||
SET_NEXT_FIELD_32(frame, ptr, htonl(ntp_ts >> 32));
|
construct_sender_info(frame, ptr, ntp_ts, rtp_ts,
|
||||||
SET_NEXT_FIELD_32(frame, ptr, htonl(ntp_ts & 0xffffffff));
|
our_stats.sent_pkts, our_stats.sent_bytes);
|
||||||
SET_NEXT_FIELD_32(frame, ptr, htonl((u_long)rtp_ts));
|
|
||||||
SET_NEXT_FIELD_32(frame, ptr, htonl(our_stats.sent_pkts));
|
|
||||||
SET_NEXT_FIELD_32(frame, ptr, htonl(our_stats.sent_bytes));
|
|
||||||
|
|
||||||
our_stats.sent_rtp_packet = false;
|
our_stats.sent_rtp_packet = false;
|
||||||
|
|
||||||
|
|
@ -1429,24 +1427,23 @@ rtp_error_t uvgrtp::rtcp::generate_report()
|
||||||
// only add report blocks if we have received data from them
|
// only add report blocks if we have received data from them
|
||||||
if (p.second->stats.received_rtp_packet)
|
if (p.second->stats.received_rtp_packet)
|
||||||
{
|
{
|
||||||
int dropped = p.second->stats.dropped_pkts;
|
uint32_t dropped_packets = p.second->stats.dropped_pkts;
|
||||||
// TODO: This should be the number of packets lost compared to number of packets expected (see fraction lost in RFC 3550)
|
// TODO: This should be the number of packets lost compared to number of packets expected (see fraction lost in RFC 3550)
|
||||||
// see https://datatracker.ietf.org/doc/html/rfc3550#appendix-A.3
|
// see https://datatracker.ietf.org/doc/html/rfc3550#appendix-A.3
|
||||||
uint8_t frac = dropped ? p.second->stats.received_bytes / dropped : 0;
|
uint8_t fraction = dropped_packets ? p.second->stats.received_bytes / dropped_packets : 0;
|
||||||
|
|
||||||
SET_NEXT_FIELD_32(frame, ptr, htonl(p.first)); /* ssrc */
|
uint64_t diff = (u_long)uvgrtp::clock::hrc::diff_now(p.second->stats.sr_ts);
|
||||||
SET_NEXT_FIELD_32(frame, ptr, htonl((frac << 24) | p.second->stats.dropped_pkts));
|
uint32_t dlrs = uvgrtp::clock::ms_to_jiffies(diff);
|
||||||
SET_NEXT_FIELD_32(frame, ptr, htonl(p.second->stats.max_seq));
|
|
||||||
SET_NEXT_FIELD_32(frame, ptr, htonl(p.second->stats.jitter));
|
|
||||||
SET_NEXT_FIELD_32(frame, ptr, htonl(p.second->stats.lsr));
|
|
||||||
|
|
||||||
/* calculate delay of last SR only if SR has been received at least once */
|
/* calculate delay of last SR only if SR has been received at least once */
|
||||||
if (p.second->stats.lsr)
|
if (p.second->stats.lsr == 0)
|
||||||
{
|
{
|
||||||
uint64_t diff = (u_long)uvgrtp::clock::hrc::diff_now(p.second->stats.sr_ts);
|
dlrs = 0;
|
||||||
SET_NEXT_FIELD_32(frame, ptr, (uint32_t)htonl((u_long)uvgrtp::clock::ms_to_jiffies(diff)));
|
|
||||||
}
|
}
|
||||||
ptr += p.second->stats.lsr ? 0 : 4;
|
|
||||||
|
construct_report_block(frame, ptr, p.first, fraction, dropped_packets,
|
||||||
|
p.second->stats.cycles, p.second->stats.max_seq, p.second->stats.jitter,
|
||||||
|
p.second->stats.lsr, dlrs);
|
||||||
|
|
||||||
// we only send reports if there is something to report since last report
|
// we only send reports if there is something to report since last report
|
||||||
p.second->stats.received_rtp_packet = false;
|
p.second->stats.received_rtp_packet = false;
|
||||||
|
|
|
||||||
|
|
@ -5,35 +5,6 @@
|
||||||
#include "uvgrtp/debug.hh"
|
#include "uvgrtp/debug.hh"
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
bool uvgrtp::construct_rtcp_header(uint8_t* frame, int& ptr, size_t packet_size,
|
|
||||||
uint16_t secondField,
|
|
||||||
uvgrtp::frame::RTCP_FRAME_TYPE frame_type,
|
|
||||||
uint32_t ssrc)
|
|
||||||
{
|
|
||||||
if (packet_size > UINT16_MAX)
|
|
||||||
{
|
|
||||||
LOG_ERROR("RTCP receiver report packet size too large!");
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
// header |V=2|P| SC | PT | length |
|
|
||||||
frame[ptr] = (2 << 6) | (0 << 5) | secondField;
|
|
||||||
frame[ptr + 1] = frame_type;
|
|
||||||
|
|
||||||
// The RTCP header length field is measured in 32-bit words - 1
|
|
||||||
*(uint16_t*)&frame[ptr + 2] = htons((uint16_t)packet_size / sizeof(uint32_t) - 1);
|
|
||||||
ptr += RTCP_HEADER_SIZE;
|
|
||||||
|
|
||||||
if (ssrc)
|
|
||||||
{
|
|
||||||
*(uint32_t*)&frame[ptr] = htonl(ssrc);
|
|
||||||
ptr += SSRC_CSRC_SIZE;
|
|
||||||
}
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
size_t uvgrtp::get_sr_packet_size(int flags, uint16_t reports)
|
size_t uvgrtp::get_sr_packet_size(int flags, uint16_t reports)
|
||||||
{
|
{
|
||||||
/* Sender report is otherwise identical with receiver report,
|
/* Sender report is otherwise identical with receiver report,
|
||||||
|
|
@ -84,6 +55,56 @@ size_t uvgrtp::get_bye_packet_size(const std::vector<uint32_t>& ssrcs)
|
||||||
return RTCP_HEADER_SIZE + ssrcs.size() * SSRC_CSRC_SIZE;
|
return RTCP_HEADER_SIZE + ssrcs.size() * SSRC_CSRC_SIZE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool uvgrtp::construct_rtcp_header(uint8_t* frame, int& ptr, size_t packet_size,
|
||||||
|
uint16_t secondField,
|
||||||
|
uvgrtp::frame::RTCP_FRAME_TYPE frame_type,
|
||||||
|
uint32_t ssrc)
|
||||||
|
{
|
||||||
|
if (packet_size > UINT16_MAX)
|
||||||
|
{
|
||||||
|
LOG_ERROR("RTCP receiver report packet size too large!");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// header |V=2|P| SC | PT | length |
|
||||||
|
frame[ptr] = (2 << 6) | (0 << 5) | secondField;
|
||||||
|
frame[ptr + 1] = frame_type;
|
||||||
|
|
||||||
|
// The RTCP header length field is measured in 32-bit words - 1
|
||||||
|
*(uint16_t*)&frame[ptr + 2] = htons((uint16_t)packet_size / sizeof(uint32_t) - 1);
|
||||||
|
ptr += RTCP_HEADER_SIZE;
|
||||||
|
|
||||||
|
if (ssrc)
|
||||||
|
{
|
||||||
|
*(uint32_t*)&frame[ptr] = htonl(ssrc);
|
||||||
|
ptr += SSRC_CSRC_SIZE;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void uvgrtp::construct_sender_info(uint8_t* frame, int& ptr, uint64_t ntp_ts, uint64_t rtp_ts,
|
||||||
|
uint32_t sent_packets, uint32_t sent_bytes)
|
||||||
|
{
|
||||||
|
SET_NEXT_FIELD_32(frame, ptr, htonl(ntp_ts >> 32)); // NTP ts msw
|
||||||
|
SET_NEXT_FIELD_32(frame, ptr, htonl(ntp_ts & 0xffffffff)); // NTP ts lsw
|
||||||
|
SET_NEXT_FIELD_32(frame, ptr, htonl((uint32_t)rtp_ts)); // RTP ts
|
||||||
|
SET_NEXT_FIELD_32(frame, ptr, htonl(sent_packets)); // sender's packet count
|
||||||
|
SET_NEXT_FIELD_32(frame, ptr, htonl(sent_bytes)); // sender's octet count (not bytes)
|
||||||
|
}
|
||||||
|
|
||||||
|
void uvgrtp::construct_report_block(uint8_t* frame, int& ptr, uint32_t ssrc, uint8_t fraction,
|
||||||
|
uint32_t dropped_packets, uint16_t seq_cycles, uint16_t max_seq, uint32_t jitter,
|
||||||
|
uint32_t lsr, uint32_t dlsr)
|
||||||
|
{
|
||||||
|
SET_NEXT_FIELD_32(frame, ptr, htonl(ssrc));
|
||||||
|
SET_NEXT_FIELD_32(frame, ptr, htonl(uint32_t(fraction << 24) | dropped_packets));
|
||||||
|
SET_NEXT_FIELD_32(frame, ptr, htonl(uint32_t(seq_cycles) << 16 | max_seq));
|
||||||
|
SET_NEXT_FIELD_32(frame, ptr, htonl(jitter));
|
||||||
|
SET_NEXT_FIELD_32(frame, ptr, htonl(lsr));
|
||||||
|
SET_NEXT_FIELD_32(frame, ptr, htonl(dlsr));
|
||||||
|
}
|
||||||
|
|
||||||
bool uvgrtp::construct_app_packet(uint8_t* frame, int& ptr,
|
bool uvgrtp::construct_app_packet(uint8_t* frame, int& ptr,
|
||||||
const char* name, const uint8_t* payload, size_t payload_len)
|
const char* name, const uint8_t* payload, size_t payload_len)
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -13,16 +13,22 @@ namespace uvgrtp
|
||||||
const uint16_t REPORT_BLOCK_SIZE = 24;
|
const uint16_t REPORT_BLOCK_SIZE = 24;
|
||||||
const uint16_t APP_NAME_SIZE = 4;
|
const uint16_t APP_NAME_SIZE = 4;
|
||||||
|
|
||||||
/* Set the first four or eight bytes of an RTCP packet */
|
|
||||||
bool construct_rtcp_header(uint8_t* frame, int& ptr, size_t packet_size,
|
|
||||||
uint16_t secondField, uvgrtp::frame::RTCP_FRAME_TYPE frame_type, uint32_t ssrc);
|
|
||||||
|
|
||||||
size_t get_sr_packet_size(int flags, uint16_t reports);
|
size_t get_sr_packet_size(int flags, uint16_t reports);
|
||||||
size_t get_rr_packet_size(int flags, uint16_t reports);
|
size_t get_rr_packet_size(int flags, uint16_t reports);
|
||||||
size_t get_sdes_packet_size(const std::vector<uvgrtp::frame::rtcp_sdes_item>& items);
|
size_t get_sdes_packet_size(const std::vector<uvgrtp::frame::rtcp_sdes_item>& items);
|
||||||
size_t get_app_packet_size(size_t payload_len);
|
size_t get_app_packet_size(size_t payload_len);
|
||||||
size_t get_bye_packet_size(const std::vector<uint32_t>& ssrcs);
|
size_t get_bye_packet_size(const std::vector<uint32_t>& ssrcs);
|
||||||
|
|
||||||
|
/* Set the first four or eight bytes of an RTCP packet */
|
||||||
|
bool construct_rtcp_header(uint8_t* frame, int& ptr, size_t packet_size,
|
||||||
|
uint16_t secondField, uvgrtp::frame::RTCP_FRAME_TYPE frame_type, uint32_t ssrc);
|
||||||
|
|
||||||
|
void construct_sender_info(uint8_t* frame, int& ptr, uint64_t ntp_ts, uint64_t rtp_ts,
|
||||||
|
uint32_t sent_packets, uint32_t sent_bytes);
|
||||||
|
void construct_report_block(uint8_t* frame, int& ptr, uint32_t ssrc, uint8_t fraction,
|
||||||
|
uint32_t dropped_packets, uint16_t seq_cycles, uint16_t max_seq, uint32_t jitter,
|
||||||
|
uint32_t lsr, uint32_t dlsr);
|
||||||
|
|
||||||
bool construct_sdes_packet(uint8_t* frame, int& ptr,
|
bool construct_sdes_packet(uint8_t* frame, int& ptr,
|
||||||
const std::vector<uvgrtp::frame::rtcp_sdes_item>& items);
|
const std::vector<uvgrtp::frame::rtcp_sdes_item>& items);
|
||||||
bool construct_app_packet(uint8_t* frame, int& ptr,
|
bool construct_app_packet(uint8_t* frame, int& ptr,
|
||||||
|
|
|
||||||
|
|
@ -153,8 +153,7 @@ void receiver_hook(uvgrtp::frame::rtcp_receiver_report* frame)
|
||||||
std::cout << "last_seq: " << block.last_seq << std::endl;
|
std::cout << "last_seq: " << block.last_seq << std::endl;
|
||||||
std::cout << "jitter: " << block.jitter << std::endl;
|
std::cout << "jitter: " << block.jitter << std::endl;
|
||||||
std::cout << "lsr: " << block.lsr << std::endl;
|
std::cout << "lsr: " << block.lsr << std::endl;
|
||||||
std::cout << "dlsr (ms): " << uvgrtp::clock::jiffies_to_ms(block.dlsr)
|
std::cout << "dlsr (jiffies): " << block.dlsr << std::endl << std::endl;
|
||||||
<< std::endl << std::endl;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* RTCP frames can be deallocated using delete */
|
/* RTCP frames can be deallocated using delete */
|
||||||
|
|
@ -178,8 +177,7 @@ void sender_hook(uvgrtp::frame::rtcp_sender_report* frame)
|
||||||
std::cout << "last_seq: " << block.last_seq << std::endl;
|
std::cout << "last_seq: " << block.last_seq << std::endl;
|
||||||
std::cout << "jitter: " << block.jitter << std::endl;
|
std::cout << "jitter: " << block.jitter << std::endl;
|
||||||
std::cout << "lsr: " << block.lsr << std::endl;
|
std::cout << "lsr: " << block.lsr << std::endl;
|
||||||
std::cout << "dlsr (ms): " << uvgrtp::clock::jiffies_to_ms(block.dlsr)
|
std::cout << "dlsr (jiffies): " << block.dlsr << std::endl << std::endl;
|
||||||
<< std::endl << std::endl;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* RTCP frames can be deallocated using delete */
|
/* RTCP frames can be deallocated using delete */
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue