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

avutil/timestamp: added 2 new print formats

diff --git a/libavutil/timestamp.h b/libavutil/timestamp.h
index e082f01..b94e5ce 100644
--- a/libavutil/timestamp.h
+++ b/libavutil/timestamp.h
@@ -48,14 +48,14 @@
 }
 
 /**
- * Convenience macro, the return value should be used only directly in
+ * Convenience macro. The return value should be used only directly in
  * function arguments but never stand-alone.
  */
-#define av_ts2str(ts) av_ts_make_string((char[AV_TS_MAX_STRING_SIZE]){0}, ts)
+#define av_ts2str(ts) av_ts_make_string((char[AV_TS_MAX_STRING_SIZE]){'\0'}, ts)
 
 /**
  * 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
@@ -70,9 +70,77 @@
 }
 
 /**
- * Convenience macro, the return value should be used only directly in
+ * Convenience macro. The return value should be used only directly in
  * function arguments but never stand-alone.
  */
-#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;
+        const char *format = (time >= 0 ? "%3d:%09.6f" : "-%3d:%09.6f");
+        time = (fabs(time) > INT_MAX * 60.0 ? INT_MAX * 60.0 : fabs(time));
+        int len = snprintf(buf, AV_TS_MAX_STRING_SIZE, format, (int)(time / 60), fmod(time, 60));
+        if (len - 9 >= 0 && buf[len - 9] > '5') // correct rare rounding issue
+            len = snprintf(buf, AV_TS_MAX_STRING_SIZE, format, (int)(time / 60) + 1, .0);
+        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
+ * @param tb the timebase of the timestamp
+ * @return the buffer in input
+ */
+static inline 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 {
+        double time = av_q2d(*tb) * ts;
+        const char *format = (time >= 0 ? "%d:%02d:%09.6f" : "-%d:%02d:%09.6f");
+        time = (fabs(time) > INT_MAX * 60.0 * 60.0 ? INT_MAX * 60.0 * 60.0 : fabs(time));
+        int hours = time / 60 / 60, minutes = fmod(time / 60, 60);
+        int len = snprintf(buf, AV_TS_MAX_STRING_SIZE, format, hours, minutes, fmod(time, 60));
+        if (len - 9 >= 0 && buf[len - 9] > '5') { // correct rare rounding issue
+            if (++minutes > 59) {
+                minutes = 0;
+                hours++;
+            }
+            len = snprintf(buf, AV_TS_MAX_STRING_SIZE, format, hours, minutes, .0);
+        }
+        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 */
