|
|
|
|
@ -1515,9 +1515,10 @@ typedef struct {
|
|
|
|
|
struct rtpengine_target_info reti;
|
|
|
|
|
kernel_output_q outputs;
|
|
|
|
|
rtp_stats_arr *payload_types;
|
|
|
|
|
bool ignore_payload_types; // temporary until refactor
|
|
|
|
|
bool blackhole;
|
|
|
|
|
bool non_forwarding;
|
|
|
|
|
bool silenced;
|
|
|
|
|
bool manipulate_pt;
|
|
|
|
|
} kernelize_state;
|
|
|
|
|
|
|
|
|
|
static void kernelize_state_clear(kernelize_state *s) {
|
|
|
|
|
@ -1600,6 +1601,9 @@ static const char *kernelize_target(kernelize_state *s, struct packet_stream *st
|
|
|
|
|
if (!reti->decrypt.cipher || !reti->decrypt.hmac)
|
|
|
|
|
return "decryption cipher or HMAC not supported by kernel module";
|
|
|
|
|
|
|
|
|
|
s->silenced = CALL_ISSET(media->call, SILENCE_MEDIA) || ML_ISSET(media->monologue, SILENCE_MEDIA);
|
|
|
|
|
s->manipulate_pt = s->silenced || ML_ISSET(media->monologue, BLOCK_SHORT);
|
|
|
|
|
|
|
|
|
|
reti->track_ssrc = 1;
|
|
|
|
|
for (unsigned int u = 0; u < G_N_ELEMENTS(stream->ssrc_in); u++) {
|
|
|
|
|
if (stream->ssrc_in[u]) {
|
|
|
|
|
@ -1645,11 +1649,17 @@ static const char *kernelize_target(kernelize_state *s, struct packet_stream *st
|
|
|
|
|
bool can_kernelize = true;
|
|
|
|
|
for (__auto_type k = stream->rtp_sinks.head; k; k = k->next) {
|
|
|
|
|
struct sink_handler *ksh = k->data;
|
|
|
|
|
|
|
|
|
|
if (ksh->attrs.silence_media)
|
|
|
|
|
s->manipulate_pt = true;
|
|
|
|
|
|
|
|
|
|
struct packet_stream *ksink = ksh->sink;
|
|
|
|
|
struct codec_handler *ch = codec_handler_get(media, rs->payload_type,
|
|
|
|
|
ksink->media, ksh);
|
|
|
|
|
if (ch->kernelize)
|
|
|
|
|
|
|
|
|
|
if (ch->kernelize && !ch->transcoder && !ksh->attrs.transcoding)
|
|
|
|
|
continue;
|
|
|
|
|
|
|
|
|
|
can_kernelize = false;
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
@ -1700,7 +1710,6 @@ static const char *kernelize_one(kernelize_state *s,
|
|
|
|
|
return "protocol not supported by kernel module";
|
|
|
|
|
|
|
|
|
|
__auto_type reti = &s->reti;
|
|
|
|
|
__auto_type payload_types = s->ignore_payload_types ? NULL : &s->payload_types;
|
|
|
|
|
|
|
|
|
|
// any output at all?
|
|
|
|
|
if (s->non_forwarding || !sink->selected_sfd)
|
|
|
|
|
@ -1714,12 +1723,10 @@ static const char *kernelize_one(kernelize_state *s,
|
|
|
|
|
redi->output.tos = call->tos;
|
|
|
|
|
|
|
|
|
|
// PT manipulations
|
|
|
|
|
bool silenced = CALL_ISSET(call, SILENCE_MEDIA) || ML_ISSET(media->monologue, SILENCE_MEDIA)
|
|
|
|
|
|| sink_handler->attrs.silence_media;
|
|
|
|
|
bool manipulate_pt = silenced || ML_ISSET(media->monologue, BLOCK_SHORT);
|
|
|
|
|
if (manipulate_pt && payload_types) {
|
|
|
|
|
for (unsigned int i = 0; i < (*payload_types)->len; i++) {
|
|
|
|
|
__auto_type rs = (*payload_types)->pdata[i];
|
|
|
|
|
bool silenced = s->silenced || sink_handler->attrs.silence_media;
|
|
|
|
|
if (s->manipulate_pt && s->payload_types) {
|
|
|
|
|
for (unsigned int i = 0; i < s->payload_types->len; i++) {
|
|
|
|
|
__auto_type rs = s->payload_types->pdata[i];
|
|
|
|
|
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);
|
|
|
|
|
@ -1741,13 +1748,8 @@ static const char *kernelize_one(kernelize_state *s,
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (MEDIA_ISSET(media, ECHO))
|
|
|
|
|
redi->output.ssrc_subst = 1;
|
|
|
|
|
|
|
|
|
|
if (sink_handler->attrs.transcoding) {
|
|
|
|
|
if (MEDIA_ISSET(media, ECHO) || sink_handler->attrs.transcoding)
|
|
|
|
|
redi->output.ssrc_subst = 1;
|
|
|
|
|
reti->pt_filter = 1;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
mutex_lock(&sink->out_lock);
|
|
|
|
|
|
|
|
|
|
@ -1828,23 +1830,29 @@ void kernelize(struct packet_stream *stream) {
|
|
|
|
|
if (err)
|
|
|
|
|
ilog(LOG_WARNING, "No support for kernel packet forwarding available (%s)", err);
|
|
|
|
|
|
|
|
|
|
// primary RTP sinks
|
|
|
|
|
for (__auto_type l = stream->rtp_sinks.head; l; l = l->next) {
|
|
|
|
|
struct sink_handler *sh = l->data;
|
|
|
|
|
if (sh->attrs.block_media)
|
|
|
|
|
continue;
|
|
|
|
|
kernelize_one_sink_handler(&s, stream, sh);
|
|
|
|
|
}
|
|
|
|
|
// RTP egress mirrors
|
|
|
|
|
for (__auto_type l = stream->rtp_mirrors.head; l; l = l->next) {
|
|
|
|
|
struct sink_handler *sh = l->data;
|
|
|
|
|
kernelize_one_sink_handler(&s, stream, sh);
|
|
|
|
|
}
|
|
|
|
|
// record number of RTP destinations
|
|
|
|
|
// RTP -> RTCP sinks
|
|
|
|
|
// record number of RTP destinations up to now
|
|
|
|
|
unsigned int num_rtp_dests = s.reti.num_destinations;
|
|
|
|
|
// ignore RTP payload types
|
|
|
|
|
rtp_stats_arr_destroy_ptr(s.payload_types);
|
|
|
|
|
s.payload_types = NULL;
|
|
|
|
|
for (__auto_type l = stream->rtcp_sinks.head; l; l = l->next) {
|
|
|
|
|
struct sink_handler *sh = l->data;
|
|
|
|
|
s.ignore_payload_types = true;
|
|
|
|
|
kernelize_one_sink_handler(&s, stream, sh);
|
|
|
|
|
}
|
|
|
|
|
// mark the start of RTCP outputs
|
|
|
|
|
s.reti.num_rtcp_destinations = s.reti.num_destinations - num_rtp_dests;
|
|
|
|
|
|
|
|
|
|
if (!s.reti.local.family)
|
|
|
|
|
|