From a1d8bf25906247c0a5a68c731ceb12dd7079de6f Mon Sep 17 00:00:00 2001 From: Richard Fuchs Date: Tue, 7 Nov 2023 11:10:16 -0500 Subject: [PATCH] MT#55283 add codec_store_merge() and logic During an offer, we update the codecs from the given list not only on the side of the offerer, but also on the answerer's side, in order to perform the codec answer routine during the answer phase. While doing this, we empty out the existing list of codecs (on both sides) and repopulate it fresh from the given list. This can cause problems during a reverse re-invite, when the list of codecs on the answerer's side already contained the codecs that had been offered before. When setting up the new re-invite offer, we want to retain codecs (and their payload types and format parameters) that were already in place, instead of recreating a new list from scratch. Improve this by adding a `merge_cs` option to the populating functions, which points back to the stream_params codec_store. Codecs that would have been removed from the codec_store during the repopulation are then moved back into the stream_params codec_store instead. This then allows the functions adding new codecs to the list (offer/transcode) to reference these codecs that were previously in place, and so they can be added back with the same options as they had existed before, instead of recreating them from scratch. Change-Id: I53e7ab10e9144a308a5c36be5ebfddd73c212f06 --- daemon/call.c | 8 +++++--- daemon/codec.c | 44 +++++++++++++++++++++++++++++++----------- include/codec.h | 1 + t/auto-daemon-tests.pl | 11 +++++------ 4 files changed, 44 insertions(+), 20 deletions(-) diff --git a/daemon/call.c b/daemon/call.c index 1a6768ff9..9616941a8 100644 --- a/daemon/call.c +++ b/daemon/call.c @@ -2424,14 +2424,16 @@ static void codecs_offer(struct call_media *media, struct call_media *other_medi if (update_answerer) { // update/create answer/receiver side - ilogs(codec, LOG_DEBUG, "Updating codecs for answerer " STR_FORMAT " #%u", + ilogs(codec, LOG_DEBUG, "Updating offer codecs for answerer " STR_FORMAT " #%u", STR_FMT(&media->monologue->tag), media->index); if (flags && flags->reuse_codec) - codec_store_populate_reuse(&media->codecs, &sp->codecs); + codec_store_populate_reuse(&media->codecs, &sp->codecs, + .merge_cs = &sp->codecs); else codec_store_populate(&media->codecs, &sp->codecs, - .allow_asymmetric = !!(flags && flags->allow_asymmetric_codecs)); + .allow_asymmetric = !!(flags && flags->allow_asymmetric_codecs), + .merge_cs = &sp->codecs); } if (flags) { codec_store_strip(&media->codecs, &flags->codec_strip, flags->codec_except); diff --git a/daemon/codec.c b/daemon/codec.c index 8e1571659..367f5192d 100644 --- a/daemon/codec.c +++ b/daemon/codec.c @@ -4987,16 +4987,17 @@ void __codec_store_populate_reuse(struct codec_store *dst, struct codec_store *s pt->payload_type); } } - if(dst->codec_prefs.head){ - for (GList *l = dst->codec_prefs.head; l;) { - struct rtp_payload_type *pt = l->data; - struct rtp_payload_type *orig_pt = g_hash_table_lookup(src->codecs, - GINT_TO_POINTER(pt->payload_type)); - if(!orig_pt){ - l = __codec_store_delete_link(l, dst); - }else{ - l = l->next; - } + for (GList *l = dst->codec_prefs.head; l;) { + struct rtp_payload_type *pt = l->data; + struct rtp_payload_type *orig_pt = g_hash_table_lookup(src->codecs, + GINT_TO_POINTER(pt->payload_type)); + if(!orig_pt){ + if (a.merge_cs) + codec_store_add_raw_link(src, rtp_payload_type_dup(pt), + src->codec_prefs.head); + l = __codec_store_delete_link(l, dst); + }else{ + l = l->next; } } } @@ -5011,6 +5012,24 @@ void codec_store_check_empty(struct codec_store *dst, struct codec_store *src) { codec_store_populate(dst, src); } +static void codec_store_merge(struct codec_store *dst, struct codec_store *src) { + while (src->codec_prefs.length) { + struct rtp_payload_type *pt = g_queue_pop_tail(&src->codec_prefs); + + // src codecs take preference over existing entries in dst: if there's + // a collision in payload types, remove the existing entry in dst, + // then replace with the entry from src + struct rtp_payload_type *old_pt = g_hash_table_lookup(dst->codecs, + GINT_TO_POINTER(pt->payload_type)); + if (old_pt) + __codec_store_delete_link(old_pt->prefs_link, dst); + + codec_store_add_raw_link(dst, pt, dst->codec_prefs.head); + } + + codec_store_cleanup(src); +} + void __codec_store_populate(struct codec_store *dst, struct codec_store *src, struct codec_store_args a) { // start fresh struct codec_store orig_dst; @@ -5059,7 +5078,10 @@ void __codec_store_populate(struct codec_store *dst, struct codec_store *src, st codec_store_add_end(dst, pt); } - codec_store_cleanup(&orig_dst); + if (a.merge_cs) + codec_store_merge(a.merge_cs, &orig_dst); + else + codec_store_cleanup(&orig_dst); } void codec_store_strip(struct codec_store *cs, GQueue *strip, GHashTable *except) { diff --git a/include/codec.h b/include/codec.h index bf214f681..0a828fb64 100644 --- a/include/codec.h +++ b/include/codec.h @@ -115,6 +115,7 @@ struct codec_store_args { GHashTable *codec_set; bool answer_only; bool allow_asymmetric; + struct codec_store *merge_cs; }; __attribute__((nonnull(1))) diff --git a/t/auto-daemon-tests.pl b/t/auto-daemon-tests.pl index 4ac7a2916..552120b8f 100755 --- a/t/auto-daemon-tests.pl +++ b/t/auto-daemon-tests.pl @@ -326,14 +326,13 @@ s=- t=0 0 a=extmap-allow-mixed a=msid-semantic: WMS 4d091157-8680-47a2-b124-36b52fefea19 -m=audio PORT RTP/AVP 0 8 9 96 +m=audio PORT RTP/AVP 126 0 8 9 c=IN IP4 203.0.113.1 a=mid:1 +a=rtpmap:126 telephone-event/8000 a=rtpmap:0 PCMU/8000 a=rtpmap:8 PCMA/8000 a=rtpmap:9 G722/8000 -a=rtpmap:96 telephone-event/8000 -a=fmtp:96 0-15 a=ssrc:572293880 cname:pHBBuw7Qa5BaQ36a a=msid:4d091157-8680-47a2-b124-36b52fefea19 ed2eaf3a-926c-4c1a-a315-e02458e05292 a=sendrecv @@ -380,14 +379,13 @@ s=- t=0 0 a=extmap-allow-mixed a=msid-semantic: WMS 4d091157-8680-47a2-b124-36b52fefea19 -m=audio PORT RTP/AVP 0 8 9 96 +m=audio PORT RTP/AVP 126 0 8 9 c=IN IP4 203.0.113.1 a=mid:1 +a=rtpmap:126 telephone-event/8000 a=rtpmap:0 PCMU/8000 a=rtpmap:8 PCMA/8000 a=rtpmap:9 G722/8000 -a=rtpmap:96 telephone-event/8000 -a=fmtp:96 0-15 a=ssrc:572293880 cname:pHBBuw7Qa5BaQ36a a=msid:4d091157-8680-47a2-b124-36b52fefea19 ed2eaf3a-926c-4c1a-a315-e02458e05292 a=sendrecv @@ -10200,6 +10198,7 @@ m=audio PORT RTP/AVP 0 9 101 a=maxptime:20 a=rtpmap:0 PCMU/8000 a=rtpmap:9 G722/8000 +a=fmtp:9 bitrate=64 a=rtpmap:101 telephone-event/8000 a=fmtp:101 0-15 a=sendrecv