aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorNicolas George <nicolas.george@normalesup.org>2011-12-08 14:42:24 +0100
committerNicolas George <nicolas.george@normalesup.org>2011-12-10 16:40:03 +0100
commit337ce558b696f49138a1ef170b219fe73b955b51 (patch)
tree55d260bab37fe558a75f71c5b056fc02e298f77a
parent5207f9597e96b4f38e4e392c4a32a8ff6601b3d4 (diff)
downloadffmpeg-337ce558b696f49138a1ef170b219fe73b955b51.tar.gz
fftools: add -report option.
-rw-r--r--Changelog1
-rw-r--r--cmdutils.c85
-rw-r--r--cmdutils.h2
-rw-r--r--cmdutils_common_opts.h1
-rw-r--r--doc/avtools-common-opts.texi10
5 files changed, 99 insertions, 0 deletions
diff --git a/Changelog b/Changelog
index e863a086ad..228293ff36 100644
--- a/Changelog
+++ b/Changelog
@@ -131,6 +131,7 @@ easier to use. The changes are:
- life source
- PCM format support in OMA demuxer
- CLJR encoder
+- new option: -report
version 0.8:
diff --git a/cmdutils.c b/cmdutils.c
index 62c87cb6b6..65628fcc86 100644
--- a/cmdutils.c
+++ b/cmdutils.c
@@ -55,6 +55,8 @@ AVDictionary *format_opts, *codec_opts;
static const int this_year = 2011;
+static FILE *report_file;
+
void init_opts(void)
{
#if CONFIG_SWSCALE
@@ -77,6 +79,20 @@ void log_callback_help(void* ptr, int level, const char* fmt, va_list vl)
vfprintf(stdout, fmt, vl);
}
+static void log_callback_report(void *ptr, int level, const char *fmt, va_list vl)
+{
+ va_list vl2;
+ char line[1024];
+ static int print_prefix = 1;
+
+ va_copy(vl2, vl);
+ av_log_default_callback(ptr, level, fmt, vl);
+ av_log_format_line(ptr, level, fmt, vl2, line, sizeof(line), &print_prefix);
+ va_end(vl2);
+ fputs(line, report_file);
+ fflush(report_file);
+}
+
double parse_number_or_die(const char *context, const char *numstr, int type, double min, double max)
{
char *tail;
@@ -344,6 +360,30 @@ static int locate_option(int argc, char **argv, const OptionDef *options, const
return 0;
}
+static void dump_argument(const char *a)
+{
+ const unsigned char *p;
+
+ for (p = a; *p; p++)
+ if (!((*p >= '+' && *p <= ':') || (*p >= '@' && *p <= 'Z') ||
+ *p == '_' || (*p >= 'a' && *p <= 'z')))
+ break;
+ if (!*p) {
+ fputs(a, report_file);
+ return;
+ }
+ fputc('"', report_file);
+ for (p = a; *p; p++) {
+ if (*p == '\\' || *p == '"' || *p == '$' || *p == '`')
+ fprintf(report_file, "\\%c", *p);
+ else if (*p < ' ' || *p > '~')
+ fprintf(report_file, "\\x%02x", *p);
+ else
+ fputc(*p, report_file);
+ }
+ fputc('"', report_file);
+}
+
void parse_loglevel(int argc, char **argv, const OptionDef *options)
{
int idx = locate_option(argc, argv, options, "loglevel");
@@ -351,6 +391,19 @@ void parse_loglevel(int argc, char **argv, const OptionDef *options)
idx = locate_option(argc, argv, options, "v");
if (idx && argv[idx + 1])
opt_loglevel("loglevel", argv[idx + 1]);
+ idx = locate_option(argc, argv, options, "report");
+ if (idx || getenv("FFREPORT")) {
+ opt_report("report");
+ if (report_file) {
+ int i;
+ fprintf(report_file, "Command line:\n");
+ for (i = 0; i < argc; i++) {
+ dump_argument(argv[i]);
+ fputc(i < argc - 1 ? ' ' : '\n', report_file);
+ }
+ fflush(report_file);
+ }
+ }
}
#define FLAGS(o) ((o)->type == AV_OPT_TYPE_FLAGS) ? AV_DICT_APPEND : 0
@@ -424,6 +477,38 @@ int opt_loglevel(const char *opt, const char *arg)
return 0;
}
+int opt_report(const char *opt)
+{
+ char filename[64];
+ time_t now;
+ struct tm *tm;
+
+ 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");
+ if (!report_file) {
+ av_log(NULL, AV_LOG_ERROR, "Failed to open report \"%s\": %s\n",
+ filename, strerror(errno));
+ return AVERROR(errno);
+ }
+ av_log_set_callback(log_callback_report);
+ av_log(NULL, AV_LOG_INFO,
+ "%s started on %04d-%02d-%02d at %02d:%02d:%02d\n"
+ "Report written to \"%s\"\n",
+ program_name,
+ tm->tm_year + 1900, tm->tm_mon + 1, tm->tm_mday,
+ tm->tm_hour, tm->tm_min, tm->tm_sec,
+ filename);
+ av_log_set_level(FFMAX(av_log_get_level(), AV_LOG_VERBOSE));
+ return 0;
+}
+
int opt_codec_debug(const char *opt, const char *arg)
{
av_log_set_level(AV_LOG_DEBUG);
diff --git a/cmdutils.h b/cmdutils.h
index 4773c3d3f4..15f983643a 100644
--- a/cmdutils.h
+++ b/cmdutils.h
@@ -76,6 +76,8 @@ int opt_default(const char *opt, const char *arg);
*/
int opt_loglevel(const char *opt, const char *arg);
+int opt_report(const char *opt);
+
int opt_codec_debug(const char *opt, const char *arg);
/**
diff --git a/cmdutils_common_opts.h b/cmdutils_common_opts.h
index cced0bb895..058f2b1e2f 100644
--- a/cmdutils_common_opts.h
+++ b/cmdutils_common_opts.h
@@ -14,3 +14,4 @@
{ "loglevel", HAS_ARG, {(void*)opt_loglevel}, "set libav* logging level", "loglevel" },
{ "v", HAS_ARG, {(void*)opt_loglevel}, "set libav* logging level", "loglevel" },
{ "debug", HAS_ARG, {(void*)opt_codec_debug}, "set debug flags", "flags" },
+ { "report", 0, {(void*)opt_report}, "generate a report" },
diff --git a/doc/avtools-common-opts.texi b/doc/avtools-common-opts.texi
index 52f4efcddc..b97a3c8b2a 100644
--- a/doc/avtools-common-opts.texi
+++ b/doc/avtools-common-opts.texi
@@ -123,6 +123,16 @@ the environment variable @env{FFMPEG_FORCE_COLOR}.
The use of the environment variable @env{NO_COLOR} is deprecated and
will be dropped in a following FFmpeg version.
+@item -report
+Dump full command line and console output to a file named
+@code{@var{program}-@var{YYYYMMDD}-@var{HHMMSS}.log} in the current
+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.
+
@end table
@section AVOptions