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
pull/1546/head
Richard Fuchs 3 years ago
parent f316deafb7
commit 1efc3d9409

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

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

@ -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])

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

Loading…
Cancel
Save