From 7480ae81981389fcd11bf6c9baabb2925dc01e45 Mon Sep 17 00:00:00 2001 From: Denial Date: Thu, 15 Dec 2022 15:45:11 +0700 Subject: [PATCH] add mix_num_inputs variable to config file closes #1581 closes 1557 Change-Id: Ic8ac6b956e83a4d64695e0ded6e70b8ffe67b36f --- recording-daemon/main.c | 6 +++++ recording-daemon/main.h | 1 + recording-daemon/metafile.c | 2 +- recording-daemon/mix.c | 32 ++++++++++++------------ recording-daemon/mix.h | 5 +--- recording-daemon/rtpengine-recording.pod | 4 +++ 6 files changed, 29 insertions(+), 21 deletions(-) diff --git a/recording-daemon/main.c b/recording-daemon/main.c index 055428eed..b3c589b15 100644 --- a/recording-daemon/main.c +++ b/recording-daemon/main.c @@ -19,6 +19,7 @@ #include "epoll.h" #include "inotify.h" #include "metafile.h" +#include "mix.h" #include "garbage.h" #include "auxlib.h" #include "decoder.h" @@ -38,6 +39,7 @@ char *output_dir = NULL; static char *output_format = NULL; int output_mixed; enum mix_method mix_method; +int mix_num_inputs = MIX_MAX_INPUTS; int output_single; int output_enabled = 1; mode_t output_chmod; @@ -190,6 +192,7 @@ static void options(int *argc, char ***argv) { { "mp3-bitrate", 0, 0, G_OPTION_ARG_INT, &mp3_bitrate, "Bits per second for MP3 encoding", "INT" }, { "output-mixed", 0, 0, G_OPTION_ARG_NONE, &output_mixed, "Mix participating sources into a single output",NULL }, { "mix-method", 0, 0, G_OPTION_ARG_STRING, &mix_method_str,"How to mix multiple sources", "direct|channels"}, + { "mix-num-inputs", 0, 0, G_OPTION_ARG_INT, &mix_num_inputs, "Number of channels for recordings", "INT" }, { "output-single", 0, 0, G_OPTION_ARG_NONE, &output_single, "Create one output file for each source",NULL }, { "output-chmod", 0, 0, G_OPTION_ARG_STRING, &chmod_mode, "File mode for recordings", "OCTAL" }, { "output-chmod-dir", 0, 0, G_OPTION_ARG_STRING, &chmod_dir_mode,"Directory mode for recordings", "OCTAL" }, @@ -256,6 +259,9 @@ static void options(int *argc, char ***argv) { else die("Invalid 'mix-method' option"); + if (mix_num_inputs <= 0 && mix_num_inputs > MIX_MAX_INPUTS) + die("Invalid mix_num_inputs value, it must be between 1 and %d", MIX_MAX_INPUTS); + if ((output_storage & OUTPUT_STORAGE_FILE) && !strcmp(output_dir, spool_dir)) die("The spool-dir cannot be the same as the output-dir"); diff --git a/recording-daemon/main.h b/recording-daemon/main.h index 7474d6d4b..222a456d7 100644 --- a/recording-daemon/main.h +++ b/recording-daemon/main.h @@ -24,6 +24,7 @@ extern char *spool_dir; extern char *output_dir; extern int output_mixed; extern enum mix_method mix_method; +extern int mix_num_inputs; extern int output_single; extern int output_enabled; extern mode_t output_chmod; diff --git a/recording-daemon/metafile.c b/recording-daemon/metafile.c index 24bd6f601..c23c2cf4b 100644 --- a/recording-daemon/metafile.c +++ b/recording-daemon/metafile.c @@ -83,7 +83,7 @@ static void meta_stream_interface(metafile_t *mf, unsigned long snum, char *cont if (!mf->mix) { mf->mix_out = output_new(output_dir, mf->parent, "mix", "mix"); if (mix_method == MM_CHANNELS) - mf->mix_out->channel_mult = MIX_NUM_INPUTS; + mf->mix_out->channel_mult = mix_num_inputs; mf->mix = mix_new(); db_do_stream(mf, mf->mix_out, "mixed", NULL, 0); } diff --git a/recording-daemon/mix.c b/recording-daemon/mix.c index 6091fe5b2..a101ab331 100644 --- a/recording-daemon/mix.c +++ b/recording-daemon/mix.c @@ -22,12 +22,12 @@ struct mix_s { out_format; AVFilterGraph *graph; - AVFilterContext *src_ctxs[MIX_NUM_INPUTS]; - uint64_t pts_offs[MIX_NUM_INPUTS]; // initialized at first input seen - uint64_t in_pts[MIX_NUM_INPUTS]; // running counter of next expected adjusted pts - struct timeval last_use[MIX_NUM_INPUTS]; // to recycle old mix inputs - void *input_ref[MIX_NUM_INPUTS]; // to avoid collisions in case of idx re-use - CH_LAYOUT_T channel_layout[MIX_NUM_INPUTS]; + AVFilterContext *src_ctxs[MIX_MAX_INPUTS]; + 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 + CH_LAYOUT_T channel_layout[MIX_MAX_INPUTS]; AVFilterContext *amix_ctx; AVFilterContext *sink_ctx; unsigned int next_idx; @@ -50,7 +50,7 @@ static void mix_shutdown(mix_t *mix) { avfilter_free(mix->sink_ctx); mix->sink_ctx = NULL; - for (unsigned int i = 0; i < MIX_NUM_INPUTS; i++) { + for (unsigned int i = 0; i < mix_num_inputs; i++) { if (mix->src_ctxs[i]) avfilter_free(mix->src_ctxs[i]); mix->src_ctxs[i] = NULL; @@ -83,7 +83,7 @@ static void mix_input_reset(mix_t *mix, unsigned int idx) { unsigned int mix_get_index(mix_t *mix, void *ptr) { unsigned int next = mix->next_idx++; - if (next < MIX_NUM_INPUTS) { + if (next < mix_num_inputs) { // must be unused mix->input_ref[next] = ptr; return next; @@ -92,7 +92,7 @@ unsigned int mix_get_index(mix_t *mix, void *ptr) { // too many inputs - find one to re-use struct timeval earliest = {0,}; next = 0; - for (unsigned int i = 0; i < MIX_NUM_INPUTS; i++) { + for (unsigned int i = 0; i < mix_num_inputs; i++) { if (earliest.tv_sec == 0 || timeval_cmp(&earliest, &mix->last_use[i]) > 0) { next = i; earliest = mix->last_use[i]; @@ -135,7 +135,7 @@ int mix_config(mix_t *mix, const format_t *format) { if (!flt) goto err; - snprintf(args, sizeof(args), "inputs=%lu", (unsigned long) MIX_NUM_INPUTS); + snprintf(args, sizeof(args), "inputs=%lu", (unsigned long) mix_num_inputs); err = "failed to create amix/amerge filter context"; if (avfilter_graph_create_filter(&mix->amix_ctx, flt, NULL, args, NULL, mix->graph)) goto err; @@ -148,9 +148,9 @@ int mix_config(mix_t *mix, const format_t *format) { CH_LAYOUT_T channel_layout, ext_layout; DEF_CH_LAYOUT(&channel_layout, mix->in_format.channels); - DEF_CH_LAYOUT(&ext_layout, mix->in_format.channels * MIX_NUM_INPUTS); + DEF_CH_LAYOUT(&ext_layout, mix->in_format.channels * mix_num_inputs); - for (unsigned int i = 0; i < MIX_NUM_INPUTS; i++) { + for (unsigned int i = 0; i < mix_num_inputs; i++) { dbg("init input ctx %i", i); CH_LAYOUT_T ch_layout = channel_layout; @@ -203,7 +203,7 @@ int mix_config(mix_t *mix, const format_t *format) { mix->out_format = mix->in_format; if (mix_method == MM_CHANNELS) - mix->out_format.channels *= MIX_NUM_INPUTS; + mix->out_format.channels *= mix_num_inputs; return 0; @@ -220,7 +220,7 @@ mix_t *mix_new() { 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; return mix; @@ -272,7 +272,7 @@ static void mix_silence_fill(mix_t *mix) { if (mix->out_pts < mix->in_format.clockrate) return; - for (unsigned int i = 0; i < MIX_NUM_INPUTS; i++) { + for (unsigned int i = 0; i < mix_num_inputs; i++) { // check the pts of each input and give them max 0.5 second of delay. // if they fall behind too much, fill input with silence. otherwise // output stalls and won't produce media @@ -285,7 +285,7 @@ int mix_add(mix_t *mix, AVFrame *frame, unsigned int idx, void *ptr, output_t *o const char *err; err = "index out of range"; - if (idx >= MIX_NUM_INPUTS) + if (idx >= mix_num_inputs) goto err; err = "mixer not initialized"; diff --git a/recording-daemon/mix.h b/recording-daemon/mix.h index 3b4e2e9f2..dcfebde51 100644 --- a/recording-daemon/mix.h +++ b/recording-daemon/mix.h @@ -4,13 +4,10 @@ #include "types.h" #include - -#define MIX_NUM_INPUTS 4 - +#define MIX_MAX_INPUTS 4 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 *); diff --git a/recording-daemon/rtpengine-recording.pod b/recording-daemon/rtpengine-recording.pod index b4e4d1a1e..bb2f5274e 100644 --- a/recording-daemon/rtpengine-recording.pod +++ b/recording-daemon/rtpengine-recording.pod @@ -259,6 +259,10 @@ input is mono audio, then the mixed output file would contain 4 audio channels. This mixing method requires an output file format which supports these kinds of multi-channel audio formats (e.g. B). +=item B<--mix-num-inputs=>I + +Change the number of recording channel in the output file. The value is between 1 to 4 (e.g. B<4>, which is also the default value). + =item B<--output-chmod=>I Change the file permissions of recording files to the given mode. Must be given