--- res/res_format_attr_h264.c (Asterisk 13.38.1) +++ res/res_format_attr_h264.c (working copy) @@ -39,2 +39,4 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revisi #include "asterisk/format.h" +#include "asterisk/strings.h" /* for ast_str_append, etc */ +#include "asterisk/utils.h" /* for MAX, ast_calloc, ast_free, etc */ @@ -52,2 +54,6 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revisi +#define H264_DEFAULT_PROFILE_IDC 66 /* 42 */ +#define H264_DEFAULT_PROFILE_IOP 160 /* a0 */ +#define H264_MIN_LEVEL 10 /* 0a */ + struct h264_attr { @@ -133,3 +139,2 @@ static struct ast_format *h264_getjoint( DETERMINE_JOINT(attr, attr1, attr2, PROFILE_IOP); - DETERMINE_JOINT(attr, attr1, attr2, LEVEL); DETERMINE_JOINT(attr, attr1, attr2, MAX_MBPS); @@ -152,2 +157,31 @@ static struct ast_format *h264_getjoint( + /* https://mailarchive.ietf.org/arch/msg/avt/o-q0iDkaZXZRg1IQUeD67pd4kAo/ */ + if (!attr->LEVEL_ASYMMETRY_ALLOWED) { + if (attr1 && attr2) { + /* Level 1b is 0x09 sometimes, see RFC 6184 section 8.2.2: + * Level 1b is one level higher than Level 1.0 */ + if (9 == attr1->LEVEL || 9 == attr2->LEVEL) { + if (!attr1->LEVEL || 10 == attr1->LEVEL || + !attr2->LEVEL || 10 == attr2->LEVEL) { + attr->LEVEL = 10; /* minimum is Level 1.0 */ + } else { + attr->LEVEL = 9; /* minimum is Level 1b */ + } + /* otherwise minimum level is 1.0; this is forced here again + * because cached formats do not have that as default but 0 */ + } else { + attr->LEVEL = MIN(MAX(attr1->LEVEL,H264_MIN_LEVEL), + MAX(attr2->LEVEL,H264_MIN_LEVEL)); + } + attr1->LEVEL = attr->LEVEL; + attr2->LEVEL = attr->LEVEL; + } else if (attr1) { + attr->LEVEL = attr1->LEVEL; + } else if (attr2) { + attr->LEVEL = attr2->LEVEL; + } else { + attr->LEVEL = H264_MIN_LEVEL; + } + } + if (attr1 && !ast_strlen_zero(attr1->SPS)) { @@ -182,3 +216,6 @@ static struct ast_format *h264_parse_sdp attr->PACKETIZATION_MODE = H264_ATTR_KEY_UNSET; - attr->LEVEL_ASYMMETRY_ALLOWED = H264_ATTR_KEY_UNSET; + + attr->PROFILE_IDC = H264_DEFAULT_PROFILE_IDC; + attr->PROFILE_IOP = H264_DEFAULT_PROFILE_IOP; + attr->LEVEL = H264_MIN_LEVEL; @@ -284,5 +321,9 @@ static void h264_generate_sdp_fmtp(const APPEND_IF_NOT_H264_UNSET(attr->PACKETIZATION_MODE, str, "packetization-mode"); - APPEND_IF_NOT_H264_UNSET(attr->LEVEL_ASYMMETRY_ALLOWED, str, "level-asymmetry-allowed"); - if (attr->PROFILE_IDC && attr->LEVEL) { + APPEND_IF_NONZERO(attr->LEVEL_ASYMMETRY_ALLOWED, str, "level-asymmetry-allowed"); + + /* cached formats have not the defaults but 0 */ + if ((attr->PROFILE_IDC && H264_DEFAULT_PROFILE_IDC != attr->PROFILE_IDC) || + (attr->PROFILE_IOP && H264_DEFAULT_PROFILE_IOP != attr->PROFILE_IOP) || + (attr->LEVEL && H264_MIN_LEVEL != attr->LEVEL)) { /* could be 0x09 for Level 1b */ if (added) {