[FFmpeg-devel] [PATCH v2 1/2] avutil/timestamp: introduce av_ts_make_time_string2 for better precision

Marton Balint cus at passwd.hu
Mon Mar 25 20:27:41 EET 2024



On Sat, 23 Mar 2024, Marton Balint wrote:

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

Will apply the series, so it can make it into 7.0.

Regards,
Marton

>
> Signed-off-by: Marton Balint <cus at passwd.hu>
> ---
> doc/APIchanges        |  5 +++++
> libavutil/Makefile    |  1 +
> libavutil/timestamp.c | 36 ++++++++++++++++++++++++++++++++++++
> libavutil/timestamp.h |  8 ++++++++
> libavutil/version.h   |  2 +-
> 5 files changed, 51 insertions(+), 1 deletion(-)
> create mode 100644 libavutil/timestamp.c
>
> diff --git a/doc/APIchanges b/doc/APIchanges
> index 2796b4d0c2..9c6fa381e1 100644
> --- a/doc/APIchanges
> +++ b/doc/APIchanges
> @@ -2,6 +2,11 @@ The last version increases of all libraries were on 2024-03-07
>
> API changes, most recent first:
>
> +2024-03-xx - xxxxxxxxxx - lavu 59.5.100 - timestamp.h
> +  Add av_ts_make_time_string2() for better timestamp precision, the new
> +  function accepts AVRational as time base instead of *AVRational, and is not
> +  an inline function like its predecessor.
> +
> 2024-03-xx - xxxxxxxxxx - lavc 61.3.100 - jni.h
>   Add av_jni_set_android_app_ctx() and av_jni_get_android_app_ctx().
>
> diff --git a/libavutil/Makefile b/libavutil/Makefile
> index 008fcfcd9c..6e6fa8d800 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..2a3e3012a4
> --- /dev/null
> +++ b/libavutil/timestamp.c
> @@ -0,0 +1,36 @@
> +/*
> + * 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_string2(char *buf, int64_t ts, AVRational tb)
> +{
> +    if (ts == AV_NOPTS_VALUE) {
> +        snprintf(buf, AV_TS_MAX_STRING_SIZE, "NOPTS");
> +    } else {
> +        double val = av_q2d(tb) * ts;
> +        double log = floor(log10(fabs(val)));
> +        int precision = (isfinite(log) && log < 0) ? -log + 5 : 6;
> +        int last = snprintf(buf, AV_TS_MAX_STRING_SIZE, "%.*f", precision, val);
> +        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;
> +}
> diff --git a/libavutil/timestamp.h b/libavutil/timestamp.h
> index 2b37781eba..7e6da894df 100644
> --- a/libavutil/timestamp.h
> +++ b/libavutil/timestamp.h
> @@ -62,6 +62,14 @@ static inline char *av_ts_make_string(char *buf, int64_t ts)
>  * @param tb the timebase of the timestamp
>  * @return the buffer in input
>  */
> +char *av_ts_make_time_string2(char *buf, int64_t ts, AVRational tb);
> +
> +/**
> + * Fill the provided buffer with a string containing a timestamp
> + * representation.
> + *
> + * @see av_ts_make_time_string2
> + */
> static inline char *av_ts_make_time_string(char *buf, int64_t ts,
>                                            const AVRational *tb)
> {
> diff --git a/libavutil/version.h b/libavutil/version.h
> index 882003f719..8a1ecd4451 100644
> --- a/libavutil/version.h
> +++ b/libavutil/version.h
> @@ -79,7 +79,7 @@
>  */
>
> #define LIBAVUTIL_VERSION_MAJOR  59
> -#define LIBAVUTIL_VERSION_MINOR   4
> +#define LIBAVUTIL_VERSION_MINOR   5
> #define LIBAVUTIL_VERSION_MICRO 100
>
> #define LIBAVUTIL_VERSION_INT   AV_VERSION_INT(LIBAVUTIL_VERSION_MAJOR, \
> -- 
> 2.35.3
>
> _______________________________________________
> ffmpeg-devel mailing list
> ffmpeg-devel at ffmpeg.org
> https://ffmpeg.org/mailman/listinfo/ffmpeg-devel
>
> To unsubscribe, visit link above, or email
> ffmpeg-devel-request at ffmpeg.org with subject "unsubscribe".
>


More information about the ffmpeg-devel mailing list