diff --git a/recording-daemon/metafile.c b/recording-daemon/metafile.c index b77b68da1..0403ca907 100644 --- a/recording-daemon/metafile.c +++ b/recording-daemon/metafile.c @@ -85,6 +85,7 @@ static void meta_destroy(metafile_t *mf) { db_close_call(mf); output_close(mf, mf->mix_out, NULL, mf->discard); mf->mix_out = NULL; + mix_close(mf->mix); } @@ -104,7 +105,7 @@ static void meta_mix_output(metafile_t *mf) { mf->mix_out = output_new_ext(mf, "mix", "mixed", "mix"); if (mix_method == MM_CHANNELS) mf->mix_out->channel_mult = mix_num_inputs; - mf->mix = mix_new(mf->media_rec_slots); + mf->mix = mix_new(&mf->mix_lock, &mf->mix_out->sink, mf->media_rec_slots); db_do_stream(mf, mf->mix_out, NULL, 0); } diff --git a/recording-daemon/mix.c b/recording-daemon/mix.c index 751dfeea6..375fd7f68 100644 --- a/recording-daemon/mix.c +++ b/recording-daemon/mix.c @@ -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; +} diff --git a/recording-daemon/mix.h b/recording-daemon/mix.h index d64b4b0c8..621e2f5d7 100644 --- a/recording-daemon/mix.h +++ b/recording-daemon/mix.h @@ -6,8 +6,9 @@ #define MIX_MAX_INPUTS 4 -mix_t *mix_new(unsigned int); +mix_t *mix_new(pthread_mutex_t *, sink_t *, unsigned int); void mix_destroy(mix_t *mix); +void mix_close(mix_t *mix); void mix_set_channel_slots(mix_t *mix, unsigned int); bool mix_config(sink_t *, const format_t *requested_format, format_t *actual_format); bool mix_add(sink_t *, AVFrame *frame); diff --git a/recording-daemon/packet.c b/recording-daemon/packet.c index a4662114a..e08d25758 100644 --- a/recording-daemon/packet.c +++ b/recording-daemon/packet.c @@ -123,6 +123,7 @@ static void packet_decode(ssrc_t *ssrc, packet_t *packet) { sink_init(&ssrc->decoders[payload_type]->mix_sink); ssrc->decoders[payload_type]->mix_sink.ssrc = ssrc; + ssrc->decoders[payload_type]->mix_sink.mix = &mf->mix; ssrc->decoders[payload_type]->mix_sink.add = mix_add; ssrc->decoders[payload_type]->mix_sink.config = mix_config; diff --git a/recording-daemon/types.h b/recording-daemon/types.h index c59cc8ba6..b658528a5 100644 --- a/recording-daemon/types.h +++ b/recording-daemon/types.h @@ -55,6 +55,9 @@ struct sink_s { ssrc_t *ssrc; tls_fwd_t **tls_fwd; }; + union { + mix_t **mix; + }; resample_t resampler;