mirror of
https://github.com/FFmpeg/FFmpeg.git
synced 2025-01-08 13:22:53 +02:00
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.
This commit is contained in:
parent
3bdf4971ba
commit
1fa47f8dea
86
cmdutils.c
86
cmdutils.c
@ -41,6 +41,7 @@
|
|||||||
#endif
|
#endif
|
||||||
#include "libavutil/avassert.h"
|
#include "libavutil/avassert.h"
|
||||||
#include "libavutil/avstring.h"
|
#include "libavutil/avstring.h"
|
||||||
|
#include "libavutil/bprint.h"
|
||||||
#include "libavutil/mathematics.h"
|
#include "libavutil/mathematics.h"
|
||||||
#include "libavutil/imgutils.h"
|
#include "libavutil/imgutils.h"
|
||||||
#include "libavutil/parseutils.h"
|
#include "libavutil/parseutils.h"
|
||||||
@ -58,6 +59,8 @@
|
|||||||
#include <sys/resource.h>
|
#include <sys/resource.h>
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
static int init_report(const char *env);
|
||||||
|
|
||||||
struct SwsContext *sws_opts;
|
struct SwsContext *sws_opts;
|
||||||
SwrContext *swr_opts;
|
SwrContext *swr_opts;
|
||||||
AVDictionary *format_opts, *codec_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)
|
void parse_loglevel(int argc, char **argv, const OptionDef *options)
|
||||||
{
|
{
|
||||||
int idx = locate_option(argc, argv, options, "loglevel");
|
int idx = locate_option(argc, argv, options, "loglevel");
|
||||||
|
const char *env;
|
||||||
if (!idx)
|
if (!idx)
|
||||||
idx = locate_option(argc, argv, options, "v");
|
idx = locate_option(argc, argv, options, "v");
|
||||||
if (idx && argv[idx + 1])
|
if (idx && argv[idx + 1])
|
||||||
opt_loglevel(NULL, "loglevel", argv[idx + 1]);
|
opt_loglevel(NULL, "loglevel", argv[idx + 1]);
|
||||||
idx = locate_option(argc, argv, options, "report");
|
idx = locate_option(argc, argv, options, "report");
|
||||||
if (idx || getenv("FFREPORT")) {
|
if ((env = getenv("FFREPORT")) || idx) {
|
||||||
opt_report("report");
|
init_report(env);
|
||||||
if (report_file) {
|
if (report_file) {
|
||||||
int i;
|
int i;
|
||||||
fprintf(report_file, "Command line:\n");
|
fprintf(report_file, "Command line:\n");
|
||||||
@ -528,24 +532,78 @@ int opt_loglevel(void *optctx, const char *opt, const char *arg)
|
|||||||
return 0;
|
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;
|
time_t now;
|
||||||
struct tm *tm;
|
struct tm *tm;
|
||||||
|
AVBPrint filename;
|
||||||
|
|
||||||
if (report_file) /* already opened */
|
if (report_file) /* already opened */
|
||||||
return 0;
|
return 0;
|
||||||
time(&now);
|
time(&now);
|
||||||
tm = localtime(&now);
|
tm = localtime(&now);
|
||||||
snprintf(filename, sizeof(filename), "%s-%04d%02d%02d-%02d%02d%02d.log",
|
|
||||||
program_name,
|
while (env && *env) {
|
||||||
tm->tm_year + 1900, tm->tm_mon + 1, tm->tm_mday,
|
if ((ret = av_opt_get_key_value(&env, "=", ":", 0, &key, &val)) < 0) {
|
||||||
tm->tm_hour, tm->tm_min, tm->tm_sec);
|
if (count)
|
||||||
report_file = fopen(filename, "w");
|
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) {
|
if (!report_file) {
|
||||||
av_log(NULL, AV_LOG_ERROR, "Failed to open report \"%s\": %s\n",
|
av_log(NULL, AV_LOG_ERROR, "Failed to open report \"%s\": %s\n",
|
||||||
filename, strerror(errno));
|
filename.str, strerror(errno));
|
||||||
return AVERROR(errno);
|
return AVERROR(errno);
|
||||||
}
|
}
|
||||||
av_log_set_callback(log_callback_report);
|
av_log_set_callback(log_callback_report);
|
||||||
@ -555,11 +613,17 @@ int opt_report(const char *opt)
|
|||||||
program_name,
|
program_name,
|
||||||
tm->tm_year + 1900, tm->tm_mon + 1, tm->tm_mday,
|
tm->tm_year + 1900, tm->tm_mon + 1, tm->tm_mday,
|
||||||
tm->tm_hour, tm->tm_min, tm->tm_sec,
|
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_log_set_level(FFMAX(av_log_get_level(), AV_LOG_VERBOSE));
|
||||||
|
av_bprint_finalize(&filename, NULL);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int opt_report(const char *opt)
|
||||||
|
{
|
||||||
|
return init_report(NULL);
|
||||||
|
}
|
||||||
|
|
||||||
int opt_max_alloc(void *optctx, const char *opt, const char *arg)
|
int opt_max_alloc(void *optctx, const char *opt, const char *arg)
|
||||||
{
|
{
|
||||||
char *tail;
|
char *tail;
|
||||||
|
@ -151,8 +151,20 @@ directory.
|
|||||||
This file can be useful for bug reports.
|
This file can be useful for bug reports.
|
||||||
It also implies @code{-loglevel verbose}.
|
It also implies @code{-loglevel verbose}.
|
||||||
|
|
||||||
Note: setting the environment variable @code{FFREPORT} to any value has the
|
Setting the environment variable @code{FFREPORT} to any value has the same
|
||||||
same effect.
|
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})
|
@item -cpuflags flags (@emph{global})
|
||||||
Allows setting and clearing cpu flags. This option is intended
|
Allows setting and clearing cpu flags. This option is intended
|
||||||
|
Loading…
Reference in New Issue
Block a user