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

Allan Cady allancady at yahoo.com
Tue Mar 26 00:13:48 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


This looks great. I ran the patch against my test program with a couple
dozen vectors of inputs, and it looks perfect to me.


Thanks to both of you Marton and Andreas for seeing this through. I
really appreciate it.


Allan


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