diff options
author | Michael Niedermayer <michaelni@gmx.at> | 2015-05-24 14:19:57 +0200 |
---|---|---|
committer | Michael Niedermayer <michaelni@gmx.at> | 2015-05-26 18:31:53 +0200 |
commit | 1fb9b2a2832444935c4c2fd5679266b0629d1bfd (patch) | |
tree | 9baac009633492f6c6b4d2e587ee7a7723d5b3b4 | |
parent | 894d8cf418aafc5f6dd697f57e24f3e96b6af2f3 (diff) | |
download | ffmpeg-1fb9b2a2832444935c4c2fd5679266b0629d1bfd.tar.gz |
avutil: Add av_q2intfloat()
This function allows writing AVRationals as IEEE floats without the need
of platform dependant float operations
Signed-off-by: Michael Niedermayer <michaelni@gmx.at>
-rw-r--r-- | doc/APIchanges | 3 | ||||
-rw-r--r-- | libavutil/rational.c | 48 | ||||
-rw-r--r-- | libavutil/rational.h | 7 | ||||
-rw-r--r-- | libavutil/version.h | 2 |
4 files changed, 59 insertions, 1 deletions
diff --git a/doc/APIchanges b/doc/APIchanges index 3cca3890cb..b0c69dcdb0 100644 --- a/doc/APIchanges +++ b/doc/APIchanges @@ -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. diff --git a/libavutil/rational.c b/libavutil/rational.c index 594a6f81e6..21d2bb72c3 100644 --- a/libavutil/rational.c +++ b/libavutil/rational.c @@ -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 diff --git a/libavutil/rational.h b/libavutil/rational.h index 7439701db2..2897469680 100644 --- a/libavutil/rational.h +++ b/libavutil/rational.h @@ -160,6 +160,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); + +/** * @} */ diff --git a/libavutil/version.h b/libavutil/version.h index eeafcfab6c..4a5e47d7a0 100644 --- a/libavutil/version.h +++ b/libavutil/version.h @@ -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, \ |