diff options
author | Thilo Borgmann <thilo.borgmann@mail.de> | 2022-02-08 11:39:46 +0100 |
---|---|---|
committer | Thilo Borgmann <thilo.borgmann@mail.de> | 2022-03-08 13:28:02 +0100 |
commit | 74117abf0c26228102587057567b39b8a57e44fb (patch) | |
tree | b491ecc9ad06befb7335e74ff70a1ab4f2c8ff08 | |
parent | 3706fb8f16525d1d937a4b037205009b341b6390 (diff) | |
download | ffmpeg-74117abf0c26228102587057567b39b8a57e44fb.tar.gz |
lavfi/drawtext: Add %N for drawing fractions of a second
Suggested-By: ffmpeg@fb.com
-rw-r--r-- | doc/filters.texi | 4 | ||||
-rw-r--r-- | libavfilter/vf_drawtext.c | 70 |
2 files changed, 71 insertions, 3 deletions
diff --git a/doc/filters.texi b/doc/filters.texi index 26c5b4db48..a5d5257b24 100644 --- a/doc/filters.texi +++ b/doc/filters.texi @@ -11431,10 +11431,14 @@ It can be used to add padding with zeros from the left. @item gmtime The time at which the filter is running, expressed in UTC. It can accept an argument: a strftime() format string. +The format string is extended to support the variable @var{%[1-6]N} +which prints fractions of the second with optionally specified number of digits. @item localtime The time at which the filter is running, expressed in the local time zone. It can accept an argument: a strftime() format string. +The format string is extended to support the variable @var{%[1-6]N} +which prints fractions of the second with optionally specified number of digits. @item metadata Frame metadata. Takes one or two arguments. diff --git a/libavfilter/vf_drawtext.c b/libavfilter/vf_drawtext.c index 6ba3f6622a..feb6898848 100644 --- a/libavfilter/vf_drawtext.c +++ b/libavfilter/vf_drawtext.c @@ -51,6 +51,7 @@ #include "libavutil/opt.h" #include "libavutil/random_seed.h" #include "libavutil/parseutils.h" +#include "libavutil/time.h" #include "libavutil/timecode.h" #include "libavutil/time_internal.h" #include "libavutil/tree.h" @@ -1045,15 +1046,78 @@ static int func_strftime(AVFilterContext *ctx, AVBPrint *bp, char *fct, unsigned argc, char **argv, int tag) { const char *fmt = argc ? argv[0] : "%Y-%m-%d %H:%M:%S"; + const char *fmt_begin = fmt; + int64_t unow; time_t now; struct tm tm; + const char *begin; + const char *tmp; + int len; + int div; + AVBPrint fmt_bp; - time(&now); - if (tag == 'L') + av_bprint_init(&fmt_bp, 0, AV_BPRINT_SIZE_UNLIMITED); + + unow = av_gettime(); + now = unow / 1000000; + if (tag == 'L' || tag == 'm') localtime_r(&now, &tm); else tm = *gmtime_r(&now, &tm); - av_bprint_strftime(bp, fmt, &tm); + + // manually parse format for %N (fractional seconds) + begin = fmt; + while ((begin = strchr(begin, '%'))) { + tmp = begin + 1; + len = 0; + + // skip escaped "%%" + if (*tmp == '%') { + begin = tmp + 1; + continue; + } + + // count digits between % and possible N + while (*tmp != '\0' && av_isdigit((int)*tmp)) { + len++; + tmp++; + } + + // N encountered, insert time + if (*tmp == 'N') { + int num_digits = 3; // default show millisecond [1,6] + + // if digit given, expect [1,6], warn & clamp otherwise + if (len == 1) { + num_digits = av_clip(*(begin + 1) - '0', 1, 6); + } else if (len > 1) { + av_log(ctx, AV_LOG_WARNING, "Invalid number of decimals for %%N, using default of %i\n", num_digits); + } + + len += 2; // add % and N to get length of string part + + div = pow(10, 6 - num_digits); + + av_bprintf(&fmt_bp, "%.*s%0*d", (int)(begin - fmt_begin), fmt_begin, num_digits, (int)(unow % 1000000) / div); + + begin += len; + fmt_begin = begin; + + continue; + } + + begin = tmp; + } + + av_bprintf(&fmt_bp, "%s", fmt_begin); + if (!av_bprint_is_complete(&fmt_bp)) { + av_log(ctx, AV_LOG_WARNING, "Format string truncated at %u/%u.", fmt_bp.size, fmt_bp.len); + } + + av_bprint_strftime(bp, fmt_bp.str, &tm); + + av_bprint_finalize(&fmt_bp, NULL); + return 0; } |