[FFmpeg-devel] [PATCH 2/2] libavutil: Make changes in softfloat needed for fixed point aac decoder.
Michael Niedermayer
michaelni at gmx.at
Wed Apr 15 22:58:47 CEST 2015
On Wed, Apr 15, 2015 at 03:14:07PM +0200, Nedeljko Babic wrote:
> From: Djordje Pesut <djordje.pesut at imgtec.com>
>
> Functions for sqrt and sincos are added.
>
> Div function is improved.
>
> Some changes are made in order for code in softfloat to be usable in fixed aac
> decoder code.
>
> This doesn't create any impact on current ffmpeg code since softfloat is
> currently not in use and this way we don't need to make much changes in
> implementation of aac fixed point decoder that uses this code.
>
> Softfloat tests are adjusted.
>
> Signed-off-by: Nedeljko Babic <nedeljko.babic at imgtec.com>
> ---
> libavutil/softfloat.c | 6 +-
> libavutil/softfloat.h | 167 +++++++++++++++++++++---
> libavutil/softfloat_tables.h | 294 +++++++++++++++++++++++++++++++++++++++++++
> 3 files changed, 447 insertions(+), 20 deletions(-)
> create mode 100644 libavutil/softfloat_tables.h
>
> diff --git a/libavutil/softfloat.c b/libavutil/softfloat.c
> index bf9cfda..23de93d 100644
> --- a/libavutil/softfloat.c
> +++ b/libavutil/softfloat.c
> @@ -27,7 +27,7 @@
> #undef printf
>
> int main(void){
> - SoftFloat one= av_int2sf(1, 0);
> + SoftFloat one= av_int2sf(1, 30);
> SoftFloat sf1, sf2;
> double d1, d2;
> int i, j;
> @@ -59,8 +59,8 @@ int main(void){
>
> for(i= 0; i<100; i++){
> START_TIMER
> - sf1= av_int2sf(i, 0);
> - sf2= av_div_sf(av_int2sf(i, 2), av_int2sf(200, 3));
> + sf1= av_int2sf(i, 30);
> + sf2= av_div_sf(av_int2sf(i, 28), av_int2sf(200, 27));
> for(j= 0; j<1000; j++){
> sf1= av_mul_sf(av_add_sf(sf1, one),sf2);
> }
> diff --git a/libavutil/softfloat.h b/libavutil/softfloat.h
> index 654a31f..c3ab316 100644
> --- a/libavutil/softfloat.h
> +++ b/libavutil/softfloat.h
> @@ -25,6 +25,7 @@
> #include "common.h"
>
> #include "avassert.h"
> +#include "softfloat_tables.h"
>
> #define MIN_EXP -126
> #define MAX_EXP 126
> @@ -35,6 +36,14 @@ typedef struct SoftFloat{
> int32_t exp;
> }SoftFloat;
>
> +static const SoftFloat FLOAT_0 = { 0, 0};
> +static const SoftFloat FLOAT_05 = { 0x20000000, 0};
> +static const SoftFloat FLOAT_1 = { 0x20000000, 1};
> +static const SoftFloat FLOAT_EPSILON = { 0x29F16B12, -16};
> +static const SoftFloat FLOAT_1584893192 = { 0x32B771ED, 1};
> +static const SoftFloat FLOAT_100000 = { 0x30D40000, 17};
> +static const SoftFloat FLOAT_0999999 = { 0x3FFFFBCE, 0};
> +
> static av_const SoftFloat av_normalize_sf(SoftFloat a){
> if(a.mant){
> #if 1
> @@ -83,17 +92,7 @@ static inline av_const SoftFloat av_mul_sf(SoftFloat a, SoftFloat b){
> a.exp += b.exp;
> av_assert2((int32_t)((a.mant * (int64_t)b.mant) >> ONE_BITS) == (a.mant * (int64_t)b.mant) >> ONE_BITS);
> a.mant = (a.mant * (int64_t)b.mant) >> ONE_BITS;
> - return av_normalize1_sf(a);
> -}
> -
> -/**
> - * b has to be normalized and not zero.
> - * @return Will not be more denormalized than a.
> - */
> -static av_const SoftFloat av_div_sf(SoftFloat a, SoftFloat b){
> - a.exp -= b.exp+1;
> - a.mant = ((int64_t)a.mant<<(ONE_BITS+1)) / b.mant;
> - return av_normalize1_sf(a);
> + return av_normalize1_sf((SoftFloat){a.mant, --a.exp});
^^^^^^
a.exp - 1
> }
>
> static inline av_const int av_cmp_sf(SoftFloat a, SoftFloat b){
> @@ -102,11 +101,18 @@ static inline av_const int av_cmp_sf(SoftFloat a, SoftFloat b){
> else return a.mant - (b.mant >> t);
> }
>
> +static inline av_const int av_gt_sf(SoftFloat a, SoftFloat b)
> +{
> + int t= a.exp - b.exp;
> + if(t<0) return (a.mant >> (-t)) > b.mant ;
> + else return a.mant > (b.mant >> t);
> +}
> +
> static inline av_const SoftFloat av_add_sf(SoftFloat a, SoftFloat b){
> int t= a.exp - b.exp;
> - if (t <-31) return b;
> - else if (t < 0) return av_normalize1_sf((SoftFloat){b.mant + (a.mant >> (-t)), b.exp});
> - else if (t < 32) return av_normalize1_sf((SoftFloat){a.mant + (b.mant >> t ), a.exp});
> + if (t <=-31) return b;
> + else if (t < 0) return av_normalize_sf(av_normalize1_sf((SoftFloat){ b.mant + (a.mant >> (-t)), b.exp}));
> + else if (t < 32) return av_normalize_sf(av_normalize1_sf((SoftFloat){ a.mant + (b.mant >> t ), a.exp}));
> else return a;
> }
>
> @@ -114,19 +120,146 @@ static inline av_const SoftFloat av_sub_sf(SoftFloat a, SoftFloat b){
> return av_add_sf(a, (SoftFloat){ -b.mant, b.exp});
> }
>
> -//FIXME sqrt, log, exp, pow, sin, cos
> +static inline av_const SoftFloat av_recip_sf(SoftFloat a)
> +{
> + int s = a.mant >> 31;
> +
> + a.exp = 1 - a.exp;
> + a.mant = (a.mant ^ s) - s;
> + a.mant = av_divtbl_sf[(a.mant - 0x20000000) >> 22];
> + a.mant = (a.mant ^ s) - s;
> +
> + return a;
> +}
> +
> +static av_always_inline SoftFloat av_div_sf(SoftFloat a, SoftFloat b){
missing documentation
is this exact ?
if not what are the gurantees to the user
> +#if 0
> + a.exp -= b.exp + 1;
> + a.mant = ((int64_t)a.mant<<(ONE_BITS+1)) / b.mant;
> + return av_normalize1_sf(a);
> +#else
enabing this breaks the tests
also is it really an advantage to have this av_always_inline ?
it looks a bit big for always inlining it
> + SoftFloat res;
> + SoftFloat iB, tmp;
> +
> + if (b.mant != 0)
> + {
> + iB = av_recip_sf(b);
> + /* Newton iteration to double precision */
> + tmp = av_sub_sf(FLOAT_1, av_mul_sf(b, iB));
> + iB = av_add_sf(iB, av_mul_sf(iB, tmp));
> + tmp = av_sub_sf(FLOAT_1, av_mul_sf(b, iB));
> + iB = av_add_sf(iB, av_mul_sf(iB, tmp));
> + tmp = av_sub_sf(FLOAT_1, av_mul_sf(b, iB));
> + iB = av_add_sf(iB, av_mul_sf(iB, tmp));
> + res = av_mul_sf(a, iB);
> + }
> + else
> + {
> + /* handle division-by-zero */
> + res.mant = 1;
> + res.exp = 0x7FFFFFFF;
> + }
> +
> + return res;
> +#endif
> +}
> +
> +//FIXME log, exp, pow
>
> static inline av_const SoftFloat av_int2sf(int v, int frac_bits){
> - return av_normalize_sf((SoftFloat){v, ONE_BITS-frac_bits});
> + return av_normalize_sf((SoftFloat){v, frac_bits});
> }
missing documentation
also please make sure that the parameters make some logic sense
and do not depend on the precission choosen by the implementation
so a "1.0" shwould be generated from the same arguments no matter
what the precision used in the implementation is
[...]
--
Michael GnuPG fingerprint: 9FF2128B147EF6730BADF133611EC787040B0FAB
DNS cache poisoning attacks, popular search engine, Google internet authority
dont be evil, please
-------------- next part --------------
A non-text attachment was scrubbed...
Name: not available
Type: application/pgp-signature
Size: 181 bytes
Desc: Digital signature
URL: <https://ffmpeg.org/pipermail/ffmpeg-devel/attachments/20150415/61dd164b/attachment.asc>
More information about the ffmpeg-devel
mailing list