From a0fed378121dbeeb40d496d295eb79322f67be86 Mon Sep 17 00:00:00 2001 From: Tom Briden <tom.briden@eckoh.com> Date: Wed, 10 May 2023 15:21:49 +0100 Subject: [PATCH] recording-daemon: Insert silence frames as needed during TLS forwarding If the forwarded streams of a call are later combined without the inserted silence, the resulting mix may end up with them out of sync. This is already handled when outputting mixed files so the same functionality from mix.c has been added for tls forwarding --- lib/common.Makefile | 2 +- recording-daemon/decoder.c | 5 +++++ recording-daemon/packet.c | 45 ++++++++++++++++++++++++++++++++++++++ recording-daemon/packet.h | 2 ++ recording-daemon/types.h | 2 ++ 5 files changed, 55 insertions(+), 1 deletion(-) diff --git a/lib/common.Makefile b/lib/common.Makefile index 1dea55701..30bf4c217 100644 --- a/lib/common.Makefile +++ b/lib/common.Makefile @@ -41,7 +41,7 @@ $(DAEMONSRCS) $(HASHSRCS): $(patsubst %,../daemon/%,$(DAEMONSRCS)) $(patsubst %, -M "date:$(shell date -I)" \ -o "$@" -resample.c codeclib.strhash.c mix.c: fix_frame_channel_layout.h +resample.c codeclib.strhash.c mix.c packet.c: fix_frame_channel_layout.h ifeq ($(with_transcoding),yes) codec.c: dtmf_rx_fillin.h diff --git a/recording-daemon/decoder.c b/recording-daemon/decoder.c index 55c3ee572..c7c47f5d3 100644 --- a/recording-daemon/decoder.c +++ b/recording-daemon/decoder.c @@ -171,6 +171,11 @@ no_recording: ssrc->sent_intro = 1; } + ssrc_tls_fwd_silence_frames_upto(ssrc, dec_frame, dec_frame->pts); + uint64_t next_pts = dec_frame->pts + dec_frame->nb_samples; + if (next_pts > ssrc->tls_in_pts) + ssrc->tls_in_pts = next_pts; + int linesize = av_get_bytes_per_sample(dec_frame->format) * dec_frame->nb_samples; dbg("Writing %u bytes PCM to TLS", linesize); streambuf_write(ssrc->tls_fwd_stream, (char *) dec_frame->extended_data[0], linesize); diff --git a/recording-daemon/packet.c b/recording-daemon/packet.c index 06b75cdb9..87ba97cc7 100644 --- a/recording-daemon/packet.c +++ b/recording-daemon/packet.c @@ -17,6 +17,7 @@ #include "streambuf.h" #include "resample.h" #include "tag.h" +#include "fix_frame_channel_layout.h" static ssize_t ssrc_tls_write(void *, const void *, size_t); @@ -144,6 +145,49 @@ void ssrc_tls_state(ssrc_t *ssrc) { } +void ssrc_tls_fwd_silence_frames_upto(ssrc_t *ssrc, AVFrame *frame, int64_t upto) { + unsigned int silence_samples = ssrc->tls_fwd_format.clockrate / 100; + + while (ssrc->tls_in_pts < upto) { + if (G_UNLIKELY(upto - ssrc->tls_in_pts > ssrc->tls_fwd_format.clockrate * 30)) { + ilog(LOG_WARN, "More than 30 seconds of silence needed to fill mix buffer, resetting"); + ssrc->tls_in_pts = upto; + break; + } + if (G_UNLIKELY(!ssrc->tls_silence_frame)) { + ssrc->tls_silence_frame = av_frame_alloc(); + ssrc->tls_silence_frame->format = ssrc->tls_fwd_format.format; + DEF_CH_LAYOUT(&ssrc->tls_silence_frame->CH_LAYOUT, ssrc->tls_fwd_format.channels); + ssrc->tls_silence_frame->nb_samples = silence_samples; + ssrc->tls_silence_frame->sample_rate = ssrc->tls_fwd_format.clockrate; + if (av_frame_get_buffer(ssrc->tls_silence_frame, 0) < 0) { + ilog(LOG_ERR, "Failed to get silence frame buffers"); + return; + } + int planes = av_sample_fmt_is_planar(ssrc->tls_silence_frame->format) ? ssrc->tls_fwd_format.channels : 1; + for (int i = 0; i < planes; i++) + memset(ssrc->tls_silence_frame->extended_data[i], 0, ssrc->tls_silence_frame->linesize[0]); + } + + dbg("pushing silence frame into TLS-formward stream (%lli < %llu)", + (long long unsigned) ssrc->tls_in_pts, + (long long unsigned) upto); + + ssrc->tls_silence_frame->pts = ssrc->tls_in_pts; + ssrc->tls_silence_frame->nb_samples = MIN(silence_samples, upto - ssrc->tls_in_pts); + ssrc->tls_in_pts += ssrc->tls_silence_frame->nb_samples; + + CH_LAYOUT_T channel_layout; + DEF_CH_LAYOUT(&channel_layout, ssrc->tls_fwd_format.channels); + ssrc->tls_silence_frame->CH_LAYOUT = channel_layout; + + int linesize = av_get_bytes_per_sample(frame->format) * ssrc->tls_silence_frame->nb_samples; + dbg("Writing %u bytes PCM to TLS", linesize); + streambuf_write(ssrc->tls_fwd_stream, (char *) ssrc->tls_silence_frame->extended_data[0], linesize); + } +} + + void ssrc_close(ssrc_t *s) { output_close(s->metafile, s->output, tag_get(s->metafile, s->stream->tag), s->metafile->discard); s->output = NULL; @@ -156,6 +200,7 @@ void ssrc_close(ssrc_t *s) { void ssrc_free(void *p) { ssrc_t *s = p; + av_frame_free(&s->tls_silence_frame); packet_sequencer_destroy(&s->sequencer); ssrc_close(s); g_slice_free1(sizeof(*s), s); diff --git a/recording-daemon/packet.h b/recording-daemon/packet.h index e6c2e9362..5fa826bb4 100644 --- a/recording-daemon/packet.h +++ b/recording-daemon/packet.h @@ -2,6 +2,7 @@ #define _PACKET_H_ #include "types.h" +#include <libavutil/frame.h> void ssrc_close(ssrc_t *s); void ssrc_free(void *p); @@ -9,5 +10,6 @@ void ssrc_free(void *p); void packet_process(stream_t *, unsigned char *, unsigned len); void ssrc_tls_state(ssrc_t *ssrc); +void ssrc_tls_fwd_silence_frames_upto(ssrc_t *ssrc, AVFrame *frame, int64_t upto); #endif diff --git a/recording-daemon/types.h b/recording-daemon/types.h index 4d699fcf8..98f3b02fc 100644 --- a/recording-daemon/types.h +++ b/recording-daemon/types.h @@ -87,6 +87,8 @@ struct ssrc_s { format_t tls_fwd_format; resample_t tls_fwd_resampler; socket_t tls_fwd_sock; + uint64_t tls_in_pts; + AVFrame *tls_silence_frame; //BIO *bio; SSL_CTX *ssl_ctx; SSL *ssl;