diff --git a/README.md b/README.md index 9c5cd3f5c..e2baab9e5 100644 --- a/README.md +++ b/README.md @@ -742,6 +742,13 @@ Optionally included keys are: and will remove all others from the list. Useful for RTP clients which get confused if more than one codec is listed in an answer. + - `reuse codecs` or `no codec renegotiation` + + Instructs *rtpengine* to prevent endpoints from switching codecs during call run-time + if possible. Codecs that were listed as preferred in the past will be kept as preferred + even if the re-offer lists other codecs as preferred, or in a different order. Recommended + to be combined with `single codec`. + - `all` Only relevant to the `unblock media` message. Instructs *rtpengine* to remove not only a diff --git a/daemon/call.c b/daemon/call.c index 2a70718f4..02c4abdb8 100644 --- a/daemon/call.c +++ b/daemon/call.c @@ -2181,11 +2181,10 @@ void codecs_offer_answer(struct call_media *media, struct call_media *other_medi STR_FMT(&other_media->monologue->tag), other_media->index); if (flags) { - if (flags->reuse_codec){ - codec_store_populate(&other_media->codecs, &sp->codecs, flags ? flags->codec_set : NULL); - }else{ - codec_store_populate_reuse(&other_media->codecs, &sp->codecs, flags ? flags->codec_set : NULL); - } + if (flags->reuse_codec) + codec_store_populate_reuse(&other_media->codecs, &sp->codecs, flags->codec_set); + else + codec_store_populate(&other_media->codecs, &sp->codecs, flags->codec_set); codec_store_strip(&other_media->codecs, &flags->codec_strip, flags->codec_except); codec_store_offer(&other_media->codecs, &flags->codec_offer, &sp->codecs); if (!other_media->codecs.strip_full) @@ -2193,9 +2192,8 @@ void codecs_offer_answer(struct call_media *media, struct call_media *other_medi codec_store_accept(&other_media->codecs, &flags->codec_accept, NULL); codec_store_accept(&other_media->codecs, &flags->codec_consume, &sp->codecs); codec_store_track(&other_media->codecs, &flags->codec_mask); - }else{ - codec_store_populate(&other_media->codecs, &sp->codecs, flags ? flags->codec_set : NULL); - } + } else + codec_store_populate(&other_media->codecs, &sp->codecs, NULL); // we don't update the answerer side if the offer is not RTP but is going // to RTP (i.e. T.38 transcoding) - instead we leave the existing codec list @@ -2209,7 +2207,10 @@ void codecs_offer_answer(struct call_media *media, struct call_media *other_medi ilogs(codec, LOG_DEBUG, "Updating receiver side codecs for answerer " STR_FORMAT " #%u", STR_FMT(&media->monologue->tag), media->index); - codec_store_populate(&media->codecs, &sp->codecs, NULL); + if (flags && flags->reuse_codec) + codec_store_populate_reuse(&media->codecs, &sp->codecs, NULL); + else + codec_store_populate(&media->codecs, &sp->codecs, NULL); } if (flags) { codec_store_strip(&media->codecs, &flags->codec_strip, flags->codec_except); @@ -2237,7 +2238,10 @@ void codecs_offer_answer(struct call_media *media, struct call_media *other_medi ilogs(codec, LOG_DEBUG, "Updating receiver side codecs for answerer " STR_FORMAT " #%u", STR_FMT(&other_media->monologue->tag), other_media->index); - codec_store_populate(&other_media->codecs, &sp->codecs, flags->codec_set); + if (flags->reuse_codec) + codec_store_populate_reuse(&other_media->codecs, &sp->codecs, flags->codec_set); + else + codec_store_populate(&other_media->codecs, &sp->codecs, flags->codec_set); codec_store_strip(&other_media->codecs, &flags->codec_strip, flags->codec_except); codec_store_offer(&other_media->codecs, &flags->codec_offer, &sp->codecs); diff --git a/daemon/call_interfaces.c b/daemon/call_interfaces.c index 174d925ba..6be8a932d 100644 --- a/daemon/call_interfaces.c +++ b/daemon/call_interfaces.c @@ -862,6 +862,12 @@ static void call_ng_flags_flags(struct sdp_ng_flags *out, str *s, void *dummy) { case CSH_LOOKUP("reorder-codecs"): ilog(LOG_INFO, "Ignoring obsolete flag `reorder-codecs`"); break; + case CSH_LOOKUP("reuse-codecs"): + out->reuse_codec = 1; + break; + case CSH_LOOKUP("no-codec-renegotiation"): + out->reuse_codec = 1; + break; case CSH_LOOKUP("single-codec"): out->single_codec = 1; break; diff --git a/t/test-transcode.c b/t/test-transcode.c index ebf603308..6b608fd77 100644 --- a/t/test-transcode.c +++ b/t/test-transcode.c @@ -1459,29 +1459,122 @@ int main(void) { end(); //reusing_codecs test - flags.reuse_codec = 1; start(); - sdp_pt(0, PCMA, 8000); - sdp_pt(8, PCMU, 8000); + sdp_pt(0, PCMU, 8000); + sdp_pt(8, PCMA, 8000); sdp_pt(9, PCMA, 8000); offer(); - expect(A, "0/PCMA/8000 8/PCMU/8000 9/PCMA/8000"); + expect(A, "0/PCMU/8000 8/PCMA/8000 9/PCMA/8000"); sdp_pt(7, PCMA, 8000); - sdp_pt(0, PCMA, 8000); - sdp_pt(8, PCMU, 8000); + sdp_pt(0, PCMU, 8000); + sdp_pt(8, PCMA, 8000); answer(); - expect(B, "7/PCMA/8000 0/PCMA/8000 8/PCMU/8000"); - sdp_pt(0, PCMA, 8000); - sdp_pt(8, PCMU, 8000); + expect(B, "7/PCMA/8000 0/PCMU/8000 8/PCMA/8000"); + sdp_pt(0, PCMU, 8000); + sdp_pt(8, PCMA, 8000); sdp_pt(9, PCMA, 8000); offer(); - expect(A, "0/PCMA/8000 8/PCMU/8000 9/PCMA/8000"); + expect(A, "0/PCMU/8000 8/PCMA/8000 9/PCMA/8000"); sdp_pt(7, PCMA, 8000); - sdp_pt(0, PCMA, 8000); - sdp_pt(8, PCMU, 8000); + sdp_pt(0, PCMU, 8000); + sdp_pt(8, PCMA, 8000); + answer(); + expect(B, "7/PCMA/8000 0/PCMU/8000 8/PCMA/8000"); + end(); + + start(); + sdp_pt(0, PCMU, 8000); + sdp_pt(8, PCMA, 8000); + sdp_pt(9, G722, 8000); + offer(); + expect(A, "0/PCMU/8000 8/PCMA/8000 9/G722/8000"); + expect(B, "0/PCMU/8000 8/PCMA/8000 9/G722/8000"); + sdp_pt(0, PCMU, 8000); + sdp_pt(8, PCMA, 8000); + sdp_pt(9, G722, 8000); + answer(); + expect(A, "0/PCMU/8000 8/PCMA/8000 9/G722/8000"); + expect(B, "0/PCMU/8000 8/PCMA/8000 9/G722/8000"); + sdp_pt(9, G722, 8000); + sdp_pt(8, PCMA, 8000); + sdp_pt(0, PCMU, 8000); + offer(); + expect(A, "9/G722/8000 8/PCMA/8000 0/PCMU/8000"); + expect(B, "9/G722/8000 8/PCMA/8000 0/PCMU/8000"); + sdp_pt(9, G722, 8000); + sdp_pt(8, PCMA, 8000); + sdp_pt(0, PCMU, 8000); answer(); - expect(B, "7/PCMA/8000 0/PCMA/8000 8/PCMU/8000"); + expect(A, "9/G722/8000 8/PCMA/8000 0/PCMU/8000"); + expect(B, "9/G722/8000 8/PCMA/8000 0/PCMU/8000"); end(); + + start(); + sdp_pt(0, PCMU, 8000); + sdp_pt(8, PCMA, 8000); + sdp_pt(9, G722, 8000); + flags.reuse_codec = 1; + offer(); + expect(A, "0/PCMU/8000 8/PCMA/8000 9/G722/8000"); + expect(B, "0/PCMU/8000 8/PCMA/8000 9/G722/8000"); + sdp_pt(0, PCMU, 8000); + sdp_pt(8, PCMA, 8000); + sdp_pt(9, G722, 8000); + flags.reuse_codec = 1; + answer(); + expect(A, "0/PCMU/8000 8/PCMA/8000 9/G722/8000"); + expect(B, "0/PCMU/8000 8/PCMA/8000 9/G722/8000"); + sdp_pt(9, G722, 8000); + sdp_pt(8, PCMA, 8000); + sdp_pt(0, PCMU, 8000); + flags.reuse_codec = 1; + offer(); + expect(A, "0/PCMU/8000 8/PCMA/8000 9/G722/8000"); + expect(B, "0/PCMU/8000 8/PCMA/8000 9/G722/8000"); + sdp_pt(9, G722, 8000); + sdp_pt(8, PCMA, 8000); + sdp_pt(0, PCMU, 8000); + flags.reuse_codec = 1; + answer(); + expect(A, "0/PCMU/8000 8/PCMA/8000 9/G722/8000"); + expect(B, "0/PCMU/8000 8/PCMA/8000 9/G722/8000"); + end(); + + start(); + sdp_pt(0, PCMU, 8000); + sdp_pt(8, PCMA, 8000); + sdp_pt(9, G722, 8000); + flags.reuse_codec = 1; + flags.single_codec = 1; + offer(); + expect(A, "0/PCMU/8000 8/PCMA/8000 9/G722/8000"); + expect(B, "0/PCMU/8000 8/PCMA/8000 9/G722/8000"); + sdp_pt(0, PCMU, 8000); + sdp_pt(8, PCMA, 8000); + sdp_pt(9, G722, 8000); + flags.reuse_codec = 1; + flags.single_codec = 1; + answer(); + expect(A, "0/PCMU/8000"); + expect(B, "0/PCMU/8000 8/PCMA/8000 9/G722/8000"); + sdp_pt(9, G722, 8000); + sdp_pt(8, PCMA, 8000); + sdp_pt(0, PCMU, 8000); + flags.reuse_codec = 1; + flags.single_codec = 1; + offer(); + expect(A, "0/PCMU/8000 9/G722/8000 8/PCMA/8000"); + expect(B, "0/PCMU/8000 8/PCMA/8000 9/G722/8000"); + sdp_pt(9, G722, 8000); + sdp_pt(8, PCMA, 8000); + sdp_pt(0, PCMU, 8000); + flags.reuse_codec = 1; + flags.single_codec = 1; + answer(); + expect(A, "0/PCMU/8000"); + expect(B, "0/PCMU/8000 8/PCMA/8000 9/G722/8000"); + end(); + return 0; }