Files
media-server/librtp/source/rtcp-sr.c

173 lines
5.0 KiB
C

// RFC3550 6.4.1 SR: Sender Report RTCP Packet
#include "rtp-internal.h"
#include "rtp-util.h"
void rtcp_sr_unpack(struct rtp_context *ctx, const rtcp_header_t *header, const uint8_t* ptr, size_t bytes)
{
uint32_t i;
rtcp_sr_t *sr;
rtcp_rb_t *rb;
struct rtcp_msg_t msg;
struct rtp_member *sender;
assert(24 == sizeof(rtcp_sr_t));
assert(24 == sizeof(rtcp_rb_t));
if (bytes < 24/*sizeof(rtcp_sr_t)*/ + header->rc * 24/*sizeof(rtcp_rb_t)*/)
{
assert(0);
return;
}
msg.ssrc = nbo_r32(ptr);
msg.type = RTCP_RR;
sender = rtp_sender_fetch(ctx, msg.ssrc);
if(!sender) return; // error
assert(sender != ctx->self);
assert(sender->rtcp_sr.ssrc == msg.ssrc);
//assert(sender->rtcp_rb.ssrc == msg.ssrc);
sender->rtcp_clock = rtpclock();
// update sender information
sr = &sender->rtcp_sr;
sr->ntpmsw = nbo_r32(ptr + 4);
sr->ntplsw = nbo_r32(ptr + 8);
sr->rtpts = nbo_r32(ptr + 12);
sr->spc = nbo_r32(ptr + 16);
sr->soc = nbo_r32(ptr + 20);
ptr += 24;
// report block
for(i = 0; i < header->rc; i++, ptr+=24/*sizeof(rtcp_rb_t)*/)
{
msg.u.sr.ssrc = nbo_r32(ptr);
//if(msg.u.rr.ssrc != ctx->self->ssrc)
// continue; // ignore
//rb = &sender->rtcp_rb;
rb = &msg.u.sr;
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_sr_pack(struct rtp_context *ctx, uint8_t* ptr, int bytes)
{
uint32_t i, timestamp;
uint64_t ntp;
rtcp_header_t header;
assert(24 == sizeof(rtcp_sr_t));
assert(24 == sizeof(rtcp_rb_t));
assert(rtp_member_list_count(ctx->senders) < 32);
header.v = 2;
header.p = 0;
header.pt = RTCP_SR;
header.rc = MIN(31, rtp_member_list_count(ctx->senders));
header.length = (24/*sizeof(rtcp_sr_t)*/ + header.rc*24/*sizeof(rtcp_rb_t)*/)/4; // see 6.4.1 SR: Sender Report RTCP Packet
if((uint32_t)bytes < (header.length+1) * 4)
return (header.length+1) * 4;
nbo_write_rtcp_header(ptr, &header);
// RFC3550 6.4.1 SR: Sender Report RTCP Packet (p32)
// Note that in most cases this timestamp will not be equal to the RTP
// timestamp in any adjacent data packet. Rather, it must be calculated from the corresponding
// NTP timestamp using the relationship between the RTP timestamp counter and real time as
// maintained by periodically checking the wallclock time at a sampling instant.
ntp = rtpclock();
if (0 == ctx->self->rtp_packets)
ctx->self->rtp_clock = ntp;
timestamp = (uint32_t)((ntp - ctx->self->rtp_clock) * ctx->frequence / 1000000) + ctx->self->rtp_timestamp;
ntp = clock2ntp(ntp);
nbo_w32(ptr+4, ctx->self->ssrc);
nbo_w32(ptr+8, (uint32_t)(ntp >> 32));
nbo_w32(ptr+12, (uint32_t)(ntp & 0xFFFFFFFF));
nbo_w32(ptr+16, timestamp);
nbo_w32(ptr+20, ctx->self->rtp_packets); // send packets
nbo_w32(ptr+24, (uint32_t)ctx->self->rtp_bytes); // send bytes
ptr += 28;
// 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;
}
int rtcp_report_block(struct rtp_member* sender, uint8_t* ptr, int bytes)
{
uint64_t delay;
int lost_interval;
int lost;
uint32_t fraction;
uint32_t expected, extseq;
uint32_t expected_interval;
uint32_t received_interval;
uint32_t lsr, dlsr;
if (bytes < 24)
return 0;
extseq = sender->rtp_seq_cycles + sender->rtp_seq; // 32-bits sequence number
assert(extseq >= sender->rtp_seq_base);
expected = extseq - sender->rtp_seq_base + 1;
expected_interval = expected - sender->rtp_expected0;
received_interval = sender->rtp_packets - sender->rtp_packets0;
lost_interval = (int)(expected_interval - received_interval);
if (lost_interval < 0 || 0 == expected_interval)
fraction = 0;
else
fraction = (lost_interval << 8) / expected_interval;
lost = expected - sender->rtp_packets;
if (lost > 0x007FFFFF)
{
lost = 0x007FFFFF;
}
else if (lost < 0)
{
// 'Clamp' this loss number to a 24-bit signed value:
// live555 RTCP.cpp RTCPInstance::enqueueReportBlock line:799
lost = 0;
}
delay = rtpclock() - sender->rtcp_clock; // now - Last SR time
lsr = ((sender->rtcp_sr.ntpmsw & 0xFFFF) << 16) | ((sender->rtcp_sr.ntplsw >> 16) & 0xFFFF);
// in units of 1/65536 seconds
// 65536/1000000 == 1024/15625
dlsr = (uint32_t)(delay / 1000000.0f * 65536);
nbo_w32(ptr, sender->ssrc);
ptr[4] = (unsigned char)fraction;
ptr[5] = (unsigned char)((lost >> 16) & 0xFF);
ptr[6] = (unsigned char)((lost >> 8) & 0xFF);
ptr[7] = (unsigned char)(lost & 0xFF);
nbo_w32(ptr + 8, extseq);
nbo_w32(ptr + 12, (uint32_t)sender->jitter);
nbo_w32(ptr + 16, lsr);
nbo_w32(ptr + 20, 0 == lsr ? 0 : dlsr);
sender->rtp_expected0 = expected; // update source prior data
sender->rtp_packets0 = sender->rtp_packets;
return 24; /*sizeof(rtcp_rb_t)*/
}