Browse Source

TT#101653 add codec-consume and codec-accept options

Change-Id: Icac343b34881628118f2c36181be66db1c6286e0
pull/1163/head
Richard Fuchs 5 years ago
parent
commit
336cb5b280
7 changed files with 323 additions and 33 deletions
  1. +13
    -0
      README.md
  2. +12
    -0
      daemon/call_interfaces.c
  3. +204
    -30
      daemon/codec.c
  4. +2
    -0
      include/call_interfaces.h
  5. +87
    -2
      t/auto-daemon-tests.pl
  6. +2
    -0
      t/transcode-test.c
  7. +3
    -1
      utils/rtpengine-ng-client

+ 13
- 0
README.md View File

@ -1234,6 +1234,19 @@ Optionally included keys are:
This option is only processed in `offer` messages and ignored otherwise.
* `consume`
Identical to `mask` but enables the transcoding engine even if no other transcoding
related options are given.
* `accept`
Similar to `mask` and `consume` but doesn't remove the codec from the list of
offered codecs. This means that a codec listed under `accept` will still be offered
to the remote peer, but if the remote peer rejects it, it will still be accepted
torwards the original offerer and then used for transcoding. It is a more selective
version of what the `always transcode` flag does.
* `set`
Contains a list of strings. This list makes it possible to set codec options


+ 12
- 0
daemon/call_interfaces.c View File

@ -865,6 +865,12 @@ static void call_ng_flags_flags(struct sdp_ng_flags *out, str *s, void *dummy) {
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))
@ -1082,6 +1088,8 @@ static void call_ng_process_flags(struct sdp_ng_flags *out, bencode_item_t *inpu
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_str_ht, &out->codec_mask);
call_ng_flags_list(out, dict, "set", call_ng_flags_str_ht_split, &out->codec_set);
call_ng_flags_list(out, dict, "accept", call_ng_flags_str_ht, &out->codec_accept);
call_ng_flags_list(out, dict, "consume", call_ng_flags_str_ht, &out->codec_consume);
}
#endif
}
@ -1095,6 +1103,10 @@ static void call_ng_free_flags(struct sdp_ng_flags *flags) {
g_hash_table_destroy(flags->codec_mask);
if (flags->codec_set)
g_hash_table_destroy(flags->codec_set);
if (flags->codec_accept)
g_hash_table_destroy(flags->codec_accept);
if (flags->codec_consume)
g_hash_table_destroy(flags->codec_consume);
if (flags->sdes_no)
g_hash_table_destroy(flags->sdes_no);
g_queue_clear_full(&flags->codec_offer, free);


+ 204
- 30
daemon/codec.c View File

@ -425,6 +425,7 @@ static struct rtp_payload_type *__check_dest_codecs(struct call_media *receiver,
const struct sdp_ng_flags *flags, GHashTable *supplemental_sinks, int *sink_transcoding)
{
struct rtp_payload_type *pref_dest_codec = NULL;
struct rtp_payload_type *first_tc_codec = NULL;
for (GList *l = sink->codecs_prefs_send.head; l; l = l->next) {
struct rtp_payload_type *pt = l->data;
@ -438,28 +439,53 @@ static struct rtp_payload_type *__check_dest_codecs(struct call_media *receiver,
if (sink->ptime)
pt->ptime = sink->ptime;
if (!pref_dest_codec && !pt->codec_def->supplemental) {
ilog(LOG_DEBUG, "Default sink codec is " STR_FORMAT, STR_FMT(&pt->encoding_with_params));
if (!pref_dest_codec && !pt->codec_def->supplemental)
pref_dest_codec = pt;
}
// also check if this is a transcoding codec: if we can send a codec to the sink,
// but can't receive it on the receiver side, then it's transcoding. this is to check
// whether transcoding on the sink side is actually needed. if transcoding has been
// previously enabled on the sink, but no transcoding codecs are actually present,
// we can disable the transcoding engine.
struct rtp_payload_type *recv_pt = g_hash_table_lookup(receiver->codecs_send,
&pt->payload_type);
if (recv_pt && rtp_payload_type_cmp(pt, recv_pt))
recv_pt = NULL;
//ilog(LOG_DEBUG, "XXXXXXXXXXXX old flag is %i", *sink_transcoding);
//ilog(LOG_DEBUG, "XXXXXXXXXXXX checking dest codec " STR_FORMAT " is %i",
//STR_FMT(&pt->encoding_with_params),
//pt->for_transcoding);
//if (recv_pt)
//ilog(LOG_DEBUG, "XXXXXXXXXXXX checking dest codec reverse " STR_FORMAT " is %i",
//STR_FMT(&recv_pt->encoding_with_params),
//recv_pt->for_transcoding);
if (MEDIA_ISSET(sink, TRANSCODE)) {
struct rtp_payload_type *recv_pt = g_hash_table_lookup(receiver->codecs_send,
&pt->payload_type);
if (!recv_pt || rtp_payload_type_cmp(pt, recv_pt)) {
// can the sink receive supplemental codec but the receiver can't send it?
if (!recv_pt) {
// can the sink receive codec but the receiver can't send it?
*sink_transcoding |= 0x3;
}
}
if (pt->for_transcoding) {
// codec is explicitly marked for transcoding. enable transcoding engine
MEDIA_SET(receiver, TRANSCODE);
*sink_transcoding |= 0x3;
if (!first_tc_codec && !pt->codec_def->supplemental)
first_tc_codec = pt;
if (pt->codec_def->supplemental)
*sink_transcoding |= 0x4;
}
//ilog(LOG_DEBUG, "XXXXXXXXXXXX new flag is %i", *sink_transcoding);
__track_supp_codec(supplemental_sinks, pt);
}
if (first_tc_codec)
pref_dest_codec = first_tc_codec;
if (pref_dest_codec)
ilog(LOG_DEBUG, "Default sink codec is " STR_FORMAT,
STR_FMT(&pref_dest_codec->encoding_with_params));
return pref_dest_codec;
}
@ -474,10 +500,21 @@ static void __check_send_codecs(struct call_media *receiver, struct call_media *
struct rtp_payload_type *recv_pt = g_hash_table_lookup(receiver->codecs_send,
&pt->payload_type);
int tc_flag = 0;
//ilog(LOG_DEBUG, "XXXXXXXXXXXX old flag is %i", *sink_transcoding);
//ilog(LOG_DEBUG, "XXXXXXXXXXXX checking send codec " STR_FORMAT " is %i",
//STR_FMT(&pt->encoding_with_params),
//pt->for_transcoding);
//if (recv_pt)
//ilog(LOG_DEBUG, "XXXXXXXXXXXX checking send codec reverse " STR_FORMAT " is %i",
//STR_FMT(&recv_pt->encoding_with_params),
//recv_pt->for_transcoding);
if (!recv_pt || rtp_payload_type_cmp(pt, recv_pt))
tc_flag |= 0x3;
if (flags && flags->inject_dtmf)
tc_flag |= 0x1;
if (pt->for_transcoding)
tc_flag |= 0x3;
//ilog(LOG_DEBUG, "XXXXXXXXXXXX set flag is %i", *sink_transcoding);
if (tc_flag) {
// can the sink receive codec but the receiver can't send it?
*sink_transcoding |= tc_flag;
@ -491,6 +528,7 @@ static void __check_send_codecs(struct call_media *receiver, struct call_media *
g_hash_table_lookup(sink->codec_handlers, GINT_TO_POINTER(recv_pt->payload_type));
if (!ch_recv)
continue;
//ilog(LOG_DEBUG, "XXXXXXXXXXXX handler transcoder %i", ch_recv->transcoder);
if (ch_recv->transcoder)
*sink_transcoding |= 0x3;
}
@ -591,8 +629,28 @@ static void __single_codec(struct call_media *media, const struct sdp_ng_flags *
}
}
static int __check_receiver_codecs(struct call_media *receiver) {
int ret = 0;
// if some codecs were explicitly marked for transcoding, then we accept only those.
// otherwise we accept all that we can.
for (GList *l = receiver->codecs_prefs_send.head; l; l = l->next) {
struct rtp_payload_type *pt = l->data;
ensure_codec_def(pt, receiver);
if (!pt->codec_def)
continue;
//ilog(LOG_DEBUG, "XXXXXXXXXXXX checking recv send " STR_FORMAT " %i %i", STR_FMT(&pt->encoding_with_params), pt->for_transcoding, pt->codec_def->supplemental);
if (pt->for_transcoding) {
if (pt->codec_def->supplemental)
ret |= 0x2 | 0x4;
else
ret |= 0x1 | 0x2;
}
}
return ret;
}
static void __accept_transcode_codecs(struct call_media *receiver, struct call_media *sink,
const struct sdp_ng_flags *flags)
const struct sdp_ng_flags *flags, int accept_only_tc)
{
// if the other side is transcoding, we need to accept codecs that were
// originally offered (recv->send) if we support them, even if the
@ -603,6 +661,9 @@ static void __accept_transcode_codecs(struct call_media *receiver, struct call_m
ensure_codec_def(pt, receiver);
if (!pt->codec_def)
continue;
if (accept_only_tc && !pt->for_transcoding)
continue;
//ilog(LOG_DEBUG, "XXXXXXXXXXX accept codec " STR_FORMAT " flag %i", STR_FMT(&pt->encoding_with_params), pt->for_transcoding);
struct rtp_payload_type *existing_pt
= g_hash_table_lookup(receiver->codecs_recv, &pt->payload_type);
if (existing_pt && !rtp_payload_type_cmp_nf(existing_pt, pt)) {
@ -645,6 +706,7 @@ static void __accept_transcode_codecs(struct call_media *receiver, struct call_m
g_hash_table_insert(receiver->codecs_recv, &existing_pt->payload_type, existing_pt);
}
//ilog(LOG_DEBUG, "XXXXXXXXXXXXX offered codec %i", pt->for_transcoding);
ilog(LOG_DEBUG, "Accepting offered codec " STR_FORMAT " due to transcoding",
STR_FMT(&pt->encoding_with_params));
MEDIA_SET(receiver, TRANSCODE);
@ -734,6 +796,7 @@ static GHashTable *__payload_type_queue_hash(GQueue *prefs, GQueue *order) {
static void __symmetric_codecs(struct call_media *receiver, struct call_media *sink,
int *sink_transcoding)
{
//ilog(LOG_DEBUG, "XXXXXXXXXXXXXXX symm codec flags %i %i", MEDIA_ISSET(sink, TRANSCODE), *sink_transcoding);
if (!MEDIA_ISSET(sink, TRANSCODE))
return;
if (!*sink_transcoding)
@ -755,28 +818,62 @@ static void __symmetric_codecs(struct call_media *receiver, struct call_media *s
// reconstruct list based on other side's preference.
int transcoding = 0;
// keep track of our reconstruction order. there might be some codecs that have been force accepted
// that aren't present in sink->codecs_prefs_send. we must add them our output (receiver->send/recv)
// in order.
GList *prefix_pt_pos = prefs_send_order.head;
for (GList *l = sink->codecs_prefs_send.head; l; l = l->next) {
struct rtp_payload_type *pt = l->data;
//ilog(LOG_DEBUG, "XXXXXXXXXXXXXXXX symm codec check " STR_FORMAT, STR_FMT(&pt->encoding_with_params));
// do we have a matching output?
struct rtp_payload_type *out_pt = g_hash_table_lookup(prefs_recv,
GINT_TO_POINTER(pt->payload_type));
if (out_pt && g_hash_table_lookup(prefs_send, GINT_TO_POINTER(pt->payload_type))) {
struct rtp_payload_type *send_pt;
if (!out_pt || !(send_pt = g_hash_table_lookup(prefs_send, GINT_TO_POINTER(pt->payload_type)))) {
// we must transcode after all.
ilog(LOG_DEBUG, "RTP payload type %i is not symmetric and must be transcoded",
pt->payload_type);
transcoding = 1;
continue;
}
// seek forward in our prefix list and check any PTs to see if they're force accepted
while (prefix_pt_pos) {
void *ptype = prefix_pt_pos->data;
struct rtp_payload_type *prefix_pt = g_hash_table_lookup(prefs_send, ptype);
prefix_pt_pos = prefix_pt_pos->next;
if (!prefix_pt)
continue; // bug?
if (prefix_pt == send_pt)
break; // caught up
//ilog(LOG_DEBUG, "XXXXXXXXXXXXXXXX prefix codec check " STR_FORMAT " %i", STR_FMT(&prefix_pt->encoding_with_params), prefix_pt->for_transcoding);
if (!prefix_pt->for_transcoding)
continue; // not interesting
// 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, 1);
// and our send leg
out_pt = g_hash_table_lookup(prefs_send, GINT_TO_POINTER(pt->payload_type));
if (out_pt) {
g_hash_table_steal(prefs_send, GINT_TO_POINTER(pt->payload_type));
__rtp_payload_type_add_send(receiver, out_pt);
ilog(LOG_DEBUG, "Adding force-accepted RTP payload type %i", prefix_pt->payload_type);
g_hash_table_steal(prefs_send, ptype);
__rtp_payload_type_add_send(receiver, prefix_pt);
// and our receive leg
struct rtp_payload_type *in_pt = g_hash_table_lookup(prefs_recv, ptype);
if (in_pt) {
g_hash_table_steal(prefs_recv, ptype);
__rtp_payload_type_add_recv(receiver, in_pt, 1);
}
continue;
transcoding = 1;
}
// 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, 1);
// and our send leg
out_pt = g_hash_table_lookup(prefs_send, GINT_TO_POINTER(pt->payload_type));
if (out_pt) {
g_hash_table_steal(prefs_send, GINT_TO_POINTER(pt->payload_type));
__rtp_payload_type_add_send(receiver, out_pt);
}
// we must transcode after all.
ilog(LOG_DEBUG, "RTP payload type %i is not symmetric and must be transcoded",
pt->payload_type);
transcoding = 1;
}
if (!transcoding)
@ -1084,6 +1181,7 @@ int __supp_codec_match(struct call_media *receiver, struct call_media *sink, int
{
if (pt == -1)
return 0;
//ilog(LOG_DEBUG, "XXXXXXXXX checking supp PT match %i", pt);
struct rtp_payload_type *sink_pt_stor = NULL;
struct rtp_payload_type *recv_pt_stor = NULL;
@ -1096,12 +1194,15 @@ int __supp_codec_match(struct call_media *receiver, struct call_media *sink, int
*sink_pt = g_hash_table_lookup(sink->codecs_send, &pt);
if (!*sink_pt)
return 0;
//ilog(LOG_DEBUG, "XXXXXXXXX sink has supp PT %i", pt);
// XXX should go by codec name/params, not payload type number
*recv_pt = g_hash_table_lookup(receiver->codecs_recv, &pt);
if (!*recv_pt)
return 1;
//ilog(LOG_DEBUG, "XXXXXXXXX recv has supp PT %i", pt);
if (rtp_payload_type_cmp(*sink_pt, *recv_pt))
return 1;
//ilog(LOG_DEBUG, "XXXXXXXXX recv has matching supp PT %i", pt);
return 2;
}
@ -1148,7 +1249,11 @@ void codec_handlers_update(struct call_media *receiver, struct call_media *sink,
// if we transcode, we transcode to the highest-preference supported codec
// that the sink specified. determine this first.
struct rtp_payload_type *pref_dest_codec = NULL;
int sink_transcoding = 0; // 0x1 = any transcoder present, 0x2 = non pseudo transcoder present
// 0x1 = any transcoder present, 0x2 = non pseudo transcoder present,
// 0x4 = supplemental codec for transcoding
int sink_transcoding = 0;
// keep track of supplemental payload types. we hash them by clock rate
// in case there's several of them. the clock rates of the destination
// codec and the supplemental codec must match.
@ -1165,6 +1270,10 @@ void codec_handlers_update(struct call_media *receiver, struct call_media *sink,
// similarly, if the sink can receive a codec that the receiver can't send, it's also transcoding
__check_send_codecs(receiver, sink, flags, supplemental_sinks, &sink_transcoding);
// 0x1 = accept only codecs marked for transcoding, 0x2 = some codecs marked for transcoding
// present, 0x4 = supplemental codec for transcoding
int receiver_transcoding = __check_receiver_codecs(receiver);
if (flags && flags->opmode == OP_ANSWER && flags->symmetric_codecs)
__symmetric_codecs(receiver, sink, &sink_transcoding);
@ -1180,13 +1289,13 @@ void codec_handlers_update(struct call_media *receiver, struct call_media *sink,
int cn_pt_match = __supp_codec_match(receiver, sink, cn_payload_type, NULL, NULL);
// stop transcoding if we've determined that we don't need it
if (MEDIA_ISSET(sink, TRANSCODE) && !sink_transcoding) {
if (MEDIA_ISSET(sink, TRANSCODE) && !sink_transcoding && !(receiver_transcoding & 0x2)) {
ilog(LOG_DEBUG, "Disabling transcoding engine (not needed)");
MEDIA_CLEAR(sink, TRANSCODE);
}
if (MEDIA_ISSET(sink, TRANSCODE) && (sink_transcoding & 0x2))
__accept_transcode_codecs(receiver, sink, flags);
__accept_transcode_codecs(receiver, sink, flags, (receiver_transcoding & 0x1));
else
__eliminate_rejected_codecs(receiver, sink, flags);
@ -1196,6 +1305,8 @@ void codec_handlers_update(struct call_media *receiver, struct call_media *sink,
GHashTable *output_transcoders = g_hash_table_new(g_direct_hash, g_direct_equal);
int transcode_supplemental = 0; // is one of our source codecs a supplemental one?
if ((sink_transcoding & 0x4))
transcode_supplemental = 1;
// do we need to detect PCM DTMF tones?
int pcm_dtmf_detect = 0;
@ -1245,10 +1356,19 @@ void codec_handlers_update(struct call_media *receiver, struct call_media *sink,
goto next;
}
//ilog(LOG_DEBUG, "XXXXXXXXXXXX pref dest codec " STR_FORMAT " is %i",
//STR_FMT(&pref_dest_codec->encoding_with_params),
//pref_dest_codec->for_transcoding);
struct rtp_payload_type *dest_pt; // transcode to this
GQueue *dest_codecs = NULL;
if (!flags || !flags->always_transcode) {
if (pref_dest_codec->for_transcoding) {
// 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);
}
else if (!flags || !flags->always_transcode) {
// we ignore output codec matches if we must transcode supp codecs
if ((dtmf_pt_match == 1 || cn_pt_match == 1) && MEDIA_ISSET(sink, TRANSCODE))
;
@ -1374,6 +1494,12 @@ next:
// if the sink does not support DTMF but we can receive it, we must transcode
// DTMF event packets to PCM. this requires all codecs to be transcoded to the
// sink's preferred destination codec.
//ilog(LOG_DEBUG, "XXXXXXXXXXXXX tc supp %i DTMF PT %i DTMF PT match %i PCM detect %i",
//transcode_supplemental, dtmf_payload_type, dtmf_pt_match, pcm_dtmf_detect);
//ilog(LOG_DEBUG, "XXXXXXXXXXXXX tc supp %i CN PT %i CN PT match %i",
//transcode_supplemental, cn_payload_type, cn_pt_match);
//ilog(LOG_DEBUG, "XXXXXXXXXXXXX %p %p %p",
//pref_dest_codec, handler->source_pt.codec_def, pref_dest_codec->codec_def);
if (!transcode_supplemental && !pcm_dtmf_detect)
__make_passthrough_ssrc(handler);
else if (dtmf_pt_match == 2)
@ -1381,9 +1507,11 @@ next:
else if (!pref_dest_codec
|| !handler->source_pt.codec_def || !pref_dest_codec->codec_def)
__make_passthrough_ssrc(handler);
else
else {
__make_transcoder(handler, pref_dest_codec, output_transcoders,
dtmf_payload_type, pcm_dtmf_detect);
handler->cn_payload_type = cn_payload_type;
}
passthrough_handlers = g_slist_delete_link(passthrough_handlers, passthrough_handlers);
}
@ -2227,6 +2355,7 @@ static void __silence_detect_ ## type(struct codec_ssrc_handler *ch, AVFrame *fr
last = NULL; \
\
for (unsigned int i = 0; i < frame->nb_samples; i++) { \
/* ilog(LOG_DEBUG, "XXXXXXXXXXXX checking %u %i vs %i", i, (int) s[i], (int) thres); */ \
if (s[i] <= thres && s[1] >= -thres) { \
/* silence */ \
if (!last) { \
@ -2253,6 +2382,7 @@ __silence_detect_type(int32_t)
__silence_detect_type(int16_t)
static void __silence_detect(struct codec_ssrc_handler *ch, AVFrame *frame) {
//ilog(LOG_DEBUG, "XXXXXXXXXXXXXXXXXXXX silence detect %i %i", rtpe_config.silence_detect_int, ch->handler->cn_payload_type);
if (!rtpe_config.silence_detect_int)
return;
if (ch->handler->cn_payload_type < 0)
@ -3120,7 +3250,7 @@ int __codec_ht_except(int all_flag, GHashTable *yes_ht, GHashTable *no_ht, struc
else if (g_hash_table_lookup(yes_ht, &pt->encoding_with_params))
do_this = 1;
}
if (no_ht) {
if (no_ht && all_flag) {
if (g_hash_table_lookup(no_ht, &pt->encoding))
do_this = 0;
else if (g_hash_table_lookup(no_ht, &pt->encoding_with_params))
@ -3128,6 +3258,19 @@ int __codec_ht_except(int all_flag, GHashTable *yes_ht, GHashTable *no_ht, struc
}
return do_this;
}
void __ht_merge(GHashTable **dst, GHashTable *src) {
if (!src)
return;
if (!*dst)
*dst = g_hash_table_new_full(str_case_hash, str_case_equal, free, NULL);
GHashTableIter iter;
g_hash_table_iter_init(&iter, src);
void *key;
while (g_hash_table_iter_next(&iter, &key, NULL)) {
str *dup = str_dup(key);
g_hash_table_replace(*dst, dup, dup);
}
}
void codec_rtp_payload_types(struct call_media *media, struct call_media *other_media,
GQueue *types, struct sdp_ng_flags *flags)
{
@ -3141,7 +3284,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;
int strip_all = 0, mask_all = 0, consume_all = 0;
// start fresh
if (!proto_is_rtp(other_media->protocol) && proto_is_rtp(media->protocol) && flags->opmode == OP_OFFER) {
@ -3164,12 +3307,21 @@ void codec_rtp_payload_types(struct call_media *media, struct call_media *other_
if (flags->codec_strip && g_hash_table_lookup(flags->codec_strip, &str_all))
strip_all = 1;
if (flags->codec_strip && g_hash_table_lookup(flags->codec_strip, &str_all))
else if (flags->codec_strip && g_hash_table_lookup(flags->codec_strip, &str_full))
strip_all = 2;
if (flags->codec_mask && g_hash_table_lookup(flags->codec_mask, &str_all))
mask_all = 1;
else if (flags->codec_mask && g_hash_table_lookup(flags->codec_mask, &str_full))
mask_all = 2;
if (flags->codec_consume && g_hash_table_lookup(flags->codec_consume, &str_all))
consume_all = 1;
else if (flags->codec_consume && g_hash_table_lookup(flags->codec_consume, &str_full))
consume_all = 2;
__ht_merge(&flags->codec_except, flags->codec_consume);
__ht_merge(&flags->codec_except, flags->codec_accept);
__ht_merge(&flags->codec_except, flags->codec_strip);
__ht_merge(&flags->codec_except, flags->codec_mask);
/* we steal the entire list to avoid duplicate allocs */
while ((pt = g_queue_pop_head(types))) {
@ -3204,6 +3356,28 @@ 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(consume_all, flags->codec_consume, flags->codec_except, pt)) {
ilog(LOG_DEBUG, "Consuming codec '" STR_FORMAT "'",
STR_FMT(&pt->encoding_with_params));
#ifdef WITH_TRANSCODING
codec_touched(pt, media);
#endif
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);
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)) {
ilog(LOG_DEBUG, "Accepting codec '" STR_FORMAT "'",
STR_FMT(&pt->encoding_with_params));
#ifdef WITH_TRANSCODING
codec_touched(pt, media);
#endif
pt->for_transcoding = 1;
__rtp_payload_type_add(media, other_media, pt);
}
else
__rtp_payload_type_add(media, other_media, pt);
}


+ 2
- 0
include/call_interfaces.h View File

@ -42,6 +42,8 @@ struct sdp_ng_flags {
GQueue codec_offer;
GQueue codec_transcode;
GHashTable *codec_mask;
GHashTable *codec_accept;
GHashTable *codec_consume;
GHashTable *codec_set;
int ptime,
rev_ptime;


+ 87
- 2
t/auto-daemon-tests.pl View File

@ -85,6 +85,93 @@ SDP
new_call;
offer('codec-accept',
{ codec => { accept => ['PCMU'] } }, <<SDP);
v=0
o=- 1545997027 1 IN IP4 198.51.101.40
s=tester
t=0 0
m=audio 3000 RTP/AVP 0 8
c=IN IP4 198.51.100.1
----------------------------------
v=0
o=- 1545997027 1 IN IP4 198.51.101.40
s=tester
t=0 0
m=audio PORT RTP/AVP 0 8
c=IN IP4 203.0.113.1
a=rtpmap:0 PCMU/8000
a=rtpmap:8 PCMA/8000
a=sendrecv
a=rtcp:PORT
SDP
answer('codec-accept',
{ }, <<SDP);
v=0
o=- 1545997027 1 IN IP4 198.51.101.40
s=tester
t=0 0
m=audio 3000 RTP/AVP 8
c=IN IP4 198.51.100.1
----------------------------------
v=0
o=- 1545997027 1 IN IP4 198.51.101.40
s=tester
t=0 0
m=audio PORT RTP/AVP 0 8
c=IN IP4 203.0.113.1
a=rtpmap:0 PCMU/8000
a=rtpmap:8 PCMA/8000
a=sendrecv
a=rtcp:PORT
SDP
new_call;
offer('codec-consume',
{ codec => { consume => ['PCMU'] } }, <<SDP);
v=0
o=- 1545997027 1 IN IP4 198.51.101.40
s=tester
t=0 0
m=audio 3000 RTP/AVP 0 8
c=IN IP4 198.51.100.1
----------------------------------
v=0
o=- 1545997027 1 IN IP4 198.51.101.40
s=tester
t=0 0
m=audio PORT RTP/AVP 8
c=IN IP4 203.0.113.1
a=rtpmap:8 PCMA/8000
a=sendrecv
a=rtcp:PORT
SDP
answer('codec-consume',
{ }, <<SDP);
v=0
o=- 1545997027 1 IN IP4 198.51.101.40
s=tester
t=0 0
m=audio 3000 RTP/AVP 8
c=IN IP4 198.51.100.1
----------------------------------
v=0
o=- 1545997027 1 IN IP4 198.51.101.40
s=tester
t=0 0
m=audio PORT RTP/AVP 0 8
c=IN IP4 203.0.113.1
a=rtpmap:0 PCMU/8000
a=rtpmap:8 PCMA/8000
a=sendrecv
a=rtcp:PORT
SDP
new_call;
offer('simple codec neg',
{ }, <<SDP);
v=0
@ -666,8 +753,6 @@ a=sendrecv
a=rtcp:PORT
SDP
##


+ 2
- 0
t/transcode-test.c View File

@ -70,6 +70,8 @@ static void __start(const char *file, int line) {
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);
}
#define transcode(codec) g_queue_push_tail(&flags.codec_transcode, sdup(#codec))


+ 3
- 1
utils/rtpengine-ng-client View File

@ -52,6 +52,8 @@ GetOptions(
'codec-offer=s@' => \$options{'codec-offer'},
'codec-transcode=s@' => \$options{'codec-transcode'},
'codec-mask=s@' => \$options{'codec-mask'},
'codec-consume=s@' => \$options{'codec-consume'},
'codec-accept=s@' => \$options{'codec-accept'},
'codec-set=s@' => \$options{'codec-set'},
'ptime=i' => \$options{'ptime'},
'flags=s@' => \$options{'flags'},
@ -106,7 +108,7 @@ if (defined($options{direction})) {
$options{direction} =~ /(.*),(.*)/ or die;
$packet{direction} = [$1,$2];
}
for my $x (qw(strip offer transcode mask set)) {
for my $x (qw(strip offer transcode mask set consume accept)) {
if ($options{'codec-'.$x} && @{$options{'codec-'.$x}}) {
if (!$options{'codec options flag'}) {
$packet{codec}{$x} = $options{'codec-'.$x};


Loading…
Cancel
Save