diff --git a/daemon/kernel.c b/daemon/kernel.c index 0d4fc633c..7dac5ecc9 100644 --- a/daemon/kernel.c +++ b/daemon/kernel.c @@ -289,3 +289,27 @@ int kernel_update_stats(struct rtpengine_command_stats *cmd) { return 0; } + +int kernel_send_rtcp(struct rtpengine_send_packet_info *info, const char *buf, size_t len) { + if (!kernel.is_open) + return -1; + + size_t total_len = len + sizeof(struct rtpengine_command_send_packet); + struct rtpengine_command_send_packet *cmd = alloca(total_len); + cmd->cmd = REMG_SEND_RTCP; + cmd->send_packet = *info; + memcpy(&cmd->send_packet.data, buf, len); + + ssize_t ret = write(kernel.fd, cmd, total_len); + + if (ret != total_len) { + if (ret == -1) + ilog(LOG_ERR, "Failed to send RTCP via kernel interface: %s", strerror(errno)); + else + ilog(LOG_ERR, "Failed to send RTCP via kernel interface (%zi != %zu)", + ret, total_len); + return -1; + } + + return 0; +} diff --git a/daemon/media_player.c b/daemon/media_player.c index dec1677af..65d8a4d77 100644 --- a/daemon/media_player.c +++ b/daemon/media_player.c @@ -19,6 +19,7 @@ #ifdef WITH_TRANSCODING #include "fix_frame_channel_layout.h" #endif +#include "kernel.h" @@ -249,8 +250,11 @@ static bool __send_timer_send_1(struct rtp_header *rh, struct packet_stream *sin endpoint_print_buf(&sink_fd->socket.local), FMT_M(endpoint_print_buf(&sink->endpoint))); - socket_sendto(&sink_fd->socket, - cp->s.s, cp->s.len, &sink->endpoint); + if (cp->kernel_send_info.local.family) + kernel_send_rtcp(&cp->kernel_send_info, cp->s.s, cp->s.len); + else + socket_sendto(&sink_fd->socket, + cp->s.s, cp->s.len, &sink->endpoint); if (sink->call->recording && rtpe_config.rec_egress) { // fill in required members diff --git a/daemon/media_socket.c b/daemon/media_socket.c index 38bbeb29c..09c88d1ca 100644 --- a/daemon/media_socket.c +++ b/daemon/media_socket.c @@ -2315,7 +2315,15 @@ int media_packet_encrypt(rewrite_func encrypt_func, struct packet_stream *out, s return ret; } -static int __media_packet_encrypt(struct packet_handler_ctx *phc) { +// return: -1 = error, 0 = ok, 1 = pass to kernel for sending +static int __media_packet_encrypt(struct packet_handler_ctx *phc, struct sink_handler *sh) { + if (phc->rtcp) { + // can the kernel handle this for us? + if (PS_ISSET(phc->mp.stream, KERNELIZED) && !PS_ISSET(phc->mp.stream, NO_KERNEL_SUPPORT) + && sh->kernel_output_idx >= 0) + return 1; + } + int ret = media_packet_encrypt(phc->encrypt_func, phc->out_srtp, &phc->mp); if (ret & 0x02) phc->update = true; @@ -2917,7 +2925,7 @@ static int stream_packet(struct packet_handler_ctx *phc) { g_queue_push_tail(&mirror_phc.mp.packets_out, codec_packet_dup(p)); } - ret = __media_packet_encrypt(&mirror_phc); + ret = __media_packet_encrypt(&mirror_phc, mirror_sh); if (ret) goto next_mirror; @@ -2941,11 +2949,24 @@ next_mirror: } } - ret = __media_packet_encrypt(phc); + ret = __media_packet_encrypt(phc, sh); errno = ENOTTY; - if (ret) + if (ret == -1) goto err_next; + if (ret == 1) { + for (GList *l = phc->mp.packets_out.head; l; l = l->next) { + struct codec_packet *p = l->data; + __re_address_translate_ep(&p->kernel_send_info.local, + &phc->mp.stream->selected_sfd->socket.local); + __re_address_translate_ep(&p->kernel_send_info.src_addr, + &sh->sink->selected_sfd->socket.local); + __re_address_translate_ep(&p->kernel_send_info.dst_addr, + &sh->sink->endpoint); + p->kernel_send_info.destination_idx = sh->kernel_output_idx; + } + } + mutex_lock(&sink->out_lock); if (!sink->advertised_endpoint.port diff --git a/include/codec.h b/include/codec.h index 4a655c6d2..4648db3f6 100644 --- a/include/codec.h +++ b/include/codec.h @@ -10,6 +10,7 @@ #include "aux.h" #include "rtplib.h" #include "timerthread.h" +#include "xt_RTPENGINE.h" struct call_media; @@ -77,6 +78,7 @@ struct codec_packet { struct ssrc_ctx *ssrc_out; void (*free_func)(void *); void (*plain_free_func)(void *); + struct rtpengine_send_packet_info kernel_send_info; }; struct codec_scheduler { diff --git a/include/kernel.h b/include/kernel.h index d81cfff1c..14bc910db 100644 --- a/include/kernel.h +++ b/include/kernel.h @@ -18,6 +18,7 @@ struct rtpengine_target_info; struct rtpengine_destination_info; +struct rtpengine_send_packet_info; struct re_address; struct rtpengine_ssrc_stats; @@ -46,6 +47,7 @@ int kernel_del_call(unsigned int); unsigned int kernel_add_intercept_stream(unsigned int call_idx, const char *id); +int kernel_send_rtcp(struct rtpengine_send_packet_info *info, const char *buf, size_t len);