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