[FFmpeg-devel,v4] Add 2 timestamp print formats

Submitted by Ulf Zibis on July 3, 2019, 5:09 p.m.

Details

Message ID 10b72bf3-c64d-1780-4310-dece360308f8@CoSoCo.de
State New
Headers show

Commit Message

Ulf Zibis July 3, 2019, 5:09 p.m.
Am 03.07.19 um 16:49 schrieb Ulf Zibis:
> Am 03.07.19 um 10:52 schrieb Michael Niedermayer:
>>>>> -#define av_ts2timestr(ts, tb) av_ts_make_time_string((char[AV_TS_MAX_STRING_SIZE]){0}, ts, tb)
>>>>> +#define av_ts2timestr(ts, tb) av_ts_make_time_string((char[AV_TS_MAX_STRING_SIZE]){'\0'}, ts, tb)
>>>>> +
>>>>> +/**
>>>>> + * Fill the provided buffer with a string containing a timestamp time
>>>>> + * representation in minutes and seconds.
>>>>> + *
>>>>> + * @param buf a buffer with size in bytes of at least AV_TS_MAX_STRING_SIZE
>>>>> + * @param ts the timestamp to represent
>>>>> + * @param tb the timebase of the timestamp
>>>>> + * @return the buffer in input
>>>>> + */
>>>>> +static inline char *av_ts_make_minute_string(char *buf, int64_t ts, AVRational *tb)
>>>>> +{
>>>>> +    if (ts == AV_NOPTS_VALUE) snprintf(buf, AV_TS_MAX_STRING_SIZE, "NOPTS");
>>>>> +    else {
>>>>> +        double time = av_q2d(*tb) * ts;
>>>> If this could be done without float/double that would be preferred as it
>>>> avoids inaccuracies / slight differences between platforms
>>> I too thought on that, but the existing functions too rely on
>>> float/double. Should I anyway provide a solution with integer arithmetic?
>> its indepedant of your patch but i think all these should use integers
>> unless its too messy
> Thanks for you opinion.
>
> Here comes a new patch.

I missed to mark the big integer literal with 'L' and add "must be less
than 2**63/1,000,000/tb->num" to all 3 functions. So I attach a correction.

-Ulf

Patch hide | download patch | download mbox

From e8c42ed84492d495e506da30dc7163edafccc9e4 Mon Sep 17 00:00:00 2001
From: Ulf Zibis <Ulf.Zibis@CoSoCo.de>
Date: 29.06.2019, 17:52:06

avutil/timestamp: 2 new print formats with av_ts2us()

diff --git a/libavutil/timestamp.h b/libavutil/timestamp.h
index e082f01..f442fc0 100644
--- a/libavutil/timestamp.h
+++ b/libavutil/timestamp.h
@@ -33,6 +33,17 @@ 
 #define AV_TS_MAX_STRING_SIZE 32
 
 /**
+ * Convert a time base scaled timestamp to micro seconds.
+ *
+ * @param ts the timestamp to convert, must be less than 2**63/1,000,000/tb->num
+ * @param tb the timebase of the timestamp
+ * @return the  timestamp in micro seconds
+ */
+static inline int64_t av_ts2us(int64_t ts, AVRational *tb) {
+    return ts * 1000000 * tb->num / tb->den;
+}
+
+/**
  * Fill the provided buffer with a string containing a timestamp
  * representation.
  *
@@ -55,7 +66,7 @@ 
 
 /**
  * Fill the provided buffer with a string containing a timestamp time
- * representation.
+ * representation in seconds.
  *
  * @param buf a buffer with size in bytes of at least AV_TS_MAX_STRING_SIZE
  * @param ts the timestamp to represent
@@ -75,4 +86,60 @@ 
  */
 #define av_ts2timestr(ts, tb) av_ts_make_time_string((char[AV_TS_MAX_STRING_SIZE]){0}, ts, tb)
 
+/**
+ * Fill the provided buffer with a string containing a timestamp time
+ * representation in minutes and seconds.
+ *
+ * @param buf a buffer with size in bytes of at least AV_TS_MAX_STRING_SIZE
+ * @param ts the timestamp to represent, must be less than 2**63/1,000,000/tb->num
+ * @param tb the timebase of the timestamp
+ * @return the buffer in input
+ */
+static char *av_ts_make_minute_string(char *buf, int64_t ts, AVRational *tb)
+{
+    if (ts == AV_NOPTS_VALUE) snprintf(buf, AV_TS_MAX_STRING_SIZE, "NOPTS");
+    else {
+        int64_t us = av_ts2us(ts, tb);
+        int len = snprintf(buf, AV_TS_MAX_STRING_SIZE, "%3ld:%02d.%06d",
+                us / 60000000, (int)(us / 1000000 % 60), (int)(us % 1000000));
+        while (buf[--len] == '0'); // search trailing zeros or ...
+        buf[len + (buf[len] != '.')] = '\0'; // dot and strip them
+    }
+    return buf;
+}
+
+/**
+ * Convenience macro. The return value should be used only directly in
+ * function arguments but never stand-alone.
+ */
+#define av_ts2minutestr(ts, tb) av_ts_make_minute_string((char[AV_TS_MAX_STRING_SIZE]){'\0'}, ts, tb)
+
+/**
+ * Fill the provided buffer with a string containing a timestamp time
+ * representation in hours, minutes and seconds.
+ *
+ * @param buf a buffer with size in bytes of at least AV_TS_MAX_STRING_SIZE
+ * @param ts the timestamp to represent, must be less than 2**63/1,000,000/tb->num
+ * @param tb the timebase of the timestamp
+ * @return the buffer in input
+ */
+static char *av_ts_make_hour_string(char *buf, int64_t ts, AVRational *tb)
+{
+    if (ts == AV_NOPTS_VALUE) snprintf(buf, AV_TS_MAX_STRING_SIZE, "NOPTS");
+    else {
+        int64_t us = av_ts2us(ts, tb);
+        int len = snprintf(buf, AV_TS_MAX_STRING_SIZE, "%ld:%02d:%02d.%06d",
+                us / 3600000000L, (int)(us / 60000000 % 60), (int)(us / 1000000 % 60), (int)(us % 1000000));
+        while (buf[--len] == '0'); // search trailing zeros or ...
+        buf[len + (buf[len] != '.')] = '\0'; // dot and strip them
+    }
+    return buf;
+}
+
+/**
+ * Convenience macro. The return value should be used only directly in
+ * function arguments but never stand-alone.
+ */
+#define av_ts2hourstr(ts, tb) av_ts_make_hour_string((char[AV_TS_MAX_STRING_SIZE]){'\0'}, ts, tb)
+
 #endif /* AVUTIL_TIMESTAMP_H */