92 lines
2.5 KiB
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;
|
|
}
|