|
|
|
@ -38,6 +38,8 @@ struct mix_s { |
|
|
|
resample_t resample; |
|
|
|
|
|
|
|
uint64_t out_pts; // starting at zero |
|
|
|
pthread_mutex_t *lock; |
|
|
|
sink_t *sink; |
|
|
|
|
|
|
|
AVFrame *silence_frame; |
|
|
|
}; |
|
|
|
@ -249,11 +251,13 @@ err: |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
mix_t *mix_new(unsigned int media_rec_slots) { |
|
|
|
mix_t *mix_new(pthread_mutex_t *lock, sink_t *sink, unsigned int media_rec_slots) { |
|
|
|
mix_t *mix = g_new0(mix_t, 1); |
|
|
|
format_init(&mix->in_format); |
|
|
|
format_init(&mix->out_format); |
|
|
|
mix->sink_frame = av_frame_alloc(); |
|
|
|
mix->lock = lock; |
|
|
|
mix->sink = sink; |
|
|
|
|
|
|
|
for (unsigned int i = 0; i < mix_num_inputs; i++) |
|
|
|
mix->pts_offs[i] = (uint64_t) -1LL; |
|
|
|
@ -325,7 +329,7 @@ static void mix_silence_fill(mix_t *mix) { |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
static int mix_add_(mix_t *mix, AVFrame *frame, unsigned int idx, void *ptr, output_t *output) { |
|
|
|
static int mix_add_(mix_t *mix, AVFrame *frame, unsigned int idx, void *ptr) { |
|
|
|
const char *err; |
|
|
|
|
|
|
|
err = "index out of range"; |
|
|
|
@ -390,7 +394,7 @@ static int mix_add_(mix_t *mix, AVFrame *frame, unsigned int idx, void *ptr, out |
|
|
|
else |
|
|
|
goto err; |
|
|
|
} |
|
|
|
bool ok = sink_add(&output->sink, mix->sink_frame, &mix->out_format); |
|
|
|
bool ok = sink_add(mix->sink, mix->sink_frame, &mix->out_format); |
|
|
|
|
|
|
|
av_frame_unref(mix->sink_frame); |
|
|
|
|
|
|
|
@ -409,14 +413,19 @@ err: |
|
|
|
|
|
|
|
bool mix_add(sink_t *sink, AVFrame *frame) { |
|
|
|
ssrc_t *ssrc = sink->ssrc; |
|
|
|
metafile_t *metafile = ssrc->metafile; |
|
|
|
mix_t *mix = *sink->mix; |
|
|
|
|
|
|
|
LOCK(&metafile->mix_lock); |
|
|
|
if (!mix) |
|
|
|
return false; |
|
|
|
if (!mix->lock) |
|
|
|
return false; |
|
|
|
|
|
|
|
LOCK(mix->lock); |
|
|
|
|
|
|
|
if (!metafile->mix_out) |
|
|
|
return true; |
|
|
|
if (!mix->sink) |
|
|
|
return false; |
|
|
|
|
|
|
|
if (mix_add_(metafile->mix, frame, sink->mixer_idx, ssrc, metafile->mix_out)) |
|
|
|
if (mix_add_(mix, frame, sink->mixer_idx, ssrc)) |
|
|
|
ilog(LOG_ERR, "Failed to add decoded packet to mixed output"); |
|
|
|
|
|
|
|
return true; |
|
|
|
@ -425,19 +434,38 @@ bool mix_add(sink_t *sink, AVFrame *frame) { |
|
|
|
|
|
|
|
bool mix_config(sink_t *sink, const format_t *requested_format, format_t *actual_format) { |
|
|
|
ssrc_t *ssrc = sink->ssrc; |
|
|
|
metafile_t *metafile = ssrc->metafile; |
|
|
|
mix_t *mix = *sink->mix; |
|
|
|
|
|
|
|
if (!mix) |
|
|
|
return false; |
|
|
|
if (!mix->lock) |
|
|
|
return false; |
|
|
|
|
|
|
|
LOCK(&metafile->mix_lock); |
|
|
|
LOCK(mix->lock); |
|
|
|
|
|
|
|
if (!metafile->mix_out) |
|
|
|
return true; |
|
|
|
if (!mix->sink) |
|
|
|
return false; |
|
|
|
|
|
|
|
stream_t *stream = ssrc->stream; |
|
|
|
|
|
|
|
if (G_UNLIKELY(sink->mixer_idx == (unsigned int) -1)) |
|
|
|
sink->mixer_idx = mix_get_index(metafile->mix, ssrc, stream->media_sdp_id, stream->channel_slot); |
|
|
|
if (output_config(metafile->mix_out, requested_format, actual_format)) |
|
|
|
return true; |
|
|
|
mix_config_(metafile->mix, actual_format); |
|
|
|
if (G_UNLIKELY(sink->mixer_idx == -1u)) |
|
|
|
sink->mixer_idx = mix_get_index(mix, ssrc, stream->media_sdp_id, stream->channel_slot); |
|
|
|
|
|
|
|
if (!mix->sink->config(mix->sink, requested_format, actual_format)) |
|
|
|
return false; |
|
|
|
|
|
|
|
mix_config_(mix, actual_format); |
|
|
|
|
|
|
|
return true; |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
void mix_close(mix_t *mix) { |
|
|
|
if (!mix) |
|
|
|
return; |
|
|
|
|
|
|
|
mix_shutdown(mix); |
|
|
|
|
|
|
|
mix->sink = NULL; |
|
|
|
mix->lock = NULL; |
|
|
|
} |