diff --git a/README.md b/README.md index d66c1d913..24ad66d63 100644 --- a/README.md +++ b/README.md @@ -1307,7 +1307,8 @@ Optionally included keys are: type that should be removed from the SDP. Codec names are case sensitive, and can be either from the list of codecs explicitly defined by the SDP through an `a=rtpmap` attribute, or can be from the list of RFC-defined codecs. Examples - are `PCMU`, `opus`, or `telephone-event`. + are `PCMU`, `opus`, or `telephone-event`. Codecs stripped using this option + are treated as if they had never been in the SDP. It is possible to specify codec format parameters alongside with the codec name in the same format as they're written in SDP for codecs that support them, @@ -1356,6 +1357,19 @@ Optionally included keys are: another slash followed by the bitrate in bits per second, e.g. `opus/48000/2/32000`. In this case, all format parameters (clock rate, channels) must also be specified. + + * `mask` + + Similar to `strip` except that codecs listed here will still be accepted and + used for transcoding on the offering side. Useful only in combination with + `transcode`. For example, if an offer advertises Opus and the options + `mask=opus, transcode=G723` are given, then the rewritten outgoing offer + will contain only G.723 as offered codec, and transcoding will happen + between Opus and G.723. In contrast, if only `transcode=G723` were given, then + the rewritten outgoing offer would contain both Opus and G.723. On the other + hand, if `strip=opus, transcode=G723` were given, then Opus would be unavailable + for transcoding. + * `ptime` Contains an integer. If set, changes the `a=ptime` attribute's value in the outgoing diff --git a/daemon/call.c b/daemon/call.c index 940868b44..d2dcc9cc2 100644 --- a/daemon/call.c +++ b/daemon/call.c @@ -1588,7 +1588,8 @@ int monologue_offer_answer(struct call_monologue *other_ml, GQueue *streams, if (flags->ptime > 0) media->ptime = flags->ptime; codec_rtp_payload_types(media, other_media, &sp->rtp_payload_types, - flags->codec_strip, &flags->codec_offer, &flags->codec_transcode); + flags->codec_strip, &flags->codec_offer, &flags->codec_transcode, + flags->codec_mask); codec_handlers_update(media, other_media); /* send and recv are from our POV */ diff --git a/daemon/call_interfaces.c b/daemon/call_interfaces.c index cb78ee6ac..4895e1cd5 100644 --- a/daemon/call_interfaces.c +++ b/daemon/call_interfaces.c @@ -624,6 +624,8 @@ static void call_ng_flags_flags(struct sdp_ng_flags *out, str *s, void *dummy) { if (call_ng_flags_prefix(out, s, "codec-transcode-", call_ng_flags_codec_list, &out->codec_transcode)) return; + if (call_ng_flags_prefix(out, s, "codec-mask-", call_ng_flags_codec_ht, out->codec_mask)) + return; #endif ilog(LOG_WARN, "Unknown flag encountered: '" STR_FORMAT "'", @@ -637,6 +639,7 @@ static void call_ng_process_flags(struct sdp_ng_flags *out, bencode_item_t *inpu ZERO(*out); out->codec_strip = g_hash_table_new_full(str_hash, str_equal, str_slice_free, NULL); + out->codec_mask = g_hash_table_new_full(str_hash, str_equal, str_slice_free, NULL); out->trust_address = trust_address_def; out->dtls_passive = dtls_passive_def; @@ -703,11 +706,13 @@ static void call_ng_process_flags(struct sdp_ng_flags *out, bencode_item_t *inpu call_ng_flags_list(out, dict, "offer", call_ng_flags_codec_list, &out->codec_offer); #ifdef WITH_TRANSCODING call_ng_flags_list(out, dict, "transcode", call_ng_flags_codec_list, &out->codec_transcode); + call_ng_flags_list(out, dict, "mask", call_ng_flags_codec_ht, out->codec_mask); #endif } } static void call_ng_free_flags(struct sdp_ng_flags *flags) { g_hash_table_destroy(flags->codec_strip); + g_hash_table_destroy(flags->codec_mask); g_queue_clear_full(&flags->codec_offer, str_slice_free); g_queue_clear_full(&flags->codec_transcode, str_slice_free); } diff --git a/daemon/call_interfaces.h b/daemon/call_interfaces.h index 4348df91f..d58c1f52f 100644 --- a/daemon/call_interfaces.h +++ b/daemon/call_interfaces.h @@ -34,6 +34,7 @@ struct sdp_ng_flags { GHashTable *codec_strip; GQueue codec_offer; GQueue codec_transcode; + GHashTable *codec_mask; int ptime; int asymmetric:1, no_redis_update:1, diff --git a/daemon/codec.c b/daemon/codec.c index f21d175c4..c7dc119d4 100644 --- a/daemon/codec.c +++ b/daemon/codec.c @@ -894,7 +894,8 @@ static int __revert_codec_strip(GHashTable *removed, const str *codec, } void codec_rtp_payload_types(struct call_media *media, struct call_media *other_media, GQueue *types, GHashTable *strip, - const GQueue *offer, const GQueue *transcode) + const GQueue *offer, const GQueue *transcode, + GHashTable *mask) { // 'media' = receiver of this offer/answer; 'other_media' = sender of this offer/answer struct call *call = media->call; @@ -934,7 +935,11 @@ void codec_rtp_payload_types(struct call_media *media, struct call_media *other_ continue; } } - __rtp_payload_type_add(media, other_media, pt); + if (!g_hash_table_lookup(mask, &pt->encoding) + && !g_hash_table_lookup(mask, &pt->encoding_with_params)) + __rtp_payload_type_add(media, other_media, pt); + else + __rtp_payload_type_add_send(other_media, pt); } // now restore codecs that have been removed, but should be offered diff --git a/daemon/codec.h b/daemon/codec.h index 897e1f754..945baaac2 100644 --- a/daemon/codec.h +++ b/daemon/codec.h @@ -41,7 +41,8 @@ void codec_packet_free(void *); void codec_rtp_payload_types(struct call_media *media, struct call_media *other_media, GQueue *types, GHashTable *strip, - const GQueue *offer, const GQueue *transcode); + const GQueue *offer, const GQueue *transcode, + GHashTable *mask); // special return value `(void *) 0x1` to signal type mismatch struct rtp_payload_type *codec_make_payload_type(const str *codec_str, struct call_media *media); diff --git a/utils/rtpengine-ng-client b/utils/rtpengine-ng-client index b7bb1ba05..e515c298a 100755 --- a/utils/rtpengine-ng-client +++ b/utils/rtpengine-ng-client @@ -48,6 +48,7 @@ GetOptions( 'codec-strip=s@' => \$options{'codec-strip'}, 'codec-offer=s@' => \$options{'codec-offer'}, 'codec-transcode=s@' => \$options{'codec-transcode'}, + 'codec-mask=s@' => \$options{'codec-mask'}, 'ptime=i' => \$options{'ptime'}, 'flags=s@' => \$options{'flags'}, ) or die; @@ -76,7 +77,7 @@ if (defined($options{direction})) { $options{direction} =~ /(.*),(.*)/ or die; $packet{direction} = [$1,$2]; } -for my $x (qw(strip offer transcode)) { +for my $x (qw(strip offer transcode mask)) { if ($options{'codec-'.$x} && @{$options{'codec-'.$x}}) { $packet{codec}{$x} = $options{'codec-'.$x}; }