History

avutil/timestamp: introduce av_ts_make_time_string2 for better precision

av_ts_make_time_string() used "%.6g" format, but this format was losing precision even when the timestamp to be printed was not that large. For example for 3 hours (10800) seconds, only 1 decimal digit was printed, which made this format inaccurate when it was used in e.g. the silencedetect filter. Other detection filters printing timestamps had similar issues. Also time base parameter of the function was *AVRational instead of AVRational. Resolve these problems by introducing a new function, av_ts_make_time_string2(). We change the used format to "%.*f", use a precision of 6, except when printing values near 0, in which case we calculate the precision dynamically to aim for a similar precision in normal form as with %.6g. No longer using scientific representation can make parsing the timestamp easier for the users, we can safely do this because the theoretical maximum of INT64_MAX*INT32_MAX still fits into the string buffer in normal form. We somewhat imitate %g by trimming ending zeroes and the potential decimal point characters. In order not to trim "inf" as well, we assume that the decimal point string does not contain the letter "f". Note that depending on printf %f implementation, we might trim "infinity" to "inf". Thanks for Allan Cady for bringing up this issue.

Marton Balint committed 2 years ago

Commit 5df901f1 parent 7c003b65 files · +51 −1Browse files

Unified · Split

5 files
  1. doc/APIchanges +5 −0
  2. libavutil/Makefile +1 −0
  3. libavutil/timestamp.c +36 −0
  4. libavutil/timestamp.h +8 −0
  5. libavutil/version.h +1 −1
doc/APIchanges+5−0
@@ -2,6 +2,11 @@ The last version increases of all libraries were on 2024-03-07 · 1 unmodified line
2 2
3API changes, most recent first:3API changes, most recent first:
4 4
52024-03-xx - xxxxxxxxxx - lavu 59.7.100 - timestamp.h
6 Add av_ts_make_time_string2() for better timestamp precision, the new
7 function accepts AVRational as time base instead of *AVRational, and is not
8 an inline function like its predecessor.
9
52024-03-xx - xxxxxxxxxx - lavu 59.6.100 - film_grain_params.h102024-03-xx - xxxxxxxxxx - lavu 59.6.100 - film_grain_params.h
6 Add av_film_grain_params_select().11 Add av_film_grain_params_select().
7 12
libavutil/Makefile+1−0
@@ -174,6 +174,7 @@ OBJS = adler32.o \ · 173 unmodified lines
174 threadmessage.o \174 threadmessage.o \
175 time.o \175 time.o \
176 timecode.o \176 timecode.o \
177 timestamp.o \
177 tree.o \178 tree.o \
178 twofish.o \179 twofish.o \
179 utils.o \180 utils.o \
libavutil/timestamp.c+36−0
@@ -0,0 +1,36 @@
1/*
2 * This file is part of FFmpeg.
3 *
4 * FFmpeg is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU Lesser General Public
6 * License as published by the Free Software Foundation; either
7 * version 2.1 of the License, or (at your option) any later version.
8 *
9 * FFmpeg is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * Lesser General Public License for more details.
13 *
14 * You should have received a copy of the GNU Lesser General Public
15 * License along with FFmpeg; if not, write to the Free Software
16 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
17 */
18
19#include "timestamp.h"
20
21char *av_ts_make_time_string2(char *buf, int64_t ts, AVRational tb)
22{
23 if (ts == AV_NOPTS_VALUE) {
24 snprintf(buf, AV_TS_MAX_STRING_SIZE, "NOPTS");
25 } else {
26 double val = av_q2d(tb) * ts;
27 double log = floor(log10(fabs(val)));
28 int precision = (isfinite(log) && log < 0) ? -log + 5 : 6;
29 int last = snprintf(buf, AV_TS_MAX_STRING_SIZE, "%.*f", precision, val);
30 last = FFMIN(last, AV_TS_MAX_STRING_SIZE - 1) - 1;
31 for (; last && buf[last] == '0'; last--);
32 for (; last && buf[last] != 'f' && (buf[last] < '0' || buf[0] > '9'); last--);
33 buf[last + 1] = '\0';
34 }
35 return buf;
36}
libavutil/timestamp.h+8−0
@@ -62,6 +62,14 @@ static inline char *av_ts_make_string(char *buf, int64_t ts) · 61 unmodified lines
62 * @param tb the timebase of the timestamp62 * @param tb the timebase of the timestamp
63 * @return the buffer in input63 * @return the buffer in input
64 */64 */
65char *av_ts_make_time_string2(char *buf, int64_t ts, AVRational tb);
66
67/**
68 * Fill the provided buffer with a string containing a timestamp
69 * representation.
70 *
71 * @see av_ts_make_time_string2
72 */
65static inline char *av_ts_make_time_string(char *buf, int64_t ts,73static inline char *av_ts_make_time_string(char *buf, int64_t ts,
66 const AVRational *tb)74 const AVRational *tb)
67{75{
libavutil/version.h+1−1
@@ -79,7 +79,7 @@ · 78 unmodified lines
79 */79 */
80 80
81#define LIBAVUTIL_VERSION_MAJOR 5981#define LIBAVUTIL_VERSION_MAJOR 59
82#define LIBAVUTIL_VERSION_MINOR 682#define LIBAVUTIL_VERSION_MINOR 7
83#define LIBAVUTIL_VERSION_MICRO 10083#define LIBAVUTIL_VERSION_MICRO 100
84 84
85#define LIBAVUTIL_VERSION_INT AV_VERSION_INT(LIBAVUTIL_VERSION_MAJOR, \85#define LIBAVUTIL_VERSION_INT AV_VERSION_INT(LIBAVUTIL_VERSION_MAJOR, \

Keyboard shortcuts

General

Show keyboard shortcuts
?
Focus the current search
/

Issues and pull requests

Open filters
f

Issues, pull requests and Inbox

Select next item
j↓
Select previous item
k↑
Open selected item
Enter
Dismiss filters or clear selection
Esc

Repository code

Go to file
t