From 1efc3d9409fb5fdc66e6f94bd9cda0a4c6726b35 Mon Sep 17 00:00:00 2001 From: Richard Fuchs Date: Wed, 31 Aug 2022 10:31:01 -0400 Subject: [PATCH] TT#189201 move kernel media silencing from input to output This makes it possible to have different media silencing options for different outputs. Functionally this commit alone is a no-op. Change-Id: I967c3e07ea4645bb49ccb76db12d51ded2d72f06 --- daemon/call.c | 2 +- daemon/media_socket.c | 41 ++++++++++++++++--------- kernel-module/xt_RTPENGINE.c | 59 ++++++++++++++++++++---------------- kernel-module/xt_RTPENGINE.h | 11 ++++--- 4 files changed, 68 insertions(+), 45 deletions(-) diff --git a/daemon/call.c b/daemon/call.c index bdac5215e..8778610aa 100644 --- a/daemon/call.c +++ b/daemon/call.c @@ -632,7 +632,7 @@ void call_timer(void *ptr) { atomic64_set(&ps->kernel_stats.errors, ke->stats.errors); for (j = 0; j < ke->target.num_payload_types; j++) { - pt = ke->target.payload_types[j].pt_num; + pt = ke->target.pt_input[j].pt_num; rs = g_hash_table_lookup(ps->rtp_stats, GINT_TO_POINTER(pt)); if (!rs) continue; diff --git a/daemon/media_socket.c b/daemon/media_socket.c index fb7f1a215..608db7987 100644 --- a/daemon/media_socket.c +++ b/daemon/media_socket.c @@ -1250,24 +1250,20 @@ static const char *kernelize_one(struct rtpengine_target_info *reti, GQueue *out *payload_types = g_hash_table_get_values(stream->rtp_stats); *payload_types = g_list_sort(*payload_types, __rtp_stats_pt_sort); for (l = *payload_types; l; ) { - if (reti->num_payload_types >= G_N_ELEMENTS(reti->payload_types)) { + if (reti->num_payload_types >= G_N_ELEMENTS(reti->pt_input)) { ilog(LOG_WARNING | LOG_FLAG_LIMIT, "Too many RTP payload types for kernel module"); break; } rs = l->data; // only add payload types that are passthrough for all sinks bool can_kernelize = true; - bool silenced = (call->silence_media || media->monologue->silence_media) ? true : false; unsigned int clockrate = 0; - str replace_pattern = STR_NULL; for (GList *k = sinks->head; k; k = k->next) { struct sink_handler *ksh = k->data; struct packet_stream *ksink = ksh->sink; struct codec_handler *ch = codec_handler_get(media, rs->payload_type, ksink->media, ksh); clockrate = ch->source_pt.clock_rate; - if (silenced && ch->source_pt.codec_def) - replace_pattern = ch->source_pt.codec_def->silence_pattern; if (ch->kernelize) continue; can_kernelize = false; @@ -1282,16 +1278,9 @@ static const char *kernelize_one(struct rtpengine_target_info *reti, GQueue *out continue; } - struct rtpengine_payload_type *rpt = &reti->payload_types[reti->num_payload_types++]; + struct rtpengine_pt_input *rpt = &reti->pt_input[reti->num_payload_types++]; rpt->pt_num = rs->payload_type; rpt->clock_rate = clockrate; - if (replace_pattern.len > sizeof(reti->payload_types->replace_pattern)) - ilog(LOG_WARNING | LOG_FLAG_LIMIT, "Payload replacement pattern too long (%zu)", - replace_pattern.len); - else { - rpt->replace_pattern_len = replace_pattern.len; - memcpy(rpt->replace_pattern, replace_pattern.s, replace_pattern.len); - } l = l->next; } @@ -1304,16 +1293,40 @@ static const char *kernelize_one(struct rtpengine_target_info *reti, GQueue *out recording_stream_kernel_info(stream, reti); output: - // output section + // output section: any output at all? if (non_forwarding || !sink || !sink->selected_sfd) return NULL; // no output if (!PS_ISSET(sink, FILLED)) return NULL; + // fill output struct redi = g_slice_alloc0(sizeof(*redi)); redi->local = reti->local; redi->output.tos = call->tos; + // media silencing + bool silenced = call->silence_media || media->monologue->silence_media; + if (silenced) { + int i = 0; + for (GList *l = *payload_types; l; l = l->next) { + struct rtp_stats *rs = l->data; + struct rtpengine_pt_output *rpt = &redi->output.pt_output[i++]; + struct codec_handler *ch = codec_handler_get(media, rs->payload_type, + sink->media, sink_handler); + str replace_pattern = STR_NULL; + if (silenced && ch->source_pt.codec_def) + replace_pattern = ch->source_pt.codec_def->silence_pattern; + if (replace_pattern.len > sizeof(rpt->replace_pattern)) + ilog(LOG_WARNING | LOG_FLAG_LIMIT, "Payload replacement pattern too long (%zu)", + replace_pattern.len); + else { + rpt->replace_pattern_len = replace_pattern.len; + memcpy(rpt->replace_pattern, replace_pattern.s, replace_pattern.len); + } + } + + } + if (MEDIA_ISSET(media, ECHO)) redi->output.ssrc_subst = 1; diff --git a/kernel-module/xt_RTPENGINE.c b/kernel-module/xt_RTPENGINE.c index d046c40fd..b3c5a0320 100644 --- a/kernel-module/xt_RTPENGINE.c +++ b/kernel-module/xt_RTPENGINE.c @@ -309,7 +309,7 @@ struct rtpengine_target { atomic_t refcnt; uint32_t table; struct rtpengine_target_info target; - unsigned int last_pt; // index into payload_types[] + unsigned int last_pt; // index into pt_input[] and pt_output[] struct rtpengine_stats_a stats; struct rtpengine_rtp_stats_a rtp_stats[RTPE_NUM_PAYLOAD_TYPES]; @@ -1650,12 +1650,9 @@ static int proc_list_show(struct seq_file *f, void *v) { (unsigned long long) atomic64_read(&g->stats.errors)); for (i = 0; i < g->target.num_payload_types; i++) { seq_printf(f, " RTP payload type %3u: %20llu bytes, %20llu packets\n", - g->target.payload_types[i].pt_num, + g->target.pt_input[i].pt_num, (unsigned long long) atomic64_read(&g->rtp_stats[i].bytes), (unsigned long long) atomic64_read(&g->rtp_stats[i].packets)); - if (g->target.payload_types[i].replace_pattern_len) - seq_printf(f, " %u bytes replacement payload\n", - g->target.payload_types[i].replace_pattern_len); } seq_printf(f, " SSRC in:"); @@ -1699,6 +1696,15 @@ static int proc_list_show(struct seq_file *f, void *v) { } seq_printf(f, "\n"); } + + for (j = 0; j < g->target.num_payload_types; j++) { + if (o->output.pt_output[j].replace_pattern_len) + seq_printf(f, " RTP payload type %3u: " + "%u bytes replacement payload\n", + g->target.pt_input[j].pt_num, + o->output.pt_output[j].replace_pattern_len); + } + if (o->output.rtcp_only) seq_printf(f, " option: RTCP only\n"); @@ -4280,7 +4286,7 @@ static inline int is_dtls(struct sk_buff *skb) { #if LINUX_VERSION_CODE >= KERNEL_VERSION(3,0,0) static int rtp_payload_match(const void *a, const void *b) { - const struct rtpengine_payload_type *A = a, *B = b; + const struct rtpengine_pt_input *A = a, *B = b; if (A->pt_num < B->pt_num) return -1; @@ -4293,19 +4299,19 @@ static int rtp_payload_match(const void *a, const void *b) { static inline int rtp_payload_type(const struct rtp_header *hdr, const struct rtpengine_target_info *tg, int *last_pt) { - struct rtpengine_payload_type pt; - const struct rtpengine_payload_type *match; + struct rtpengine_pt_input pt; + const struct rtpengine_pt_input *match; pt.pt_num = hdr->m_pt & 0x7f; if (*last_pt < tg->num_payload_types) { - match = &tg->payload_types[*last_pt]; + match = &tg->pt_input[*last_pt]; if (rtp_payload_match(match, &pt) == 0) goto found; } #if LINUX_VERSION_CODE >= KERNEL_VERSION(3,0,0) - match = bsearch(&pt, tg->payload_types, tg->num_payload_types, sizeof(pt), rtp_payload_match); + match = bsearch(&pt, tg->pt_input, tg->num_payload_types, sizeof(pt), rtp_payload_match); #else - for (match = tg->payload_types; match < tg->payload_types + tg->num_payload_types; match++) { + for (match = tg->pt_input; match < tg->pt_input + tg->num_payload_types; match++) { if (match->pt_num == pt.pt_num) goto found; } @@ -4314,7 +4320,7 @@ static inline int rtp_payload_type(const struct rtp_header *hdr, const struct rt if (!match) return -1; found: - *last_pt = match - tg->payload_types; + *last_pt = match - tg->pt_input; return *last_pt; } @@ -4435,7 +4441,7 @@ static void rtp_stats(struct rtpengine_target *g, struct rtp_parsed *rtp, s64 ar // jitter // RFC 3550 A.8 - clockrate = g->target.payload_types[pt_idx].clock_rate; + clockrate = g->target.pt_input[pt_idx].clock_rate; transit = ((uint32_t) (div64_s64(arrival_time, 1000) * clockrate) / 1000) - ts; d = 0; if (s->transit) @@ -4625,19 +4631,6 @@ intercept_done: } no_intercept: - // pattern rewriting - if (rtp_pt_idx >= 0 && g->target.payload_types[rtp_pt_idx].replace_pattern_len && rtp.ok) { - if (g->target.payload_types[rtp_pt_idx].replace_pattern_len == 1) - memset(rtp.payload, g->target.payload_types[rtp_pt_idx].replace_pattern[0], - rtp.payload_len); - else { - for (i = 0; i < rtp.payload_len; - i += g->target.payload_types[rtp_pt_idx].replace_pattern_len) - memcpy(&rtp.payload[i], g->target.payload_types[rtp_pt_idx].replace_pattern, - g->target.payload_types[rtp_pt_idx].replace_pattern_len); - } - } - // output for (i = 0; i < g->target.num_destinations; i++) { struct rtpengine_output *o = &g->outputs[i]; @@ -4659,6 +4652,20 @@ no_intercept: rtp2.header = (void *) (((char *) rtp2.header) + offset); rtp2.payload = (void *) (((char *) rtp2.payload) + offset); + // pattern rewriting + if (rtp_pt_idx >= 0 && o->output.pt_output[rtp_pt_idx].replace_pattern_len && rtp2.ok) { + if (o->output.pt_output[rtp_pt_idx].replace_pattern_len == 1) + memset(rtp2.payload, o->output.pt_output[rtp_pt_idx].replace_pattern[0], + rtp2.payload_len); + else { + for (i = 0; i < rtp2.payload_len; + i += o->output.pt_output[rtp_pt_idx].replace_pattern_len) + memcpy(&rtp2.payload[i], + o->output.pt_output[rtp_pt_idx].replace_pattern, + o->output.pt_output[rtp_pt_idx].replace_pattern_len); + } + } + if (rtp2.ok) { // SSRC substitution if (o->output.ssrc_subst && ssrc_idx != -1 && o->output.ssrc_out[ssrc_idx]) diff --git a/kernel-module/xt_RTPENGINE.h b/kernel-module/xt_RTPENGINE.h index 2a063505b..fac19a22d 100644 --- a/kernel-module/xt_RTPENGINE.h +++ b/kernel-module/xt_RTPENGINE.h @@ -93,11 +93,13 @@ enum rtpengine_src_mismatch { MSM_PROPAGATE, /* propagate to userspace daemon */ }; -struct rtpengine_payload_type { +struct rtpengine_pt_input { unsigned char pt_num; - unsigned char replace_pattern_len; uint32_t clock_rate; +}; +struct rtpengine_pt_output { char replace_pattern[16]; + unsigned char replace_pattern_len; }; struct rtpengine_target_info { @@ -110,7 +112,7 @@ struct rtpengine_target_info { struct rtpengine_srtp decrypt; uint32_t ssrc[RTPE_NUM_SSRC_TRACKING]; // Expose the SSRC to userspace when we resync. - struct rtpengine_payload_type payload_types[RTPE_NUM_PAYLOAD_TYPES]; /* must be sorted */ + struct rtpengine_pt_input pt_input[RTPE_NUM_PAYLOAD_TYPES]; /* must be sorted */ unsigned int num_payload_types; unsigned int rtcp_mux:1, @@ -132,6 +134,7 @@ struct rtpengine_output_info { struct rtpengine_srtp encrypt; uint32_t ssrc_out[RTPE_NUM_SSRC_TRACKING]; // Rewrite SSRC + struct rtpengine_pt_output pt_output[RTPE_NUM_PAYLOAD_TYPES]; // same indexes as pt_input unsigned char tos; unsigned int rtcp_only:1; @@ -218,7 +221,7 @@ struct rtpengine_message { struct rtpengine_list_entry { struct rtpengine_target_info target; struct rtpengine_stats stats; - struct rtpengine_rtp_stats rtp_stats[RTPE_NUM_PAYLOAD_TYPES]; + struct rtpengine_rtp_stats rtp_stats[RTPE_NUM_PAYLOAD_TYPES]; // same index as pt_input struct rtpengine_output_info outputs[RTPE_MAX_FORWARD_DESTINATIONS]; };