lavfi/drawtext: Add %N for drawing fractions of a second

Suggested-By: ffmpeg@fb.com
release/5.1
Thilo Borgmann 3 years ago
parent 3706fb8f16
commit 74117abf0c
  1. 4
      doc/filters.texi
  2. 70
      libavfilter/vf_drawtext.c

@ -11431,10 +11431,14 @@ It can be used to add padding with zeros from the left.
@item gmtime @item gmtime
The time at which the filter is running, expressed in UTC. The time at which the filter is running, expressed in UTC.
It can accept an argument: a strftime() format string. 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 @item localtime
The time at which the filter is running, expressed in the local time zone. The time at which the filter is running, expressed in the local time zone.
It can accept an argument: a strftime() format string. 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 @item metadata
Frame metadata. Takes one or two arguments. Frame metadata. Takes one or two arguments.

@ -51,6 +51,7 @@
#include "libavutil/opt.h" #include "libavutil/opt.h"
#include "libavutil/random_seed.h" #include "libavutil/random_seed.h"
#include "libavutil/parseutils.h" #include "libavutil/parseutils.h"
#include "libavutil/time.h"
#include "libavutil/timecode.h" #include "libavutil/timecode.h"
#include "libavutil/time_internal.h" #include "libavutil/time_internal.h"
#include "libavutil/tree.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) char *fct, unsigned argc, char **argv, int tag)
{ {
const char *fmt = argc ? argv[0] : "%Y-%m-%d %H:%M:%S"; const char *fmt = argc ? argv[0] : "%Y-%m-%d %H:%M:%S";
const char *fmt_begin = fmt;
int64_t unow;
time_t now; time_t now;
struct tm tm; struct tm tm;
const char *begin;
const char *tmp;
int len;
int div;
AVBPrint fmt_bp;
time(&now); av_bprint_init(&fmt_bp, 0, AV_BPRINT_SIZE_UNLIMITED);
if (tag == 'L')
unow = av_gettime();
now = unow / 1000000;
if (tag == 'L' || tag == 'm')
localtime_r(&now, &tm); localtime_r(&now, &tm);
else else
tm = *gmtime_r(&now, &tm); 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; return 0;
} }

Loading…
Cancel
Save