From 1fa47f8deafed3263ecdf5b0eb4807b77cfbb868 Mon Sep 17 00:00:00 2001 From: Nicolas George Date: Fri, 2 Nov 2012 13:15:51 +0100 Subject: [PATCH] cmdutils: allow to set the report file name. The file name can be set by setting the FFREPORT environment variable to "file=something". Fix trac ticket #1823. --- cmdutils.c | 86 +++++++++++++++++++++++++++++++----- doc/avtools-common-opts.texi | 16 ++++++- 2 files changed, 89 insertions(+), 13 deletions(-) diff --git a/cmdutils.c b/cmdutils.c index f696700142..2375d4e8a0 100644 --- a/cmdutils.c +++ b/cmdutils.c @@ -41,6 +41,7 @@ #endif #include "libavutil/avassert.h" #include "libavutil/avstring.h" +#include "libavutil/bprint.h" #include "libavutil/mathematics.h" #include "libavutil/imgutils.h" #include "libavutil/parseutils.h" @@ -58,6 +59,8 @@ #include #endif +static int init_report(const char *env); + struct SwsContext *sws_opts; SwrContext *swr_opts; AVDictionary *format_opts, *codec_opts; @@ -414,13 +417,14 @@ static void dump_argument(const char *a) void parse_loglevel(int argc, char **argv, const OptionDef *options) { int idx = locate_option(argc, argv, options, "loglevel"); + const char *env; if (!idx) idx = locate_option(argc, argv, options, "v"); if (idx && argv[idx + 1]) opt_loglevel(NULL, "loglevel", argv[idx + 1]); idx = locate_option(argc, argv, options, "report"); - if (idx || getenv("FFREPORT")) { - opt_report("report"); + if ((env = getenv("FFREPORT")) || idx) { + init_report(env); if (report_file) { int i; fprintf(report_file, "Command line:\n"); @@ -528,24 +532,78 @@ int opt_loglevel(void *optctx, const char *opt, const char *arg) return 0; } -int opt_report(const char *opt) +static void expand_filename_template(AVBPrint *bp, const char *template, + struct tm *tm) { - char filename[64]; + int c; + + while ((c = *(template++))) { + if (c == '%') { + if (!(c = *(template++))) + break; + switch (c) { + case 'p': + av_bprintf(bp, "%s", program_name); + break; + case 't': + av_bprintf(bp, "%04d%02d%02d-%02d%02d%02d", + tm->tm_year + 1900, tm->tm_mon + 1, tm->tm_mday, + tm->tm_hour, tm->tm_min, tm->tm_sec); + break; + case '%': + av_bprint_chars(bp, c, 1); + break; + } + } else { + av_bprint_chars(bp, c, 1); + } + } +} + +static int init_report(const char *env) +{ + const char *filename_template = "%p-%t.log"; + char *key, *val; + int ret, count = 0; time_t now; struct tm *tm; + AVBPrint filename; if (report_file) /* already opened */ return 0; time(&now); tm = localtime(&now); - snprintf(filename, sizeof(filename), "%s-%04d%02d%02d-%02d%02d%02d.log", - program_name, - tm->tm_year + 1900, tm->tm_mon + 1, tm->tm_mday, - tm->tm_hour, tm->tm_min, tm->tm_sec); - report_file = fopen(filename, "w"); + + while (env && *env) { + if ((ret = av_opt_get_key_value(&env, "=", ":", 0, &key, &val)) < 0) { + if (count) + av_log(NULL, AV_LOG_ERROR, + "Failed to parse FFREPORT environment variable: %s\n", + av_err2str(ret)); + break; + } + count++; + if (!strcmp(key, "file")) { + filename_template = val; + val = NULL; + } else { + av_log(NULL, AV_LOG_ERROR, "Unknown key '%s' in FFREPORT\n", key); + } + av_free(val); + av_free(key); + } + + av_bprint_init(&filename, 0, 1); + expand_filename_template(&filename, filename_template, tm); + if (!av_bprint_is_complete(&filename)) { + av_log(NULL, AV_LOG_ERROR, "Out of memory building report file name\n"); + return AVERROR(ENOMEM); + } + + report_file = fopen(filename.str, "w"); if (!report_file) { av_log(NULL, AV_LOG_ERROR, "Failed to open report \"%s\": %s\n", - filename, strerror(errno)); + filename.str, strerror(errno)); return AVERROR(errno); } av_log_set_callback(log_callback_report); @@ -555,11 +613,17 @@ int opt_report(const char *opt) program_name, tm->tm_year + 1900, tm->tm_mon + 1, tm->tm_mday, tm->tm_hour, tm->tm_min, tm->tm_sec, - filename); + filename.str); av_log_set_level(FFMAX(av_log_get_level(), AV_LOG_VERBOSE)); + av_bprint_finalize(&filename, NULL); return 0; } +int opt_report(const char *opt) +{ + return init_report(NULL); +} + int opt_max_alloc(void *optctx, const char *opt, const char *arg) { char *tail; diff --git a/doc/avtools-common-opts.texi b/doc/avtools-common-opts.texi index 1fc12aa966..d43ff6e015 100644 --- a/doc/avtools-common-opts.texi +++ b/doc/avtools-common-opts.texi @@ -151,8 +151,20 @@ directory. This file can be useful for bug reports. It also implies @code{-loglevel verbose}. -Note: setting the environment variable @code{FFREPORT} to any value has the -same effect. +Setting the environment variable @code{FFREPORT} to any value has the same +effect. If the value is a ':'-separated key=value sequence, these options +will affect the report; options values must be +@ref{quoting_and_escaping, escaped} if they contain special characters or +the options delimiter ':'. The following option is recognized: +@table @option +@item file +set the file name to use for the report; @code{%p} is expanded to the name +of the program, @code{%t} is expanded to a timestamp, @code{%%} is expanded +to a plain @code{%} +@end table + +Errors in parsing the environment variable are not fatal, and will not +appear in the report. @item -cpuflags flags (@emph{global}) Allows setting and clearing cpu flags. This option is intended