Browse Source

fix for strange reused ssrc issue

pull/2009/head
Peter Kelly 8 months ago
parent
commit
b60741e07c
6 changed files with 60 additions and 19 deletions
  1. +2
    -0
      .gitignore
  2. +10
    -3
      recording-daemon/decoder.c
  3. +35
    -11
      recording-daemon/mix.c
  4. +4
    -5
      recording-daemon/mix.h
  5. +1
    -0
      recording-daemon/types.h
  6. +8
    -0
      rtpengine.code-workspace

+ 2
- 0
.gitignore View File

@ -1,3 +1,5 @@
.*.sw? .*.sw?
*.strhash.c *.strhash.c
docs/_* docs/_*
config.mk
/.idea

+ 10
- 3
recording-daemon/decoder.c View File

@ -23,7 +23,7 @@
int resample_audio; 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) { decode_t *decoder_new(const char *payload_str, const char *format, int ptime, output_t *outp) {
char *slash = strchr(payload_str, '/'); 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); pthread_mutex_lock(&metafile->mix_lock);
if (metafile->mix_out) { if (metafile->mix_out) {
dbg("adding packet from stream #%lu to mix output", stream->id); 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)) 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; format_t actual_format;
if (output_config(metafile->mix_out, &dec->dest_format, &actual_format)) if (output_config(metafile->mix_out, &dec->dest_format, &actual_format))
goto no_mix_out; 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); pthread_mutex_unlock(&metafile->mix_lock);
goto err; 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"); 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: no_mix_out:
pthread_mutex_unlock(&metafile->mix_lock); pthread_mutex_unlock(&metafile->mix_lock);


+ 35
- 11
recording-daemon/mix.c View File

@ -27,7 +27,7 @@ struct mix_s {
uint64_t pts_offs[MIX_MAX_INPUTS]; // initialized at first input seen 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 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 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]; CH_LAYOUT_T channel_layout[MIX_MAX_INPUTS];
AVFilterContext *amix_ctx; AVFilterContext *amix_ctx;
AVFilterContext *sink_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) { static void mix_input_reset(mix_t *mix, unsigned int idx) {
mix->pts_offs[idx] = (uint64_t) -1LL; mix->pts_offs[idx] = (uint64_t) -1LL;
ZERO(mix->last_use[idx]); ZERO(mix->last_use[idx]);
mix->input_ref[idx] = NULL;
mix->input_ref[idx] = 0xFFFFFFFF; // invalid SSRC
mix->in_pts[idx] = 0; 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) { 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; 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); ilog(LOG_DEBUG, "Re-using mix input index #%u", next);
mix_input_reset(mix, 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; return next;
} }
@ -222,8 +237,10 @@ mix_t *mix_new(void) {
format_init(&mix->out_format); format_init(&mix->out_format);
mix->sink_frame = av_frame_alloc(); 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->pts_offs[i] = (uint64_t) -1LL;
mix->input_ref[i] = 0xFFFFFFFF; // invalid SSRC
}
return mix; 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; 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"; err = "index out of range";
if (idx >= mix_num_inputs) if (idx >= mix_num_inputs)
goto err; goto err;
ilog(LOG_DEBUG, "mix_add: about to use src_ctxs[%u]=%p", idx, mix->src_ctxs[idx]);
err = "mixer not initialized"; 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; goto err;
}
err = "received samples for old re-used input channel"; 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; goto err;
}
gettimeofday(&mix->last_use[idx], NULL); gettimeofday(&mix->last_use[idx], NULL);


+ 4
- 5
recording-daemon/mix.h View File

@ -3,15 +3,14 @@
#include "types.h" #include "types.h"
#include <libavutil/frame.h> #include <libavutil/frame.h>
#include <stdint.h>
#define MIX_MAX_INPUTS 4
#define MIX_MAX_INPUTS 8
mix_t *mix_new(void); mix_t *mix_new(void);
void mix_destroy(mix_t *mix); void mix_destroy(mix_t *mix);
int mix_config(mix_t *, const format_t *format); 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 #endif

+ 1
- 0
recording-daemon/types.h View File

@ -184,6 +184,7 @@ struct decode_s {
decoder_t *dec; decoder_t *dec;
resample_t mix_resampler; resample_t mix_resampler;
unsigned int mixer_idx; unsigned int mixer_idx;
uint32_t last_ssrc;
}; };


+ 8
- 0
rtpengine.code-workspace View File

@ -0,0 +1,8 @@
{
"folders": [
{
"path": "."
}
],
"settings": {}
}

Loading…
Cancel
Save