stream-deploy/ZLM/3rdpart/media-server/librtp/source/rtcp-rr.c

92 lines
2.5 KiB
C++

// RFC3550 6.4.2 RR: Receiver Report RTCP Packet
#include "rtp-internal.h"
#include "rtp-util.h"
void rtcp_rr_unpack(struct rtp_context *ctx, const rtcp_header_t *header, const uint8_t* ptr, size_t bytes)
{
uint32_t i;
rtcp_rb_t *rb;
struct rtcp_msg_t msg;
struct rtp_member *receiver;
assert(24 == sizeof(rtcp_rb_t) && 4 == sizeof(rtcp_rr_t));
if (bytes < 4/*sizeof(rtcp_rr_t)*/ + header->rc * 24/*sizeof(rtcp_rb_t)*/) // RR SSRC + Report Block
{
assert(0);
return;
}
msg.ssrc = nbo_r32(ptr);
msg.type = RTCP_RR;
receiver = rtp_member_fetch(ctx, msg.ssrc);
if(!receiver) return; // error
assert(receiver != ctx->self);
assert(receiver->rtcp_sr.ssrc == msg.ssrc);
//assert(receiver->rtcp_rb.ssrc == msg.ssrc);
receiver->rtcp_clock = rtpclock(); // last received clock, for keep-alive
ptr += 4;
// report block
for(i = 0; i < header->rc; i++, ptr+=24/*sizeof(rtcp_rb_t)*/)
{
msg.u.rr.ssrc = nbo_r32(ptr);
//if(msg.u.rr.ssrcssrc != ctx->self->ssrc)
// continue; // ignore
//rb = &receiver->rtcp_rb;
rb = &msg.u.rr;
rb->fraction = ptr[4];
rb->cumulative = (((uint32_t)ptr[5])<<16) | (((uint32_t)ptr[6])<<8)| ptr[7];
rb->exthsn = nbo_r32(ptr+8);
rb->jitter = nbo_r32(ptr+12);
rb->lsr = nbo_r32(ptr+16);
rb->dlsr = nbo_r32(ptr+20);
ctx->handler.on_rtcp(ctx->cbparam, &msg);
}
}
int rtcp_rr_pack(struct rtp_context *ctx, uint8_t* ptr, int bytes)
{
// RFC3550 6.1 RTCP Packet Format
// An individual RTP participant should send only one compound RTCP packet per report interval
// in order for the RTCP bandwidth per participant to be estimated correctly (see Section 6.2),
// except when the compound RTCP packet is split for partial encryption as described in Section 9.1.
uint32_t i;
rtcp_header_t header;
assert(4 == sizeof(rtcp_rr_t));
assert(24 == sizeof(rtcp_rb_t));
assert(rtp_member_list_count(ctx->senders) < 32);
header.v = 2;
header.p = 0;
header.pt = RTCP_RR;
header.rc = MIN(31, rtp_member_list_count(ctx->senders));
header.length = (4/*sizeof(rtcp_rr_t)*/ + header.rc*24/*sizeof(rtcp_rb_t)*/) / 4;
if((uint32_t)bytes < 4 + header.length * 4)
return 4 + header.length * 4;
nbo_write_rtcp_header(ptr, &header);
// receiver SSRC
nbo_w32(ptr+4, ctx->self->ssrc);
ptr += 8;
// report block
for(i = 0; i < header.rc; i++)
{
struct rtp_member *sender;
sender = rtp_member_list_get(ctx->senders, i);
if(0 == sender->rtp_packets || sender->ssrc == ctx->self->ssrc)
continue; // don't receive any packet
ptr += rtcp_report_block(sender, ptr, 24);
}
return (header.length+1) * 4;
}