1 /*****************************************************************************
2  * rist.h: RIST (Reliable Internet Stream Transport) helper
3  *****************************************************************************
4  * Copyright (C) 2018, DVEO, the Broadcast Division of Computer Modules, Inc.
5  * Copyright (C) 2018, SipRadius LLC
6  *
7  * Authors: Sergio Ammirata <sergio@ammirata.net>
8  *          Daniele Lacamera <root@danielinux.net>
9  *
10  * This program is free software; you can redistribute it and/or modify it
11  * under the terms of the GNU Lesser General Public License as published by
12  * the Free Software Foundation; either version 2.1 of the License, or
13  * (at your option) any later version.
14  *
15  * This program is distributed in the hope that it will be useful,
16  * but WITHOUT ANY WARRANTY; without even the implied warranty of
17  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18  * GNU Lesser General Public License for more details.
19  *
20  * You should have received a copy of the GNU Lesser General Public License
21  * along with this program; if not, write to the Free Software Foundation,
22  * Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
23  *****************************************************************************/
24 
25 #include <stdint.h>
26 #ifdef HAVE_ARPA_INET_H
27 #include <arpa/inet.h>
28 #endif
29 #include <errno.h>
30 #include <assert.h>
31 
32 /*****************************************************************************
33  * Public API
34  *****************************************************************************/
35 
36 /* RIST */
37 
38 /* RTP header format (RFC 3550) */
39 /*
40    0                   1                   2                   3
41    0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
42    +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
43    |V=2|P|X|  CC   |M|     PT      |       sequence number         |
44    +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
45    |                           timestamp                           |
46    +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
47    |           synchronization source (SSRC) identifier            |
48    +=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+
49    |            contributing source (CSRC) identifiers             |
50    |                             ....                              |
51    +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
52 */
53 
54 #define RIST_QUEUE_SIZE 65536
55 #define RTP_PKT_SIZE (1472)
56 
57 #define RTCP_INTERVAL 75 /*ms*/
58 
59 #define SEVENTY_YEARS_OFFSET (2208988800ULL)
60 #define MAX_NACKS 32
61 #define MAX_CNAME 128
62 #define RTCP_EMPTY_RR_SIZE 8
63 
64 #define RTCP_PT_RTPFR             204
65 
66 #define RIST_TICK_FROM_MS(ms) ((CLOCK_FREQ / INT64_C(1000)) * (ms))
67 
68 struct rtp_pkt {
69     uint32_t rtp_ts;
70     struct block_t *buffer;
71 };
72 
73 /* RIST NACK header format  */
74 /*
75    0                   1                   2                   3
76    0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
77    +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
78    |       SNBase low bits         |        Length recovery        |
79    +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
80    |E| PT recovery |                    Mask                       |
81    +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
82    |                          TS recovery                          |
83    +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
84    |N|D|type |index|    Offset     |      NA       |SNBase ext bits|
85    +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
86 */
87 
88 struct rist_flow {
89     uint8_t reset;
90     struct rtp_pkt *buffer;
91     uint32_t qsize;
92     uint32_t last_out;
93     uint32_t ssrc;
94     char cname[MAX_CNAME];
95     struct sockaddr_storage peer_sockaddr;
96     socklen_t peer_socklen;
97     uint16_t ri, wi;
98     int fd_in;
99     int fd_out;
100     int fd_rtcp;
101     int fd_rtcp_m;
102     int fd_nack;
103     uint8_t nacks_retries[RIST_QUEUE_SIZE];
104     uint32_t hi_timestamp;
105     uint64_t feedback_time;
106     uint32_t latency;
107     uint32_t rtp_latency;
108     uint32_t retry_interval;
109     uint32_t reorder_buffer;
110     uint8_t max_retries;
111     uint32_t packets_count;
112     uint32_t bytes_count;
113 };
114 
rtcp_fb_nack_get_range_start(const uint8_t * p_rtcp_fb_nack)115 static inline uint16_t rtcp_fb_nack_get_range_start(const uint8_t *p_rtcp_fb_nack)
116 {
117     return (p_rtcp_fb_nack[0] << 8) | p_rtcp_fb_nack[1];
118 }
119 
rtcp_fb_nack_get_range_extra(const uint8_t * p_rtcp_fb_nack)120 static inline uint16_t rtcp_fb_nack_get_range_extra(const uint8_t *p_rtcp_fb_nack)
121 {
122     return (p_rtcp_fb_nack[2] << 8) | p_rtcp_fb_nack[3];
123 }
124 
rtcp_fb_nack_set_range_start(uint8_t * p_rtcp_fb_nack,uint16_t start)125 static inline void rtcp_fb_nack_set_range_start(uint8_t *p_rtcp_fb_nack,
126                                               uint16_t start)
127 {
128     p_rtcp_fb_nack[0] = (start >> 8) & 0xff;
129     p_rtcp_fb_nack[1] = start & 0xff;
130 }
131 
rtcp_fb_nack_set_range_extra(uint8_t * p_rtcp_fb_nack,uint16_t extra)132 static inline void rtcp_fb_nack_set_range_extra(uint8_t *p_rtcp_fb_nack,
133                                                  uint16_t extra)
134 {
135     p_rtcp_fb_nack[2] = (extra >> 8) & 0xff;
136     p_rtcp_fb_nack[3] = extra & 0xff;
137 }
138 
populate_cname(int fd,char * identifier)139 static inline void populate_cname(int fd, char *identifier)
140 {
141     /* Set the CNAME Identifier as host@ip:port and fallback to hostname if needed */
142     char hostname[MAX_CNAME];
143     struct sockaddr_storage peer_sockaddr;
144     int name_length = 0;
145     socklen_t peer_socklen = 0;
146     int ret_hostname = gethostname(hostname, MAX_CNAME);
147     if (ret_hostname == -1)
148         snprintf(hostname, MAX_CNAME, "UnknownHost");
149     int ret_sockname = getsockname(fd, (struct sockaddr *)&peer_sockaddr, &peer_socklen);
150     if (ret_sockname == 0)
151     {
152         struct sockaddr *peer = (struct sockaddr *)&peer_sockaddr;
153         if (peer->sa_family == AF_INET) {
154             struct sockaddr_in *xin = (void*)peer;
155             name_length = snprintf(identifier, MAX_CNAME, "%s@%s:%u", hostname,
156                             inet_ntoa(xin->sin_addr), ntohs(xin->sin_port));
157             if (name_length >= MAX_CNAME)
158                 identifier[MAX_CNAME-1] = 0;
159         } else if (peer->sa_family == AF_INET6) {
160             struct sockaddr_in6 *xin6 = (void*)peer;
161             char str[INET6_ADDRSTRLEN];
162             inet_ntop(xin6->sin6_family, &xin6->sin6_addr, str, sizeof(struct in6_addr));
163             name_length = snprintf(identifier, MAX_CNAME, "%s@%s:%u", hostname,
164                             str, ntohs(xin6->sin6_port));
165             if (name_length >= MAX_CNAME)
166                 identifier[MAX_CNAME-1] = 0;
167         }
168     }
169     if (name_length == 0)
170     {
171         name_length = snprintf(identifier, MAX_CNAME, "%s", hostname);
172         if (name_length >= MAX_CNAME)
173             identifier[MAX_CNAME-1] = 0;
174     }
175 }
176 
rtp_get_ts(int64_t i_pts)177 static inline uint32_t rtp_get_ts( int64_t i_pts )
178 {
179     unsigned i_clock_rate = 90000;
180     /* This is an overflow-proof way of doing:
181      * return i_pts * (int64_t)i_clock_rate / CLOCK_FREQ;
182      *
183      * NOTE: this plays nice with offsets because the (equivalent)
184      * calculations are linear. */
185     lldiv_t q = lldiv(i_pts, CLOCK_FREQ);
186     return q.quot * (int64_t)i_clock_rate
187           + q.rem * (int64_t)i_clock_rate / CLOCK_FREQ;
188 }
189 
ts_get_from_rtp(uint32_t i_rtp_ts)190 static inline int64_t ts_get_from_rtp( uint32_t i_rtp_ts )
191 {
192     unsigned i_clock_rate = 90000;
193     return (int64_t)i_rtp_ts * (int64_t)(CLOCK_FREQ/i_clock_rate);
194 }
195 
rist_ReadFrom_i11e(int fd,void * buf,size_t len,struct sockaddr * peer,socklen_t * slen)196 static inline ssize_t rist_ReadFrom_i11e(int fd, void *buf, size_t len, struct sockaddr *peer,
197     socklen_t *slen)
198 {
199     ssize_t ret = -1;
200 
201     if (peer == NULL)
202         ret = vlc_recv_i11e(fd, buf, len, 0);
203     else
204         ret = vlc_recvfrom_i11e(fd, buf, len, 0, peer, slen);
205 
206     if (ret == -1)
207     {
208         switch (errno)
209         {
210         case EAGAIN:
211         case EINTR:
212             if (vlc_killed())
213                 return ret;
214 
215             /* retry one time */
216             if (peer == NULL)
217                 ret = vlc_recv_i11e(fd, buf, len, 0);
218             else
219                 ret = vlc_recvfrom_i11e(fd, buf, len, 0, peer, slen);
220         default:
221             break;
222         }
223     }
224     return ret;
225 }
226 
rist_Read_i11e(int fd,void * buf,size_t len)227 static inline ssize_t rist_Read_i11e(int fd, void *buf, size_t len)
228 {
229     return rist_ReadFrom_i11e(fd, buf, len, NULL, NULL);
230 }
231 
rist_ReadFrom(int fd,void * buf,size_t len,struct sockaddr * peer,socklen_t * slen)232 static inline ssize_t rist_ReadFrom(int fd, void *buf, size_t len, struct sockaddr *peer,
233     socklen_t *slen)
234 {
235     ssize_t ret = -1;
236 
237     if (peer == NULL)
238         ret = recv(fd, buf, len, 0);
239     else
240         ret = recvfrom(fd, buf, len, 0, peer, slen);
241 
242     if (ret == -1)
243     {
244         switch (errno)
245         {
246         case EAGAIN:
247         case EINTR:
248             /* retry one time */
249             if (peer == NULL)
250                 ret = recv(fd, buf, len, 0);
251             else
252                 ret = recvfrom(fd, buf, len, 0, peer, slen);
253         default:
254             break;
255         }
256     }
257     return ret;
258 }
259 
rist_Read(int fd,void * buf,size_t len)260 static inline ssize_t rist_Read(int fd, void *buf, size_t len)
261 {
262     return rist_ReadFrom(fd, buf, len, NULL, NULL);
263 }
264 
rist_WriteTo_i11e(int fd,const void * buf,size_t len,const struct sockaddr * peer,socklen_t slen)265 static inline ssize_t rist_WriteTo_i11e(int fd, const void *buf, size_t len,
266     const struct sockaddr *peer, socklen_t slen)
267 {
268 #ifdef _WIN32
269     # define ENOBUFS      WSAENOBUFS
270     # define EAGAIN       WSAEWOULDBLOCK
271     # define EWOULDBLOCK  WSAEWOULDBLOCK
272 #endif
273     ssize_t r = -1;
274     if (slen == 0)
275         r = vlc_send_i11e( fd, buf, len, 0 );
276     else
277         r = vlc_sendto_i11e( fd, buf, len, 0, peer, slen );
278     if( r == -1
279         && net_errno != EAGAIN && net_errno != EWOULDBLOCK
280         && net_errno != ENOBUFS && net_errno != ENOMEM )
281     {
282         int type;
283         if (!getsockopt( fd, SOL_SOCKET, SO_TYPE,
284                     &type, &(socklen_t){ sizeof(type) }))
285         {
286             if( type == SOCK_DGRAM )
287             {
288                 /* ICMP soft error: ignore and retry */
289                 if (slen == 0)
290                     r = vlc_send_i11e( fd, buf, len, 0 );
291                 else
292                     r = vlc_sendto_i11e( fd, buf, len, 0, peer, slen );
293             }
294         }
295     }
296     return r;
297 }
298 
rist_Write_i11e(int fd,const void * buf,size_t len)299 static inline ssize_t rist_Write_i11e(int fd, const void *buf, size_t len)
300 {
301     return rist_WriteTo_i11e(fd, buf, len, NULL, 0);
302 }
303 
rist_WriteTo(int fd,const void * buf,size_t len,const struct sockaddr * peer,socklen_t slen)304 static inline ssize_t rist_WriteTo(int fd, const void *buf, size_t len, const struct sockaddr *peer,
305     socklen_t slen)
306 {
307 #ifdef _WIN32
308     # define ENOBUFS      WSAENOBUFS
309     # define EAGAIN       WSAEWOULDBLOCK
310     # define EWOULDBLOCK  WSAEWOULDBLOCK
311 #endif
312     ssize_t r = -1;
313     if (slen == 0)
314         r = send( fd, buf, len, 0 );
315     else
316         r = sendto( fd, buf, len, 0, peer, slen );
317     if( r == -1
318         && net_errno != EAGAIN && net_errno != EWOULDBLOCK
319         && net_errno != ENOBUFS && net_errno != ENOMEM )
320     {
321         int type;
322         if (!getsockopt( fd, SOL_SOCKET, SO_TYPE,
323                     &type, &(socklen_t){ sizeof(type) }))
324         {
325             if( type == SOCK_DGRAM )
326             {
327                 /* ICMP soft error: ignore and retry */
328                 if (slen == 0)
329                     r = send( fd, buf, len, 0 );
330                 else
331                     r = sendto( fd, buf, len, 0, peer, slen );
332             }
333         }
334     }
335     return r;
336 }
337 
rist_Write(int fd,const void * buf,size_t len)338 static inline ssize_t rist_Write(int fd, const void *buf, size_t len)
339 {
340     return rist_WriteTo(fd, buf, len, NULL, 0);
341 }
342 
is_multicast_address(char * psz_dst_server)343 static bool is_multicast_address(char *psz_dst_server)
344 {
345     int ret;
346     int ismulticast = 0;
347 
348     struct addrinfo hint = {
349         .ai_socktype = SOCK_DGRAM,
350         .ai_protocol = IPPROTO_UDP,
351         .ai_flags = AI_NUMERICSERV | AI_IDN | AI_PASSIVE,
352     }, *res;
353 
354     ret = vlc_getaddrinfo(psz_dst_server, 0, &hint, &res);
355     if (ret) {
356         return 0;
357     } else if(res->ai_family == AF_INET) {
358         unsigned long addr = ntohl(inet_addr(psz_dst_server));
359         ismulticast =  IN_MULTICAST(addr);
360     } else if (res->ai_family == AF_INET6) {
361         if (strlen(psz_dst_server) >= 5 && (strncmp("[ff00", psz_dst_server, 5) == 0 ||
362                     strncmp("[FF00", psz_dst_server, 5) == 0))
363             ismulticast = 1;
364     }
365 
366     freeaddrinfo(res);
367 
368     return ismulticast;
369 }
370 
371 // imported from bitstream
372 #define RIST_RTP_HEADER_SIZE               12
373 #define RIST_RTCP_SR_SIZE                  28
374 #define RIST_RTCP_SDES_SIZE                10
375 #define RIST_RTCP_FB_HEADER_SIZE           12
376 #define RIST_RTCP_FB_FCI_GENERIC_NACK_SIZE 4
377 #define RIST_RTCP_PT_SR                    200
378 #define RIST_RTCP_PT_RR                    201
379 #define RIST_RTCP_PT_SDES                  202
380 #define RIST_RTCP_PT_RTPFB                 205
381 
rist_rtp_get_timestamp(const uint8_t * p_rtp)382 static inline uint32_t rist_rtp_get_timestamp(const uint8_t *p_rtp)
383 {
384     return (p_rtp[4] << 24) | (p_rtp[5] << 16) | (p_rtp[6] << 8) | p_rtp[7];
385 }
386 
rist_rtp_set_timestamp(uint8_t * p_rtp,uint32_t i_timestamp)387 static inline void rist_rtp_set_timestamp(uint8_t *p_rtp, uint32_t i_timestamp)
388 {
389     p_rtp[4] = (i_timestamp >> 24) & 0xff;
390     p_rtp[5] = (i_timestamp >> 16) & 0xff;
391     p_rtp[6] = (i_timestamp >> 8) & 0xff;
392     p_rtp[7] = i_timestamp & 0xff;
393 }
394 
rist_rtp_get_seqnum(const uint8_t * p_rtp)395 static inline uint16_t rist_rtp_get_seqnum(const uint8_t *p_rtp)
396 {
397     return (p_rtp[2] << 8) | p_rtp[3];
398 }
399 
rist_rtp_set_seqnum(uint8_t * p_rtp,uint16_t i_seqnum)400 static inline void rist_rtp_set_seqnum(uint8_t *p_rtp, uint16_t i_seqnum)
401 {
402     p_rtp[2] = i_seqnum >> 8;
403     p_rtp[3] = i_seqnum & 0xff;
404 }
405 
rist_rtcp_sdes_get_name_length(const uint8_t * p_rtcp_sdes)406 static inline int8_t rist_rtcp_sdes_get_name_length(const uint8_t *p_rtcp_sdes)
407 {
408     return p_rtcp_sdes[9];
409 }
410 
rist_rtcp_get_length(const uint8_t * p_rtcp)411 static inline uint16_t rist_rtcp_get_length(const uint8_t *p_rtcp)
412 {
413     return (p_rtcp[2] << 8) | p_rtcp[3];
414 }
415 
rist_rtcp_set_length(uint8_t * p_rtcp,uint16_t length)416 static inline void rist_rtcp_set_length(uint8_t *p_rtcp,
417                                       uint16_t length)
418 {
419     p_rtcp[2] = length >> 8;
420     p_rtcp[3] = length & 0xff;
421 }
422 
rist_rtcp_get_pt(const uint8_t * p_rtcp)423 static inline uint8_t rist_rtcp_get_pt(const uint8_t *p_rtcp)
424 {
425     return p_rtcp[1];
426 }
427 
rist_rtcp_set_pt(uint8_t * p_rtcp,uint8_t pt)428 static inline void rist_rtcp_set_pt(uint8_t *p_rtcp, uint8_t pt)
429 {
430     p_rtcp[1] = pt;
431 }
432 
rist_rtp_check_hdr(const uint8_t * p_rtp)433 static inline bool rist_rtp_check_hdr(const uint8_t *p_rtp)
434 {
435     return (p_rtp[0] & 0xc0) == 0x80;
436 }
437 
rist_rtp_set_hdr(uint8_t * p_rtp)438 static inline void rist_rtp_set_hdr(uint8_t *p_rtp)
439 {
440     p_rtp[0] = 0x80;
441 }
442 
rist_rtcp_rr_set_pt(uint8_t * p_rtcp_rr)443 static inline void rist_rtcp_rr_set_pt(uint8_t *p_rtcp_rr)
444 {
445     rist_rtcp_set_pt(p_rtcp_rr, RIST_RTCP_PT_RR);
446 }
447 
rist_rtcp_fb_set_int_ssrc_pkt_sender(uint8_t * p_rtcp_fb,uint32_t i_ssrc)448 static inline void rist_rtcp_fb_set_int_ssrc_pkt_sender(uint8_t *p_rtcp_fb, uint32_t i_ssrc)
449 {
450     p_rtcp_fb[4] = (i_ssrc >> 24) & 0xff;
451     p_rtcp_fb[5] = (i_ssrc >> 16) & 0xff;
452     p_rtcp_fb[6] = (i_ssrc >> 8) & 0xff;
453     p_rtcp_fb[7] = i_ssrc & 0xff;
454 }
455 
rist_rtp_set_cc(uint8_t * p_rtp,uint8_t i_cc)456 static inline void rist_rtp_set_cc(uint8_t *p_rtp, uint8_t i_cc)
457 {
458     p_rtp[0] &= 0xf0;
459     p_rtp[0] |= i_cc & 0xf;
460 }
461 
rist_rtcp_sdes_set_pt(uint8_t * p_rtcp_rr)462 static inline void rist_rtcp_sdes_set_pt(uint8_t *p_rtcp_rr)
463 {
464     rist_rtcp_set_pt(p_rtcp_rr, RIST_RTCP_PT_SDES);
465 }
466 
rist_rtcp_sdes_set_cname(uint8_t * p_rtcp_sdes,uint8_t cname)467 static inline void rist_rtcp_sdes_set_cname(uint8_t *p_rtcp_sdes, uint8_t cname)
468 {
469     p_rtcp_sdes[8] = cname;
470 }
471 
rist_rtcp_sdes_set_name_length(uint8_t * p_rtcp_sdes,int8_t name_length)472 static inline void rist_rtcp_sdes_set_name_length(uint8_t *p_rtcp_sdes,
473         int8_t name_length)
474 {
475     p_rtcp_sdes[9] = name_length;
476 }
477 
rist_rtcp_fb_get_fmt(const uint8_t * p_rtcp)478 static inline uint8_t rist_rtcp_fb_get_fmt(const uint8_t *p_rtcp)
479 {
480     return p_rtcp[0] & 0x1f;
481 }
482 
rist_rtcp_fb_set_fmt(uint8_t * p_rtcp,uint8_t fmt)483 static inline void rist_rtcp_fb_set_fmt(uint8_t *p_rtcp, uint8_t fmt)
484 {
485     p_rtcp[0] |= fmt & 0x1f;
486 }
487 
rist_rtcp_fb_nack_get_packet_id(const uint8_t * p_rtcp_fb_nack)488 static inline uint16_t rist_rtcp_fb_nack_get_packet_id(const uint8_t *p_rtcp_fb_nack)
489 {
490     return (p_rtcp_fb_nack[0] << 8) | p_rtcp_fb_nack[1];
491 }
492 
rist_rtcp_fb_nack_set_packet_id(uint8_t * p_rtcp_fb_nack,uint16_t packet_id)493 static inline void rist_rtcp_fb_nack_set_packet_id(uint8_t *p_rtcp_fb_nack,
494                                               uint16_t packet_id)
495 {
496     p_rtcp_fb_nack[0] = (packet_id >> 8) & 0xff;
497     p_rtcp_fb_nack[1] = packet_id & 0xff;
498 }
499 
rist_rtcp_fb_nack_get_bitmask_lost(const uint8_t * p_rtcp_fb_nack)500 static inline uint16_t rist_rtcp_fb_nack_get_bitmask_lost(const uint8_t *p_rtcp_fb_nack)
501 {
502     return (p_rtcp_fb_nack[2] << 8) | p_rtcp_fb_nack[3];
503 }
504 
rist_rtcp_fb_nack_set_bitmask_lost(uint8_t * p_rtcp_fb_nack,uint16_t bitmask)505 static inline void rist_rtcp_fb_nack_set_bitmask_lost(uint8_t *p_rtcp_fb_nack,
506                                                  uint16_t bitmask)
507 {
508     p_rtcp_fb_nack[2] = (bitmask >> 8) & 0xff;
509     p_rtcp_fb_nack[3] = bitmask & 0xff;
510 }
511 
rist_rtcp_fb_get_ssrc_media_src(const uint8_t * p_rtcp_fb,uint8_t pi_ssrc[4])512 static inline void rist_rtcp_fb_get_ssrc_media_src(const uint8_t *p_rtcp_fb,
513                                               uint8_t pi_ssrc[4])
514 {
515     pi_ssrc[0] = p_rtcp_fb[8];
516     pi_ssrc[1] = p_rtcp_fb[9];
517     pi_ssrc[2] = p_rtcp_fb[10];
518     pi_ssrc[3] = p_rtcp_fb[11];
519 }
520 
rist_rtcp_fb_set_ssrc_media_src(uint8_t * p_rtcp_fb,const uint8_t pi_ssrc[4])521 static inline void rist_rtcp_fb_set_ssrc_media_src(uint8_t *p_rtcp_fb,
522                                               const uint8_t pi_ssrc[4])
523 {
524     p_rtcp_fb[8] = pi_ssrc[0];
525     p_rtcp_fb[9] = pi_ssrc[1];
526     p_rtcp_fb[10] = pi_ssrc[2];
527     p_rtcp_fb[11] = pi_ssrc[3];
528 }
529 
rist_rtcp_sr_set_pt(uint8_t * p_rtcp_sr)530 static inline void rist_rtcp_sr_set_pt(uint8_t *p_rtcp_sr)
531 {
532     rist_rtcp_set_pt(p_rtcp_sr, RIST_RTCP_PT_SR);
533 }
534 
rist_rtcp_sr_set_length(uint8_t * p_rtcp_sr,uint16_t length)535 static inline void rist_rtcp_sr_set_length(uint8_t *p_rtcp_sr,
536                                       uint16_t length)
537 {
538     rist_rtcp_set_length(p_rtcp_sr, length);
539 }
540 
rist_rtcp_sr_set_ntp_time_msw(uint8_t * p_rtcp_sr,uint32_t ntp_time_msw)541 static inline void rist_rtcp_sr_set_ntp_time_msw(uint8_t *p_rtcp_sr,
542                                             uint32_t ntp_time_msw)
543 {
544     p_rtcp_sr[8] = (ntp_time_msw >> 24) & 0xff;
545     p_rtcp_sr[9] = (ntp_time_msw >> 16) & 0xff;
546     p_rtcp_sr[10] = (ntp_time_msw >> 8) & 0xff;
547     p_rtcp_sr[11] = ntp_time_msw & 0xff;
548 }
549 
rist_rtcp_sr_set_ntp_time_lsw(uint8_t * p_rtcp_sr,uint32_t ntp_time_lsw)550 static inline void rist_rtcp_sr_set_ntp_time_lsw(uint8_t *p_rtcp_sr,
551                                             uint32_t ntp_time_lsw)
552 {
553     p_rtcp_sr[12] = (ntp_time_lsw >> 24) & 0xff;
554     p_rtcp_sr[13] = (ntp_time_lsw >> 16) & 0xff;
555     p_rtcp_sr[14] = (ntp_time_lsw >> 8) & 0xff;
556     p_rtcp_sr[15] = ntp_time_lsw & 0xff;
557 }
558 
rist_rtcp_sr_set_rtp_time(uint8_t * p_rtcp_sr,uint32_t rtp_time)559 static inline void rist_rtcp_sr_set_rtp_time(uint8_t *p_rtcp_sr,
560                                             uint32_t rtp_time)
561 {
562     p_rtcp_sr[16] = (rtp_time >> 24) & 0xff;
563     p_rtcp_sr[17] = (rtp_time >> 16) & 0xff;
564     p_rtcp_sr[18] = (rtp_time >> 8) & 0xff;
565     p_rtcp_sr[19] = rtp_time & 0xff;
566 }
567 
rist_rtcp_sr_set_packet_count(uint8_t * p_rtcp_sr,uint32_t packet_count)568 static inline void rist_rtcp_sr_set_packet_count(uint8_t *p_rtcp_sr,
569                                             uint32_t packet_count)
570 {
571     p_rtcp_sr[20] = (packet_count >> 24) & 0xff;
572     p_rtcp_sr[21] = (packet_count >> 16) & 0xff;
573     p_rtcp_sr[22] = (packet_count >> 8) & 0xff;
574     p_rtcp_sr[23] = packet_count & 0xff;
575 }
576 
rist_rtcp_sr_set_octet_count(uint8_t * p_rtcp_sr,uint32_t octet_count)577 static inline void rist_rtcp_sr_set_octet_count(uint8_t *p_rtcp_sr,
578                                             uint32_t octet_count)
579 {
580     p_rtcp_sr[24] = (octet_count >> 24) & 0xff;
581     p_rtcp_sr[25] = (octet_count >> 16) & 0xff;
582     p_rtcp_sr[26] = (octet_count >> 8) & 0xff;
583     p_rtcp_sr[27] = octet_count & 0xff;
584 }
585 
rist_rtp_set_type(uint8_t * p_rtp,uint8_t i_type)586 static inline void rist_rtp_set_type(uint8_t *p_rtp, uint8_t i_type)
587 {
588     p_rtp[1] = i_type & 0x7f;
589 }
590 
rist_rtp_set_int_ssrc(uint8_t * p_rtp,uint32_t i_ssrc)591 static inline void rist_rtp_set_int_ssrc(uint8_t *p_rtp, uint32_t i_ssrc)
592 {
593     p_rtp[8] = (i_ssrc >> 24) & 0xff;
594     p_rtp[9] = (i_ssrc >> 16) & 0xff;
595     p_rtp[10] = (i_ssrc >> 8) & 0xff;
596     p_rtp[11] = i_ssrc & 0xff;
597 }
598