TT#31700 implement payload-type specific passthrough kernel forwarding

Change-Id: I14d33b976933e8198720c1323e38af85f4f6eed7
changes/48/18948/6
Richard Fuchs 8 years ago
parent 126a69f29c
commit 0636b083dc

@ -882,6 +882,10 @@ be engaged for that call.
With transcoding active for a call, all unsupported codecs will be removed from the SDP. Transcoding
happens in userspace only, so in-kernel packet forwarding will not be available for transcoded codecs.
However, even if the transcoding feature has been engaged for a call, not all codecs will necessarily
end up being transcoded. Codecs that are supported by both sides will simply be passed through
transparently (unless repacketization is active). In-kernel packet forwarding will still be available
for these codecs.
The following codecs are supported by *rtpengine*:

@ -21,6 +21,7 @@ static void __rtp_payload_type_add_name(GHashTable *, struct rtp_payload_type *p
static struct codec_handler codec_handler_stub = {
.source_pt.payload_type = -1,
.func = handler_func_passthrough,
.passthrough = 1,
};
@ -62,12 +63,14 @@ static void __transcode_packet_free(struct transcode_packet *);
static struct codec_handler codec_handler_stub_ssrc = {
.source_pt.payload_type = -1,
.func = handler_func_passthrough_ssrc,
.passthrough = 1,
};
static void __handler_shutdown(struct codec_handler *handler) {
free_ssrc_hash(&handler->ssrc_hash);
handler->passthrough = 0;
}
static void __codec_handler_free(void *pp) {
@ -85,11 +88,13 @@ static struct codec_handler *__handler_new(struct rtp_payload_type *pt) {
static void __make_passthrough(struct codec_handler *handler) {
__handler_shutdown(handler);
handler->func = handler_func_passthrough;
handler->passthrough = 1;
}
static void __make_passthrough_ssrc(struct codec_handler *handler) {
__handler_shutdown(handler);
handler->func = handler_func_passthrough_ssrc;
handler->passthrough = 1;
}
static void __make_transcoder(struct codec_handler *handler, struct rtp_payload_type *source,

@ -22,6 +22,7 @@ struct codec_handler {
struct rtp_payload_type source_pt; // source_pt.payload_type = hashtable index
struct rtp_payload_type dest_pt;
codec_handler_func *func;
int passthrough;
struct ssrc_hash *ssrc_hash;
};

@ -941,8 +941,6 @@ void kernelize(struct packet_stream *stream) {
return;
if (call->recording != NULL && !selected_recording_method->kernel_support)
goto no_kernel;
if (MEDIA_ISSET(stream->media, TRANSCODE)) // XXX make this granular per payload type?
goto no_kernel;
if (!kernel.is_wanted)
goto no_kernel;
nk_warn_msg = "interface to kernel module not open";
@ -993,7 +991,13 @@ void kernelize(struct packet_stream *stream) {
__re_address_translate_ep(&reti.dst_addr, &sink->endpoint);
__re_address_translate_ep(&reti.src_addr, &sink->selected_sfd->socket.local);
reti.ssrc = stream->ssrc_in ? htonl(stream->ssrc_in->parent->h.ssrc) : 0;
if (stream->ssrc_in) {
reti.ssrc = htonl(stream->ssrc_in->parent->h.ssrc);
if (MEDIA_ISSET(stream->media, TRANSCODE)) {
reti.ssrc_out = htonl(stream->ssrc_in->ssrc_map_out);
reti.transcoding = 1;
}
}
stream->handler->in->kernel(&reti.decrypt, stream);
stream->handler->out->kernel(&reti.encrypt, sink);
@ -1022,6 +1026,12 @@ void kernelize(struct packet_stream *stream) {
break;
}
rs = l->data;
if (MEDIA_ISSET(stream->media, TRANSCODE)) {
// only add payload types that are passthrough
struct codec_handler *ch = codec_handler_get(stream->media, rs->payload_type);
if (!ch->passthrough)
continue;
}
reti.payload_types[reti.num_payload_types++] = rs->payload_type;
}
g_list_free(values);

@ -8,7 +8,8 @@
static void init_ssrc_ctx(struct ssrc_ctx *c, struct ssrc_entry_call *parent) {
c->parent = parent;
c->ssrc_map_out = random();
while (!c->ssrc_map_out)
c->ssrc_map_out = random();
}
static void init_ssrc_entry(struct ssrc_entry *ent, u_int32_t ssrc) {
ent->ssrc = ssrc;

@ -1505,6 +1505,10 @@ static int proc_list_show(struct seq_file *f, void *v) {
seq_printf(f, " option: rtcp-mux\n");
if (g->target.dtls)
seq_printf(f, " option: dtls\n");
if (g->target.stun)
seq_printf(f, " option: stun\n");
if (g->target.transcoding)
seq_printf(f, " option: transcoding\n");
target_put(g);
@ -3913,6 +3917,10 @@ src_check_ok:
if (unlikely((g->target.ssrc) && (g->target.ssrc != rtp.header->ssrc)))
goto skip_error;
// if transcoding, only forward packets of passthrough payload types
if (g->target.transcoding && rtp_pt_idx < 0)
goto skip1;
pkt_idx = packet_index(&g->decrypt, &g->target.decrypt, rtp.header);
errstr = "SRTP authentication tag mismatch";
if (srtp_auth_validate(&g->decrypt, &g->target.decrypt, &rtp, &pkt_idx))
@ -3966,6 +3974,10 @@ no_intercept:
srtp_encrypt(&g->encrypt, &g->target.encrypt, &rtp, pkt_idx);
skb_put(skb, g->target.encrypt.mki_len + g->target.encrypt.auth_tag_len);
srtp_authenticate(&g->encrypt, &g->target.encrypt, &rtp, pkt_idx);
// SSRC substitution
if (g->target.transcoding && g->target.ssrc_out)
rtp.header->ssrc = g->target.ssrc_out;
}
err = send_proxy_packet(skb, &g->target.src_addr, &g->target.dst_addr, g->target.tos, par);

@ -92,6 +92,7 @@ struct rtpengine_target_info {
struct rtpengine_srtp decrypt;
struct rtpengine_srtp encrypt;
u_int32_t ssrc; // Expose the SSRC to userspace when we resync.
u_int32_t ssrc_out; // Rewrite SSRC
unsigned char payload_types[NUM_PAYLOAD_TYPES]; /* must be sorted */
unsigned int num_payload_types;
@ -102,7 +103,8 @@ struct rtpengine_target_info {
stun:1,
rtp:1,
rtp_only:1,
do_intercept:1;
do_intercept:1,
transcoding:1; // SSRC subst and RTP PT filtering
};
struct rtpengine_call_info {

Loading…
Cancel
Save