You've already forked FFmpeg
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:
@@ -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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user