From 8bb41e73dc54bbc3159b0c69927ba017d6894e8f Mon Sep 17 00:00:00 2001 From: Peter Kelly Date: Mon, 9 Sep 2024 10:43:02 +0100 Subject: [PATCH 1/3] back to old parser --- daemon/call_interfaces.c | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/daemon/call_interfaces.c b/daemon/call_interfaces.c index eaa78bb3d9..ad75dc7e95 100644 --- a/daemon/call_interfaces.c +++ b/daemon/call_interfaces.c @@ -1739,6 +1739,19 @@ static void call_ng_main_flags(sdp_ng_flags *out, str *key, bencode_item_t *valu case CSH_LOOKUP("recording file"): out->recording_file = s; break; + case CSH_LOOKUP("recording-media-slot-offer"): + // This needs to be > 0 + out->media_rec_slot_offer = bencode_get_integer_str(value, out->media_rec_slot_offer); + //out->media_rec_slot_offer = parser->get_int_str(value, out->media_rec_slot_offer); + break; + case CSH_LOOKUP("recording-media-slot-answer"): + // This needs to be > 0 + out->media_rec_slot_answer = bencode_get_integer_str(value, out->media_rec_slot_answer); + //out->media_rec_slot_answer = parser->get_int_str(value, out->media_rec_slot_answer); + break; + case CSH_LOOKUP("recording-media-slots"): + out->media_rec_slots = parser->get_int_str(value, out->media_rec_slots); + break; case CSH_LOOKUP("passthrough"): case CSH_LOOKUP("passthru"): switch (__csh_lookup(&s)) { From a859a445141657ebf47c8d82cce7f1d6ae58e269 Mon Sep 17 00:00:00 2001 From: Peter Kelly Date: Mon, 9 Sep 2024 10:47:37 +0100 Subject: [PATCH 2/3] back to the old parser again... --- daemon/call_interfaces.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/daemon/call_interfaces.c b/daemon/call_interfaces.c index ad75dc7e95..c5022d3f68 100644 --- a/daemon/call_interfaces.c +++ b/daemon/call_interfaces.c @@ -1750,7 +1750,8 @@ static void call_ng_main_flags(sdp_ng_flags *out, str *key, bencode_item_t *valu //out->media_rec_slot_answer = parser->get_int_str(value, out->media_rec_slot_answer); break; case CSH_LOOKUP("recording-media-slots"): - out->media_rec_slots = parser->get_int_str(value, out->media_rec_slots); + out->media_rec_slots = bencode_get_integer_str(value, out->media_rec_slots); + //out->media_rec_slots = parser->get_int_str(value, out->media_rec_slots); break; case CSH_LOOKUP("passthrough"): case CSH_LOOKUP("passthru"): From b60741e07cd7bec81da2ee624ae9e33884b99922 Mon Sep 17 00:00:00 2001 From: Peter Kelly Date: Fri, 16 May 2025 16:13:15 +0100 Subject: [PATCH 3/3] fix for strange reused ssrc issue --- .gitignore | 2 ++ recording-daemon/decoder.c | 13 ++++++++--- recording-daemon/mix.c | 46 +++++++++++++++++++++++++++++--------- recording-daemon/mix.h | 9 ++++---- recording-daemon/types.h | 1 + rtpengine.code-workspace | 8 +++++++ 6 files changed, 60 insertions(+), 19 deletions(-) create mode 100644 rtpengine.code-workspace diff --git a/.gitignore b/.gitignore index cd17050f66..a3baa2c2df 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,5 @@ .*.sw? *.strhash.c docs/_* +config.mk +/.idea diff --git a/recording-daemon/decoder.c b/recording-daemon/decoder.c index d7c8413d5a..57534cbbbb 100644 --- a/recording-daemon/decoder.c +++ b/recording-daemon/decoder.c @@ -23,7 +23,7 @@ int resample_audio; - +// Remove duplicate struct definition; use the one from types.h decode_t *decoder_new(const char *payload_str, const char *format, int ptime, output_t *outp) { char *slash = strchr(payload_str, '/'); @@ -114,8 +114,13 @@ static int decoder_got_frame(decoder_t *dec, AVFrame *frame, void *sp, void *dp) pthread_mutex_lock(&metafile->mix_lock); if (metafile->mix_out) { dbg("adding packet from stream #%lu to mix output", stream->id); + // If SSRC changed, force a new slot lookup + if (deco->last_ssrc != ssrc->ssrc) { + deco->mixer_idx = (unsigned int)-1; + deco->last_ssrc = ssrc->ssrc; + } if (G_UNLIKELY(deco->mixer_idx == (unsigned int) -1)) - deco->mixer_idx = mix_get_index(metafile->mix, ssrc); + deco->mixer_idx = mix_get_index(metafile->mix, ssrc->ssrc, stream->media_sdp_id, stream->channel_slot); format_t actual_format; if (output_config(metafile->mix_out, &dec->dest_format, &actual_format)) goto no_mix_out; @@ -126,8 +131,10 @@ static int decoder_got_frame(decoder_t *dec, AVFrame *frame, void *sp, void *dp) pthread_mutex_unlock(&metafile->mix_lock); goto err; } - if (mix_add(metafile->mix, dec_frame, deco->mixer_idx, ssrc, metafile->mix_out)) + if (mix_add(metafile->mix, dec_frame, deco->mixer_idx, ssrc->ssrc, metafile->mix_out)) { ilog(LOG_ERR, "Failed to add decoded packet to mixed output"); + deco->mixer_idx = (unsigned int)-1; // Force new slot lookup on next frame + } } no_mix_out: pthread_mutex_unlock(&metafile->mix_lock); diff --git a/recording-daemon/mix.c b/recording-daemon/mix.c index 386ab6a4ae..f553c02cac 100644 --- a/recording-daemon/mix.c +++ b/recording-daemon/mix.c @@ -27,7 +27,7 @@ struct mix_s { uint64_t pts_offs[MIX_MAX_INPUTS]; // initialized at first input seen uint64_t in_pts[MIX_MAX_INPUTS]; // running counter of next expected adjusted pts struct timeval last_use[MIX_MAX_INPUTS]; // to recycle old mix inputs - void *input_ref[MIX_MAX_INPUTS]; // to avoid collisions in case of idx re-use + uint32_t input_ref[MIX_MAX_INPUTS]; // use SSRC value as key CH_LAYOUT_T channel_layout[MIX_MAX_INPUTS]; AVFilterContext *amix_ctx; AVFilterContext *sink_ctx; @@ -78,16 +78,29 @@ void mix_destroy(mix_t *mix) { static void mix_input_reset(mix_t *mix, unsigned int idx) { mix->pts_offs[idx] = (uint64_t) -1LL; ZERO(mix->last_use[idx]); - mix->input_ref[idx] = NULL; + mix->input_ref[idx] = 0xFFFFFFFF; // invalid SSRC mix->in_pts[idx] = 0; } -unsigned int mix_get_index(mix_t *mix, void *ptr) { - unsigned int next = mix->next_idx++; +unsigned int mix_get_index(mix_t *mix, uint32_t ssrc, unsigned int media_sdp_id, unsigned int stream_channel_slot) { + unsigned int next; + + if (mix_output_per_media) { + next = media_sdp_id; + if (next >= mix_num_inputs) { + ilog(LOG_WARNING, "Error with mix_output_per_media sdp_label next %i is bigger than mix_num_inputs %i", next, mix_num_inputs ); + } + } else { + ilog(LOG_DEBUG, "getting mix input index for slot %u. channel slots for this mix are %u", stream_channel_slot, mix->channel_slots); + next = mix->next_idx[stream_channel_slot]; + mix->next_idx[stream_channel_slot] += mix->channel_slots; + ilog(LOG_DEBUG, "mix input index chosen is #%u", next); + } + if (next < mix_num_inputs) { - // must be unused - mix->input_ref[next] = ptr; + ilog(LOG_DEBUG, "mix_get_index: assigning slot %u to SSRC 0x%08x (was 0x%08x)", next, ssrc, mix->input_ref[next]); + mix->input_ref[next] = ssrc; return next; } @@ -103,7 +116,9 @@ unsigned int mix_get_index(mix_t *mix, void *ptr) { ilog(LOG_DEBUG, "Re-using mix input index #%u", next); mix_input_reset(mix, next); - mix->input_ref[next] = ptr; + ilog(LOG_DEBUG, "mix_get_index: re-assigning slot %u to SSRC 0x%08x (was 0x%08x)", next, ssrc, mix->input_ref[next]); + mix->input_ref[next] = ssrc; + mix->next_idx[stream_channel_slot] = next; return next; } @@ -222,8 +237,10 @@ mix_t *mix_new(void) { format_init(&mix->out_format); mix->sink_frame = av_frame_alloc(); - for (unsigned int i = 0; i < mix_num_inputs; i++) + for (unsigned int i = 0; i < mix_num_inputs; i++) { mix->pts_offs[i] = (uint64_t) -1LL; + mix->input_ref[i] = 0xFFFFFFFF; // invalid SSRC + } return mix; } @@ -283,20 +300,27 @@ static void mix_silence_fill(mix_t *mix) { } -int mix_add(mix_t *mix, AVFrame *frame, unsigned int idx, void *ptr, output_t *output) { +int mix_add(mix_t *mix, AVFrame *frame, unsigned int idx, uint32_t ssrc, output_t *output) { const char *err; + ilog(LOG_DEBUG, "mix_add: slot %u, incoming SSRC 0x%08x, input_ref[%u]=0x%08x", idx, ssrc, idx, mix->input_ref[idx]); + err = "index out of range"; if (idx >= mix_num_inputs) goto err; + ilog(LOG_DEBUG, "mix_add: about to use src_ctxs[%u]=%p", idx, mix->src_ctxs[idx]); err = "mixer not initialized"; - if (!mix->src_ctxs[idx]) + if (!mix->src_ctxs[idx]) { + ilog(LOG_ERR, "mix_add: src_ctxs[%u] is NULL!", idx); goto err; + } err = "received samples for old re-used input channel"; - if (ptr != mix->input_ref[idx]) + if (ssrc != mix->input_ref[idx]) { + mix_input_reset(mix, idx); // Reset slot for next use goto err; + } gettimeofday(&mix->last_use[idx], NULL); diff --git a/recording-daemon/mix.h b/recording-daemon/mix.h index dcfebde515..20edb943bd 100644 --- a/recording-daemon/mix.h +++ b/recording-daemon/mix.h @@ -3,15 +3,14 @@ #include "types.h" #include +#include -#define MIX_MAX_INPUTS 4 +#define MIX_MAX_INPUTS 8 mix_t *mix_new(void); void mix_destroy(mix_t *mix); int mix_config(mix_t *, const format_t *format); -int mix_add(mix_t *mix, AVFrame *frame, unsigned int idx, void *, output_t *output); -unsigned int mix_get_index(mix_t *, void *); - - +int mix_add(mix_t *mix, AVFrame *frame, unsigned int idx, uint32_t ssrc, output_t *output); +unsigned int mix_get_index(mix_t *, uint32_t ssrc, unsigned int, unsigned int); #endif diff --git a/recording-daemon/types.h b/recording-daemon/types.h index 99bb85e1a5..d14144833a 100644 --- a/recording-daemon/types.h +++ b/recording-daemon/types.h @@ -184,6 +184,7 @@ struct decode_s { decoder_t *dec; resample_t mix_resampler; unsigned int mixer_idx; + uint32_t last_ssrc; }; diff --git a/rtpengine.code-workspace b/rtpengine.code-workspace new file mode 100644 index 0000000000..876a1499c0 --- /dev/null +++ b/rtpengine.code-workspace @@ -0,0 +1,8 @@ +{ + "folders": [ + { + "path": "." + } + ], + "settings": {} +} \ No newline at end of file