From 604aa5a9a0634a431cde2bafc09f00f7ed74eb2f Mon Sep 17 00:00:00 2001 From: Richard Fuchs Date: Thu, 17 Dec 2020 15:34:05 -0500 Subject: [PATCH] TT#92250 add new reorder-codecs flag Change-Id: I93587b6675540438f81193896ae8d8966b3a12a6 --- README.md | 11 ++++++++++ daemon/call_interfaces.c | 3 +++ daemon/codec.c | 43 +++++++++++++++++++++++++++++++++++++-- daemon/main.c | 1 + daemon/rtpengine.pod | 5 +++++ daemon/sdp.c | 5 ++++- include/call_interfaces.h | 1 + include/main.h | 1 + 8 files changed, 67 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index 028d443a8..d6cae485b 100644 --- a/README.md +++ b/README.md @@ -778,6 +778,17 @@ Optionally included keys are: PCMA. With this flag however, *rtpengine* honours the single accepted codec from the answer and so is able to eliminate PCMA from its own answer as it's not needed. + - `reorder codecs` + + This flag adds an additional stage in the processing of the `answer` codecs. Instead of + accepting codecs in the same order that they were offered, reorder the list of codecs + to match the codecs on the opposite (answer) side. This can avoid asymmetric codec flow + in certain cases, at the cost of the answer message possibly listing codecs in a different + order from the offer message (which then could be suppressed using `single codec`). + + The config option `reorder-codecs` can be set to make this the default behaviour for + all answer messages. + - `single codec` Using this flag in an `answer` message will leave only the first listed codec in place diff --git a/daemon/call_interfaces.c b/daemon/call_interfaces.c index 445eecf2b..6300a8591 100644 --- a/daemon/call_interfaces.c +++ b/daemon/call_interfaces.c @@ -820,6 +820,9 @@ static void call_ng_flags_flags(struct sdp_ng_flags *out, str *s, void *dummy) { case CSH_LOOKUP("symmetric-codecs"): out->symmetric_codecs = 1; break; + case CSH_LOOKUP("reorder-codecs"): + out->reorder_codecs = 1; + break; case CSH_LOOKUP("single-codec"): out->single_codec = 1; break; diff --git a/daemon/codec.c b/daemon/codec.c index a7dae5e6e..aa44baa6e 100644 --- a/daemon/codec.c +++ b/daemon/codec.c @@ -753,6 +753,35 @@ static void __accept_pt(struct call_media *receiver, struct call_media *sink, in *insert_pos = (*insert_pos)->next; } } +static void __reorder_transcode_codecs(struct call_media *receiver, struct call_media *sink, + const struct sdp_ng_flags *flags, int accept_only_tc) +{ + // if the other side is transcoding, we need to accept codecs that were + // originally offered (recv->send) if we support them, even if the + // response (sink->send) doesn't include them + GList *insert_pos = NULL; + for (GList *l = sink->codecs_prefs_recv.head; l; l = l->next) { + // take the PT that we can receive on the sink side and get the appropriate + // output PT on the receiver side to ensure codec symmetry. + struct rtp_payload_type *sink_pt = l->data; + // determine output PT from the codec handler + struct codec_handler *ch = codec_handler_get(sink, sink_pt->payload_type); + if (ch && ch->source_pt.payload_type != -1 && ch->dest_pt.payload_type != -1) { + __accept_pt(receiver, sink, ch->dest_pt.payload_type, sink_pt->payload_type, + accept_only_tc, &insert_pos); + if (ch->dtmf_payload_type != -1) + __accept_pt(receiver, sink, ch->dtmf_payload_type, -1, + accept_only_tc, &insert_pos); + if (ch->cn_payload_type != -1) + __accept_pt(receiver, sink, ch->cn_payload_type, -1, + accept_only_tc, &insert_pos); + } + else + __accept_pt(receiver, sink, sink_pt->payload_type, -1, accept_only_tc, &insert_pos); + } + + __single_codec(receiver, flags); +} static void __accept_transcode_codecs(struct call_media *receiver, struct call_media *sink, const struct sdp_ng_flags *flags, int accept_only_tc) { @@ -903,6 +932,7 @@ static void __symmetric_codecs(struct call_media *receiver, struct call_media *s struct rtp_payload_type *out_pt = g_hash_table_lookup(prefs_recv, ptype); if (!out_pt) continue; + //ilog(LOG_DEBUG, "XXXXXXXXXXXXXXXX appending recv codec " STR_FORMAT, STR_FMT(&out_pt->encoding_with_params)); g_hash_table_steal(prefs_recv, ptype); __rtp_payload_type_add_recv(receiver, out_pt, 1); } @@ -911,6 +941,7 @@ static void __symmetric_codecs(struct call_media *receiver, struct call_media *s struct rtp_payload_type *out_pt = g_hash_table_lookup(prefs_send, ptype); if (!out_pt) continue; + //ilog(LOG_DEBUG, "XXXXXXXXXXXXXXXX appending send codec " STR_FORMAT, STR_FMT(&out_pt->encoding_with_params)); g_hash_table_steal(prefs_send, ptype); __rtp_payload_type_add_send(receiver, out_pt); } @@ -1312,8 +1343,13 @@ void codec_handlers_update(struct call_media *receiver, struct call_media *sink, MEDIA_CLEAR(sink, TRANSCODE); } - if (MEDIA_ISSET(sink, TRANSCODE) && (sink_transcoding & 0x2)) - __accept_transcode_codecs(receiver, sink, flags, (receiver_transcoding & 0x1)); + if (MEDIA_ISSET(sink, TRANSCODE) && (sink_transcoding & 0x2)) { + if (flags && flags->opmode == OP_ANSWER && + (rtpe_config.reorder_codecs || flags->reorder_codecs)) + __reorder_transcode_codecs(receiver, sink, flags, (receiver_transcoding & 0x1)); + else + __accept_transcode_codecs(receiver, sink, flags, (receiver_transcoding & 0x1)); + } else __eliminate_rejected_codecs(receiver, sink, flags); @@ -1489,6 +1525,9 @@ next: for (GList *l = receiver->codecs_prefs_recv.head; l; ) { struct rtp_payload_type *pt = l->data; + //ilog(LOG_DEBUG, "XXXX checking recv codec " STR_FORMAT, + //STR_FMT(&pt->encoding)); + if (pt->codec_def) { // supported l = l->next; diff --git a/daemon/main.c b/daemon/main.c index afbd6a0a4..7e96816e9 100644 --- a/daemon/main.c +++ b/daemon/main.c @@ -477,6 +477,7 @@ static void options(int *argc, char ***argv) { { "max-dtx", 0,0, G_OPTION_ARG_INT, &rtpe_config.max_dtx, "Maximum duration of DTX handling", "INT"}, { "silence-detect",0,0, G_OPTION_ARG_DOUBLE, &silence_detect, "Audio level threshold in percent for silence detection","FLOAT"}, { "cn-payload",0,0, G_OPTION_ARG_STRING_ARRAY,&cn_payload, "Comfort noise parameters to replace silence with","INT INT INT ..."}, + { "reorder-codecs",0,0, G_OPTION_ARG_NONE, &rtpe_config.reorder_codecs,"Reorder answer codecs based on sender preference",NULL}, #endif { NULL, } diff --git a/daemon/rtpengine.pod b/daemon/rtpengine.pod index 3e9104ab9..c28065358 100644 --- a/daemon/rtpengine.pod +++ b/daemon/rtpengine.pod @@ -810,6 +810,11 @@ of coefficients listed (model order) is variable. The default values are 32 (-32 dBov) for the noise level and no spectral information. +=item B<--reorder-codecs> + +Always sets the option B in answer messages as described in the +F. + =back =head1 INTERFACES diff --git a/daemon/sdp.c b/daemon/sdp.c index fa6c1704c..af3c08f0f 100644 --- a/daemon/sdp.c +++ b/daemon/sdp.c @@ -2063,10 +2063,13 @@ static int process_media_attributes(struct sdp_chopper *chop, struct sdp_media * case ATTR_RTPMAP: case ATTR_FMTP: - case ATTR_PTIME: if (media->codecs_prefs_recv.length > 0) goto strip; break; + case ATTR_PTIME: + if (media->ptime) + goto strip; + break; case ATTR_RTCP_FB: if (attr->u.rtcp_fb.payload_type == -1) break; // leave this one alone diff --git a/include/call_interfaces.h b/include/call_interfaces.h index d839866b9..8afca8c5f 100644 --- a/include/call_interfaces.h +++ b/include/call_interfaces.h @@ -93,6 +93,7 @@ struct sdp_ng_flags { original_sendrecv:1, asymmetric_codecs:1, symmetric_codecs:1, + reorder_codecs:1, single_codec:1, inject_dtmf:1, t38_decode:1, diff --git a/include/main.h b/include/main.h index 8dedb7cc1..5cfcf693d 100644 --- a/include/main.h +++ b/include/main.h @@ -110,6 +110,7 @@ struct rtpengine_config { double silence_detect_double; uint32_t silence_detect_int; str cn_payload; + int reorder_codecs; };