[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