Asterisk - The Open Source Telephony Project GIT-master-650240a
res_format_attr_h263.c
Go to the documentation of this file.
1/*
2 * Asterisk -- An open source telephony toolkit.
3 *
4 * Copyright (C) 2012, Digium, Inc.
5 *
6 * Joshua Colp <jcolp@digium.com>
7 *
8 * See http://www.asterisk.org for more information about
9 * the Asterisk project. Please do not directly contact
10 * any of the maintainers of this project for assistance;
11 * the project provides a web site, mailing lists and IRC
12 * channels for your use.
13 *
14 * This program is free software, distributed under the terms of
15 * the GNU General Public License Version 2. See the LICENSE file
16 * at the top of the source tree.
17 *
18 */
19
20/*! \file
21 *
22 * \brief H.263 Format Attribute Module
23 *
24 * \author\verbatim Joshua Colp <jcolp@digium.com> \endverbatim
25 *
26 * This is a format attribute module for the H.263 codec.
27 * \ingroup applications
28 */
29
30/*** MODULEINFO
31 <support_level>core</support_level>
32 ***/
33
34#include "asterisk.h"
35
36#include <ctype.h> /* for toupper */
37
38#include "asterisk/module.h"
39#include "asterisk/format.h"
40#include "asterisk/strings.h" /* for ast_str_append */
41#include "asterisk/utils.h" /* for ast_strip */
42
43/*! \brief Value that indicates an attribute is actually unset */
44#define H263_ATTR_KEY_UNSET UINT8_MAX
45
46struct h263_attr {
47 unsigned int SQCIF; /*!< Minimum picture interval for SQCIF resolution */
48 unsigned int QCIF; /*!< Minimum picture interval for QCIF resolution */
49 unsigned int CIF; /*!< Minimum picture interval for CIF resolution */
50 unsigned int CIF4; /*!< Minimum picture interval for CIF4 resolution */
51 unsigned int CIF16; /*!< Minimum picture interval for CIF16 resolution */
52 unsigned int VGA; /*!< Minimum picture interval for VGA resolution */
53 unsigned int CUSTOM_XMAX; /*!< Custom resolution (Xmax) */
54 unsigned int CUSTOM_YMAX; /*!< Custom resolution (Ymax) */
55 unsigned int CUSTOM_MPI; /*!< Custom resolution (MPI) */
56 unsigned int CPCF; /*!< Custom Picture Clock Frequency */
57 unsigned int CPCF_2;
58 unsigned int CPCF_3;
59 unsigned int CPCF_4;
60 unsigned int CPCF_5;
61 unsigned int CPCF_6;
62 unsigned int CPCF_7;
63 unsigned int CPCF_MPI;
64 unsigned int F; /*!< F annex support */
65 unsigned int I; /*!< I annex support */
66 unsigned int J; /*!< J annex support */
67 unsigned int T; /*!< T annex support */
68 unsigned int K; /*!< K annex support */
69 unsigned int N; /*!< N annex support */
70 unsigned int P_SUB1; /*!< Reference picture resampling (sub mode 1) */
71 unsigned int P_SUB2; /*!< Reference picture resampling (sub mode 2) */
72 unsigned int P_SUB3; /*!< Reference picture resampling (sub mode 3) */
73 unsigned int P_SUB4; /*!< Reference picture resampling (sub mode 4) */
74 unsigned int PAR_WIDTH; /*!< Pixel aspect ratio (width) */
75 unsigned int PAR_HEIGHT; /*!< Pixel aspect ratio (height) */
76 unsigned int BPP; /*!< Bits per picture maximum */
77 unsigned int HRD; /*!< Hypothetical reference decoder status */
78 unsigned int MaxBR; /*!< Vendor Specific: CounterPath Bria (Solo) */
79};
80
81static void h263_destroy(struct ast_format *format)
82{
83 struct h263_attr *attr = ast_format_get_attribute_data(format);
84
85 ast_free(attr);
86}
87
88static int h263_clone(const struct ast_format *src, struct ast_format *dst)
89{
90 struct h263_attr *original = ast_format_get_attribute_data(src);
91 struct h263_attr *attr = ast_calloc(1, sizeof(*attr));
92
93 if (!attr) {
94 return -1;
95 }
96
97 if (original) {
98 *attr = *original;
99 }
100
102
103 return 0;
104}
105
106static enum ast_format_cmp_res h263_cmp(const struct ast_format *format1, const struct ast_format *format2)
107{
108 struct h263_attr *attr1 = ast_format_get_attribute_data(format1);
109 struct h263_attr *attr2 = ast_format_get_attribute_data(format2);
110
111 if (!attr1 || !attr2 || (attr1 && attr2 && !memcmp(attr1, attr2, sizeof(*attr1)))) {
113 }
115}
116
117#define DETERMINE_JOINT(joint, attr1, attr2, field) (joint->field = (attr1 && attr1->field) ? attr1->field : (attr2 && attr2->field) ? attr2->field : 0)
118
119static struct ast_format *h263_getjoint(const struct ast_format *format1, const struct ast_format *format2)
120{
121 struct ast_format *cloned;
122 struct h263_attr *attr, *attr1, *attr2;
123
124 cloned = ast_format_clone(format1);
125 if (!cloned) {
126 return NULL;
127 }
128 attr = ast_format_get_attribute_data(cloned);
129
130 attr1 = ast_format_get_attribute_data(format1);
131 attr2 = ast_format_get_attribute_data(format2);
132
133 DETERMINE_JOINT(attr, attr1, attr2, SQCIF);
134 DETERMINE_JOINT(attr, attr1, attr2, QCIF);
135 DETERMINE_JOINT(attr, attr1, attr2, CIF);
136 DETERMINE_JOINT(attr, attr1, attr2, CIF4);
137 DETERMINE_JOINT(attr, attr1, attr2, CIF16);
138 DETERMINE_JOINT(attr, attr1, attr2, VGA);
139 DETERMINE_JOINT(attr, attr1, attr2, CUSTOM_XMAX);
140 DETERMINE_JOINT(attr, attr1, attr2, CUSTOM_YMAX);
141 DETERMINE_JOINT(attr, attr1, attr2, CUSTOM_MPI);
142 DETERMINE_JOINT(attr, attr1, attr2, CPCF);
143 DETERMINE_JOINT(attr, attr1, attr2, CPCF_2);
144 DETERMINE_JOINT(attr, attr1, attr2, CPCF_3);
145 DETERMINE_JOINT(attr, attr1, attr2, CPCF_4);
146 DETERMINE_JOINT(attr, attr1, attr2, CPCF_5);
147 DETERMINE_JOINT(attr, attr1, attr2, CPCF_6);
148 DETERMINE_JOINT(attr, attr1, attr2, CPCF_7);
149 DETERMINE_JOINT(attr, attr1, attr2, CPCF_MPI);
150 DETERMINE_JOINT(attr, attr1, attr2, F);
151 DETERMINE_JOINT(attr, attr1, attr2, I);
152 DETERMINE_JOINT(attr, attr1, attr2, J);
153 DETERMINE_JOINT(attr, attr1, attr2, T);
154 DETERMINE_JOINT(attr, attr1, attr2, K);
155 DETERMINE_JOINT(attr, attr1, attr2, N);
156 DETERMINE_JOINT(attr, attr1, attr2, P_SUB1);
157 DETERMINE_JOINT(attr, attr1, attr2, P_SUB2);
158 DETERMINE_JOINT(attr, attr1, attr2, P_SUB3);
159 DETERMINE_JOINT(attr, attr1, attr2, P_SUB4);
160 DETERMINE_JOINT(attr, attr1, attr2, PAR_WIDTH);
161 DETERMINE_JOINT(attr, attr1, attr2, PAR_HEIGHT);
162 DETERMINE_JOINT(attr, attr1, attr2, BPP);
163 DETERMINE_JOINT(attr, attr1, attr2, HRD);
164 DETERMINE_JOINT(attr, attr1, attr2, MaxBR);
165
166 return cloned;
167}
168
169static struct ast_format *h263_parse_sdp_fmtp(const struct ast_format *format, const char *attributes)
170{
171 char *attribs = ast_strdupa(attributes), *attrib;
172 struct ast_format *cloned;
173 struct h263_attr *attr;
174
175 cloned = ast_format_clone(format);
176 if (!cloned) {
177 return NULL;
178 }
179 attr = ast_format_get_attribute_data(cloned);
180
181 /* upper-case everything, so we are case-insensitive */
182 for (attrib = attribs; *attrib; ++attrib) {
183 *attrib = toupper(*attrib);
184 } /* based on channels/chan_sip.c:process_a_sdp_image() */
185
186 attr->BPP = H263_ATTR_KEY_UNSET;
190
191 while ((attrib = strsep(&attribs, ";"))) {
192 unsigned int val, val2 = 0, val3 = 0, val4 = 0, val5 = 0, val6 = 0, val7 = 0, val8 = 0;
193
194 attrib = ast_strip(attrib);
195
196 if (sscanf(attrib, "SQCIF=%30u", &val) == 1) {
197 attr->SQCIF = val;
198 } else if (strcmp(attrib, "SQCIF") == 0) {
199 attr->SQCIF = 1;
200 } else if (sscanf(attrib, "QCIF=%30u", &val) == 1) {
201 attr->QCIF = val;
202 } else if (strcmp(attrib, "QCIF") == 0) {
203 attr->QCIF = 1;
204 } else if (sscanf(attrib, "CIF=%30u", &val) == 1) {
205 attr->CIF = val;
206 } else if (strcmp(attrib, "CIF") == 0) {
207 attr->CIF = 1;
208 } else if (sscanf(attrib, "CIF4=%30u", &val) == 1) {
209 attr->CIF4 = val;
210 } else if (strcmp(attrib, "CIF4") == 0) {
211 attr->CIF4 = 1;
212 } else if (sscanf(attrib, "CIF16=%30u", &val) == 1) {
213 attr->CIF16 = val;
214 } else if (strcmp(attrib, "CIF16") == 0) {
215 attr->CIF16 = 1;
216 } else if (sscanf(attrib, "VGA=%30u", &val) == 1) {
217 attr->VGA = val;
218 } else if (strcmp(attrib, "VGA") == 0) {
219 attr->VGA = 1;
220 } else if (sscanf(attrib, "CUSTOM=%30u,%30u,%30u", &val, &val2, &val3) == 3) {
221 attr->CUSTOM_XMAX = val;
222 attr->CUSTOM_YMAX = val2;
223 attr->CUSTOM_MPI = val3;
224 } else if (sscanf(attrib, "CPCF=%30u,%30u,%30u,%30u,%30u,%30u,%30u,%30u",
225 &val, &val2, &val3, &val4, &val5, &val6, &val7, &val8) == 8) {
226 attr->CPCF = val;
227 attr->CPCF_2 = val2;
228 attr->CPCF_3 = val3;
229 attr->CPCF_4 = val4;
230 attr->CPCF_5 = val5;
231 attr->CPCF_6 = val6;
232 attr->CPCF_7 = val7;
233 attr->CPCF_MPI = val8;
234 } else if (sscanf(attrib, "F=%30u", &val) == 1) {
235 attr->F = val;
236 } else if (sscanf(attrib, "I=%30u", &val) == 1) {
237 attr->I = val;
238 } else if (sscanf(attrib, "J=%30u", &val) == 1) {
239 attr->J = val;
240 } else if (sscanf(attrib, "T=%30u", &val) == 1) {
241 attr->T = val;
242 } else if (sscanf(attrib, "K=%30u", &val) == 1) {
243 attr->K = val;
244 } else if (sscanf(attrib, "N=%30u", &val) == 1) {
245 attr->N = val;
246 } else if (sscanf(attrib, "PAR=%30u:%30u", &val, &val2) == 2) {
247 attr->PAR_WIDTH = val;
248 attr->PAR_HEIGHT = val2;
249 } else if (sscanf(attrib, "BPP=%30u", &val) == 1) {
250 attr->BPP = val;
251 } else if (sscanf(attrib, "HRD=%30u", &val) == 1) {
252 attr->HRD = val;
253 } else if (sscanf(attrib, "P=%30u,%30u,%30u,%30u", &val, &val2, &val3, &val4) > 0) {
254 attr->P_SUB1 = val;
255 attr->P_SUB2 = val2;
256 attr->P_SUB3 = val3;
257 attr->P_SUB4 = val4;
258 } else if (sscanf(attrib, "MAXBR=%30u", &val) == 1) {
259 attr->MaxBR = val;
260 }
261 }
262
263 return cloned;
264}
265
266#define APPEND_IF_NOT_H263_UNSET(field, str, name) do { \
267 if (field != H263_ATTR_KEY_UNSET) { \
268 if (added) { \
269 ast_str_append(str, 0, ";"); \
270 } else if (0 < ast_str_append(str, 0, "a=fmtp:%u ", payload)) { \
271 added = 1; \
272 } \
273 ast_str_append(str, 0, "%s=%u", name, field); \
274 } \
275} while (0)
276
277#define APPEND_IF_NONZERO(field, str, name) do { \
278 if (field) { \
279 if (added) { \
280 ast_str_append(str, 0, ";"); \
281 } else if (0 < ast_str_append(str, 0, "a=fmtp:%u ", payload)) { \
282 added = 1; \
283 } \
284 ast_str_append(str, 0, "%s=%u", name, field); \
285 } \
286} while (0)
287
288static void h263_generate_sdp_fmtp(const struct ast_format *format, unsigned int payload, struct ast_str **str)
289{
290 struct h263_attr *attr = ast_format_get_attribute_data(format);
291 int added = 0;
292
293 if (!attr) {
294 return;
295 }
296
297 if (attr->CPCF) {
298 if (added) {
299 ast_str_append(str, 0, ";");
300 } else if (0 < ast_str_append(str, 0, "a=fmtp:%u ", payload)) {
301 added = 1;
302 }
303 ast_str_append(str, 0, "CPCF=%u,%u,%u,%u,%u,%u,%u,%u", attr->CPCF, attr->CPCF_2, attr->CPCF_3,
304 attr->CPCF_4, attr->CPCF_5, attr->CPCF_6, attr->CPCF_7, attr->CPCF_MPI);
305 }
306
307 APPEND_IF_NONZERO(attr->CIF16, str, "CIF16");
308 APPEND_IF_NONZERO(attr->CIF4, str, "CIF4");
309 APPEND_IF_NONZERO(attr->VGA, str, "VGA");
310 APPEND_IF_NONZERO(attr->CIF, str, "CIF");
311 APPEND_IF_NONZERO(attr->QCIF, str, "QCIF");
312 APPEND_IF_NONZERO(attr->SQCIF, str, "SQCIF");
313
314 if (attr->CUSTOM_XMAX && attr->CUSTOM_YMAX && attr->CUSTOM_MPI) {
315 if (added) {
316 ast_str_append(str, 0, ";");
317 } else if (0 < ast_str_append(str, 0, "a=fmtp:%u ", payload)) {
318 added = 1;
319 }
320 ast_str_append(str, 0, "CUSTOM=%u,%u,%u", attr->CUSTOM_XMAX, attr->CUSTOM_YMAX, attr->CUSTOM_MPI);
321 }
322
323 APPEND_IF_NONZERO(attr->F, str, "F");
324 APPEND_IF_NONZERO(attr->I, str, "I");
325 APPEND_IF_NONZERO(attr->J, str, "J");
326 APPEND_IF_NONZERO(attr->T, str, "T");
327 APPEND_IF_NONZERO(attr->K, str, "K");
328 APPEND_IF_NONZERO(attr->N, str, "N");
329
330 if (attr->P_SUB1) {
331 if (added) {
332 ast_str_append(str, 0, ";");
333 } else if (0 < ast_str_append(str, 0, "a=fmtp:%u ", payload)) {
334 added = 1;
335 }
336 ast_str_append(str, 0, "P=%u", attr->P_SUB1);
337 if (attr->P_SUB2) {
338 ast_str_append(str, 0, ",%u", attr->P_SUB2);
339 }
340 if (attr->P_SUB3) {
341 ast_str_append(str, 0, ",%u", attr->P_SUB3);
342 }
343 if (attr->P_SUB4) {
344 ast_str_append(str, 0, ",%u", attr->P_SUB4);
345 }
346 }
347
349 if (added) {
350 ast_str_append(str, 0, ";");
351 } else if (0 < ast_str_append(str, 0, "a=fmtp:%u ", payload)) {
352 added = 1; \
353 }
354 ast_str_append(str, 0, "PAR=%u:%u", attr->PAR_WIDTH, attr->PAR_HEIGHT);
355 }
356
357 APPEND_IF_NOT_H263_UNSET(attr->BPP, str, "BPP");
358
359 APPEND_IF_NONZERO(attr->HRD, str, "HRD");
360
361 APPEND_IF_NOT_H263_UNSET(attr->MaxBR, str, "MaxBR");
362
363 ast_str_append(str, 0, "\r\n");
364
365 return;
366}
367
370 .format_clone = h263_clone,
371 .format_cmp = h263_cmp,
372 .format_get_joint = h263_getjoint,
373 .format_parse_sdp_fmtp = h263_parse_sdp_fmtp,
374 .format_generate_sdp_fmtp = h263_generate_sdp_fmtp,
375};
376
377static int unload_module(void)
378{
379 return 0;
380}
381
382static int load_module(void)
383{
386 }
387
390 }
391
393}
394
395AST_MODULE_INFO(ASTERISK_GPL_KEY, AST_MODFLAG_DEFAULT, "H.263 Format Attribute Module",
396 .support_level = AST_MODULE_SUPPORT_CORE,
397 .load = load_module,
398 .unload = unload_module,
const char * str
Definition: app_jack.c:147
Asterisk main include file. File version handling, generic pbx functions.
#define ast_free(a)
Definition: astmm.h:180
#define ast_strdupa(s)
duplicate a string in memory from the stack
Definition: astmm.h:298
#define ast_calloc(num, len)
A wrapper for calloc()
Definition: astmm.h:202
Media Format API.
void * ast_format_get_attribute_data(const struct ast_format *format)
Get the attribute data on a format.
Definition: format.c:125
void ast_format_set_attribute_data(struct ast_format *format, void *attribute_data)
Set the attribute data on a format.
Definition: format.c:130
ast_format_cmp_res
Format comparison results.
Definition: format.h:34
@ AST_FORMAT_CMP_EQUAL
Definition: format.h:36
@ AST_FORMAT_CMP_NOT_EQUAL
Definition: format.h:38
struct ast_format * ast_format_clone(const struct ast_format *format)
Clone an existing media format so it can be modified.
Definition: format.c:180
#define ast_format_interface_register(codec, interface)
Register a format interface for use with the provided codec.
Definition: format.h:273
char * strsep(char **str, const char *delims)
Asterisk module definitions.
@ AST_MODFLAG_DEFAULT
Definition: module.h:315
#define AST_MODULE_INFO(keystr, flags_to_set, desc, fields...)
Definition: module.h:543
@ AST_MODULE_SUPPORT_CORE
Definition: module.h:121
#define ASTERISK_GPL_KEY
The text the key() function should return.
Definition: module.h:46
@ AST_MODULE_LOAD_SUCCESS
Definition: module.h:70
@ AST_MODULE_LOAD_DECLINE
Module has failed to load, may be in an inconsistent state.
Definition: module.h:78
#define APPEND_IF_NOT_H263_UNSET(field, str, name)
static struct ast_format * h263_getjoint(const struct ast_format *format1, const struct ast_format *format2)
static int h263_clone(const struct ast_format *src, struct ast_format *dst)
#define APPEND_IF_NONZERO(field, str, name)
#define DETERMINE_JOINT(joint, attr1, attr2, field)
static enum ast_format_cmp_res h263_cmp(const struct ast_format *format1, const struct ast_format *format2)
static struct ast_format_interface h263_interface
static struct ast_format * h263_parse_sdp_fmtp(const struct ast_format *format, const char *attributes)
#define H263_ATTR_KEY_UNSET
Value that indicates an attribute is actually unset.
static int load_module(void)
static void h263_destroy(struct ast_format *format)
static int unload_module(void)
static void h263_generate_sdp_fmtp(const struct ast_format *format, unsigned int payload, struct ast_str **str)
#define NULL
Definition: resample.c:96
String manipulation functions.
int ast_str_append(struct ast_str **buf, ssize_t max_len, const char *fmt,...)
Append to a thread local dynamic string.
Definition: strings.h:1136
char * ast_strip(char *s)
Strip leading/trailing whitespace from a string.
Definition: strings.h:223
Optional format interface to extend format operations.
Definition: format.h:44
void(*const format_destroy)(struct ast_format *format)
Callback for when the format is destroyed, used to release attribute resources.
Definition: format.h:50
Definition of a media format.
Definition: format.c:43
Support for dynamic strings.
Definition: strings.h:623
unsigned int CPCF_2
unsigned int CUSTOM_YMAX
unsigned int F
unsigned int CIF4
unsigned int J
unsigned int HRD
unsigned int K
unsigned int CPCF_4
unsigned int P_SUB1
unsigned int P_SUB4
unsigned int CPCF
unsigned int CPCF_6
unsigned int CPCF_3
unsigned int VGA
unsigned int SQCIF
unsigned int CPCF_MPI
unsigned int P_SUB3
unsigned int I
unsigned int PAR_HEIGHT
unsigned int CUSTOM_XMAX
unsigned int QCIF
unsigned int CUSTOM_MPI
unsigned int CIF16
unsigned int T
unsigned int BPP
unsigned int CPCF_7
unsigned int MaxBR
unsigned int CIF
unsigned int N
unsigned int P_SUB2
unsigned int CPCF_5
unsigned int PAR_WIDTH
Definition: ast_expr2.c:325
Utility functions.