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 << "jitter: " << block.jitter << 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;
|
||||
}
|
||||
|
||||
|
@ -147,7 +147,7 @@ void sender_hook(uvgrtp::frame::rtcp_sender_report *frame)
|
|||
std::cout << "last_seq: " << block.last_seq << std::endl;
|
||||
std::cout << "jitter: " << block.jitter << 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;
|
||||
}
|
||||
|
||||
|
|
|
@ -39,7 +39,7 @@ namespace uvgrtp {
|
|||
uint32_t received_bytes = 0; /* Number of bytes received excluding RTP Header */
|
||||
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: */
|
||||
|
||||
|
||||
|
@ -54,7 +54,7 @@ namespace uvgrtp {
|
|||
uint16_t max_seq = 0; /* Highest sequence number received */
|
||||
uint32_t base_seq = 0; /* First sequence number received */
|
||||
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 {
|
||||
|
|
|
@ -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)
|
||||
{
|
||||
return (uint64_t)(((double)ms / 1000) * 65536);
|
||||
return (uint64_t)(((double)ms/1000)* 65536);
|
||||
}
|
||||
|
||||
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)
|
||||
{
|
||||
/* Sequence number wrapped - count another 64K cycle. */
|
||||
p->stats.cycles += RTP_SEQ_MOD;
|
||||
p->stats.cycles += 1;
|
||||
}
|
||||
p->stats.max_seq = seq;
|
||||
} 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);
|
||||
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)
|
||||
{
|
||||
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 rtp_ts = rtp_ts_start_ + (uvgrtp::clock::ntp::diff(clock_start_, ntp_ts))
|
||||
* float(clock_rate_ / 1000);
|
||||
|
||||
SET_NEXT_FIELD_32(frame, ptr, htonl(ntp_ts >> 32));
|
||||
SET_NEXT_FIELD_32(frame, ptr, htonl(ntp_ts & 0xffffffff));
|
||||
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));
|
||||
construct_sender_info(frame, ptr, ntp_ts, rtp_ts,
|
||||
our_stats.sent_pkts, our_stats.sent_bytes);
|
||||
|
||||
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
|
||||
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)
|
||||
// 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 */
|
||||
SET_NEXT_FIELD_32(frame, ptr, htonl((frac << 24) | p.second->stats.dropped_pkts));
|
||||
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));
|
||||
uint64_t diff = (u_long)uvgrtp::clock::hrc::diff_now(p.second->stats.sr_ts);
|
||||
uint32_t dlrs = uvgrtp::clock::ms_to_jiffies(diff);
|
||||
|
||||
/* 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);
|
||||
SET_NEXT_FIELD_32(frame, ptr, (uint32_t)htonl((u_long)uvgrtp::clock::ms_to_jiffies(diff)));
|
||||
dlrs = 0;
|
||||
}
|
||||
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
|
||||
p.second->stats.received_rtp_packet = false;
|
||||
|
|
|
@ -5,35 +5,6 @@
|
|||
#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)
|
||||
{
|
||||
/* 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;
|
||||
}
|
||||
|
||||
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,
|
||||
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 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_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_app_packet_size(size_t payload_len);
|
||||
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,
|
||||
const std::vector<uvgrtp::frame::rtcp_sdes_item>& items);
|
||||
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 << "jitter: " << block.jitter << std::endl;
|
||||
std::cout << "lsr: " << block.lsr << std::endl;
|
||||
std::cout << "dlsr (ms): " << uvgrtp::clock::jiffies_to_ms(block.dlsr)
|
||||
<< std::endl << std::endl;
|
||||
std::cout << "dlsr (jiffies): " << block.dlsr << std::endl << std::endl;
|
||||
}
|
||||
|
||||
/* 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 << "jitter: " << block.jitter << std::endl;
|
||||
std::cout << "lsr: " << block.lsr << std::endl;
|
||||
std::cout << "dlsr (ms): " << uvgrtp::clock::jiffies_to_ms(block.dlsr)
|
||||
<< std::endl << std::endl;
|
||||
std::cout << "dlsr (jiffies): " << block.dlsr << std::endl << std::endl;
|
||||
}
|
||||
|
||||
/* RTCP frames can be deallocated using delete */
|
||||
|
|
Loading…
Reference in New Issue