[FFmpeg-soc] [soc]: r369 - jpeg2000/j2kenc.c

Kamil Nowosad kamil.nowosad at gmail.com
Sun Jul 15 15:34:46 CEST 2007


Hi

On Fri, Jul 13, 2007 at 09:45:22PM +0200, Michael Niedermayer wrote:
> > > >  static double getwmsedec(int nmsedec, int bandpos, int lev, int bpno)
> > > >  {
> > > > -   static const double dwt_norms[4][10] = {
> > > > -    {1.000, 1.500, 2.750, 5.375, 10.68, 21.34, 42.67, 85.33, 170.7, 341.3},
> > > > -    {1.038, 1.592, 2.919, 5.703, 11.33, 22.64, 45.25, 90.48, 180.9},
> > > > -    {1.038, 1.592, 2.919, 5.703, 11.33, 22.64, 45.25, 90.48, 180.9},
> > > > -    {.7186, .9218, 1.586, 3.043, 6.019, 12.01, 24.00, 47.97, 95.93}};
> > > > +   static const int dwt_norms[4][10] = { // multiplied by 10000
> > > > +    {10000, 15000, 27500, 53750, 106800, 213400, 426700, 853300, 1707000, 3413000},
> > > > +    {10380, 15920, 29190, 57030, 113300, 226400, 452500, 904800, 1809000},
> > > > +    {10380, 15920, 29190, 57030, 113300, 226400, 452500, 904800, 1809000},
> > > > +    { 7186,  9218, 15860, 30430,  60190, 120100, 240000, 479700,  959300}};
> > > >  
> > > > -    double t = dwt_norms[bandpos][lev] * (1 << bpno);
> > > > -    return t * t * nmsedec / 8192.0;
> > > > +    int t = (dwt_norms[bandpos][lev]) * (1 << bpno);
> > > > +    return (double) t * (double) t * nmsedec;
> > > >  }
> > > 
> > > why is the returned values not int64_t or int?
> > > same question for the code which uses getwmsedec() ?
> > 
> > The values returned by this function can reach 2^81 (nmsedec - 2^23,
> > dwt_norms - 2^22, 1<<bpno - 2^7), and they are then summed up for whole
> > code block [about 20 times], and for whole tile (up to 256 code blocks).
> > But in some cases the values can be small. So dividing them by a
> > constant would make, in my opinion, too big precision loss.
> > Maybe there exists a smart solution, but I don't see it.
> 
> i really would like to see the float&double useage decreased, if not
> regression tests will be impossible as we will have different results on
> different compilers and hw
> also the code would be very slow on fpu-less systems
> that said i understand that the 9/7 wavelet is better (and faster on fpu+cpu)
> implemented with
> floats and so iam not objecting to have only a float implementation of that
> also i dont mind if the other wavelets are done with floats but i think
> in general float code should be avoided where possible
> 
> and in this specific case the value represents distortion, a 8bit 4096x4096
> image has a maximum squared distortion which fits in 40bit when a single
> pixel +-1 change can still be represented so i do think 64bit is plenty
> and theres no need or sense in floating point
> adding the maximum of variables which are not able to reach this maximum
> at the same times is not really usefull ...

Ok, so would something like that be good:

#define WMSEDEC_SHIFT 13

and in getwmsedec()

int64_t t = (dwt_norms[bandpos][lev]) * (1 << bpno);
return (t * t >> WMSEDEC_SHIFT) * nmsedec;
?

> also you could add the same dwt_norms cases first and then at the end
> add do the dwt_norms scaling and adding this would be more accurate
> with double as well as int

But dwt_norms are multiplied by 1<<bpno which changes in consecutive
coding passes, and the exact distortion values are needed, because they
are stored for each coding pass and minimum and maximum rate /
distortion slope on each coding pass (tile->minrd, maxrd) is computed.
Maybe i've understood you wrong, but i don't see where i could make such
changes.

-- 
Best regards,
Kamil Nowosad



More information about the FFmpeg-soc mailing list