// 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; }