Fix RTCP Receiver Report reception code

Craft user-friendly rtcp_receiver_report struct from the raw
message which can be fetched using SSRC
This commit is contained in:
Aaro Altonen 2020-08-26 11:02:15 +03:00
parent ea8f1d2039
commit fc117e6eba
3 changed files with 44 additions and 40 deletions

View File

@ -9,6 +9,7 @@
#endif
#include <string>
#include <vector>
#include "util.hh"
@ -115,6 +116,12 @@ namespace uvg_rtp {
struct rtcp_report_block blocks[1];
};
struct rtcp_receiver_report {
struct rtcp_header header;
uint32_t ssrc;
std::vector<rtcp_report_block> report_blocks;
};
PACKED_STRUCT(rtcp_receiver_frame) {
struct rtcp_header header;
uint32_t sender_ssrc;

View File

@ -64,10 +64,10 @@ namespace uvg_rtp {
/* Save the latest RTCP packets received from this participant
* Users can query these packets using the SSRC of participant */
uvg_rtp::frame::rtcp_sender_frame *s_frame;
uvg_rtp::frame::rtcp_receiver_frame *r_frame;
uvg_rtp::frame::rtcp_sdes_frame *sdes_frame;
uvg_rtp::frame::rtcp_app_frame *app_frame;
uvg_rtp::frame::rtcp_sender_frame *s_frame;
uvg_rtp::frame::rtcp_receiver_report *r_frame;
uvg_rtp::frame::rtcp_sdes_frame *sdes_frame;
uvg_rtp::frame::rtcp_app_frame *app_frame;
};
class rtcp : public runner {
@ -127,10 +127,10 @@ namespace uvg_rtp {
* Return nullptr if we haven't received this kind of packet or if "ssrc" doesn't exist
*
* NOTE: Caller is responsible for deallocating the memory */
uvg_rtp::frame::rtcp_sender_frame *get_sender_packet(uint32_t ssrc);
uvg_rtp::frame::rtcp_receiver_frame *get_receiver_packet(uint32_t ssrc);
uvg_rtp::frame::rtcp_sdes_frame *get_sdes_packet(uint32_t ssrc);
uvg_rtp::frame::rtcp_app_frame *get_app_packet(uint32_t ssrc);
uvg_rtp::frame::rtcp_sender_frame *get_sender_packet(uint32_t ssrc);
uvg_rtp::frame::rtcp_receiver_report *get_receiver_packet(uint32_t ssrc);
uvg_rtp::frame::rtcp_sdes_frame *get_sdes_packet(uint32_t ssrc);
uvg_rtp::frame::rtcp_app_frame *get_app_packet(uint32_t ssrc);
/* create RTCP BYE packet using our own SSRC and send it to all participants */
rtp_error_t terminate_self();
@ -189,7 +189,7 @@ namespace uvg_rtp {
* polling an RTCP packet, user can install a function that is called when
* a specific RTCP packet is received. */
rtp_error_t install_sender_hook(void (*hook)(uvg_rtp::frame::rtcp_sender_frame *));
rtp_error_t install_receiver_hook(void (*hook)(uvg_rtp::frame::rtcp_receiver_frame *));
rtp_error_t install_receiver_hook(void (*hook)(uvg_rtp::frame::rtcp_receiver_report *));
rtp_error_t install_sdes_hook(void (*hook)(uvg_rtp::frame::rtcp_sdes_frame *));
rtp_error_t install_app_hook(void (*hook)(uvg_rtp::frame::rtcp_app_frame *));
@ -324,7 +324,7 @@ namespace uvg_rtp {
std::vector<uvg_rtp::socket> sockets_;
void (*sender_hook_)(uvg_rtp::frame::rtcp_sender_frame *);
void (*receiver_hook_)(uvg_rtp::frame::rtcp_receiver_frame *);
void (*receiver_hook_)(uvg_rtp::frame::rtcp_receiver_report *);
void (*sdes_hook_)(uvg_rtp::frame::rtcp_sdes_frame *);
void (*app_hook_)(uvg_rtp::frame::rtcp_app_frame *);
};

View File

@ -6,7 +6,7 @@
#define SET_NEXT_FIELD_32(a, p, v) do { *(uint32_t *)&(a)[p] = (v); ptr += 4; } while (0)
uvg_rtp::frame::rtcp_receiver_frame *uvg_rtp::rtcp::get_receiver_packet(uint32_t ssrc)
uvg_rtp::frame::rtcp_receiver_report *uvg_rtp::rtcp::get_receiver_packet(uint32_t ssrc)
{
if (participants_.find(ssrc) == participants_.end())
return nullptr;
@ -17,7 +17,7 @@ uvg_rtp::frame::rtcp_receiver_frame *uvg_rtp::rtcp::get_receiver_packet(uint32_t
return frame;
}
rtp_error_t uvg_rtp::rtcp::install_receiver_hook(void (*hook)(uvg_rtp::frame::rtcp_receiver_frame *))
rtp_error_t uvg_rtp::rtcp::install_receiver_hook(void (*hook)(uvg_rtp::frame::rtcp_receiver_report *))
{
if (!hook)
return RTP_INVALID_VALUE;
@ -31,53 +31,50 @@ rtp_error_t uvg_rtp::rtcp::handle_receiver_report_packet(uint8_t *packet, size_t
if (!packet || !size)
return RTP_INVALID_VALUE;
frame->header.length = ntohs(frame->header.length);
frame->sender_ssrc = ntohl(frame->sender_ssrc);
auto frame = new uvg_rtp::frame::rtcp_receiver_report;
frame->header.version = (packet[0] >> 6) & 0x3f;
frame->header.padding = (packet[0] >> 5) & 0x1;
frame->header.count = packet[0] & 0x1f;
frame->header.length = ntohs(*(uint16_t *)&packet[2]);
frame->ssrc = ntohl(*(uint32_t *)&packet[4]);
/* Receiver Reports are sent from participant that don't send RTP packets
* This means that the sender of this report is not in the participants_ map
* but rather in the initial_participants_ vector
*
* Check if that's the case and if so, move the entry from initial_participants_ to participants_ */
if (!is_participant(frame->sender_ssrc)) {
/* TODO: this is not correct way to do it! fix before multicast */
add_participant(frame->sender_ssrc);
if (!is_participant(frame->ssrc)) {
LOG_WARN("Got a Receiver Report from an unknown participant");
add_participant(frame->ssrc);
}
if (frame->header.count == 0) {
if (!frame->header.count) {
LOG_ERROR("Receiver Report cannot have 0 report blocks!");
return RTP_INVALID_VALUE;
}
/* We need to make a copy of the frame because right now frame points to RTCP recv buffer
* Deallocate previous frame if it exists */
if (participants_[frame->sender_ssrc]->r_frame != nullptr)
(void)uvg_rtp::frame::dealloc_frame(participants_[frame->sender_ssrc]->r_frame);
/* Deallocate previous frame from the buffer if it exists, it's going to get overwritten */
if (participants_[frame->ssrc]->r_frame)
delete participants_[frame->ssrc]->r_frame;
auto cpy_frame = uvg_rtp::frame::alloc_rtcp_receiver_frame(frame->header.count);
memcpy(cpy_frame, frame, size);
fprintf(stderr, "Receiver report:\n");
for (int i = 0; i < frame->header.count; ++i) {
cpy_frame->blocks[i].lost = ntohl(frame->blocks[i].lost);
cpy_frame->blocks[i].last_seq = ntohl(frame->blocks[i].last_seq);
cpy_frame->blocks[i].jitter = ntohl(frame->blocks[i].jitter);
cpy_frame->blocks[i].lsr = ntohl(frame->blocks[i].lsr);
cpy_frame->blocks[i].dlsr = ntohl(frame->blocks[i].dlsr);
uvg_rtp::frame::rtcp_report_block report;
fprintf(stderr, "-------\n");
fprintf(stderr, "lost: %d\n", cpy_frame->blocks[i].lost);
fprintf(stderr, "last_seq: %u\n", cpy_frame->blocks[i].last_seq);
fprintf(stderr, "jitter: %u\n", cpy_frame->blocks[i].jitter);
fprintf(stderr, "last sr: %u\n", cpy_frame->blocks[i].lsr);
fprintf(stderr, "dlsr: %u\n", cpy_frame->blocks[i].dlsr);
fprintf(stderr, "-------\n");
report.ssrc = ntohl(*(uint32_t *)&packet[(i * 24) + 8 + 0]);
report.lost = ntohl(*(uint32_t *)&packet[(i * 24) + 8 + 4]);
report.last_seq = ntohl(*(uint32_t *)&packet[(i * 24) + 8 + 8]);
report.jitter = ntohl(*(uint32_t *)&packet[(i * 24) + 8 + 12]);
report.lsr = ntohl(*(uint32_t *)&packet[(i * 24) + 8 + 16]);
report.dlsr = ntohl(*(uint32_t *)&packet[(i * 24) + 8 + 20]);
frame->report_blocks.push_back(report);
}
if (receiver_hook_)
receiver_hook_(cpy_frame);
receiver_hook_(frame);
else
participants_[frame->sender_ssrc]->r_frame = cpy_frame;
participants_[frame->ssrc]->r_frame = frame;
return RTP_OK;
}