Squashed commit of the following:

commit d15fd4a547
Author: Damir Nedžibović <damir.nedzibovic@enreach.com>
Date:   Tue Jul 6 14:07:42 2021 +0200

    Also free the character data.

commit 8869187215
Author: Damir Nedžibović <damir.nedzibovic@enreach.com>
Date:   Mon Jul 5 16:11:32 2021 +0200

    Make documentation and parameters consistant.

commit 4b15aea2ee
Author: Damir Nedžibović <damir.nedzibovic@enreach.com>
Date:   Thu Jun 10 15:34:00 2021 +0200

    Update documentation.

commit 6ec1b3035d
Author: Damir Nedžibović <damir.nedzibovic@enreach.com>
Date:   Thu Jun 10 15:33:12 2021 +0200

    Do not use metadata for setting the recording file; use output_destination instead.

commit f65a76e8a3
Author: Damir Nedžibović <damir.nedzibovic@enreach.com>
Date:   Wed Jun 9 15:56:02 2021 +0200

    Only append file extension if skip_filename_extension is not set.

commit 92e9d7c679
Author: Damir Nedžibović <damir.nedzibovic@enreach.com>
Date:   Wed Jun 9 14:12:48 2021 +0200

    Rename the option to better match its usage.

commit 11128bff49
Author: Damir Nedžibović <damir.nedzibovic@enreach.com>
Date:   Wed Jun 9 13:19:10 2021 +0200

    Implement support for seting an output file and folder per recording.

Change-Id: I1579d62467eaf06a7aa1ac11e59dbb374f150deb
pull/1307/head
Damir Nedžibović 4 years ago committed by Richard Fuchs
parent 94a5feea7d
commit cc09099660

@ -1753,6 +1753,9 @@ call legs, therefore all keys other than `call-id` are currently ignored.
If the chosen recording method doesn't support in-kernel packet forwarding, enabling call recording
via this messages will force packet forwarding to happen in userspace only.
If the optional 'output-destination' key is set, then its value will be used
as an output file. Note that a filename extension will not be added.
`stop recording` Message
-------------------------

@ -1445,7 +1445,7 @@ static const char *call_offer_answer_ng(struct ng_buffer *ngbuf, bencode_item_t
detect_setup_recording(call, &flags.record_call_str, &flags.metadata);
if (flags.record_call) {
call->recording_on = 1;
recording_start(call, NULL, &flags.metadata);
recording_start(call, NULL, &flags.metadata, NULL);
}
if (flags.drop_traffic_start) {
@ -1914,16 +1914,18 @@ const char *call_start_recording_ng(bencode_item_t *input, bencode_item_t *outpu
str callid;
struct call *call;
str metadata;
str output_dest;
if (!bencode_dictionary_get_str(input, "call-id", &callid))
return "No call-id in message";
bencode_dictionary_get_str(input, "metadata", &metadata);
bencode_dictionary_get_str(input, "output-destination", &output_dest);
call = call_get_opmode(&callid, OP_OTHER);
if (!call)
return "Unknown call-id";
call->recording_on = 1;
recording_start(call, NULL, &metadata);
recording_start(call, NULL, &metadata, &output_dest);
rwlock_unlock_w(&call->master_lock);
obj_put(call);
@ -2034,7 +2036,7 @@ const char *call_start_forwarding_ng(bencode_item_t *input, bencode_item_t *outp
call->rec_forwarding = 1;
}
recording_start(call, NULL, &flags.metadata);
recording_start(call, NULL, &flags.metadata, NULL);
errstr = NULL;
out:
if (call) {

@ -244,6 +244,12 @@ static void update_metadata(struct call *call, str *metadata) {
}
}
static void update_output_dest(struct call *call, str *output_dest) {
if (!output_dest || !output_dest->s || !call->recording)
return;
recording_meta_chunk(call->recording, "OUTPUT_DESTINATION", output_dest);
}
// lock must be held
static void update_flags_proc(struct call *call) {
append_meta_chunk_null(call->recording, "RECORDING %u", call->recording_on ? 1 : 0);
@ -259,9 +265,11 @@ static void recording_update_flags(struct call *call) {
}
// lock must be held
void recording_start(struct call *call, const char *prefix, str *metadata) {
void recording_start(struct call *call, const char *prefix, str *metadata, str *output_dest) {
update_metadata(call, metadata);
update_output_dest(call, output_dest);
if (call->recording) {
// already active
recording_update_flags(call);
@ -350,7 +358,7 @@ void detect_setup_recording(struct call *call, const str *recordcall, str *metad
if (!str_cmp(recordcall, "yes") || !str_cmp(recordcall, "on")) {
call->recording_on = 1;
recording_start(call, NULL, NULL);
recording_start(call, NULL, NULL, NULL);
}
else if (!str_cmp(recordcall, "no") || !str_cmp(recordcall, "off")) {
call->recording_on = 0;

@ -1923,7 +1923,7 @@ static void json_restore_call(struct redis *r, const str *callid, int foreign) {
if (!redis_hash_get_str(&s, &call, "recording_meta_prefix")) {
// coverity[check_return : FALSE]
redis_hash_get_str(&meta, &call, "recording_metadata");
recording_start(c, s.s, &meta);
recording_start(c, s.s, &meta, NULL);
}
err = NULL;

@ -117,7 +117,7 @@ void recording_fs_free(void);
*/
void detect_setup_recording(struct call *call, const str *recordcall, str *metadata);
void recording_start(struct call *call, const char *prefix, str *metadata);
void recording_start(struct call *call, const char *prefix, str *metadata, str *output_dest);
void recording_stop(struct call *call, str *metadata);

@ -149,7 +149,6 @@ static void meta_ptime(metafile_t *mf, unsigned long mnum, int ptime)
mf->media_ptimes[mnum] = ptime;
}
// mf is locked
static void meta_metadata(metafile_t *mf, char *content) {
mf->metadata = g_string_chunk_insert(mf->gsc, content);
@ -192,6 +191,8 @@ static void meta_section(metafile_t *mf, char *section, char *content, unsigned
mf->forwarding_on = u ? 1 : 0;
else if (sscanf_match(section, "STREAM %lu FORWARDING %u", &lu, &u) == 2)
stream_forwarding_on(mf, lu, u);
else if (!strcmp(section, "OUTPUT_DESTINATION"))
mf->output_dest = g_string_chunk_insert(mf->gsc, content);
}

@ -81,6 +81,19 @@ static void create_parent_dirs(char *dir) {
}
}
static output_t *output_alloc(const char *path, const char *name) {
output_t *ret = g_slice_alloc0(sizeof(*ret));
ret->file_path = g_strdup(path);
ret->file_name = g_strdup(name);
ret->full_filename = g_strdup_printf("%s/%s", path, name);
ret->file_format = output_file_format;
ret->encoder = encoder_new();
ret->channel_mult = 1;
ret->requested_format.format = -1;
ret->actual_format.format = -1;
return ret;
}
output_t *output_new(const char *path, const char *call, const char *type) {
// construct output file name
@ -159,23 +172,20 @@ output_t *output_new(const char *path, const char *call, const char *type) {
}
done:;
output_t *ret = g_slice_alloc0(sizeof(*ret));
ret->file_path = g_strdup(path);
ret->file_name = f->str; // stealing the content
ret->full_filename = g_strdup_printf("%s/%s", path, f->str);
ret->file_format = output_file_format;
ret->encoder = encoder_new();
ret->channel_mult = 1;
ret->requested_format.format = -1;
ret->actual_format.format = -1;
output_t *ret = output_alloc(path, f->str);
create_parent_dirs(ret->full_filename);
g_string_free(f, FALSE);
g_string_free(f, TRUE);
return ret;
}
output_t *output_new_from_full_path(const char *path, char *name) {
output_t *ret = output_alloc(path, name);
create_parent_dirs(ret->full_filename);
return ret;
}
int output_config(output_t *output, const format_t *requested_format, format_t *actual_format) {
const char *err;
@ -238,9 +248,15 @@ int output_config(output_t *output, const format_t *requested_format, format_t *
char *full_fn = NULL;
char suff[16] = "";
for (int i = 1; i < 20; i++) {
full_fn = g_strdup_printf("%s%s.%s", output->full_filename, suff, output->file_format);
if (!output->skip_filename_extension) {
full_fn = g_strdup_printf("%s%s.%s", output->full_filename, suff, output->file_format);
}
else {
full_fn = g_strdup_printf("%s%s", output->full_filename, suff);
}
if (!g_file_test(full_fn, G_FILE_TEST_EXISTS))
goto got_fn;
ilog(LOG_INFO, "Storing record in %s", full_fn);
snprintf(suff, sizeof(suff), "-%i", i);
g_free(full_fn);
}

@ -11,6 +11,7 @@ extern int mp3_bitrate;
void output_init(const char *format);
output_t *output_new(const char *path, const char *call, const char *type);
output_t *output_new_from_full_path(const char *path, char *name);
void output_close(output_t *);
int output_config(output_t *output, const format_t *requested_format, format_t *actual_format);

@ -152,7 +152,6 @@ void ssrc_free(void *p) {
g_slice_free1(sizeof(*s), s);
}
// mf must be unlocked; returns ssrc locked
static ssrc_t *ssrc_get(stream_t *stream, unsigned long ssrc) {
metafile_t *mf = stream->metafile;
@ -177,9 +176,26 @@ out:
dbg("Init for SSRC %s%lx%s of stream #%lu", FMT_M(ret->ssrc), stream->id);
if (mf->recording_on && !ret->output && output_single) {
char buf[16];
snprintf(buf, sizeof(buf), "%08lx", ssrc);
ret->output = output_new(output_dir, mf->parent, buf);
dbg("Metadata %s, output destination %s", mf->metadata, mf->output_dest);
if (mf->output_dest) {
char path[256];
strncpy(path, mf->output_dest, sizeof(path));
char *sep = strrchr(path, '/');
if (sep) {
char *filename = sep + 1;
*sep = 0;
ret->output = output_new_from_full_path(path, filename);
ret->output->skip_filename_extension = TRUE;
}
else {
ret->output = output_new_from_full_path(output_dir, path);
}
}
else {
char buf[16];
snprintf(buf, sizeof(buf), "%08lx", ssrc);
ret->output = output_new(output_dir, mf->parent, buf);
}
db_do_stream(mf, ret->output, "single", stream, ssrc);
}
if ((stream->forwarding_on || mf->forwarding_on) && !ret->tls_fwd_stream) {

@ -111,6 +111,7 @@ struct metafile_s {
char *call_id;
char *metadata;
char *metadata_db;
char *output_dest;
off_t pos;
unsigned long long db_id;
@ -146,6 +147,7 @@ struct output_s {
*filename; // path + filename + suffix
const char *file_format;
unsigned long long db_id;
gboolean skip_filename_extension;
unsigned int channel_mult;
AVFormatContext *fmtctx;

Loading…
Cancel
Save