[FFmpeg-cvslog] lavfi/drawtext: Add %N for drawing fractions of a second
Thilo Borgmann
git at videolan.org
Tue Mar 8 14:30:05 EET 2022
ffmpeg | branch: master | Thilo Borgmann <thilo.borgmann at mail.de> | Tue Feb 8 11:39:46 2022 +0100| [74117abf0c26228102587057567b39b8a57e44fb] | committer: Thilo Borgmann
lavfi/drawtext: Add %N for drawing fractions of a second
Suggested-By: ffmpeg at fb.com
> http://git.videolan.org/gitweb.cgi/ffmpeg.git/?a=commit;h=74117abf0c26228102587057567b39b8a57e44fb
---
doc/filters.texi | 4 +++
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;
}
More information about the ffmpeg-cvslog
mailing list