|
|
|
@ -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); |
|
|
|
} |
|
|
|
|