FreeCalypso > hg > themwi-rtp-lib
comparison src/rtcp_tx.c @ 32:aa97e77e7de6
implement RTCP Tx
author | Mychaela Falconia <falcon@freecalypso.org> |
---|---|
date | Mon, 08 Jul 2024 07:17:38 +0000 |
parents | |
children | fc77c3482084 |
comparison
equal
deleted
inserted
replaced
31:284fcb5868e2 | 32:aa97e77e7de6 |
---|---|
1 /* | |
2 * Here we implement RTCP Tx functionality. | |
3 */ | |
4 | |
5 #include <stdint.h> | |
6 #include <stdbool.h> | |
7 #include <string.h> | |
8 #include <errno.h> | |
9 #include <arpa/inet.h> /* for network byte order functions */ | |
10 | |
11 #include <osmocom/core/msgb.h> | |
12 #include <osmocom/core/osmo_io.h> | |
13 #include <osmocom/core/timer.h> | |
14 | |
15 #include <themwi/rtp/endp.h> | |
16 #include <themwi/rtp/rtcp_defs.h> | |
17 #include <themwi/rtp/twjit.h> | |
18 #include "endp_internal.h" | |
19 | |
20 #define NTP_EPOCH_MJD 15020 | |
21 #define UNIX_EPOCH_MJD 40587 | |
22 | |
23 #define NTP_UNIX_EPOCH_DIFF ((UNIX_EPOCH_MJD-NTP_EPOCH_MJD) * 86400UL) | |
24 #define TWO_TO_32_DOUBLE 4294967296.0 | |
25 | |
26 static void fill_rr_block(struct twrtp_endp *endp, struct rtcp_rr_block *rr) | |
27 { | |
28 struct twrtp_jibuf_inst *twjit = endp->twjit; | |
29 struct twrtp_jibuf_rr_info *rri = &twjit->rr_info; | |
30 struct twrtp_endp_rtcp_rx *rxs = &endp->rtcp_rx; | |
31 struct twrtp_endp_rtcp_tx *txs = &endp->rtcp_tx; | |
32 uint32_t delta_expect, delta_rcvd; | |
33 int32_t cumulative_lost, newly_lost; | |
34 uint32_t lost_fract, lost_word; | |
35 struct timespec now, time_delta; | |
36 | |
37 cumulative_lost = (int32_t)(rri->expected_pkt - rri->rx_packets); | |
38 if (cumulative_lost > 0x7FFFFF) | |
39 cumulative_lost = 0x7FFFFF; | |
40 else if (cumulative_lost < -0x800000) | |
41 cumulative_lost = -0x800000; | |
42 delta_expect = rri->expected_pkt - txs->last_expected; | |
43 txs->last_expected = rri->expected_pkt; | |
44 delta_rcvd = rri->rx_packets - txs->last_received; | |
45 txs->last_received = rri->rx_packets; | |
46 newly_lost = (int32_t)(delta_expect - delta_rcvd); | |
47 if (delta_expect == 0 || newly_lost <= 0) | |
48 lost_fract = 0; | |
49 else | |
50 lost_fract = (newly_lost << 8) / delta_expect; | |
51 lost_word = (lost_fract << 8) | (cumulative_lost & 0xFFFFFF); | |
52 | |
53 rr->ssrc = htonl(twjit->last_ssrc); | |
54 rr->lost_word = htonl(lost_word); | |
55 rr->max_seq_ext = htonl(rri->max_seq_ext); | |
56 rr->jitter = htonl(rri->jitter_accum >> 4); | |
57 | |
58 if (rxs->got_sr && rxs->sr_ssrc == twjit->last_ssrc) { | |
59 osmo_clock_gettime(CLOCK_MONOTONIC, &now); | |
60 time_delta.tv_sec = now.tv_sec - rxs->sr_rx_time.tv_sec; | |
61 time_delta.tv_nsec = now.tv_nsec - rxs->sr_rx_time.tv_nsec; | |
62 if (time_delta.tv_nsec < 0) { | |
63 time_delta.tv_sec--; | |
64 time_delta.tv_nsec += 1000000000; | |
65 } | |
66 rr->lsr_sec = htons(rxs->sr_ntp_sec); | |
67 rr->lsr_fract = htons(rxs->sr_ntp_fract); | |
68 rr->dlsr_sec = htons(time_delta.tv_sec); | |
69 rr->dlsr_fract = htons(time_delta.tv_nsec / 1000000000.0f * | |
70 65536.0f); | |
71 } else { | |
72 rr->lsr_sec = 0; | |
73 rr->lsr_fract = 0; | |
74 rr->dlsr_sec = 0; | |
75 rr->dlsr_fract = 0; | |
76 } | |
77 } | |
78 | |
79 int _twrtp_endp_send_rtcp(struct twrtp_endp *endp, bool send_sr, | |
80 const struct timespec *utc, uint32_t rtp_ts) | |
81 { | |
82 bool send_rr = endp->twjit->got_first_packet; | |
83 struct msgb *msg; | |
84 struct rtcp_sr_rr_hdr *hdr; | |
85 struct rtcp_sr_block *sr; | |
86 struct rtcp_rr_block *rr; | |
87 uint8_t *sdes_out; | |
88 int rc; | |
89 | |
90 if (!endp->register_done || !endp->remote_set || !endp->sdes_buf) | |
91 return -EINVAL; | |
92 if (!send_sr && !send_rr) | |
93 return -ENODATA; /* nothing to send, neither SR nor RR */ | |
94 msg = msgb_alloc_c(endp, sizeof(struct rtcp_sr_rr_hdr) + | |
95 sizeof(struct rtcp_sr_block) + | |
96 sizeof(struct rtcp_rr_block) + endp->sdes_len, | |
97 "ThemWi-RTCP-Tx"); | |
98 if (!msg) | |
99 return -ENOMEM; | |
100 | |
101 hdr = (struct rtcp_sr_rr_hdr *) | |
102 msgb_put(msg, sizeof(struct rtcp_sr_rr_hdr)); | |
103 hdr->v_p_rc = send_rr ? 0x81 : 0x80; | |
104 if (send_sr) { | |
105 hdr->pt = RTCP_PT_SR; | |
106 hdr->len = htons(send_rr ? 12 : 6); | |
107 } else { | |
108 hdr->pt = RTCP_PT_RR; | |
109 hdr->len = htons(7); | |
110 } | |
111 hdr->ssrc = htonl(endp->tx.ssrc); | |
112 if (send_sr) { | |
113 sr = (struct rtcp_sr_block *) | |
114 msgb_put(msg, sizeof(struct rtcp_sr_block)); | |
115 sr->ntp_sec = htonl(utc->tv_sec + NTP_UNIX_EPOCH_DIFF); | |
116 sr->ntp_fract = htonl(utc->tv_nsec / 1000000000.0 * | |
117 TWO_TO_32_DOUBLE); | |
118 sr->rtp_ts = htonl(rtp_ts); | |
119 sr->pkt_count = htonl(endp->stats.tx_rtp_pkt); | |
120 sr->octet_count = htonl(endp->stats.tx_rtp_bytes); | |
121 } | |
122 if (send_rr) { | |
123 rr = (struct rtcp_rr_block *) | |
124 msgb_put(msg, sizeof(struct rtcp_rr_block)); | |
125 fill_rr_block(endp, rr); | |
126 } | |
127 sdes_out = msgb_put(msg, endp->sdes_len); | |
128 memcpy(sdes_out, endp->sdes_buf, endp->sdes_len); | |
129 | |
130 rc = osmo_iofd_sendto_msgb(endp->iofd_rtcp, msg, 0, &endp->rtcp_remote); | |
131 if (rc < 0) { | |
132 msgb_free(msg); | |
133 return rc; | |
134 } | |
135 endp->stats.tx_rtcp_pkt++; | |
136 return 0; | |
137 } |