From c066b69df58209718cd8a6ad7481689bc382a2c2 Mon Sep 17 00:00:00 2001 From: Richard Fuchs Date: Fri, 15 Aug 2025 12:20:00 -0400 Subject: [PATCH] MT#61977 streamline output_close Introduce output_get_content as a central point to obtain the contents of a recording, whether stored as a file or in memory. Cache contents so that we don't have to read a file multiple times. Delegate closing of the recording file to output_close. Change-Id: Ic5471b840d86966f547b3b8ea4bac7eca012c474 --- recording-daemon/db.c | 59 +++++------------------------- recording-daemon/db.h | 2 +- recording-daemon/output.c | 76 +++++++++++++++++++++++++-------------- recording-daemon/output.h | 1 + recording-daemon/types.h | 2 ++ 5 files changed, 63 insertions(+), 77 deletions(-) diff --git a/recording-daemon/db.c b/recording-daemon/db.c index c5e360a0c..cfc5cb18d 100644 --- a/recording-daemon/db.c +++ b/recording-daemon/db.c @@ -9,6 +9,7 @@ #include "log.h" #include "tag.h" #include "recaux.h" +#include "output.h" /* @@ -375,64 +376,24 @@ void db_close_call(metafile_t *mf) { } } -bool db_close_stream(output_t *op, FILE *fp, GString *gs) { - if (check_conn() || op->db_id == 0) { - if (fp) - fclose(fp); +bool db_close_stream(output_t *op) { + if (check_conn() || op->db_id == 0) return !(output_storage & OUTPUT_STORAGE_DB); // error if DB storage is requested - } int64_t now = now_us(); str stream = STR_NULL; MYSQL_BIND b[3]; - bool ok = false; + bool ok = true; if ((output_storage & OUTPUT_STORAGE_DB)) { - if (gs) { - if (fp) - fclose(fp); - stream.len = gs->len; - stream.s = g_string_free(gs, FALSE); - } - else { - FILE *f = fp; - if (!f) - f = fopen(op->filename, "rb"); - if (!f) { - ilog(LOG_ERR, "Failed to open file: %s%s%s", FMT_M(op->filename)); - goto entry; - } - fseek(f, 0, SEEK_END); - long pos = ftell(f); - if (pos < 0) { - ilog(LOG_ERR, "Failed to get file position: %s", strerror(errno)); - fclose(f); - goto entry; - } - stream.len = pos; - fseek(f, 0, SEEK_SET); - stream.s = g_malloc(stream.len); - if (stream.s) { - size_t count = fread(stream.s, 1, stream.len, f); - if (count != stream.len) { - stream.len = 0; - ilog(LOG_ERR, "Failed to read from stream"); - fclose(f); - goto entry; - } - } - ok = true; - fclose(f); - } + GString *content = output_get_content(op); + if (content) + stream = STR_GS(content); + else + ok = false; } - else { - ok = true; - if (fp) - fclose(fp); - } -entry:; int par_idx = 0; double ts; my_ts(&b[par_idx++], now, &ts); @@ -442,8 +403,6 @@ entry:; execute_wrap(&stm_close_stream, b, NULL); - g_free(stream.s); - return ok; } diff --git a/recording-daemon/db.h b/recording-daemon/db.h index 993739d03..ae6287376 100644 --- a/recording-daemon/db.h +++ b/recording-daemon/db.h @@ -7,7 +7,7 @@ void db_do_call(metafile_t *); void db_close_call(metafile_t *); void db_do_stream(metafile_t *mf, output_t *op, stream_t *, unsigned long ssrc); -bool db_close_stream(output_t *op, FILE *, GString *); +bool db_close_stream(output_t *op); void db_delete_stream(metafile_t *, output_t *op); void db_config_stream(output_t *op); void db_thread_end(void); diff --git a/recording-daemon/output.c b/recording-daemon/output.c index a6a45ae9a..a326b9bd5 100644 --- a/recording-daemon/output.c +++ b/recording-daemon/output.c @@ -26,7 +26,7 @@ int mp3_bitrate; -static bool output_shutdown(output_t *output, FILE **, GString **); +static bool output_shutdown(output_t *output); static bool output_config(sink_t *, output_t *output, const format_t *requested_format, format_t *actual_format); @@ -381,6 +381,9 @@ static const char *output_open_file(output_t *output) { output->filename = full_fn; + if (output->fp) + fclose(output->fp); + output->fp = fopen(full_fn, (output_storage & OUTPUT_STORAGE_DB) ? "wb+" : "wb"); if (!output->fp) return "failed to open output file"; @@ -402,7 +405,7 @@ static const char *output_open_file(output_t *output) { } static const char *output_setup(output_t *output, const format_t *requested_format, format_t *req_fmt) { - output_shutdown(output, NULL, NULL); + output_shutdown(output); output->fmtctx = avformat_alloc_context(); if (!output->fmtctx) @@ -504,7 +507,7 @@ static bool output_config(sink_t *sink, output_t *output, const format_t *reques if (G_UNLIKELY(!format_eq(&req_fmt, &output->requested_format))) { const char *err = output_setup(output, requested_format, &req_fmt); if (err) { - output_shutdown(output, NULL, NULL); + output_shutdown(output); ilog(LOG_ERR, "Error configuring media output: %s", err); return false; } @@ -517,7 +520,37 @@ static bool output_config(sink_t *sink, output_t *output, const format_t *reques } -static bool output_shutdown(output_t *output, FILE **fp, GString **gs) { +GString *output_get_content(output_t *output) { + if (output->content) + return output->content; + + if (!output->fp) + return NULL; + + fseek(output->fp, 0, SEEK_END); + long pos = ftell(output->fp); + if (pos < 0) { + ilog(LOG_ERR, "Failed to get file position: %s", strerror(errno)); + return NULL; + } + + size_t len = pos; + fseek(output->fp, 0, SEEK_SET); + GString *content = g_string_new(""); + g_string_set_size(content, len); + size_t count = fread(content->str, 1, len, output->fp); + if (count != len) { + g_string_free(content, TRUE); + ilog(LOG_ERR, "Failed to read from stream"); + return NULL; + } + + output->content = content; + return content; +} + + +static bool output_shutdown(output_t *output) { if (!output) return false; if (!output->fmtctx) @@ -529,23 +562,15 @@ static bool output_shutdown(output_t *output, FILE **fp, GString **gs) { if (output->fmtctx->pb) av_write_trailer(output->fmtctx); if (output->fp) { - if (ftell(output->fp)) { + if (ftell(output->fp)) ret = true; - if (fp && (output_storage & OUTPUT_STORAGE_DB)) { - *fp = output->fp; - output->fp = NULL; - } - } - if (output->fp) - fclose(output->fp); - output->fp = NULL; } else if (output->membuf) { if (output->membuf->len) { - if (gs) { - *gs = output->membuf; - output->membuf = NULL; - } + if (output->content) + g_string_free(output->content, TRUE); + output->content = output->membuf; + output->membuf = NULL; ret = true; } } @@ -580,21 +605,16 @@ void output_close(metafile_t *mf, output_t *output, tag_t *tag, bool discard) { return; bool do_delete = !(output_storage & OUTPUT_STORAGE_FILE); if (!discard) { - GString *membuf = NULL; - FILE *fp = NULL; - if (output_shutdown(output, &fp, &membuf)) { - if (!db_close_stream(output, fp, membuf)) + if (output_shutdown(output)) { + if (!db_close_stream(output)) do_delete = false; notify_push_output(output, mf, tag); } - else { + else db_delete_stream(mf, output); - if (membuf) - g_string_free(membuf, TRUE); - } } else { - output_shutdown(output, NULL, NULL); + output_shutdown(output); do_delete = true; db_delete_stream(mf, output); } @@ -612,6 +632,10 @@ void output_close(metafile_t *mf, output_t *output, tag_t *tag, bool discard) { g_clear_pointer(&output->iobuf, g_free); if (output->membuf) g_string_free(output->membuf, TRUE); + if (output->content) + g_string_free(output->content, TRUE); + if (output->fp) + fclose(output->fp); sink_close(&output->sink); g_free(output); } diff --git a/recording-daemon/output.h b/recording-daemon/output.h index 49be5bda0..07e753ce0 100644 --- a/recording-daemon/output.h +++ b/recording-daemon/output.h @@ -12,6 +12,7 @@ void output_init(const char *format); output_t *output_new_ext(metafile_t *, const char *type, const char *kind, const char *label); void output_close(metafile_t *, output_t *, tag_t *, bool discard); +GString *output_get_content(output_t *); void sink_init(sink_t *); diff --git a/recording-daemon/types.h b/recording-daemon/types.h index 9be96ae38..9563a39b3 100644 --- a/recording-daemon/types.h +++ b/recording-daemon/types.h @@ -211,6 +211,8 @@ struct output_s { encoder_t *encoder; format_t requested_format, actual_format; + + GString *content; };