av_ts_make_time_string() used "%.6g" format in the past, 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.
So let's change the used format to "%.6f" instead, we have plenty of
space in
the string buffer, we can somewhat imitate existing behaviour of %g by
trimming
ending zeroes and the potential decimal point, which can be any
non-numeric
character. In order not to trim "inf" as well, we assume that the
decimal
point does not contain the letter "f".
We also no longer use scientific representation to make parsing and
printing
easier, because the theoretical maximum of INT64_MAX*INT32_MAX still
fits into
the string buffer in normal form.
Since the additional processing yields more code, inlineing this
function no
longer make sense, so this commit also changes the API to actually
export the
function instead of having it inlinable in the header.
Thanks for Allan Cady for bringing up this issue.
Signed-off-by: Marton Balint <c...@passwd.hu>
---
doc/APIchanges | 3 ++
libavutil/Makefile | 1 +
libavutil/timestamp.c | 33 ++++++++++++++++++++
libavutil/timestamp.h | 8 +----
libavutil/version.h | 2 +-
tests/ref/fate/filter-metadata-scdet | 12 +++----
tests/ref/fate/filter-metadata-silencedetect | 2 +-
7 files changed, 46 insertions(+), 15 deletions(-)
create mode 100644 libavutil/timestamp.c
diff --git a/doc/APIchanges b/doc/APIchanges
index a44c8e4f10..1afde062a5 100644
--- a/doc/APIchanges
+++ b/doc/APIchanges
@@ -2,6 +2,9 @@ The last version increases of all libraries were on
@@ 2024-03-07
API changes, most recent first:
+2024-03-xx - xxxxxxxxxx - lavu 59.3.100 - timestamp.h
+ av_ts_make_time_string() is no longer an inline function. It is now
exported.
+
2024-03-xx - xxxxxxxxxx - lavu 59.2.100 - channel_layout.h
Add AV_CHANNEL_LAYOUT_RETYPE_FLAG_CANONICAL.
diff --git a/libavutil/Makefile b/libavutil/Makefile
index e7709b97d0..5e75aa1855 100644
--- a/libavutil/Makefile
+++ b/libavutil/Makefile
@@ -174,6 +174,7 @@ OBJS = adler32.o
@@ \
threadmessage.o
\
time.o
\
timecode.o
\
+ timestamp.o
\
tree.o
\
twofish.o
\
utils.o
\
diff --git a/libavutil/timestamp.c b/libavutil/timestamp.c
new file mode 100644
index 0000000000..06fb47e94c
--- /dev/null
+++ b/libavutil/timestamp.c
@@ -0,0 +1,33 @@
+/*
+ * This file is part of FFmpeg.
+ *
+ * FFmpeg is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * FFmpeg is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with FFmpeg; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
02110-1301 USA
+ */
+
+#include "timestamp.h"
+
+char *av_ts_make_time_string(char *buf, int64_t ts, const AVRational
*tb)
+{
+ if (ts == AV_NOPTS_VALUE) {
+ snprintf(buf, AV_TS_MAX_STRING_SIZE, "NOPTS");
+ } else {
+ int last = snprintf(buf, AV_TS_MAX_STRING_SIZE, "%.6f",
av_q2d(*tb) * ts);
+ last = FFMIN(last, AV_TS_MAX_STRING_SIZE - 1) - 1;
+ for (; last && buf[last] == '0'; last--);
+ for (; last && buf[last] != 'f' && (buf[last] < '0' || buf[0] >
'9'); last--);
+ buf[last + 1] = '\0';
+ }
+ return buf;
+}