// 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)*/ }