|
|
|
|
@ -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);
|
|
|
|
|
|
|
|
|
|
|