avutil: Add av_q2intfloat()
authorMichael Niedermayer <michaelni@gmx.at>
Sun, 24 May 2015 12:19:57 +0000 (14:19 +0200)
committerMichael Niedermayer <michaelni@gmx.at>
Tue, 26 May 2015 16:31:53 +0000 (18:31 +0200)
This function allows writing AVRationals as IEEE floats without the need
of platform dependant float operations

Signed-off-by: Michael Niedermayer <michaelni@gmx.at>
doc/APIchanges
libavutil/rational.c
libavutil/rational.h
libavutil/version.h

index 3cca389..b0c69dc 100644 (file)
@@ -15,6 +15,9 @@ libavutil:     2014-08-09
 
 API changes, most recent first:
 
+2015-05-26 - xxxxxxx - lavu 54.25.100 - rational.h
+  Add av_q2intfloat().
+
 2015-05-13 - xxxxxxx - lavc 56.39.100 / 56.23.0
   Add av_vda_default_init2.
 
index 594a6f8..21d2bb7 100644 (file)
@@ -148,6 +148,40 @@ int av_find_nearest_q_idx(AVRational q, const AVRational* q_list)
     return nearest_q_idx;
 }
 
+uint32_t av_q2intfloat(AVRational q) {
+    int64_t n;
+    int shift;
+    int sign = 0;
+
+    if (q.den < 0) {
+        q.den *= -1;
+        q.num *= -1;
+    }
+    if (q.num < 0) {
+        q.num *= -1;
+        sign = 1;
+    }
+
+    if (!q.num && !q.den) return 0xFFC00000;
+    if (!q.num) return 0;
+    if (!q.den) return 0x7F800000 | (q.num & 0x80000000);
+
+    shift = 23 + av_log2(q.den) - av_log2(q.num);
+    if (shift >= 0) n = av_rescale(q.num, 1LL<<shift, q.den);
+    else            n = av_rescale(q.num, 1, ((int64_t)q.den) << -shift);
+
+    shift -= n >= (1<<24);
+    shift += n <  (1<<23);
+
+    if (shift >= 0) n = av_rescale(q.num, 1LL<<shift, q.den);
+    else            n = av_rescale(q.num, 1, ((int64_t)q.den) << -shift);
+
+    av_assert1(n <  (1<<24));
+    av_assert1(n >= (1<<23));
+
+    return sign<<31 | (150-shift)<<23 | (n - (1<<23));
+}
+
 #ifdef TEST
 int main(void)
 {
@@ -202,6 +236,20 @@ int main(void)
             }
         }
     }
+
+    for (a.den = 1; a.den < 0x100000000U/3; a.den*=3) {
+        for (a.num = -1; a.num < (1<<27); a.num += 1 + a.num/100) {
+            float f  = av_int2float(av_q2intfloat(a));
+            float f2 = av_q2d(a);
+            if (fabs(f - f2) > fabs(f)/5000000) {
+                av_log(NULL, AV_LOG_ERROR, "%d/%d %f %f\n", a.num,
+                       a.den, f, f2);
+                return 1;
+            }
+
+        }
+    }
+
     return 0;
 }
 #endif
index 7439701..2897469 100644 (file)
@@ -159,6 +159,13 @@ int av_nearer_q(AVRational q, AVRational q1, AVRational q2);
  */
 int av_find_nearest_q_idx(AVRational q, const AVRational* q_list);
 
+/**
+ * Converts a AVRational to a IEEE 32bit float.
+ *
+ * The float is returned in a uint32_t and its value is platform indepenant.
+ */
+uint32_t av_q2intfloat(AVRational q);
+
 /**
  * @}
  */
index eeafcfa..4a5e47d 100644 (file)
@@ -56,7 +56,7 @@
  */
 
 #define LIBAVUTIL_VERSION_MAJOR  54
-#define LIBAVUTIL_VERSION_MINOR  24
+#define LIBAVUTIL_VERSION_MINOR  25
 #define LIBAVUTIL_VERSION_MICRO 100
 
 #define LIBAVUTIL_VERSION_INT   AV_VERSION_INT(LIBAVUTIL_VERSION_MAJOR, \