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: 383973 $")
00037
00038 #include "asterisk/module.h"
00039 #include "asterisk/format.h"
00040
00041
00042 #define H264_ATTR_KEY_UNSET UINT8_MAX
00043
00044
00045
00046
00047 #define H264_MAX_SPS_PPS_SIZE 16
00048
00049
00050
00051 #define H264_MAX_SPS_PPS_SIZE_SCAN_LIMIT "15"
00052
00053 enum h264_attr_keys {
00054 H264_ATTR_KEY_PROFILE_IDC,
00055 H264_ATTR_KEY_PROFILE_IOP,
00056 H264_ATTR_KEY_LEVEL,
00057 H264_ATTR_KEY_MAX_MBPS,
00058 H264_ATTR_KEY_MAX_FS,
00059 H264_ATTR_KEY_MAX_CPB,
00060 H264_ATTR_KEY_MAX_DPB,
00061 H264_ATTR_KEY_MAX_BR,
00062 H264_ATTR_KEY_MAX_SMBPS,
00063 H264_ATTR_KEY_MAX_FPS,
00064 H264_ATTR_KEY_REDUNDANT_PIC_CAP,
00065 H264_ATTR_KEY_PARAMETER_ADD,
00066 H264_ATTR_KEY_PACKETIZATION_MODE,
00067 H264_ATTR_KEY_SPROP_INTERLEAVING_DEPTH,
00068 H264_ATTR_KEY_SPROP_DEINT_BUF_REQ,
00069 H264_ATTR_KEY_DEINT_BUF_CAP,
00070 H264_ATTR_KEY_SPROP_INIT_BUF_TIME,
00071 H264_ATTR_KEY_SPROP_MAX_DON_DIFF,
00072 H264_ATTR_KEY_MAX_RCMD_NALU_SIZE,
00073 H264_ATTR_KEY_LEVEL_ASYMMETRY_ALLOWED,
00074 H264_ATTR_KEY_SPS_LEN,
00075 H264_ATTR_KEY_PPS_LEN,
00076 H264_ATTR_KEY_SPS,
00077 H264_ATTR_KEY_PPS = H264_ATTR_KEY_SPS + H264_MAX_SPS_PPS_SIZE,
00078 H264_ATTR_KEY_END = H264_ATTR_KEY_PPS + H264_MAX_SPS_PPS_SIZE,
00079 };
00080
00081 static enum ast_format_cmp_res h264_format_attr_cmp(const struct ast_format_attr *fattr1, const struct ast_format_attr *fattr2)
00082 {
00083 if (!fattr1->format_attr[H264_ATTR_KEY_PROFILE_IDC] || !fattr2->format_attr[H264_ATTR_KEY_PROFILE_IDC] ||
00084 (fattr1->format_attr[H264_ATTR_KEY_PROFILE_IDC] == fattr2->format_attr[H264_ATTR_KEY_PROFILE_IDC])) {
00085 return AST_FORMAT_CMP_EQUAL;
00086 }
00087
00088 return AST_FORMAT_CMP_NOT_EQUAL;
00089 }
00090
00091 static int h264_format_attr_get_joint(const struct ast_format_attr *fattr1, const struct ast_format_attr *fattr2, struct ast_format_attr *result)
00092 {
00093 int i;
00094
00095 for (i = H264_ATTR_KEY_PROFILE_IDC; i < H264_ATTR_KEY_END; i++) {
00096 result->format_attr[i] = fattr1->format_attr[i] ? fattr1->format_attr[i] : fattr2->format_attr[i];
00097 }
00098
00099 return 0;
00100 }
00101
00102 static int h264_format_attr_sdp_parse(struct ast_format_attr *format_attr, const char *attributes)
00103 {
00104 char *attribs = ast_strdupa(attributes), *attrib;
00105
00106 format_attr->format_attr[H264_ATTR_KEY_REDUNDANT_PIC_CAP] = H264_ATTR_KEY_UNSET;
00107 format_attr->format_attr[H264_ATTR_KEY_PARAMETER_ADD] = H264_ATTR_KEY_UNSET;
00108 format_attr->format_attr[H264_ATTR_KEY_PACKETIZATION_MODE] = H264_ATTR_KEY_UNSET;
00109 format_attr->format_attr[H264_ATTR_KEY_LEVEL_ASYMMETRY_ALLOWED] = H264_ATTR_KEY_UNSET;
00110
00111 while ((attrib = strsep(&attribs, ";"))) {
00112 unsigned int val;
00113 unsigned long int val2;
00114 char sps[H264_MAX_SPS_PPS_SIZE], pps[H264_MAX_SPS_PPS_SIZE];
00115
00116 if (sscanf(attrib, "profile-level-id=%lx", &val2) == 1) {
00117 format_attr->format_attr[H264_ATTR_KEY_PROFILE_IDC] = ((val2 >> 16) & 0xFF);
00118 format_attr->format_attr[H264_ATTR_KEY_PROFILE_IOP] = ((val2 >> 8) & 0xFF);
00119 format_attr->format_attr[H264_ATTR_KEY_LEVEL] = (val2 & 0xFF);
00120 } else if (sscanf(attrib, "sprop-parameter-sets=%" H264_MAX_SPS_PPS_SIZE_SCAN_LIMIT "[^','],%" H264_MAX_SPS_PPS_SIZE_SCAN_LIMIT "s", sps, pps) == 2) {
00121
00122 unsigned char spsdecoded[H264_MAX_SPS_PPS_SIZE] = { 0, }, ppsdecoded[H264_MAX_SPS_PPS_SIZE] = { 0, };
00123 int i;
00124
00125 ast_base64decode(spsdecoded, sps, sizeof(spsdecoded));
00126 ast_base64decode(ppsdecoded, pps, sizeof(ppsdecoded));
00127
00128 format_attr->format_attr[H264_ATTR_KEY_SPS_LEN] = 0;
00129 format_attr->format_attr[H264_ATTR_KEY_PPS_LEN] = 0;
00130
00131 for (i = 0; i < H264_MAX_SPS_PPS_SIZE; i++) {
00132 if (spsdecoded[i]) {
00133 format_attr->format_attr[H264_ATTR_KEY_SPS + i] = spsdecoded[i];
00134 format_attr->format_attr[H264_ATTR_KEY_SPS_LEN]++;
00135 }
00136 if (ppsdecoded[i]) {
00137 format_attr->format_attr[H264_ATTR_KEY_PPS + i] = ppsdecoded[i];
00138 format_attr->format_attr[H264_ATTR_KEY_PPS_LEN]++;
00139 }
00140 }
00141 } else if (sscanf(attrib, "max-mbps=%30u", &val) == 1) {
00142 format_attr->format_attr[H264_ATTR_KEY_MAX_MBPS] = val;
00143 } else if (sscanf(attrib, "max-fs=%30u", &val) == 1) {
00144 format_attr->format_attr[H264_ATTR_KEY_MAX_FS] = val;
00145 } else if (sscanf(attrib, "max-cpb=%30u", &val) == 1) {
00146 format_attr->format_attr[H264_ATTR_KEY_MAX_CPB] = val;
00147 } else if (sscanf(attrib, "max-dpb=%30u", &val) == 1) {
00148 format_attr->format_attr[H264_ATTR_KEY_MAX_DPB] = val;
00149 } else if (sscanf(attrib, "max-br=%30u", &val) == 1) {
00150 format_attr->format_attr[H264_ATTR_KEY_MAX_BR] = val;
00151 } else if (sscanf(attrib, "max-smbps=%30u", &val) == 1) {
00152 format_attr->format_attr[H264_ATTR_KEY_MAX_SMBPS] = val;
00153 } else if (sscanf(attrib, "max-fps=%30u", &val) == 1) {
00154 format_attr->format_attr[H264_ATTR_KEY_MAX_FPS] = val;
00155 } else if (sscanf(attrib, "redundant-pic-cap=%30u", &val) == 1) {
00156 format_attr->format_attr[H264_ATTR_KEY_REDUNDANT_PIC_CAP] = val;
00157 } else if (sscanf(attrib, "parameter-add=%30u", &val) == 1) {
00158 format_attr->format_attr[H264_ATTR_KEY_PARAMETER_ADD] = val;
00159 } else if (sscanf(attrib, "packetization-mode=%30u", &val) == 1) {
00160 format_attr->format_attr[H264_ATTR_KEY_PACKETIZATION_MODE] = val;
00161 } else if (sscanf(attrib, "sprop-interleaving-depth=%30u", &val) == 1) {
00162 format_attr->format_attr[H264_ATTR_KEY_SPROP_INTERLEAVING_DEPTH] = val;
00163 } else if (sscanf(attrib, "sprop-deint-buf-req=%30u", &val) == 1) {
00164 format_attr->format_attr[H264_ATTR_KEY_SPROP_DEINT_BUF_REQ] = val;
00165 } else if (sscanf(attrib, "deint-buf-cap=%30u", &val) == 1) {
00166 format_attr->format_attr[H264_ATTR_KEY_DEINT_BUF_CAP] = val;
00167 } else if (sscanf(attrib, "sprop-init-buf-time=%30u", &val) == 1) {
00168 format_attr->format_attr[H264_ATTR_KEY_SPROP_INIT_BUF_TIME] = val;
00169 } else if (sscanf(attrib, "sprop-max-don-diff=%30u", &val) == 1) {
00170 format_attr->format_attr[H264_ATTR_KEY_SPROP_MAX_DON_DIFF] = val;
00171 } else if (sscanf(attrib, "max-rcmd-nalu-size=%30u", &val) == 1) {
00172 format_attr->format_attr[H264_ATTR_KEY_MAX_RCMD_NALU_SIZE] = val;
00173 } else if (sscanf(attrib, "level-asymmetry-allowed=%30u", &val) == 1) {
00174 format_attr->format_attr[H264_ATTR_KEY_LEVEL_ASYMMETRY_ALLOWED] = val;
00175 }
00176 }
00177
00178 return 0;
00179 }
00180
00181
00182 static const char *h264_attr_key_to_str(enum h264_attr_keys key)
00183 {
00184 switch (key) {
00185 case H264_ATTR_KEY_MAX_MBPS:
00186 return "max-mbps";
00187 case H264_ATTR_KEY_MAX_FS:
00188 return "max-fs";
00189 case H264_ATTR_KEY_MAX_CPB:
00190 return "max-cpb";
00191 case H264_ATTR_KEY_MAX_DPB:
00192 return "max-dpb";
00193 case H264_ATTR_KEY_MAX_BR:
00194 return "max-br";
00195 case H264_ATTR_KEY_MAX_SMBPS:
00196 return "max-smbps";
00197 case H264_ATTR_KEY_MAX_FPS:
00198 return "max-fps";
00199 case H264_ATTR_KEY_REDUNDANT_PIC_CAP:
00200 return "redundant-pic-cap";
00201 case H264_ATTR_KEY_PARAMETER_ADD:
00202 return "parameter-add";
00203 case H264_ATTR_KEY_PACKETIZATION_MODE:
00204 return "packetization-mode";
00205 case H264_ATTR_KEY_SPROP_INTERLEAVING_DEPTH:
00206 return "sprop-interleaving-depth";
00207 case H264_ATTR_KEY_SPROP_DEINT_BUF_REQ:
00208 return "sprop-deint-buf-req";
00209 case H264_ATTR_KEY_DEINT_BUF_CAP:
00210 return "deint-buf-cap";
00211 case H264_ATTR_KEY_SPROP_INIT_BUF_TIME:
00212 return "sprop-init-buf-time";
00213 case H264_ATTR_KEY_SPROP_MAX_DON_DIFF:
00214 return "sprop-max-don-diff";
00215 case H264_ATTR_KEY_MAX_RCMD_NALU_SIZE:
00216 return "max-rcmd-nalu-size";
00217 case H264_ATTR_KEY_LEVEL_ASYMMETRY_ALLOWED:
00218 return "level-asymmetry-allowed";
00219 default:
00220 return NULL;
00221 }
00222
00223 return NULL;
00224 }
00225
00226
00227 static int h264_attr_key_addable(const struct ast_format_attr *format_attr, enum h264_attr_keys key)
00228 {
00229 switch (key) {
00230 case H264_ATTR_KEY_REDUNDANT_PIC_CAP:
00231 case H264_ATTR_KEY_PARAMETER_ADD:
00232 case H264_ATTR_KEY_PACKETIZATION_MODE:
00233 case H264_ATTR_KEY_LEVEL_ASYMMETRY_ALLOWED:
00234 return (format_attr->format_attr[key] != H264_ATTR_KEY_UNSET) ? 1 : 0;
00235 default:
00236 return format_attr->format_attr[key] ? 1 : 0;
00237 }
00238
00239 return 1;
00240 }
00241
00242 static void h264_format_attr_sdp_generate(const struct ast_format_attr *format_attr, unsigned int payload, struct ast_str **str)
00243 {
00244 int i, added = 0;
00245
00246 for (i = H264_ATTR_KEY_PROFILE_IDC; i < H264_ATTR_KEY_END; i++) {
00247 const char *name;
00248
00249 if (i == H264_ATTR_KEY_SPS && format_attr->format_attr[H264_ATTR_KEY_SPS] && format_attr->format_attr[H264_ATTR_KEY_PPS]) {
00250 unsigned char spsdecoded[H264_MAX_SPS_PPS_SIZE] = { 0, }, ppsdecoded[H264_MAX_SPS_PPS_SIZE] = { 0, };
00251 int pos;
00252 char sps[H264_MAX_SPS_PPS_SIZE], pps[H264_MAX_SPS_PPS_SIZE];
00253
00254 for (pos = 0; pos < H264_MAX_SPS_PPS_SIZE; pos++) {
00255 spsdecoded[pos] = format_attr->format_attr[H264_ATTR_KEY_SPS + pos];
00256 ppsdecoded[pos] = format_attr->format_attr[H264_ATTR_KEY_PPS + pos];
00257 }
00258
00259 ast_base64encode(sps, spsdecoded, format_attr->format_attr[H264_ATTR_KEY_SPS_LEN], H264_MAX_SPS_PPS_SIZE);
00260 ast_base64encode(pps, ppsdecoded, format_attr->format_attr[H264_ATTR_KEY_PPS_LEN], H264_MAX_SPS_PPS_SIZE);
00261
00262 if (!added) {
00263 ast_str_append(str, 0, "a=fmtp:%d sprop-parameter-sets=%s,%s", payload, sps, pps);
00264 added = 1;
00265 } else {
00266 ast_str_append(str, 0, ";sprop-parameter-sets=%s,%s", sps, pps);
00267 }
00268 } else if (i == H264_ATTR_KEY_PROFILE_IDC && format_attr->format_attr[H264_ATTR_KEY_PROFILE_IDC] &&
00269 format_attr->format_attr[H264_ATTR_KEY_PROFILE_IOP] && format_attr->format_attr[H264_ATTR_KEY_LEVEL]) {
00270 if (!added) {
00271 ast_str_append(str, 0, "a=fmtp:%d profile-level-id=%X%X%X", payload, format_attr->format_attr[H264_ATTR_KEY_PROFILE_IDC],
00272 format_attr->format_attr[H264_ATTR_KEY_PROFILE_IOP], format_attr->format_attr[H264_ATTR_KEY_LEVEL]);
00273 added = 1;
00274 } else {
00275 ast_str_append(str, 0, ";profile-level-id=%X%X%X", format_attr->format_attr[H264_ATTR_KEY_PROFILE_IDC],
00276 format_attr->format_attr[H264_ATTR_KEY_PROFILE_IOP], format_attr->format_attr[H264_ATTR_KEY_LEVEL]);
00277 }
00278 } else if ((name = h264_attr_key_to_str(i)) && h264_attr_key_addable(format_attr, i)) {
00279 if (!added) {
00280 ast_str_append(str, 0, "a=fmtp:%d %s=%u", payload, name, format_attr->format_attr[i]);
00281 added = 1;
00282 } else {
00283 ast_str_append(str, 0, ";%s=%u", name, format_attr->format_attr[i]);
00284 }
00285 }
00286 }
00287
00288 if (added) {
00289 ast_str_append(str, 0, "\r\n");
00290 }
00291
00292 return;
00293 }
00294
00295 static struct ast_format_attr_interface h264_format_attr_interface = {
00296 .id = AST_FORMAT_H264,
00297 .format_attr_cmp = h264_format_attr_cmp,
00298 .format_attr_get_joint = h264_format_attr_get_joint,
00299 .format_attr_sdp_parse = h264_format_attr_sdp_parse,
00300 .format_attr_sdp_generate = h264_format_attr_sdp_generate,
00301 };
00302
00303 static int unload_module(void)
00304 {
00305 ast_format_attr_unreg_interface(&h264_format_attr_interface);
00306
00307 return 0;
00308 }
00309
00310 static int load_module(void)
00311 {
00312 if (ast_format_attr_reg_interface(&h264_format_attr_interface)) {
00313 return AST_MODULE_LOAD_DECLINE;
00314 }
00315
00316 return AST_MODULE_LOAD_SUCCESS;
00317 }
00318
00319 AST_MODULE_INFO(ASTERISK_GPL_KEY, AST_MODFLAG_LOAD_ORDER, "H.264 Format Attribute Module",
00320 .load = load_module,
00321 .unload = unload_module,
00322 .load_pri = AST_MODPRI_DEFAULT,
00323 );