1 /**
2 * @file sdp/format.c SDP format
3 *
4 * Copyright (C) 2010 Creytiv.com
5 */
6 #include <stdlib.h>
7 #include <string.h>
8 #include <re_types.h>
9 #include <re_fmt.h>
10 #include <re_mem.h>
11 #include <re_mbuf.h>
12 #include <re_list.h>
13 #include <re_sa.h>
14 #include <re_sdp.h>
15 #include "sdp.h"
16
17
destructor(void * arg)18 static void destructor(void *arg)
19 {
20 struct sdp_format *fmt = arg;
21
22 list_unlink(&fmt->le);
23
24 if (fmt->ref)
25 mem_deref(fmt->data);
26
27 mem_deref(fmt->id);
28 mem_deref(fmt->params);
29 mem_deref(fmt->rparams);
30 mem_deref(fmt->name);
31 }
32
33
34 /**
35 * Add an SDP Format to an SDP Media line
36 *
37 * @param fmtp Pointer to allocated SDP Format
38 * @param m SDP Media line
39 * @param prepend True to prepend, False to append
40 * @param id Format identifier
41 * @param name Format name
42 * @param srate Sampling rate
43 * @param ch Number of channels
44 * @param ench Optional format encode handler
45 * @param cmph Optional format comparison handler
46 * @param data Opaque data for handler
47 * @param ref True to mem_ref() data
48 * @param params Formatted parameters
49 *
50 * @return 0 if success, otherwise errorcode
51 */
sdp_format_add(struct sdp_format ** fmtp,struct sdp_media * m,bool prepend,const char * id,const char * name,uint32_t srate,uint8_t ch,sdp_fmtp_enc_h * ench,sdp_fmtp_cmp_h * cmph,void * data,bool ref,const char * params,...)52 int sdp_format_add(struct sdp_format **fmtp, struct sdp_media *m,
53 bool prepend, const char *id, const char *name,
54 uint32_t srate, uint8_t ch, sdp_fmtp_enc_h *ench,
55 sdp_fmtp_cmp_h *cmph, void *data, bool ref,
56 const char *params, ...)
57 {
58 struct sdp_format *fmt;
59 int err;
60
61 if (!m)
62 return EINVAL;
63
64 if (!id && (m->dynpt > RTP_DYNPT_END))
65 return ERANGE;
66
67 fmt = mem_zalloc(sizeof(*fmt), destructor);
68 if (!fmt)
69 return ENOMEM;
70
71 if (prepend)
72 list_prepend(&m->lfmtl, &fmt->le, fmt);
73 else
74 list_append(&m->lfmtl, &fmt->le, fmt);
75
76 if (id)
77 err = str_dup(&fmt->id, id);
78 else
79 err = re_sdprintf(&fmt->id, "%i", m->dynpt++);
80 if (err)
81 goto out;
82
83 if (name) {
84 err = str_dup(&fmt->name, name);
85 if (err)
86 goto out;
87 }
88
89 if (params) {
90 va_list ap;
91
92 va_start(ap, params);
93 err = re_vsdprintf(&fmt->params, params, ap);
94 va_end(ap);
95
96 if (err)
97 goto out;
98 }
99
100 fmt->pt = atoi(fmt->id);
101 fmt->srate = srate;
102 fmt->ch = ch;
103 fmt->ench = ench;
104 fmt->cmph = cmph;
105 fmt->data = ref ? mem_ref(data) : data;
106 fmt->ref = ref;
107 fmt->sup = true;
108
109 out:
110 if (err)
111 mem_deref(fmt);
112 else if (fmtp)
113 *fmtp = fmt;
114
115 return err;
116 }
117
118
sdp_format_radd(struct sdp_media * m,const struct pl * id)119 int sdp_format_radd(struct sdp_media *m, const struct pl *id)
120 {
121 struct sdp_format *fmt;
122 int err;
123
124 if (!m || !id)
125 return EINVAL;
126
127 fmt = mem_zalloc(sizeof(*fmt), destructor);
128 if (!fmt)
129 return ENOMEM;
130
131 list_append(&m->rfmtl, &fmt->le, fmt);
132
133 err = pl_strdup(&fmt->id, id);
134 if (err)
135 goto out;
136
137 fmt->pt = atoi(fmt->id);
138
139 out:
140 if (err)
141 mem_deref(fmt);
142
143 return err;
144 }
145
146
sdp_format_find(const struct list * lst,const struct pl * id)147 struct sdp_format *sdp_format_find(const struct list *lst, const struct pl *id)
148 {
149 struct le *le;
150
151 if (!lst || !id)
152 return NULL;
153
154 for (le=lst->head; le; le=le->next) {
155
156 struct sdp_format *fmt = le->data;
157
158 if (pl_strcmp(id, fmt->id))
159 continue;
160
161 return fmt;
162 }
163
164 return NULL;
165 }
166
167
168 /**
169 * Set the parameters of an SDP format
170 *
171 * @param fmt SDP Format
172 * @param params Formatted parameters
173 *
174 * @return 0 if success, otherwise errorcode
175 */
sdp_format_set_params(struct sdp_format * fmt,const char * params,...)176 int sdp_format_set_params(struct sdp_format *fmt, const char *params, ...)
177 {
178 int err = 0;
179
180 if (!fmt)
181 return EINVAL;
182
183 fmt->params = mem_deref(fmt->params);
184
185 if (params) {
186 va_list ap;
187
188 va_start(ap, params);
189 err = re_vsdprintf(&fmt->params, params, ap);
190 va_end(ap);
191 }
192
193 return err;
194 }
195
196
197 /**
198 * Compare two SDP Formats
199 *
200 * @param fmt1 First SDP format
201 * @param fmt2 Second SDP format
202 *
203 * @return True if matching, False if not
204 */
sdp_format_cmp(const struct sdp_format * fmt1,const struct sdp_format * fmt2)205 bool sdp_format_cmp(const struct sdp_format *fmt1,
206 const struct sdp_format *fmt2)
207 {
208 if (!fmt1 || !fmt2)
209 return false;
210
211 if (fmt1->pt < RTP_DYNPT_START && fmt2->pt < RTP_DYNPT_START) {
212
213 if (!fmt1->id || !fmt2->id)
214 return false;
215
216 return strcmp(fmt1->id, fmt2->id) ? false : true;
217 }
218
219 if (str_casecmp(fmt1->name, fmt2->name))
220 return false;
221
222 if (fmt1->srate != fmt2->srate)
223 return false;
224
225 if (fmt1->ch != fmt2->ch)
226 return false;
227
228 if (fmt1->cmph && !fmt1->cmph(fmt1->params, fmt2->params, fmt1->data))
229 return false;
230
231 if (fmt2->cmph && !fmt2->cmph(fmt2->params, fmt1->params, fmt2->data))
232 return false;
233
234 return true;
235 }
236
237
238 /**
239 * Print SDP Format debug information
240 *
241 * @param pf Print function for output
242 * @param fmt SDP Format
243 *
244 * @return 0 if success, otherwise errorcode
245 */
sdp_format_debug(struct re_printf * pf,const struct sdp_format * fmt)246 int sdp_format_debug(struct re_printf *pf, const struct sdp_format *fmt)
247 {
248 int err;
249
250 if (!fmt)
251 return 0;
252
253 err = re_hprintf(pf, "%3s", fmt->id);
254
255 if (fmt->name)
256 err |= re_hprintf(pf, " %s/%u/%u",
257 fmt->name, fmt->srate, fmt->ch);
258
259 if (fmt->params)
260 err |= re_hprintf(pf, " (%s)", fmt->params);
261
262 if (fmt->sup)
263 err |= re_hprintf(pf, " *");
264
265 return err;
266 }
267