diff --git a/daemon/call_interfaces.c b/daemon/call_interfaces.c index d7eea712c..0fdcece04 100644 --- a/daemon/call_interfaces.c +++ b/daemon/call_interfaces.c @@ -810,8 +810,9 @@ static void call_ng_flags_flags(struct sdp_ng_flags *out, str *s, void *dummy) { case CSH_LOOKUP("original-sendrecv"): out->original_sendrecv = 1; break; - case CSH_LOOKUP("always-transcode"): - out->always_transcode = 1; + case CSH_LOOKUP("always-transcode"):; + static const str str_all = STR_CONST_INIT("all"); + call_ng_flags_str_ht(out, (str *) &str_all, &out->codec_accept); break; case CSH_LOOKUP("asymmetric-codecs"): out->asymmetric_codecs = 1; @@ -862,20 +863,20 @@ static void call_ng_flags_flags(struct sdp_ng_flags *out, str *s, void *dummy) { if (call_ng_flags_prefix(out, s, "codec-mask-", call_ng_flags_str_ht, &out->codec_mask)) return; - if (call_ng_flags_prefix(out, s, "codec-set-", call_ng_flags_str_ht_split, - &out->codec_set)) - return; - if (call_ng_flags_prefix(out, s, "codec-accept-", call_ng_flags_str_ht, - &out->codec_accept)) - return; - if (call_ng_flags_prefix(out, s, "codec-consume-", call_ng_flags_str_ht, - &out->codec_consume)) - return; if (call_ng_flags_prefix(out, s, "T38-", ng_t38_option, NULL)) return; if (call_ng_flags_prefix(out, s, "T.38-", ng_t38_option, NULL)) return; } + if (call_ng_flags_prefix(out, s, "codec-set-", call_ng_flags_str_ht_split, + &out->codec_set)) + return; + if (call_ng_flags_prefix(out, s, "codec-accept-", call_ng_flags_str_ht, + &out->codec_accept)) + return; + if (call_ng_flags_prefix(out, s, "codec-consume-", call_ng_flags_str_ht, + &out->codec_consume)) + return; #endif ilog(LOG_WARN, "Unknown flag encountered: '" STR_FORMAT "'", diff --git a/daemon/codec.c b/daemon/codec.c index c6d8dcd2d..164cc1f11 100644 --- a/daemon/codec.c +++ b/daemon/codec.c @@ -523,7 +523,7 @@ static void __check_send_codecs(struct call_media *receiver, struct call_media * // even if the receiver can receive the same codec that the sink can // send, we might still have it configured as a transcoder due to - // always-transcode in the offer + // force accepted codec in the offer struct codec_handler *ch_recv = g_hash_table_lookup(sink->codec_handlers, GINT_TO_POINTER(recv_pt->payload_type)); if (!ch_recv) @@ -1310,7 +1310,7 @@ void codec_handlers_update(struct call_media *receiver, struct call_media *sink, // do we need to detect PCM DTMF tones? int pcm_dtmf_detect = 0; - if ((MEDIA_ISSET(sink, TRANSCODE) || (flags && flags->always_transcode)) + if ((MEDIA_ISSET(sink, TRANSCODE) || (sink_transcoding & 0x2)) && dtmf_payload_type != -1 && dtmf_pt && (!reverse_dtmf_pt || reverse_dtmf_pt->for_transcoding || !g_hash_table_lookup(receiver->codecs_send, &dtmf_payload_type))) @@ -1364,11 +1364,11 @@ void codec_handlers_update(struct call_media *receiver, struct call_media *sink, GQueue *dest_codecs = NULL; if (pref_dest_codec->for_transcoding) { - // with always-transcode, we still accept DTMF payloads if possible + // with force accepted codec, we still accept DTMF payloads if possible if (pt->codec_def && pt->codec_def->supplemental) dest_codecs = g_hash_table_lookup(sink->codec_names_send, &pt->encoding); } - else if (!flags || !flags->always_transcode) { + else { // we ignore output codec matches if we must transcode supp codecs if ((dtmf_pt_match == 1 || cn_pt_match == 1) && MEDIA_ISSET(sink, TRANSCODE)) ; @@ -1377,11 +1377,6 @@ void codec_handlers_update(struct call_media *receiver, struct call_media *sink, else dest_codecs = g_hash_table_lookup(sink->codec_names_send, &pt->encoding); } - else if (flags->always_transcode) { - // with always-transcode, we still accept DTMF payloads if possible - if (pt->codec_def && pt->codec_def->supplemental) - dest_codecs = g_hash_table_lookup(sink->codec_names_send, &pt->encoding); - } if (dest_codecs) { // the sink supports this codec - check offered formats dest_pt = NULL; @@ -3284,7 +3279,7 @@ void codec_rtp_payload_types(struct call_media *media, struct call_media *other_ static const str str_full = STR_CONST_INIT("full"); GHashTable *stripped = g_hash_table_new_full(str_case_hash, str_case_equal, free, __payload_queue_free); GHashTable *masked = g_hash_table_new_full(str_case_hash, str_case_equal, free, __payload_queue_free); - int strip_all = 0, mask_all = 0, consume_all = 0; + int strip_all = 0, mask_all = 0, consume_all = 0, accept_all = 0; // start fresh if (!proto_is_rtp(other_media->protocol) && proto_is_rtp(media->protocol) && flags->opmode == OP_OFFER) { @@ -3317,6 +3312,8 @@ void codec_rtp_payload_types(struct call_media *media, struct call_media *other_ consume_all = 1; else if (flags->codec_consume && g_hash_table_lookup(flags->codec_consume, &str_full)) consume_all = 2; + if (flags->codec_accept && g_hash_table_lookup(flags->codec_accept, &str_all)) + accept_all = 1; __ht_merge(&flags->codec_except, flags->codec_consume); __ht_merge(&flags->codec_except, flags->codec_accept); @@ -3350,6 +3347,11 @@ void codec_rtp_payload_types(struct call_media *media, struct call_media *other_ #ifdef WITH_TRANSCODING codec_touched(pt, media); #endif + // special case for handling of the legacy always-transcode flag (= accept-all) + // in combination with codec-mask + if (accept_all) + pt->for_transcoding = 1; + GQueue *q = g_hash_table_lookup_queue_new(masked, str_dup(&pt->encoding), free); g_queue_push_tail(q, __rtp_payload_type_copy(pt)); q = g_hash_table_lookup_queue_new(masked, str_dup(&pt->encoding_with_params), free); @@ -3369,7 +3371,7 @@ void codec_rtp_payload_types(struct call_media *media, struct call_media *other_ g_queue_push_tail(q, __rtp_payload_type_copy(pt)); __rtp_payload_type_add_send(other_media, pt); } - else if (__codec_ht_except(0, flags->codec_accept, NULL, pt)) { + else if (__codec_ht_except(accept_all, flags->codec_accept, NULL, pt)) { ilog(LOG_DEBUG, "Accepting codec '" STR_FORMAT "'", STR_FMT(&pt->encoding_with_params)); #ifdef WITH_TRANSCODING diff --git a/include/call_interfaces.h b/include/call_interfaces.h index 8f3f8ea25..d839866b9 100644 --- a/include/call_interfaces.h +++ b/include/call_interfaces.h @@ -91,7 +91,6 @@ struct sdp_ng_flags { record_call:1, loop_protect:1, original_sendrecv:1, - always_transcode:1, asymmetric_codecs:1, symmetric_codecs:1, single_codec:1, diff --git a/t/transcode-test.c b/t/transcode-test.c index da483efcc..983dbf64c 100644 --- a/t/transcode-test.c +++ b/t/transcode-test.c @@ -39,10 +39,20 @@ static struct call_media *media_A; static struct call_media *media_B; struct call_monologue ml_A; struct call_monologue ml_B; -static GQueue rtp_types; +static GQueue rtp_types = G_QUEUE_INIT; #define start() __start(__FILE__, __LINE__) +static void __init(void) { + g_queue_clear(&rtp_types); + memset(&flags, 0, sizeof(flags)); + flags.codec_strip = g_hash_table_new_full(str_case_hash, str_case_equal, free, NULL); + flags.codec_mask = g_hash_table_new_full(str_case_hash, str_case_equal, free, NULL); + flags.codec_except = g_hash_table_new_full(str_case_hash, str_case_equal, free, NULL); + flags.codec_set = g_hash_table_new_full(str_case_hash, str_case_equal, free, free); + flags.codec_consume = g_hash_table_new_full(str_case_hash, str_case_equal, free, NULL); + flags.codec_accept = g_hash_table_new_full(str_case_hash, str_case_equal, free, NULL); +} static void __start(const char *file, int line) { printf("running test %s:%i\n", file, line); rtp_ts_ht = g_hash_table_new(g_direct_hash, g_direct_equal); @@ -53,7 +63,6 @@ static void __start(const char *file, int line) { call.ssrc_hash = create_ssrc_hash_call(); call.tags = g_hash_table_new(g_str_hash, g_str_equal); str_init(&call.callid, "test-call"); - flags = (struct sdp_ng_flags) {0,}; bencode_buffer_init(&call.buffer); media_A = call_media_new(&call); // originator media_B = call_media_new(&call); // output destination @@ -65,13 +74,7 @@ static void __start(const char *file, int line) { str_init(&ml_B.tag, "tag_B"); media_B->monologue = &ml_B; media_B->protocol = &transport_protocols[PROTO_RTP_AVP]; - g_queue_init(&rtp_types); // parsed from received SDP - flags.codec_strip = g_hash_table_new_full(str_case_hash, str_case_equal, free, NULL); - flags.codec_mask = g_hash_table_new_full(str_case_hash, str_case_equal, free, NULL); - flags.codec_except = g_hash_table_new_full(str_case_hash, str_case_equal, free, NULL); - flags.codec_set = g_hash_table_new_full(str_case_hash, str_case_equal, free, free); - flags.codec_consume = g_hash_table_new_full(str_case_hash, str_case_equal, free, NULL); - flags.codec_accept = g_hash_table_new_full(str_case_hash, str_case_equal, free, NULL); + __init(); } #define transcode(codec) g_queue_push_tail(&flags.codec_transcode, sdup(#codec)) @@ -94,6 +97,12 @@ static void codec_set(char *c) { } #endif +static void __ht_set(GHashTable *h, char *x) { + str *d = sdup(x); + g_hash_table_insert(h, d, d); +} +#define ht_set(ht, s) __ht_set(flags.ht, #s) + #define sdp_pt_fmt(num, codec, clockrate, fmt) \ __sdp_pt_fmt(num, (str) STR_CONST_INIT(#codec), clockrate, (str) STR_CONST_INIT(#codec "/" #clockrate), \ (str) STR_CONST_INIT(fmt)) @@ -114,8 +123,7 @@ static void offer(void) { codec_rtp_payload_types(media_B, media_A, &rtp_types, &flags); codec_handlers_update(media_B, media_A, &flags, NULL); codec_tracker_finish(media_B); - g_queue_clear(&rtp_types); - memset(&flags, 0, sizeof(flags)); + __init(); } static void answer(void) { @@ -125,8 +133,7 @@ static void answer(void) { codec_rtp_payload_types(media_A, media_B, &rtp_types, &flags); codec_handlers_update(media_A, media_B, &flags, NULL); codec_tracker_finish(media_A); - g_queue_clear(&rtp_types); - memset(&flags, 0, sizeof(flags)); + __init(); } #define expect(side, dir, codecs) \ @@ -412,7 +419,7 @@ int main(void) { // plain with two offered and two answered + always-transcode one way start(); - flags.always_transcode = 1; + ht_set(codec_accept, all); sdp_pt(0, PCMU, 8000); sdp_pt(8, PCMA, 8000); offer(); @@ -435,7 +442,7 @@ int main(void) { // plain with two offered and two answered + always-transcode both ways start(); - flags.always_transcode = 1; + ht_set(codec_accept, all); sdp_pt(0, PCMU, 8000); sdp_pt(8, PCMA, 8000); offer(); @@ -443,7 +450,7 @@ int main(void) { expect(A, send, "0/PCMU/8000 8/PCMA/8000"); expect(B, recv, "0/PCMU/8000 8/PCMA/8000"); expect(B, send, ""); - flags.always_transcode = 1; + ht_set(codec_accept, all); sdp_pt(0, PCMU, 8000); sdp_pt(8, PCMA, 8000); answer();