[FFmpeg-devel] [PATCH 4/4] cmdutils: allow to set the report file name.

Stefano Sabatini stefasab at gmail.com
Sat Nov 3 11:45:45 CET 2012


On date Friday 2012-11-02 13:36:15 +0100, Nicolas George encoded:
> The file name can be set by setting the FFREPORT environment
> variable to "file=something".
> 
> Fix trac ticket #1823.
> 
> Signed-off-by: Nicolas George <nicolas.george at normalesup.org>
> ---
>  cmdutils.c                   |   86 ++++++++++++++++++++++++++++++++++++------
>  doc/avtools-common-opts.texi |   13 ++++++-
>  2 files changed, 86 insertions(+), 13 deletions(-)
> 
> diff --git a/cmdutils.c b/cmdutils.c
> index f696700..2375d4e 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 <sys/resource.h>
>  #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)
> +{
> +    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)
>  {
> -    char filename[64];
> +    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;

Unrelated: maybe here it should complain and exit (so that -report
... -report won't result in unexpected behavior).

>      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 1fc12aa..6778a5a 100644
> --- a/doc/avtools-common-opts.texi
> +++ b/doc/avtools-common-opts.texi
> @@ -151,8 +151,17 @@ 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:
> + at table @option
> + at 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

set the filename template to use for the report; ..., @code{%%} is expandend to a literal @code{%}

> + at end table
> +
> +Errors in parsing the environment variable are not fatal, and will not
> +appear in the report.

I'm not really sure about this, having
FFREPORT=file=funky-filename-template

looks more extensible, but I don't know if we'll need to add more
options. Also if you want to really support
FFREPORT=key1=val1:key2=val2... then the usual considerations on
escaping should be applied (think about C:\Windows\file), which
complicates the interface for the user.

>  
>  @item -cpuflags flags (@emph{global})
>  Allows setting and clearing cpu flags. This option is intended
> -- 
> 1.7.10.4
> 
> _______________________________________________
> ffmpeg-devel mailing list
> ffmpeg-devel at ffmpeg.org
> http://ffmpeg.org/mailman/listinfo/ffmpeg-devel

-- 
FFmpeg = Fascinating & Faithful Meaningless Puristic Enhancing Gymnast


More information about the ffmpeg-devel mailing list