00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034 #include "asterisk.h"
00035
00036 ASTERISK_FILE_VERSION(__FILE__, "$Revision: 370060 $")
00037
00038 #include "asterisk/module.h"
00039 #include "asterisk/format.h"
00040
00041 enum h263_attr_keys {
00042 H263_ATTR_KEY_SQCIF,
00043 H263_ATTR_KEY_QCIF,
00044 H263_ATTR_KEY_CIF,
00045 H263_ATTR_KEY_CIF4,
00046 H263_ATTR_KEY_CIF16,
00047 H263_ATTR_KEY_VGA,
00048 H263_ATTR_KEY_CUSTOM_XMAX,
00049 H263_ATTR_KEY_CUSTOM_YMAX,
00050 H263_ATTR_KEY_CUSTOM_MPI,
00051 H263_ATTR_KEY_F,
00052 H263_ATTR_KEY_I,
00053 H263_ATTR_KEY_J,
00054 H263_ATTR_KEY_T,
00055 H263_ATTR_KEY_K,
00056 H263_ATTR_KEY_N,
00057 H263_ATTR_KEY_P_SUB1,
00058 H263_ATTR_KEY_P_SUB2,
00059 H263_ATTR_KEY_P_SUB3,
00060 H263_ATTR_KEY_P_SUB4,
00061 H263_ATTR_KEY_PAR_WIDTH,
00062 H263_ATTR_KEY_PAR_HEIGHT,
00063 H263_ATTR_KEY_BPP,
00064 H263_ATTR_KEY_HRD,
00065 H263_ATTR_KEY_END,
00066 };
00067
00068 static int h263_format_attr_get_joint(const struct ast_format_attr *fattr1, const struct ast_format_attr *fattr2, struct ast_format_attr *result)
00069 {
00070 int i;
00071
00072
00073 for (i = H263_ATTR_KEY_SQCIF; i < H263_ATTR_KEY_END; i++) {
00074 result->format_attr[i] = fattr1->format_attr[i] ? fattr1->format_attr[i] : fattr2->format_attr[i];
00075 }
00076
00077 return 0;
00078 }
00079
00080 static int h263_format_attr_sdp_parse(struct ast_format_attr *format_attr, const char *attributes)
00081 {
00082 char *attribs = ast_strdupa(attributes), *attrib;
00083
00084 while ((attrib = strsep(&attribs, ";"))) {
00085 unsigned int val, val2 = 0, val3 = 0, val4 = 0;
00086
00087 if (sscanf(attrib, "SQCIF=%30u", &val) == 1) {
00088 format_attr->format_attr[H263_ATTR_KEY_SQCIF] = val;
00089 } else if (sscanf(attrib, "QCIF=%30u", &val) == 1) {
00090 format_attr->format_attr[H263_ATTR_KEY_QCIF] = val;
00091 } else if (sscanf(attrib, "CIF=%30u", &val) == 1) {
00092 format_attr->format_attr[H263_ATTR_KEY_CIF] = val;
00093 } else if (sscanf(attrib, "CIF4=%30u", &val) == 1) {
00094 format_attr->format_attr[H263_ATTR_KEY_CIF4] = val;
00095 } else if (sscanf(attrib, "CIF16=%30u", &val) == 1) {
00096 format_attr->format_attr[H263_ATTR_KEY_CIF16] = val;
00097 } else if (sscanf(attrib, "VGA=%30u", &val) == 1) {
00098 format_attr->format_attr[H263_ATTR_KEY_VGA] = val;
00099 } else if (sscanf(attrib, "CUSTOM=%30u,%30u,%30u", &val, &val2, &val3) == 3) {
00100 format_attr->format_attr[H263_ATTR_KEY_CUSTOM_XMAX] = val;
00101 format_attr->format_attr[H263_ATTR_KEY_CUSTOM_YMAX] = val2;
00102 format_attr->format_attr[H263_ATTR_KEY_CUSTOM_MPI] = val3;
00103 } else if (sscanf(attrib, "F=%30u", &val) == 1) {
00104 format_attr->format_attr[H263_ATTR_KEY_F] = val;
00105 } else if (sscanf(attrib, "I=%30u", &val) == 1) {
00106 format_attr->format_attr[H263_ATTR_KEY_I] = val;
00107 } else if (sscanf(attrib, "J=%30u", &val) == 1) {
00108 format_attr->format_attr[H263_ATTR_KEY_J] = val;
00109 } else if (sscanf(attrib, "T=%30u", &val) == 1) {
00110 format_attr->format_attr[H263_ATTR_KEY_T] = val;
00111 } else if (sscanf(attrib, "K=%30u", &val) == 1) {
00112 format_attr->format_attr[H263_ATTR_KEY_K] = val;
00113 } else if (sscanf(attrib, "N=%30u", &val) == 1) {
00114 format_attr->format_attr[H263_ATTR_KEY_N] = val;
00115 } else if (sscanf(attrib, "PAR=%30u:%30u", &val, &val2) == 2) {
00116 format_attr->format_attr[H263_ATTR_KEY_PAR_WIDTH] = val;
00117 format_attr->format_attr[H263_ATTR_KEY_PAR_HEIGHT] = val2;
00118 } else if (sscanf(attrib, "BPP=%30u", &val) == 1) {
00119 format_attr->format_attr[H263_ATTR_KEY_BPP] = val;
00120 } else if (sscanf(attrib, "HRD=%30u", &val) == 1) {
00121 format_attr->format_attr[H263_ATTR_KEY_HRD] = val;
00122 } else if (sscanf(attrib, "P=%30u,%30u,%30u,%30u", &val, &val2, &val3, &val4) > 0) {
00123 format_attr->format_attr[H263_ATTR_KEY_P_SUB1] = val;
00124 format_attr->format_attr[H263_ATTR_KEY_P_SUB2] = val2;
00125 format_attr->format_attr[H263_ATTR_KEY_P_SUB3] = val3;
00126 format_attr->format_attr[H263_ATTR_KEY_P_SUB4] = val4;
00127 }
00128 }
00129
00130 return 0;
00131 }
00132
00133
00134 static const char *h263_attr_key_to_str(enum h263_attr_keys key, const struct ast_format_attr *format_attr)
00135 {
00136 switch (key) {
00137 case H263_ATTR_KEY_SQCIF:
00138 return format_attr->format_attr[key] ? "SQCIF" : NULL;
00139 case H263_ATTR_KEY_QCIF:
00140 return format_attr->format_attr[key] ? "QCIF" : NULL;
00141 case H263_ATTR_KEY_CIF:
00142 return format_attr->format_attr[key] ? "CIF" : NULL;
00143 case H263_ATTR_KEY_CIF4:
00144 return format_attr->format_attr[key] ? "CIF4" : NULL;
00145 case H263_ATTR_KEY_CIF16:
00146 return format_attr->format_attr[key] ? "CIF16" : NULL;
00147 case H263_ATTR_KEY_VGA:
00148 return format_attr->format_attr[key] ? "VGA" : NULL;
00149 case H263_ATTR_KEY_F:
00150 return "F";
00151 case H263_ATTR_KEY_I:
00152 return "I";
00153 case H263_ATTR_KEY_J:
00154 return "J";
00155 case H263_ATTR_KEY_T:
00156 return "T";
00157 case H263_ATTR_KEY_K:
00158 return "K";
00159 case H263_ATTR_KEY_N:
00160 return "N";
00161 case H263_ATTR_KEY_BPP:
00162 return "BPP";
00163 case H263_ATTR_KEY_HRD:
00164 return "HRD";
00165 case H263_ATTR_KEY_CUSTOM_XMAX:
00166 case H263_ATTR_KEY_CUSTOM_YMAX:
00167 case H263_ATTR_KEY_CUSTOM_MPI:
00168 case H263_ATTR_KEY_P_SUB1:
00169 case H263_ATTR_KEY_P_SUB2:
00170 case H263_ATTR_KEY_P_SUB3:
00171 case H263_ATTR_KEY_P_SUB4:
00172 case H263_ATTR_KEY_PAR_WIDTH:
00173 case H263_ATTR_KEY_PAR_HEIGHT:
00174 case H263_ATTR_KEY_END:
00175 default:
00176 return NULL;
00177 }
00178
00179 return NULL;
00180 }
00181
00182 static void h263_format_attr_sdp_generate(const struct ast_format_attr *format_attr, unsigned int payload, struct ast_str **str)
00183 {
00184 int i, added = 0;
00185
00186 for (i = H263_ATTR_KEY_SQCIF; i < H263_ATTR_KEY_END; i++) {
00187 const char *name;
00188
00189 if (i == H263_ATTR_KEY_CUSTOM_XMAX) {
00190 if (!format_attr->format_attr[H263_ATTR_KEY_CUSTOM_XMAX] || !format_attr->format_attr[H263_ATTR_KEY_CUSTOM_YMAX] ||
00191 !format_attr->format_attr[H263_ATTR_KEY_CUSTOM_MPI]) {
00192 continue;
00193 }
00194
00195 if (!added) {
00196 ast_str_append(str, 0, "a=fmtp:%d CUSTOM=%u,%u,%u", payload, format_attr->format_attr[H263_ATTR_KEY_CUSTOM_XMAX],
00197 format_attr->format_attr[H263_ATTR_KEY_CUSTOM_YMAX], format_attr->format_attr[H263_ATTR_KEY_CUSTOM_MPI]);
00198 added = 1;
00199 } else {
00200 ast_str_append(str, 0, ";CUSTOM=%u,%u,%u", format_attr->format_attr[H263_ATTR_KEY_CUSTOM_XMAX],
00201 format_attr->format_attr[H263_ATTR_KEY_CUSTOM_YMAX], format_attr->format_attr[H263_ATTR_KEY_CUSTOM_MPI]);
00202 }
00203 } else if (i == H263_ATTR_KEY_PAR_WIDTH) {
00204 if (!format_attr->format_attr[H263_ATTR_KEY_PAR_WIDTH] || !format_attr->format_attr[H263_ATTR_KEY_PAR_HEIGHT]) {
00205 continue;
00206 }
00207
00208 if (!added) {
00209 ast_str_append(str, 0, "a=fmtp:%d PAR=%u:%u", payload, format_attr->format_attr[H263_ATTR_KEY_PAR_WIDTH],
00210 format_attr->format_attr[H263_ATTR_KEY_PAR_HEIGHT]);
00211 added = 1;
00212 } else {
00213 ast_str_append(str, 0, ";PAR=%u:%u", format_attr->format_attr[H263_ATTR_KEY_PAR_WIDTH],
00214 format_attr->format_attr[H263_ATTR_KEY_PAR_HEIGHT]);
00215 }
00216 } else if (i == H263_ATTR_KEY_P_SUB1) {
00217 if (!format_attr->format_attr[H263_ATTR_KEY_P_SUB1]) {
00218 continue;
00219 }
00220
00221 if (!added) {
00222 ast_str_append(str, 0, "a=fmtp:%d P=%u", payload, format_attr->format_attr[H263_ATTR_KEY_P_SUB1]);
00223 added = 1;
00224 } else {
00225 ast_str_append(str, 0, ";P=%u", format_attr->format_attr[H263_ATTR_KEY_P_SUB1]);
00226 }
00227
00228 if (format_attr->format_attr[H263_ATTR_KEY_P_SUB2]) {
00229 ast_str_append(str, 0, ",%u", format_attr->format_attr[H263_ATTR_KEY_P_SUB2]);
00230 }
00231 if (format_attr->format_attr[H263_ATTR_KEY_P_SUB3]) {
00232 ast_str_append(str, 0, ",%u", format_attr->format_attr[H263_ATTR_KEY_P_SUB3]);
00233 }
00234 if (format_attr->format_attr[H263_ATTR_KEY_P_SUB4]) {
00235 ast_str_append(str, 0, ",%u", format_attr->format_attr[H263_ATTR_KEY_P_SUB4]);
00236 }
00237
00238 } else if ((name = h263_attr_key_to_str(i, format_attr))) {
00239 if (!added) {
00240 ast_str_append(str, 0, "a=fmtp:%d %s=%u", payload, name, format_attr->format_attr[i]);
00241 added = 1;
00242 } else {
00243 ast_str_append(str, 0, ";%s=%u", name, format_attr->format_attr[i]);
00244 }
00245 }
00246 }
00247
00248 if (added) {
00249 ast_str_append(str, 0, "\r\n");
00250 }
00251
00252 return;
00253 }
00254
00255 static struct ast_format_attr_interface h263_format_attr_interface = {
00256 .id = AST_FORMAT_H263,
00257 .format_attr_get_joint = h263_format_attr_get_joint,
00258 .format_attr_sdp_parse = h263_format_attr_sdp_parse,
00259 .format_attr_sdp_generate = h263_format_attr_sdp_generate,
00260 };
00261
00262 static struct ast_format_attr_interface h263p_format_attr_interface = {
00263 .id = AST_FORMAT_H263_PLUS,
00264 .format_attr_get_joint = h263_format_attr_get_joint,
00265 .format_attr_sdp_parse = h263_format_attr_sdp_parse,
00266 .format_attr_sdp_generate = h263_format_attr_sdp_generate,
00267 };
00268
00269 static int unload_module(void)
00270 {
00271 ast_format_attr_unreg_interface(&h263_format_attr_interface);
00272 ast_format_attr_unreg_interface(&h263p_format_attr_interface);
00273
00274 return 0;
00275 }
00276
00277 static int load_module(void)
00278 {
00279 if (ast_format_attr_reg_interface(&h263_format_attr_interface)) {
00280 return AST_MODULE_LOAD_DECLINE;
00281 }
00282
00283 if (ast_format_attr_reg_interface(&h263p_format_attr_interface)) {
00284 ast_format_attr_unreg_interface(&h263_format_attr_interface);
00285 return AST_MODULE_LOAD_DECLINE;
00286 }
00287
00288 return AST_MODULE_LOAD_SUCCESS;
00289 }
00290
00291 AST_MODULE_INFO(ASTERISK_GPL_KEY, AST_MODFLAG_LOAD_ORDER, "H.263 Format Attribute Module",
00292 .load = load_module,
00293 .unload = unload_module,
00294 .load_pri = AST_MODPRI_DEFAULT,
00295 );