diff options
Diffstat (limited to 'src/libmsc/sdp_msg.c')
-rw-r--r-- | src/libmsc/sdp_msg.c | 82 |
1 files changed, 66 insertions, 16 deletions
diff --git a/src/libmsc/sdp_msg.c b/src/libmsc/sdp_msg.c index 6170e8eb4..9d3d5e417 100644 --- a/src/libmsc/sdp_msg.c +++ b/src/libmsc/sdp_msg.c @@ -30,31 +30,78 @@ #include <osmocom/msc/debug.h> #include <osmocom/msc/sdp_msg.h> +#define CMP(a,b) (a < b? -1 : (a > b? 1 : 0)) + /* Compare name, rate and fmtp, returning typical cmp result: 0 on match, and -1 / 1 on mismatch. - * Do *not* compare the payload_type number. + * If cmp_fmtp is false, do *not* compare the fmtp string; if true, compare fmtp 1:1 as strings. + * If cmp_payload_type is false, do *not* compare the payload_type number. * The fmtp is only string-compared -- e.g. if AMR parameters appear in a different order, it amounts to a mismatch even * though all parameters are the same. */ -int sdp_audio_codec_cmp(const struct sdp_audio_codec *a, const struct sdp_audio_codec *b) +int sdp_audio_codec_cmp(const struct sdp_audio_codec *a, const struct sdp_audio_codec *b, + bool cmp_fmtp, bool cmp_payload_type) { - int rc; + int cmp; if (a == b) return 0; if (!a) return -1; if (!b) return 1; - rc = strncmp(a->subtype_name, b->subtype_name, sizeof(a->subtype_name)); - if (rc) - return rc; + cmp = strncmp(a->subtype_name, b->subtype_name, sizeof(a->subtype_name)); + if (cmp) + return cmp; + cmp = CMP(a->rate, b->rate); + if (cmp) + return cmp; + if (cmp_fmtp) { + cmp = strncmp(a->fmtp, b->fmtp, sizeof(a->fmtp)); + if (cmp) + return cmp; + } + if (cmp_payload_type) { + cmp = CMP(a->payload_type, b->payload_type); + if (cmp) + return cmp; + } + return 0; +} - if (a->rate < b->rate) +int sdp_audio_codecs_cmp(const struct sdp_audio_codecs *a, const struct sdp_audio_codecs *b, + bool cmp_fmtp, bool cmp_payload_type) +{ + const struct sdp_audio_codec *codec_a; + const struct sdp_audio_codec *codec_b; + int cmp; + if (a == b) + return 0; + if (!a) return -1; - if (a->rate > b->rate) + if (!b) return 1; - rc = strncmp(a->fmtp, b->fmtp, sizeof(a->fmtp)); - if (rc) - return rc; + /* The first codec is the "chosen" codec and should match. The others may appear in different order. */ + if (a->count && b->count) { + cmp = sdp_audio_codec_cmp(&a->codec[0], &b->codec[0], cmp_fmtp, cmp_payload_type); + if (cmp) + return cmp; + } + + cmp = CMP(a->count, b->count); + if (cmp) + return cmp; + + /* See if each codec in a is also present in b */ + foreach_sdp_audio_codec(codec_a, a) { + bool match_found = false; + foreach_sdp_audio_codec(codec_b, b) { + if (!sdp_audio_codec_cmp(codec_a, codec_b, cmp_fmtp, cmp_payload_type)) { + match_found = true; + break; + } + } + if (!match_found) + return -1; + } return 0; } @@ -130,13 +177,13 @@ struct sdp_audio_codec *sdp_audio_codec_by_payload_type(struct sdp_audio_codecs return codec; } -/* Return a given sdp_msg's codec entry that matches the subtype_name, rate and fmtp of the given codec, or NULL if no - * match is found. Comparison is made by sdp_audio_codec_cmp(). */ +/* Return a given sdp_msg's codec entry that matches the subtype_name and rate of the given codec, or NULL if no + * match is found. Comparison is made by sdp_audio_codec_cmp(cmp_payload_type=false). */ struct sdp_audio_codec *sdp_audio_codec_by_descr(struct sdp_audio_codecs *ac, const struct sdp_audio_codec *codec) { struct sdp_audio_codec *i; foreach_sdp_audio_codec(i, ac) { - if (!sdp_audio_codec_cmp(i, codec)) + if (!sdp_audio_codec_cmp(i, codec, false, false)) return i; } return NULL; @@ -452,8 +499,8 @@ next_line: } /* Leave only those codecs in 'ac_dest' that are also present in 'ac_other'. - * The matching is made by sdp_audio_codec_cmp(), i.e. payload_type numbers are not compared and fmtp parameters are - * compared 1:1 as plain strings. + * The matching is made by sdp_audio_codec_cmp(cmp_payload_type=false), i.e. payload_type numbers are not compared and + * fmtp parameters are compared 1:1 as plain strings. * If translate_payload_type_numbers has an effect if ac_dest and ac_other have mismatching payload_type numbers for the * same SDP codec descriptions. If translate_payload_type_numbers is true, take the payload_type numbers from ac_other. * If false, keep payload_type numbers in ac_dest unchanged. */ @@ -509,8 +556,11 @@ int sdp_audio_codec_name_buf(char *buf, size_t buflen, const struct sdp_audio_co { struct osmo_strbuf sb = { .buf = buf, .len = buflen }; OSMO_STRBUF_PRINTF(sb, "%s", codec->subtype_name); + if (codec->rate != 8000) + OSMO_STRBUF_PRINTF(sb, "/%u", codec->rate); if (codec->fmtp[0]) OSMO_STRBUF_PRINTF(sb, ":%s", codec->fmtp); + OSMO_STRBUF_PRINTF(sb, "#%d", codec->payload_type); return sb.chars_needed; } |