From d04c4c2c1b9fda2d997e5aaf091a7d83806e1eff Mon Sep 17 00:00:00 2001 From: Richard Fuchs Date: Tue, 6 Oct 2020 08:33:24 -0400 Subject: [PATCH] TT#92250 keep supplemental codecs last in list when transcoding Change-Id: I3172414fd724e5c5fe9d69b5a78270bed41f83b6 (cherry picked from commit 5ac91499fec4d99fbe871ccf57c1fae23b3d5aa8) --- daemon/codec.c | 48 ++++++++++++++++++++++++++++++++++-------- daemon/redis.c | 2 +- include/codec.h | 2 +- t/auto-daemon-tests.pl | 40 +++++++++++++++++------------------ t/transcode-test.c | 8 +++---- 5 files changed, 65 insertions(+), 35 deletions(-) diff --git a/daemon/codec.c b/daemon/codec.c index 0ca5b7c39..34691ac57 100644 --- a/daemon/codec.c +++ b/daemon/codec.c @@ -623,7 +623,7 @@ static void __symmetric_codecs(struct call_media *receiver, struct call_media *s // add it to the list ilog(LOG_DEBUG, "Adding symmetric RTP payload type %i", pt->payload_type); g_hash_table_steal(prefs_recv, GINT_TO_POINTER(pt->payload_type)); - __rtp_payload_type_add_recv(receiver, out_pt); + __rtp_payload_type_add_recv(receiver, out_pt, 1); // and our send leg out_pt = g_hash_table_lookup(prefs_send, GINT_TO_POINTER(pt->payload_type)); if (out_pt) { @@ -648,7 +648,7 @@ static void __symmetric_codecs(struct call_media *receiver, struct call_media *s if (!out_pt) continue; g_hash_table_steal(prefs_recv, ptype); - __rtp_payload_type_add_recv(receiver, out_pt); + __rtp_payload_type_add_recv(receiver, out_pt, 1); } while (prefs_send_order.length) { void *ptype = g_queue_pop_head(&prefs_send_order); @@ -2187,12 +2187,42 @@ static void __rtp_payload_type_add_name(GHashTable *ht, struct rtp_payload_type q = g_hash_table_lookup_queue_new(ht, &pt->encoding_with_params); g_queue_push_tail(q, GUINT_TO_POINTER(pt->payload_type)); } +static void __queue_insert_supp(GQueue *q, struct rtp_payload_type *pt, int supp_check) { + // do we care at all? + if (!supp_check) { + g_queue_push_tail(q, pt); + return; + } + + // all new supp codecs go last + if (pt->codec_def && pt->codec_def->supplemental) { + g_queue_push_tail(q, pt); + return; + } + + // find the cut-off point between non-supp and supp codecs + GList *insert_pos = NULL; // last non-supp codec + for (GList *l = q->tail; l; l = l->prev) { + struct rtp_payload_type *ptt = l->data; + if (!ptt->codec_def || !ptt->codec_def->supplemental) { + insert_pos = l; + break; + } + } + // do we have any non-supp codecs? + if (!insert_pos) { + g_queue_push_head(q, pt); + return; + } + g_queue_insert_after(q, insert_pos, pt); +} // consumes 'pt' void __rtp_payload_type_add_recv(struct call_media *media, - struct rtp_payload_type *pt) + struct rtp_payload_type *pt, int supp_check) { if (!pt) return; + ensure_codec_def(pt, media); if (proto_is_not_rtp(media->protocol)) { payload_type_free(pt); return; @@ -2202,7 +2232,7 @@ void __rtp_payload_type_add_recv(struct call_media *media, pt->ptime = media->ptime; g_hash_table_insert(media->codecs_recv, &pt->payload_type, pt); __rtp_payload_type_add_name(media->codec_names_recv, pt); - g_queue_push_tail(&media->codecs_prefs_recv, pt); + __queue_insert_supp(&media->codecs_prefs_recv, pt, supp_check); } // consumes 'pt' void __rtp_payload_type_add_send(struct call_media *other_media, @@ -2235,7 +2265,7 @@ static void __rtp_payload_type_add(struct call_media *media, struct call_media * struct rtp_payload_type *pt) { __rtp_payload_type_add_send_dup(other_media, pt); - __rtp_payload_type_add_recv(media, pt); + __rtp_payload_type_add_recv(media, pt, 0); } static void __payload_queue_free(void *qq) { @@ -2396,7 +2426,7 @@ void codec_rtp_payload_types(struct call_media *media, struct call_media *other_ ilog(LOG_DEBUG, "Codec '" STR_FORMAT "' added for transcoding with payload type %u", STR_FMT(&pt->encoding_with_params), pt->payload_type); - __rtp_payload_type_add_recv(media, pt); + __rtp_payload_type_add_recv(media, pt, 1); } if (media->type_id == MT_AUDIO && other_media->type_id == MT_IMAGE) { @@ -2412,7 +2442,7 @@ void codec_rtp_payload_types(struct call_media *media, struct call_media *other_ if (media->t38_gateway && media->t38_gateway->pcm_player && media->t38_gateway->pcm_player->handler) __rtp_payload_type_add_recv(media, - __rtp_payload_type_copy(&media->t38_gateway->pcm_player->handler->dest_pt)); + __rtp_payload_type_copy(&media->t38_gateway->pcm_player->handler->dest_pt), 1); } else if (flags->opmode == OP_OFFER) { // T.38 -> audio transcoder, initial offer, and no codecs have been given. @@ -2422,10 +2452,10 @@ void codec_rtp_payload_types(struct call_media *media, struct call_media *other_ static const str PCMA_str = STR_CONST_INIT("PCMA"); pt = codec_add_payload_type(&PCMU_str, media); assert(pt != NULL); - __rtp_payload_type_add_recv(media, pt); + __rtp_payload_type_add_recv(media, pt, 1); pt = codec_add_payload_type(&PCMA_str, media); assert(pt != NULL); - __rtp_payload_type_add_recv(media, pt); + __rtp_payload_type_add_recv(media, pt, 1); ilog(LOG_DEBUG, "Using default codecs PCMU and PCMA for T.38 gateway"); } diff --git a/daemon/redis.c b/daemon/redis.c index 11d10ddcc..a92dfd1d4 100644 --- a/daemon/redis.c +++ b/daemon/redis.c @@ -1271,7 +1271,7 @@ static struct rtp_payload_type *rbl_cb_plts_g(str *s, GQueue *q, struct redis_li } static int rbl_cb_plts_r(str *s, GQueue *q, struct redis_list *list, void *ptr) { struct call_media *med = ptr; - __rtp_payload_type_add_recv(med, rbl_cb_plts_g(s, q, list, ptr)); + __rtp_payload_type_add_recv(med, rbl_cb_plts_g(s, q, list, ptr), 0); return 0; } static int rbl_cb_plts_s(str *s, GQueue *q, struct redis_list *list, void *ptr) { diff --git a/include/codec.h b/include/codec.h index 054f0a2f0..262d2eeee 100644 --- a/include/codec.h +++ b/include/codec.h @@ -77,7 +77,7 @@ void codec_init_payload_type(struct rtp_payload_type *, struct call_media *); // used by redis -void __rtp_payload_type_add_recv(struct call_media *media, struct rtp_payload_type *pt); +void __rtp_payload_type_add_recv(struct call_media *media, struct rtp_payload_type *pt, int supp_check); void __rtp_payload_type_add_send(struct call_media *other_media, struct rtp_payload_type *pt); diff --git a/t/auto-daemon-tests.pl b/t/auto-daemon-tests.pl index a8cbaed19..9cd79d42e 100755 --- a/t/auto-daemon-tests.pl +++ b/t/auto-daemon-tests.pl @@ -296,11 +296,11 @@ o=dev 623840 205550 IN IP4 8.8.8.61 s=SIP Media Capabilities c=IN IP4 203.0.113.1 t=0 0 -m=audio PORT RTP/AVP 101 0 9 +m=audio PORT RTP/AVP 0 9 101 a=maxptime:20 -a=rtpmap:101 telephone-event/8000 a=rtpmap:0 PCMU/8000 a=rtpmap:9 G722/8000 +a=rtpmap:101 telephone-event/8000 a=fmtp:101 0-15 a=sendrecv a=rtcp:PORT @@ -362,11 +362,11 @@ o=dev 623840 205550 IN IP4 8.8.8.61 s=SIP Media Capabilities c=IN IP4 203.0.113.1 t=0 0 -m=audio PORT RTP/AVP 101 0 9 +m=audio PORT RTP/AVP 0 9 101 a=maxptime:20 -a=rtpmap:101 telephone-event/8000 a=rtpmap:0 PCMU/8000 a=rtpmap:9 G722/8000 +a=rtpmap:101 telephone-event/8000 a=fmtp:101 0-15 a=sendrecv a=rtcp:PORT @@ -2135,12 +2135,12 @@ o=- 1822058533 1822058533 IN IP4 1.2.3.4 s=Asterisk c=IN IP4 203.0.113.1 t=0 0 -m=audio PORT RTP/AVP 8 107 101 9 +m=audio PORT RTP/AVP 8 107 9 101 a=maxptime:20 a=rtpmap:8 PCMA/8000 a=rtpmap:107 opus/48000/2 -a=rtpmap:101 telephone-event/8000 a=rtpmap:9 G722/8000 +a=rtpmap:101 telephone-event/8000 a=fmtp:101 0-16 a=sendrecv a=rtcp:PORT @@ -2210,12 +2210,12 @@ o=- 1822058533 1822058533 IN IP4 1.2.3.4 s=Asterisk c=IN IP4 203.0.113.1 t=0 0 -m=audio PORT RTP/AVP 8 107 101 9 +m=audio PORT RTP/AVP 8 107 9 101 a=maxptime:20 a=rtpmap:8 PCMA/8000 a=rtpmap:107 opus/48000/2 -a=rtpmap:101 telephone-event/8000 a=rtpmap:9 G722/8000 +a=rtpmap:101 telephone-event/8000 a=fmtp:101 0-16 a=sendrecv a=rtcp:PORT @@ -2282,12 +2282,12 @@ o=- 1822058533 1822058533 IN IP4 1.2.3.4 s=Asterisk c=IN IP4 203.0.113.1 t=0 0 -m=audio PORT RTP/AVP 8 107 101 9 +m=audio PORT RTP/AVP 8 107 9 101 a=maxptime:20 a=rtpmap:8 PCMA/8000 a=rtpmap:107 opus/48000/2 -a=rtpmap:101 telephone-event/8000 a=rtpmap:9 G722/8000 +a=rtpmap:101 telephone-event/8000 a=fmtp:101 0-16 a=sendrecv a=rtcp:PORT @@ -2357,12 +2357,12 @@ o=- 1822058533 1822058533 IN IP4 1.2.3.4 s=Asterisk c=IN IP4 203.0.113.1 t=0 0 -m=audio PORT RTP/AVP 8 107 101 9 +m=audio PORT RTP/AVP 8 107 9 101 a=maxptime:20 a=rtpmap:8 PCMA/8000 a=rtpmap:107 opus/48000/2 -a=rtpmap:101 telephone-event/8000 a=rtpmap:9 G722/8000 +a=rtpmap:101 telephone-event/8000 a=fmtp:101 0-16 a=sendrecv a=rtcp:PORT @@ -2433,12 +2433,12 @@ o=- 1822058533 1822058533 IN IP4 1.2.3.4 s=Asterisk c=IN IP4 203.0.113.1 t=0 0 -m=audio PORT RTP/AVP 8 107 101 9 +m=audio PORT RTP/AVP 8 107 9 101 a=maxptime:20 a=rtpmap:8 PCMA/8000 a=rtpmap:107 opus/48000/2 -a=rtpmap:101 telephone-event/8000 a=rtpmap:9 G722/8000 +a=rtpmap:101 telephone-event/8000 a=fmtp:101 0-16 a=sendrecv a=rtcp:PORT @@ -2503,12 +2503,12 @@ o=- 1822058533 1822058533 IN IP4 1.2.3.4 s=Asterisk c=IN IP4 203.0.113.1 t=0 0 -m=audio PORT RTP/AVP 8 107 101 9 +m=audio PORT RTP/AVP 8 107 9 101 a=maxptime:20 a=rtpmap:8 PCMA/8000 a=rtpmap:107 opus/48000/2 -a=rtpmap:101 telephone-event/8000 a=rtpmap:9 G722/8000 +a=rtpmap:101 telephone-event/8000 a=fmtp:101 0-16 a=sendrecv a=rtcp:PORT @@ -3688,11 +3688,11 @@ v=0 o=- 1545997027 1 IN IP4 203.0.113.1 s=tester t=0 0 -m=audio PORT RTP/AVP 0 96 8 +m=audio PORT RTP/AVP 0 8 96 c=IN IP4 203.0.113.1 a=rtpmap:0 PCMU/8000 -a=rtpmap:96 telephone-event/8000 a=rtpmap:8 PCMA/8000 +a=rtpmap:96 telephone-event/8000 a=sendrecv a=rtcp:PORT SDP @@ -7533,11 +7533,11 @@ v=0 o=- 1545997027 1 IN IP4 203.0.113.1 s=tester t=0 0 -m=audio PORT RTP/AVP 100 101 8 96 +m=audio PORT RTP/AVP 100 8 101 96 c=IN IP4 203.0.113.1 a=rtpmap:100 PCMU/16000 -a=rtpmap:101 telephone-event/16000 a=rtpmap:8 PCMA/8000 +a=rtpmap:101 telephone-event/16000 a=rtpmap:96 telephone-event/8000 a=fmtp:101 0-15 a=fmtp:96 0-15 diff --git a/t/transcode-test.c b/t/transcode-test.c index 7c1473f8f..fd744dcfa 100644 --- a/t/transcode-test.c +++ b/t/transcode-test.c @@ -888,14 +888,14 @@ int main(void) { offer(); expect(A, recv, ""); expect(A, send, "8/PCMA/8000 101/telephone-event/8000"); - expect(B, recv, "8/PCMA/8000 101/telephone-event/8000 0/PCMU/8000"); + expect(B, recv, "8/PCMA/8000 0/PCMU/8000 101/telephone-event/8000"); expect(B, send, ""); sdp_pt(0, PCMU, 8000); sdp_pt(101, telephone-event, 8000); answer(); expect(A, recv, "8/PCMA/8000 101/telephone-event/8000"); expect(A, send, "8/PCMA/8000 101/telephone-event/8000"); - expect(B, recv, "101/telephone-event/8000 0/PCMU/8000"); + expect(B, recv, "0/PCMU/8000 101/telephone-event/8000"); expect(B, send, "0/PCMU/8000 101/telephone-event/8000"); packet_seq(A, 8, PCMA_payload, 1000000, 200, 0, PCMU_payload); // start with marker @@ -1061,14 +1061,14 @@ int main(void) { offer(); expect(A, recv, ""); expect(A, send, "8/PCMA/8000 101/telephone-event/8000"); - expect(B, recv, "8/PCMA/8000 101/telephone-event/8000 0/PCMU/8000"); + expect(B, recv, "8/PCMA/8000 0/PCMU/8000 101/telephone-event/8000"); expect(B, send, ""); sdp_pt(0, PCMU, 8000); sdp_pt(101, telephone-event, 8000); answer(); expect(A, recv, "8/PCMA/8000 101/telephone-event/8000"); expect(A, send, "8/PCMA/8000 101/telephone-event/8000"); - expect(B, recv, "101/telephone-event/8000 0/PCMU/8000"); + expect(B, recv, "0/PCMU/8000 101/telephone-event/8000"); expect(B, send, "0/PCMU/8000 101/telephone-event/8000"); packet_seq(A, 8, PCMA_payload, 1000000, 200, 0, PCMU_payload); // start with marker