diff --git a/daemon/codec.c b/daemon/codec.c index 183f29dae..00f064b35 100644 --- a/daemon/codec.c +++ b/daemon/codec.c @@ -512,12 +512,32 @@ static int __dtmf_payload_type(GHashTable *supplemental_sinks, struct rtp_payloa return dtmf_payload_type; } -static int __unused_pt_number(struct call_media *media, int num) { +static int __unused_pt_number(struct call_media *media, struct call_media *other_media, + struct rtp_payload_type *pt) +{ + int num = pt ? pt->payload_type : -1; + struct rtp_payload_type *pt_match; + if (num < 0) num = 96; // default first dynamic payload type number while (1) { - if (!g_hash_table_lookup(media->codecs_recv, &num)) - break; // OK + if ((pt_match = g_hash_table_lookup(media->codecs_recv, &num))) + goto next; + if ((pt_match = g_hash_table_lookup(media->codecs_send, &num))) + goto next; + if (other_media) { + if ((pt_match = g_hash_table_lookup(other_media->codecs_recv, &num))) + goto next; + if ((pt_match = g_hash_table_lookup(other_media->codecs_send, &num))) + goto next; + } + // OK + break; + +next: + // is this actually the same? + if (pt && !rtp_payload_type_cmp_nf(pt, pt_match)) + break; num++; if (num < 96) // if an RFC type was taken already num = 96; @@ -587,7 +607,7 @@ static void __accept_transcode_codecs(struct call_media *receiver, struct call_m // PT collision. We must renumber one of the entries. `pt` is taken // from the send list, so the PT should remain the same. Renumber // the existing entry. - int new_pt = __unused_pt_number(receiver, existing_pt->payload_type); + int new_pt = __unused_pt_number(receiver, sink, existing_pt); if (new_pt < 0) { ilog(LOG_WARN, "Ran out of RTP payload type numbers while accepting '" STR_FORMAT "' due to '" STR_FORMAT "'", @@ -1163,7 +1183,10 @@ void codec_handlers_update(struct call_media *receiver, struct call_media *sink, goto transcode; } - // XXX check format parameters as well + // XXX needs more intelligent fmtp matching + if (rtp_payload_type_cmp_nf(pt, dest_pt)) + goto transcode; + ilog(LOG_DEBUG, "Sink supports codec " STR_FORMAT, STR_FMT(&pt->encoding_with_params)); __make_passthrough_gsl(handler, &passthrough_handlers); if (pt->codec_def && pt->codec_def->dtmf) @@ -2486,7 +2509,9 @@ err: } -static struct rtp_payload_type *codec_add_payload_type(const str *codec, struct call_media *media) { +static struct rtp_payload_type *codec_add_payload_type(const str *codec, struct call_media *media, + struct call_media *other_media) +{ struct rtp_payload_type *pt = codec_make_payload_type_sup(codec, media); if (!pt) { ilog(LOG_WARN, "Codec '" STR_FORMAT "' requested for transcoding is not supported", @@ -2496,7 +2521,7 @@ static struct rtp_payload_type *codec_add_payload_type(const str *codec, struct if (pt == (void *) 0x1) return NULL; - pt->payload_type = __unused_pt_number(media, pt->payload_type); + pt->payload_type = __unused_pt_number(media, other_media, pt); if (pt->payload_type < 0) { ilog(LOG_WARN, "Ran out of RTP payload type numbers while adding codec '" STR_FORMAT "' for transcoding", @@ -2789,7 +2814,7 @@ void codec_tracker_finish(struct call_media *media) { str pt_str; str_init(&pt_str, pt_s); - struct rtp_payload_type *pt = codec_add_payload_type(&pt_str, media); + struct rtp_payload_type *pt = codec_add_payload_type(&pt_str, media, NULL); if (!pt) continue; pt->for_transcoding = 1; @@ -2971,7 +2996,7 @@ void codec_rtp_payload_types(struct call_media *media, struct call_media *other_ } // create new payload type - pt = codec_add_payload_type(codec, media); + pt = codec_add_payload_type(codec, media, other_media); if (!pt) continue; pt->for_transcoding = 1; @@ -3003,10 +3028,10 @@ void codec_rtp_payload_types(struct call_media *media, struct call_media *other_ // XXX can we improve the codec lookup/synthesis? static const str PCMU_str = STR_CONST_INIT("PCMU"); static const str PCMA_str = STR_CONST_INIT("PCMA"); - pt = codec_add_payload_type(&PCMU_str, media); + pt = codec_add_payload_type(&PCMU_str, media, NULL); assert(pt != NULL); __rtp_payload_type_add_recv(media, pt, 1); - pt = codec_add_payload_type(&PCMA_str, media); + pt = codec_add_payload_type(&PCMA_str, media, NULL); assert(pt != NULL); __rtp_payload_type_add_recv(media, pt, 1); diff --git a/t/auto-daemon-tests.pl b/t/auto-daemon-tests.pl index b4fcda659..b4244d9f6 100755 --- a/t/auto-daemon-tests.pl +++ b/t/auto-daemon-tests.pl @@ -198,6 +198,52 @@ exit; +new_call; + +offer('dup codec number', { + codec => { + mask => ['all'], + transcode => ['G722', 'opus/48000/1//test=1', 'speex', 'PCMA', 'telephone-event'], + } +}, <