blob: 51b8d44970bb3fb16abac5284845a3cdbcd1daca [file] [log] [blame]
James Kuszmaul82f6c042021-01-17 11:30:16 -08001/**
2 * @file fb.c Real-time Transport Control Protocol (RTCP)-Based Feedback
3 *
4 * Copyright (C) 2010 Creytiv.com
5 */
6#include <string.h>
7#include <re_types.h>
8#include <re_fmt.h>
9#include <re_mem.h>
10#include <re_mbuf.h>
11#include <re_list.h>
12#include <re_sys.h>
13#include <re_sa.h>
14#include <re_rtp.h>
15#include "rtcp.h"
16
17
18#define DEBUG_MODULE "rtcp_pb"
19#define DEBUG_LEVEL 5
20#include <re_dbg.h>
21
22
23enum {
24 GNACK_SIZE = 4,
25 SLI_SIZE = 4
26};
27
28
29/* Encode functions */
30
31
32/**
33 * Encode an RTCP Generic NACK (GNACK) message
34 *
35 * @param mb Buffer to encode into
36 * @param pid Packet ID
37 * @param blp Bitmask of following lost packets (BLP)
38 *
39 * @return 0 for success, otherwise errorcode
40 */
41int rtcp_rtpfb_gnack_encode(struct mbuf *mb, uint16_t pid, uint16_t blp)
42{
43 int err;
44 err = mbuf_write_u16(mb, htons(pid));
45 err |= mbuf_write_u16(mb, htons(blp));
46 return err;
47}
48
49
50/**
51 * Encode an RTCP Slice Loss Indication (SLI) message
52 *
53 * @param mb Buffer to encode into
54 * @param first Macroblock (MB) address of the first lost macroblock
55 * @param number Number of lost macroblocks
56 * @param picid Picture ID
57 *
58 * @return 0 for success, otherwise errorcode
59 */
60int rtcp_psfb_sli_encode(struct mbuf *mb, uint16_t first, uint16_t number,
61 uint8_t picid)
62{
63 const uint32_t v = first<<19 | number<<6 | picid;
64 return mbuf_write_u32(mb, htonl(v));
65}
66
67
68/* Decode functions */
69
70
71/**
72 * Decode an RTCP Transport Layer Feedback Message
73 *
74 * @param mb Buffer to decode
75 * @param msg RTCP Message to decode into
76 *
77 * @return 0 for success, otherwise errorcode
78 */
79int rtcp_rtpfb_decode(struct mbuf *mb, struct rtcp_msg *msg)
80{
81 size_t i, sz;
82
83 if (!msg)
84 return EINVAL;
85
86 switch (msg->hdr.count) {
87
88 case RTCP_RTPFB_GNACK:
89 sz = msg->r.fb.n * sizeof(*msg->r.fb.fci.gnackv);
90 msg->r.fb.fci.gnackv = mem_alloc(sz, NULL);
91 if (!msg->r.fb.fci.gnackv)
92 return ENOMEM;
93
94 if (mbuf_get_left(mb) < msg->r.fb.n * GNACK_SIZE)
95 return EBADMSG;
96 for (i=0; i<msg->r.fb.n; i++) {
97 msg->r.fb.fci.gnackv[i].pid = ntohs(mbuf_read_u16(mb));
98 msg->r.fb.fci.gnackv[i].blp = ntohs(mbuf_read_u16(mb));
99 }
100 break;
101
102 default:
103 DEBUG_NOTICE("unknown RTPFB fmt %d\n", msg->hdr.count);
104 break;
105 }
106
107 return 0;
108}
109
110
111/**
112 * Decode an RTCP Payload-Specific Feedback Message
113 *
114 * @param mb Buffer to decode
115 * @param msg RTCP Message to decode into
116 *
117 * @return 0 for success, otherwise errorcode
118 */
119int rtcp_psfb_decode(struct mbuf *mb, struct rtcp_msg *msg)
120{
121 size_t i, sz;
122
123 if (!msg)
124 return EINVAL;
125
126 switch (msg->hdr.count) {
127
128 case RTCP_PSFB_PLI:
129 /* no params */
130 break;
131
132 case RTCP_PSFB_SLI:
133 sz = msg->r.fb.n * sizeof(*msg->r.fb.fci.sliv);
134 msg->r.fb.fci.sliv = mem_alloc(sz, NULL);
135 if (!msg->r.fb.fci.sliv)
136 return ENOMEM;
137
138 if (mbuf_get_left(mb) < msg->r.fb.n * SLI_SIZE)
139 return EBADMSG;
140 for (i=0; i<msg->r.fb.n; i++) {
141 const uint32_t v = ntohl(mbuf_read_u32(mb));
142
143 msg->r.fb.fci.sliv[i].first = v>>19 & 0x1fff;
144 msg->r.fb.fci.sliv[i].number = v>> 6 & 0x1fff;
145 msg->r.fb.fci.sliv[i].picid = v>> 0 & 0x003f;
146 }
147 break;
148
149 case RTCP_PSFB_AFB:
150 sz = msg->r.fb.n * 4;
151
152 if (mbuf_get_left(mb) < sz)
153 return EBADMSG;
154
155 msg->r.fb.fci.afb = mbuf_alloc_ref(mb);
156 if (!msg->r.fb.fci.afb)
157 return ENOMEM;
158
159 msg->r.fb.fci.afb->end = msg->r.fb.fci.afb->pos + sz;
160 mbuf_advance(mb, sz);
161 break;
162
163 default:
164 DEBUG_NOTICE("unknown PSFB fmt %d\n", msg->hdr.count);
165 break;
166 }
167
168 return 0;
169}