[FFmpeg-devel] [RFC] AAC encoder optimizations

Michael Niedermayer michaelni
Sun Sep 14 18:13:46 CEST 2008


On Sun, Sep 14, 2008 at 05:09:56PM +0300, Kostya wrote:
> On Sun, Sep 14, 2008 at 02:34:09PM +0200, Michael Niedermayer wrote:
> > On Sun, Sep 14, 2008 at 08:34:11AM +0300, Kostya wrote:
[...]
> > > Oh, and headphones are one of the
> > > cheapest there.
> > 
> > Once you cant find a difference anymore, it might be a good idea that someone
> > would donates some more expensive headphones to you.
> 
> Gabriel has done that already, but I don't dare to take them to work
> and encoding at home is a waaay slower. 

what about working remotely over ssh with some more powerfull computer?


[...]
> > [...]
> > > > > 
> > > > > /**
> > > > >  * structure used in optimal codebook search
> > > > >  */
> > > > > typedef struct BandCodingPath {
> > > > >     int prev_idx; ///< pointer to the previous path point
> > > > >     int codebook; ///< codebook for coding band run
> > > > >     float cost;   ///< path cost
> > > > >     int run;
> > > > > } BandCodingPath;
> > > > > 
> > > > > /**
> > > > >  * Encode band info for single window group bands.
> > > > >  */
> > > > > static void encode_window_bands_info(AACEncContext *s, SingleChannelElement *sce,
> > > > >                                      int win, int group_len, const float lambda)
> > > > > {
> > > > >     BandCodingPath path[120][12];
> > > > >     int w, swb, cb, start, start2, size;
> > > > >     int i, j;
> > > > >     const int max_sfb = sce->ics.max_sfb;
> > > > >     const int run_bits = sce->ics.num_windows == 1 ? 5 : 3;
> > > > >     const int run_esc = (1 << run_bits) - 1;
> > > > >     int idx, ppos, count;
> > > > >     int stackrun[120], stackcb[120], stack_len;
> > > > > 
> > > > >     start = win*128;
> > > > >     for(cb = 0; cb < 12; cb++){
> > > > >         path[0][cb].cost = 0.0f;
> > > > >         path[0][cb].prev_idx = -1;
> > > > >         path[0][cb].run = 0;
> > > > >     }
> > > > >     for(swb = 0; swb < max_sfb; swb++){
> > > > >         start2 = start;
> > > > >         size = sce->ics.swb_sizes[swb];
> > > > >         if(sce->zeroes[win*16 + swb]){
> > > > >             for(cb = 0; cb < 12; cb++){
> > > > >                 path[swb+1][cb].prev_idx = cb;
> > > > >                 path[swb+1][cb].cost = path[swb][cb].cost;
> > > > >                 path[swb+1][cb].run = path[swb][cb].run + 1;
> > > > >             }
> > > > >         }else{
> > > > >             float minrd = INFINITY;
> > > > >             int mincb = 0;
> > > > >             for(cb = 0; cb < 12; cb++){
> > > > >                 float rd = 0.0f;
> > > > >                 for(w = 0; w < group_len; w++){
> > > > >                     rd += quantize_band_cost(sce->coeffs + start + w*128, size, sce->sf_idx[(win+w)*16+swb], cb, lambda, minrd);
> > > > >                 }
> > > > >                 path[swb+1][cb].prev_idx = cb;
> > > > >                 path[swb+1][cb].cost = path[swb][cb].cost + rd;
> > > > >                 path[swb+1][cb].run = path[swb][cb].run + 1;
> > > > >                 if(rd < minrd){
> > > > >                     minrd = rd;
> > > > >                     mincb = cb;
> > > > >                 }
> > > > >             }
> > > > >             for(cb = 0; cb < 12; cb++){
> > > > >                 float cost = path[swb][cb].cost + minrd + run_bits + 4;
> > > > >                 if(cost < path[swb+1][cb].cost){
> > > > >                     path[swb+1][cb].prev_idx = mincb;
> > > > >                     path[swb+1][cb].cost = cost;
> > > > >                     path[swb+1][cb].run = 1;
> > > > >                 }
> > > > >             }
> > > > >         }
> > > > >         start += sce->ics.swb_sizes[swb];
> > > > >     }
> > > > 
> > > > Have you tested this code against the previous cb viterbi search?
> > > > do they both find the global optimum? Iam asking because this code looks
> > > > wrong in several ways, but i may be missing something. Also the paper looked
> > > > wrong from what i remember though not in that many ways, the algo described
> > > > there for choosing cbs did seem to ignore the run escapes. This may or may not
> > > > be significant, but requires tests to understand what effect ignoring
> > > > run escapes has, the previous code and what i suggested did not ignore them.
> > > 
> > > Well, run escape can happen only for run lengths >= 31 (with 51 max)
> > > for long window and >=7 of 15 bands for short windows. I will add check for
> > > that and recheck code.
> > 
> > thanks, but note i do not think the run esc is the only bug in this code.
> > the non run case and where the min is added looks quite odd.
> 
> In a nutshell, at each point it just calculates the cost of continuing the
> run sequence and then tests if the switch to the codebook with minimum cost
> results in less rate distortion. 

i know that this is what it is supposed to do, but iam not sure if it does do
that, i mean:

> > > > >             for(cb = 0; cb < 12; cb++){
> > > > >                 float rd = 0.0f;
> > > > >                 for(w = 0; w < group_len; w++){
> > > > >                     rd += quantize_band_cost(sce->coeffs + start + w*128, size, sce->sf_idx[(win+w)*16+swb], cb, lambda, minrd);
> > > > >                 }
> > > > >                 path[swb+1][cb].prev_idx = cb;
> > > > >                 path[swb+1][cb].cost = path[swb][cb].cost + rd;
> > > > >                 path[swb+1][cb].run = path[swb][cb].run + 1;
> > > > >                 if(rd < minrd){
> > > > >                     minrd = rd;
> > > > >                     mincb = cb;
> > > > >                 }
> > > > >             }
> > > > >             for(cb = 0; cb < 12; cb++){
> > > > >                 float cost = path[swb][cb].cost + minrd + run_bits + 4;
> > > > >                 if(cost < path[swb+1][cb].cost){
> > > > >                     path[swb+1][cb].prev_idx = mincb;
> > > > >                     path[swb+1][cb].cost = cost;
> > > > >                     path[swb+1][cb].run = 1;
> > > > >                 }

in this path[swb][cb].cost is the past cost for a cb run, minrd is the
best rd for any next cb with run=1, and that is stored in path[swb+1][cb].cost
but this really appears to be wrong, i mean shouldnt it be

that each current run (path[swb+1][cb].cost) is compared against the
best previous run (path[swb]["best"].cost) + current cb with run=1 ?

though of course it must be noted that either way this is ignoring run
escapes.

[...]
-- 
Michael     GnuPG fingerprint: 9FF2128B147EF6730BADF133611EC787040B0FAB

Observe your enemies, for they first find out your faults. -- Antisthenes
-------------- next part --------------
A non-text attachment was scrubbed...
Name: not available
Type: application/pgp-signature
Size: 189 bytes
Desc: Digital signature
URL: <http://lists.mplayerhq.hu/pipermail/ffmpeg-devel/attachments/20080914/f5b6eb14/attachment.pgp>



More information about the ffmpeg-devel mailing list