1
0
mirror of https://github.com/FFmpeg/FFmpeg.git synced 2025-08-15 14:13:16 +02:00

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

Suggested-By: ffmpeg@fb.com
This commit is contained in:
Thilo Borgmann
2022-02-08 11:39:46 +01:00
parent 3706fb8f16
commit 74117abf0c
2 changed files with 71 additions and 3 deletions

View File

@@ -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.

View File

@@ -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;
} }