FreeCalypso > hg > themwi-rtp-lib
view src/rtcp_tx.c @ 42:334d883b96ba
twrtp_jibuf_create: make config argument const
While this config structure is not a constant in the mathematical
sense of the term (it is expected that vty config changes may happen
while twjit instance is alive), twjit functions never write to it,
only read, hence it is 'const' in the not-quite-mathematical C-standard
sense.
author | Mychaela Falconia <falcon@freecalypso.org> |
---|---|
date | Fri, 20 Dec 2024 22:47:20 +0000 |
parents | fc77c3482084 |
children |
line wrap: on
line source
/* * Here we implement RTCP Tx functionality. */ #include <stdint.h> #include <stdbool.h> #include <string.h> #include <errno.h> #include <arpa/inet.h> /* for network byte order functions */ #include <osmocom/core/msgb.h> #include <osmocom/core/osmo_io.h> #include <osmocom/core/timer.h> #include <themwi/rtp/endp.h> #include <themwi/rtp/rtcp_defs.h> #include <themwi/rtp/twjit.h> #include "endp_internal.h" #define NTP_EPOCH_MJD 15020 #define UNIX_EPOCH_MJD 40587 #define NTP_UNIX_EPOCH_DIFF ((UNIX_EPOCH_MJD-NTP_EPOCH_MJD) * 86400UL) #define TWO_TO_32_DOUBLE 4294967296.0 static void fill_rr_block(struct twrtp_endp *endp, struct rtcp_rr_block *rr) { struct twrtp_jibuf_inst *twjit = endp->twjit; struct twrtp_jibuf_rr_info *rri = &twjit->rr_info; struct twrtp_endp_rtcp_rx *rxs = &endp->rtcp_rx; struct twrtp_endp_rtcp_tx *txs = &endp->rtcp_tx; uint32_t delta_expect, delta_rcvd; int32_t cumulative_lost, newly_lost; uint32_t lost_fract, lost_word; struct timespec now, time_delta; cumulative_lost = (int32_t)(rri->expected_pkt - rri->rx_packets); if (cumulative_lost > 0x7FFFFF) cumulative_lost = 0x7FFFFF; else if (cumulative_lost < -0x800000) cumulative_lost = -0x800000; delta_expect = rri->expected_pkt - txs->last_expected; txs->last_expected = rri->expected_pkt; delta_rcvd = rri->rx_packets - txs->last_received; txs->last_received = rri->rx_packets; newly_lost = (int32_t)(delta_expect - delta_rcvd); if (delta_expect == 0 || newly_lost <= 0) lost_fract = 0; else lost_fract = (newly_lost << 8) / delta_expect; lost_word = (lost_fract << 8) | (cumulative_lost & 0xFFFFFF); rr->ssrc = htonl(twjit->last_ssrc); rr->lost_word = htonl(lost_word); rr->max_seq_ext = htonl(rri->max_seq_ext); rr->jitter = htonl(rri->jitter_accum >> 4); if (rxs->got_sr && rxs->sr_ssrc == twjit->last_ssrc) { osmo_clock_gettime(CLOCK_MONOTONIC, &now); time_delta.tv_sec = now.tv_sec - rxs->sr_rx_time.tv_sec; time_delta.tv_nsec = now.tv_nsec - rxs->sr_rx_time.tv_nsec; if (time_delta.tv_nsec < 0) { time_delta.tv_sec--; time_delta.tv_nsec += 1000000000; } rr->lsr_sec = htons(rxs->sr_ntp_sec); rr->lsr_fract = htons(rxs->sr_ntp_fract); rr->dlsr_sec = htons(time_delta.tv_sec); rr->dlsr_fract = htons(time_delta.tv_nsec / 1000000000.0f * 65536.0f); } else { rr->lsr_sec = 0; rr->lsr_fract = 0; rr->dlsr_sec = 0; rr->dlsr_fract = 0; } } int _twrtp_endp_send_rtcp(struct twrtp_endp *endp, bool send_sr, const struct timespec *utc, uint32_t rtp_ts) { bool send_rr = endp->twjit->got_first_packet; struct msgb *msg; struct rtcp_sr_rr_hdr *hdr; struct rtcp_sr_block *sr; struct rtcp_rr_block *rr; uint8_t *sdes_out; int rc; if (!endp->register_done || !endp->remote_set || !endp->sdes_buf) return -EINVAL; if (!send_sr && !send_rr) return -ENODATA; /* nothing to send, neither SR nor RR */ msg = msgb_alloc_c(endp, sizeof(struct rtcp_sr_rr_hdr) + sizeof(struct rtcp_sr_block) + sizeof(struct rtcp_rr_block) + endp->sdes_len, "ThemWi-RTCP-Tx"); if (!msg) return -ENOMEM; hdr = (struct rtcp_sr_rr_hdr *) msgb_put(msg, sizeof(struct rtcp_sr_rr_hdr)); hdr->v_p_rc = send_rr ? 0x81 : 0x80; if (send_sr) { hdr->pt = RTCP_PT_SR; hdr->len = htons(send_rr ? 12 : 6); } else { hdr->pt = RTCP_PT_RR; hdr->len = htons(7); } hdr->ssrc = htonl(endp->tx.ssrc); if (send_sr) { sr = (struct rtcp_sr_block *) msgb_put(msg, sizeof(struct rtcp_sr_block)); sr->ntp_sec = htonl(utc->tv_sec + NTP_UNIX_EPOCH_DIFF); sr->ntp_fract = htonl(utc->tv_nsec / 1000000000.0 * TWO_TO_32_DOUBLE); sr->rtp_ts = htonl(rtp_ts); sr->pkt_count = htonl(endp->stats.tx_rtp_pkt); sr->octet_count = htonl(endp->stats.tx_rtp_bytes); } if (send_rr) { rr = (struct rtcp_rr_block *) msgb_put(msg, sizeof(struct rtcp_rr_block)); fill_rr_block(endp, rr); } sdes_out = msgb_put(msg, endp->sdes_len); memcpy(sdes_out, endp->sdes_buf, endp->sdes_len); rc = osmo_iofd_sendto_msgb(endp->iofd_rtcp, msg, 0, &endp->rtcp_remote); if (rc < 0) { msgb_free(msg); return rc; } endp->stats.tx_rtcp_pkt++; return 0; } int twrtp_endp_send_rtcp_rr(struct twrtp_endp *endp) { return _twrtp_endp_send_rtcp(endp, false, NULL, 0); }