[Ffmpeg-devel] [PATCH] ac3 decoder

Michael Niedermayer michaelni
Sun Oct 1 00:18:13 CEST 2006


Hi

On Thu, Sep 28, 2006 at 08:41:01PM +0200, Benjamin Larsson wrote:
> Here is the patch with the ac3 decoder from SoC. Included is the patch
> to enable the sse imdct from Loren Merrit.
[...]
> 
> #define N 512   /* constant for IMDCT Block size */

change the commets to doxygen compatible format


> 
> #define MAX_CHANNELS    6
> #define BLOCK_SIZE    256
> #define AUDIO_BLOCKS    6
> 
> /* Exponent strategies. */
> #define AC3_EXPSTR_D15      0x01
> #define AC3_EXPSTR_D25      0x02
> #define AC3_EXPSTR_D45      0x03
> #define AC3_EXPSTR_REUSE    0x00

this could be a enum maybe
id also suggest to remove the AC3 prefix, its rather redundant for a local
identifer in a ac3 specific file


[...]
> /* Mersenne Twister */
> #define NMT 624
> #define MMT 397
> #define MATRIX_A    0x9908b0df
> #define UPPER_MASK  0x80000000
> #define LOWER_MASK  0x7fffffff
> 
> 
> typedef struct {
>     uint32_t mt[NMT];
>     int      mti;
> } dither_state;
> /* Mersenne Twister */

the mersenne twister should be split out of this file and patch


[...]
>     DECLARE_ALIGNED_16(float, window[BLOCK_SIZE]);                  //window coefficients

window is constant, isnt it? if so it should be static and not duplicated in
every context


[...]
> /*********** BEGIN INIT HELPER FUNCTIONS ***********/
> /**
>  * Generate a Kaiser-Bessel Derived Window.
>  */
> static void ac3_window_init(float *window)
> {
>    int i, j;
>    double sum = 0.0, bessel, tmp;
>    double local_window[256];
>    double alpha2 = (5.0 * M_PI / 256.0) * (5.0 * M_PI / 256.0);
> 
>    for (i = 0; i < 256; i++) {
>        tmp = i * (256 - i) * alpha2;
>        bessel = 1.0;
>        for (j = 100; j > 0; j--) /* defaul to 100 iterations */
>            bessel = bessel * tmp / (j * j) + 1;
>        sum += bessel;
>        local_window[i] = sum;
>    }
> 
>    sum++;
>    for (i = 0; i < 256; i++)
>        window[i] = sqrt(local_window[i] / sum);
> }

figure out what sum is and hardcode it so the local_window and the second
loop can be avoided


> 
> /* 
>  * Generate quantizer tables.
>  */
> static void generate_quantizers_table(int16_t quantizers[], int level, int length)
> {
>     int i;
> 
>     for (i = 0; i < length; i++)
>         quantizers[i] = ((2 * i - level + 1) << 15) / level;
> }
> 
> static void generate_quantizers_table_1(int16_t quantizers[], int level, int length1, int length2, int size)
> {
>     int i, j;
>     int16_t v;
> 
>     for (i = 0; i < length1; i++) {
>         v = ((2 * i - level + 1) << 15) / level;
>         for (j = 0; j < length2; j++) 
>             quantizers[i * length2 + j] = v;
>     }
> 
>     for (i = length1 * length2; i < size; i++)
>         quantizers[i] = 0;
> }

why is v not an int?
and generate_quantizers_table() seems just a redundant special case of this


> 
> static void generate_quantizers_table_2(int16_t quantizers[], int level, int length1, int length2, int size)
> {
>     int i, j;
>     int16_t v;
> 
>     for (i = 0; i < length1; i++) {
>         v = ((2 * (i % level) - level + 1) << 15) / level;
>         for (j = 0; j < length2; j++) 
>             quantizers[i * length2 + j] = v;
>     }
> 
>     for (i = length1 * length2; i < size; i++)
>         quantizers[i] = 0;
> 
> }

this should be merged with generate_quantizers_table_1()
i also think all the = 0 stuff at the end is unneeded, isnt the memory
memset() to 0 somewhere anyway?


[...]
>     /* Exponent Decoding Tables */
>     for (i = 0; i < 5; i++) {
>         v = i - 2;
>         for (j = 0; j < 25; j++) 
>             exp_1[i * 25 + j] = v;
>     }
> 
>     for (i = 0; i < 25; i++) {
>         v = (i % 5) - 2;
>         for (j = 0; j < 5; j++) 
>             exp_2[i * 5 + j] = v;
>     }
> 
>     for (i = 0; i < 25; i++) {
>         v = -2; 
>         for (j = 0; j < 5; j++) 
>             exp_3[i * 5 + j] = v++;
>     }

the 3 loops can be merged, this is just init code and not speed critical


[...]
> /* Synchronize to ac3 bitstream.
>  * This function searches for the syncword '0xb77'.
>  *
>  * @param buf Pointer to "probable" ac3 bitstream buffer
>  * @param buf_size Size of buffer
>  * @return Returns the position where syncword is found, -1 if no syncword is found
>  */

doxygen comments start with /** or various other ones but normal
/* isnt parsed i think


[...]
> static int ac3_parse_sync_info(AC3DecodeContext *ctx)
> {
>     GetBitContext *gb = &ctx->gb;
>     int frmsizecod, bsid;
> 
>     skip_bits(gb, 16); //skip the sync_word, sync_info->sync_word = get_bits(gb, 16);
>     ctx->crc1 = get_bits(gb, 16);
>     ctx->fscod = get_bits(gb, 2);
>     if (ctx->fscod == 0x03)
>         return 0;
>     frmsizecod = get_bits(gb, 6);
>     if (frmsizecod >= 38)
>         return 0;

id suggest to return negative values for errors, for consistency with the
rest of lavc


[...]
>     switch (ctx->fscod) {
>         case 0x00:
>             ctx->frame_size = 4 * ctx->bit_rate;
>             return ctx->frame_size;
>         case 0x01:
>             ctx->frame_size = 2 * (320 * ctx->bit_rate / 147 + (frmsizecod & 1));
>             return ctx->frame_size;
>         case 0x02:
>             ctx->frame_size =  6 * ctx->bit_rate;
>             return ctx->frame_size;
>     }
> 
>     /* never reached */
>     return 0;

the return ctx->frame_size; in the switch can be factored out


[...]
>         i = get_bits(gb, 6); //additional bsi length
>         do {
>             skip_bits(gb, 8);
>         } while(i--);

skip_bits_long(gb, 8*i);


[...]
>             if (deltba[seg] >= 4)
>                 delta = (deltba[seg] - 3) << 7;
>             else
>                 delta = (deltba[seg] - 4) << 7;

maybe change to
delta = (deltba[seg] - 3 - (deltba[seg] < 4)) << 7;


>             for (k = 0; k < deltlen[seg]; k++) {
>                 mask[band] += delta;
>                 band++;
>             }
>         }
>     }
> 
>     /*compute the bit allocation */
>     i = start;
>     j = masktab[start];
>     do {
>         lastbin = FFMIN((bndtab[j] + bndsz[j]), end);

superfluous () and this isnt the only one, not that i suggest to remove
every () which can be removed but this one here and a few others dont
help readability at all ...


>         mask[j] -= snroffset;
>         mask[j] -= floor;
>         if (mask[j] < 0)
>             mask[j] = 0;
>         mask[j] &= 0x1fe0;
>         mask[j] += floor;
>         for (k = i; k < lastbin; k++) {
>             address = (psd[i] - mask[j]) >> 5;
>             address = FFMIN(63, (FFMAX(0, address)));

clip()


[...]
>     if ((ctx->csnroffst) || (ctx->cplinu && ctx->cplfsnroffst) ||
>             (ctx->lfeon && ctx->lfefsnroffst))

if(   ctx->csnroffst
   ||(ctx->cplinu && ctx->cplfsnroffst)
   ||(ctx->lfeon  && ctx->lfefsnroffst))

is IMHO more readable 


[...]
> static int get_transform_coeffs_cpling(AC3DecodeContext *ctx, mant_groups *m)
> {
>     GetBitContext *gb = &ctx->gb;
>     int ch, start, end, cplbndstrc, bnd, gcode, tbap;
>     float cplcos[5], cplcoeff;
>     uint8_t *exps = ctx->dcplexps;
>     uint8_t *bap = ctx->cplbap;
> 
>     cplbndstrc = ctx->cplbndstrc;
>     start = ctx->cplstrtmant;
>     bnd = 0;
> 
>     while (start < ctx->cplendmant) {
>         end = start + 12;
>         while (cplbndstrc & 1) {
>             end += 12;
>             cplbndstrc >>= 1;
>         }
>         cplbndstrc >>= 1;
>         for (ch = 0; ch < ctx->nfchans; ch++) 
>             cplcos[ch] = ctx->chcoeffs[ch] * ctx->cplco[ch][bnd];
>         bnd++;
> 
>         while (start < end) {
>             tbap = bap[start];
>             switch(tbap) {
>                 case 0:
>                     for (ch = 0; ch < ctx->nfchans; ch++)
>                         if (((ctx->chincpl) >> ch) & 1) {
>                             if ((ctx->dithflag >> ch) & 1) {
>                                 TRANSFORM_COEFF(cplcoeff, dither_int16(&ctx->dith_state), exps[start], scale_factors);
>                                 ctx->transform_coeffs[ch + 1][start] = cplcoeff * cplcos[ch] * LEVEL_MINUS_3DB;
>                             } else 
>                                 ctx->transform_coeffs[ch + 1][start] = 0;
>                         }
>                     start++;
>                     continue;
>                 case 1:
>                     if (m->l3ptr > 2) {
>                         gcode = get_bits(gb, 5);
>                         m->l3_quantizers[0] = l3_quantizers_1[gcode];
>                         m->l3_quantizers[1] = l3_quantizers_2[gcode];
>                         m->l3_quantizers[2] = l3_quantizers_3[gcode];
>                         m->l3ptr = 0;
>                     }
>                     TRANSFORM_COEFF(cplcoeff, m->l3_quantizers[m->l3ptr++], exps[start], scale_factors);
>                     break;
> 
>                 case 2:
>                     if (m->l5ptr > 2) {
>                         gcode = get_bits(gb, 7);
>                         m->l5_quantizers[0] = l5_quantizers_1[gcode];
>                         m->l5_quantizers[1] = l5_quantizers_2[gcode];
>                         m->l5_quantizers[2] = l5_quantizers_3[gcode];
>                         m->l5ptr = 0;
>                     }
>                     TRANSFORM_COEFF(cplcoeff, m->l5_quantizers[m->l5ptr++], exps[start], scale_factors);
>                     break;
> 
>                 case 3:
>                     TRANSFORM_COEFF(cplcoeff, l7_quantizers[get_bits(gb, 3)], exps[start], scale_factors);
>                     break;
> 
>                 case 4:
>                     if (m->l11ptr > 1) {
>                         gcode = get_bits(gb, 7);
>                         m->l11_quantizers[0] = l11_quantizers_1[gcode];
>                         m->l11_quantizers[1] = l11_quantizers_2[gcode];
>                         m->l11ptr = 0;
>                     }
>                     TRANSFORM_COEFF(cplcoeff, m->l11_quantizers[m->l11ptr++], exps[start], scale_factors);
>                     break;
> 
>                 case 5:
>                     TRANSFORM_COEFF(cplcoeff, l15_quantizers[get_bits(gb, 4)], exps[start], scale_factors);
>                     break;
> 
>                 default:
>                     TRANSFORM_COEFF(cplcoeff, get_sbits(gb, qntztab[tbap]) << (16 - qntztab[tbap]),
>                             exps[start], scale_factors);
>             }
>             for (ch = 0; ch < ctx->nfchans; ch++)
>                 if ((ctx->chincpl >> ch) & 1) 
>                     ctx->transform_coeffs[ch + 1][start] = cplcoeff * cplcos[ch];
>             start++;
>         }
>     }
> 
>     return 0;
> }
> 
> /* Get the transform coefficients for particular channel */
> static int get_transform_coeffs_ch(AC3DecodeContext *ctx, int ch_index, mant_groups *m)
> {
>     GetBitContext *gb = &ctx->gb;
>     int i, gcode, tbap, dithflag, end;
>     uint8_t *exps;
>     uint8_t *bap;
>     float *coeffs;
>     float factors[25];
> 
>     for (i = 0; i < 25; i++) 
>         factors[i] = scale_factors[i] * ctx->chcoeffs[ch_index];
> 
>     if (ch_index != -1) { /* fbw channels */
>         dithflag = (ctx->dithflag >> ch_index) & 1;
>         exps = ctx->dexps[ch_index];
>         bap = ctx->bap[ch_index];
>         coeffs = ctx->transform_coeffs[ch_index + 1];
>         end = ctx->endmant[ch_index];
>     } else if (ch_index == -1) {
>         dithflag = 0;
>         exps = ctx->dlfeexps;
>         bap = ctx->lfebap;
>         coeffs = ctx->transform_coeffs[0];
>         end = 7;
>     }
> 
> 
>     for (i = 0; i < end; i++) {
>         tbap = bap[i];
>         switch (tbap) {
>             case 0:
>                 if (!dithflag) {
>                     coeffs[i] = 0;
>                     continue;
>                 }
>                 else {
>                     TRANSFORM_COEFF(coeffs[i], dither_int16(&ctx->dith_state), exps[i], factors);
>                     coeffs[i] *= LEVEL_MINUS_3DB;
>                     continue;
>                 }
> 
>             case 1:
>                 if (m->l3ptr > 2) {
>                     gcode = get_bits(gb, 5);
>                     m->l3_quantizers[0] = l3_quantizers_1[gcode];
>                     m->l3_quantizers[1] = l3_quantizers_2[gcode];
>                     m->l3_quantizers[2] = l3_quantizers_3[gcode];
>                     m->l3ptr = 0;
>                 }
>                 TRANSFORM_COEFF(coeffs[i], m->l3_quantizers[m->l3ptr++], exps[i], factors);
>                 continue;
> 
>             case 2:
>                 if (m->l5ptr > 2) {
>                     gcode = get_bits(gb, 7);
>                     m->l5_quantizers[0] = l5_quantizers_1[gcode];
>                     m->l5_quantizers[1] = l5_quantizers_2[gcode];
>                     m->l5_quantizers[2] = l5_quantizers_3[gcode];
>                     m->l5ptr = 0;
>                 }
>                 TRANSFORM_COEFF(coeffs[i], m->l5_quantizers[m->l5ptr++], exps[i], factors);
>                 continue;
> 
>             case 3:
>                 TRANSFORM_COEFF(coeffs[i], l7_quantizers[get_bits(gb, 3)], exps[i], factors);
>                 continue;
> 
>             case 4:
>                 if (m->l11ptr > 1) {
>                     gcode = get_bits(gb, 7);
>                     m->l11_quantizers[0] = l11_quantizers_1[gcode];
>                     m->l11_quantizers[1] = l11_quantizers_2[gcode];
>                     m->l11ptr = 0;
>                 }
>                 TRANSFORM_COEFF(coeffs[i], m->l11_quantizers[m->l11ptr++], exps[i], factors);
>                 continue;
> 
>             case 5:
>                 TRANSFORM_COEFF(coeffs[i], l15_quantizers[get_bits(gb, 4)], exps[i], factors);
>                 continue;
> 
>             default:
>                 TRANSFORM_COEFF(coeffs[i], get_sbits(gb, qntztab[tbap]) << (16 - qntztab[tbap]), exps[i], factors);
>                 continue;
>         }
>     }
> 
>     return 0;
> }

this looks fairly similar to get_transform_coeffs_cpling() shouldnt that 
be merged ...


[...]
>         do 
>             ctx->transform_coeffs[i + 1][end] = 0;
>         while(++end < 256);

memset(0)


>     }
>     if (ctx->lfeon) {
>         if (get_transform_coeffs_ch(ctx, -1, &m))
>                 return -1;
>         for (i = 7; i < 256; i++) {
>             ctx->transform_coeffs[0][i] = 0;
>         }

memset(0)


[...]
> static void do_rematrixing(AC3DecodeContext *ctx)
> {
>     int bnd1 = 13, bnd2 = 25, bnd3 = 37, bnd4 = 61;
>     int end, bndend;
> 
>     end = FFMIN(ctx->endmant[0], ctx->endmant[1]);
> 
>     if (ctx->rematflg & 1) 
>         do_rematrixing1(ctx, bnd1, bnd2);
> 
>     if (ctx->rematflg & 2) 
>         do_rematrixing1(ctx, bnd2, bnd3);
> 
>     bndend = bnd4;
>     if (bndend > end) {
>         bndend = end;
>         if (ctx->rematflg & 4) 
>             do_rematrixing1(ctx, bnd3, bndend);
>     } else {
>         if (ctx->rematflg & 4) 
>             do_rematrixing1(ctx, bnd3, bnd4);
>         if (ctx->rematflg & 8) 
>             do_rematrixing1(ctx, bnd4, end);
>     }

the following is simpler

bnd[4]= FFMIN(ctx->endmant[0], ctx->endmant[1]);
bnd[3]= FFMIN(bnd[3], bnd[4]);
for(i=0; i<4; i++){
    if(ctx->rematflg & (1<<i))
        do_rematrixing1(ctx, bnd[i], bnd[i+1]);
}


[...]
> /* This function sets the normalized channel coefficients.
>  * Transform coefficients are multipllied by the channel
>  * coefficients to get normalized transform coefficients.
>  */
> static void get_downmix_coeffs(AC3DecodeContext *ctx)
> {
>     int from = ctx->acmod;
>     int to = ctx->blkoutput;
>     float clev = clevs[ctx->cmixlev];
>     float slev = slevs[ctx->surmixlev];
>     float nf = 1.0; //normalization factor for downmix coeffs
>     int i;
> 
>     if (!ctx->acmod) {
>         ctx->chcoeffs[0] = 2 * ctx->dynrng;
>         ctx->chcoeffs[1] = 2 * ctx->dynrng2;
>     } else {
>         for (i = 0; i < ctx->nfchans; i++)
>             ctx->chcoeffs[i] = 2 * ctx->dynrng;
>     }
> 
>     if (to == AC3_OUTPUT_UNMODIFIED)
>         return;
> 
>     switch (from) {
>         case AC3_INPUT_DUALMONO:
>             switch (to) {
>                 case AC3_OUTPUT_MONO:
>                 case AC3_OUTPUT_STEREO: /* We Assume that sum of both mono channels is requested */
>                     nf = 0.5;
>                     ctx->chcoeffs[0] *= nf;
>                     ctx->chcoeffs[1] *= nf;
>                     break;
>             }
>             break;
>         case AC3_INPUT_MONO:
>             switch (to) {
>                 case AC3_OUTPUT_STEREO:
>                     nf = LEVEL_MINUS_3DB;
>                     ctx->chcoeffs[0] *= nf;
>                     break;
>             }
>             break;
>         case AC3_INPUT_STEREO:
>             switch (to) {
>                 case AC3_OUTPUT_MONO:
>                     nf = LEVEL_MINUS_3DB;
>                     ctx->chcoeffs[0] *= nf;
>                     ctx->chcoeffs[1] *= nf;
>                     break;
>             }
>             break;
>         case AC3_INPUT_3F:
>             switch (to) {
>                 case AC3_OUTPUT_MONO:
>                     nf = LEVEL_MINUS_3DB / (1.0 + clev);
>                     ctx->chcoeffs[0] *= (nf * LEVEL_MINUS_3DB);
>                     ctx->chcoeffs[2] *= (nf * LEVEL_MINUS_3DB);
>                     ctx->chcoeffs[1] *= ((nf * clev * LEVEL_MINUS_3DB) / 2.0);
>                     break;
>                 case AC3_OUTPUT_STEREO:
>                     nf = 1.0 / (1.0 + clev);
>                     ctx->chcoeffs[0] *= nf;
>                     ctx->chcoeffs[2] *= nf;
>                     ctx->chcoeffs[1] *= (nf * clev);
>                     break;
>             }
>             break;
>         case AC3_INPUT_2F_1R:
>             switch (to) {
>                 case AC3_OUTPUT_MONO:
>                     nf = 2.0 * LEVEL_MINUS_3DB / (2.0 + slev);
>                     ctx->chcoeffs[0] *= (nf * LEVEL_MINUS_3DB);
>                     ctx->chcoeffs[1] *= (nf * LEVEL_MINUS_3DB);
>                     ctx->chcoeffs[2] *= (nf * slev * LEVEL_MINUS_3DB);
>                     break;
>                 case AC3_OUTPUT_STEREO:
>                     nf = 1.0 / (1.0 + (slev * LEVEL_MINUS_3DB));
>                     ctx->chcoeffs[0] *= nf;
>                     ctx->chcoeffs[1] *= nf;
>                     ctx->chcoeffs[2] *= (nf * slev * LEVEL_MINUS_3DB);
>                     break;
>                 case AC3_OUTPUT_DOLBY:
>                     nf = 1.0 / (1.0 + LEVEL_MINUS_3DB);
>                     ctx->chcoeffs[0] *= nf;
>                     ctx->chcoeffs[1] *= nf;
>                     ctx->chcoeffs[2] *= (nf * LEVEL_MINUS_3DB);
>                     break;
>             }
>             break;
>         case AC3_INPUT_3F_1R:
>             switch (to) {
>                 case AC3_OUTPUT_MONO:
>                     nf = LEVEL_MINUS_3DB / (1.0 + clev + (slev / 2.0));
>                     ctx->chcoeffs[0] *= (nf * LEVEL_MINUS_3DB);
>                     ctx->chcoeffs[2] *= (nf * LEVEL_MINUS_3DB);
>                     ctx->chcoeffs[1] *= (nf * clev * LEVEL_PLUS_3DB);
>                     ctx->chcoeffs[3] *= (nf * slev * LEVEL_MINUS_3DB);
>                     break;
>                 case AC3_OUTPUT_STEREO:
>                     nf = 1.0 / (1.0 + clev + (slev * LEVEL_MINUS_3DB));
>                     ctx->chcoeffs[0] *= nf;
>                     ctx->chcoeffs[2] *= nf;
>                     ctx->chcoeffs[1] *= (nf * clev);
>                     ctx->chcoeffs[3] *= (nf * slev * LEVEL_MINUS_3DB);
>                     break;
>                 case AC3_OUTPUT_DOLBY:
>                     nf = 1.0 / (1.0 + (2.0 * LEVEL_MINUS_3DB));
>                     ctx->chcoeffs[0] *= nf;
>                     ctx->chcoeffs[1] *= nf;
>                     ctx->chcoeffs[1] *= (nf * LEVEL_MINUS_3DB);
>                     ctx->chcoeffs[3] *= (nf * LEVEL_MINUS_3DB);
>                     break;
>             }
>             break;
>         case AC3_INPUT_2F_2R:
>             switch (to) {
>                 case AC3_OUTPUT_MONO:
>                     nf = LEVEL_MINUS_3DB / (1.0 + slev);
>                     ctx->chcoeffs[0] *= (nf * LEVEL_MINUS_3DB);
>                     ctx->chcoeffs[1] *= (nf * LEVEL_MINUS_3DB);
>                     ctx->chcoeffs[2] *= (nf * slev * LEVEL_MINUS_3DB);
>                     ctx->chcoeffs[3] *= (nf * slev * LEVEL_MINUS_3DB);
>                     break;
>                 case AC3_OUTPUT_STEREO:
>                     nf = 1.0 / (1.0 + slev);
>                     ctx->chcoeffs[0] *= nf;
>                     ctx->chcoeffs[1] *= nf;
>                     ctx->chcoeffs[2] *= (nf * slev);
>                     ctx->chcoeffs[3] *= (nf * slev);
>                     break;
>                 case AC3_OUTPUT_DOLBY:
>                     nf = 1.0 / (1.0 + (2.0 * LEVEL_MINUS_3DB));
>                     ctx->chcoeffs[0] *= nf;
>                     ctx->chcoeffs[1] *= nf;
>                     ctx->chcoeffs[2] *= (nf * LEVEL_MINUS_3DB);
>                     ctx->chcoeffs[3] *= (nf * LEVEL_MINUS_3DB);
>                     break;
>             }
>             break;
>         case AC3_INPUT_3F_2R:
>             switch (to) {
>                 case AC3_OUTPUT_MONO:
>                     nf = LEVEL_MINUS_3DB / (1.0 + clev + slev);
>                     ctx->chcoeffs[0] *= (nf * LEVEL_MINUS_3DB);
>                     ctx->chcoeffs[2] *= (nf * LEVEL_MINUS_3DB);
>                     ctx->chcoeffs[1] *= (nf * clev * LEVEL_PLUS_3DB);
>                     ctx->chcoeffs[3] *= (nf * slev * LEVEL_MINUS_3DB);
>                     ctx->chcoeffs[4] *= (nf * slev * LEVEL_MINUS_3DB);
>                     break;
>                 case AC3_OUTPUT_STEREO:
>                     nf = 1.0 / (1.0 + clev + slev);
>                     ctx->chcoeffs[0] *= nf;
>                     ctx->chcoeffs[2] *= nf;
>                     ctx->chcoeffs[1] *= (nf * clev);
>                     ctx->chcoeffs[3] *= (nf * slev);
>                     ctx->chcoeffs[4] *= (nf * slev);
>                     break;
>                 case AC3_OUTPUT_DOLBY:
>                     nf = 1.0 / (1.0 + (3.0 * LEVEL_MINUS_3DB));
>                     ctx->chcoeffs[0] *= nf;
>                     ctx->chcoeffs[1] *= nf;
>                     ctx->chcoeffs[1] *= (nf * LEVEL_MINUS_3DB);

typo?


>                     ctx->chcoeffs[3] *= (nf * LEVEL_MINUS_3DB);
>                     ctx->chcoeffs[4] *= (nf * LEVEL_MINUS_3DB);
>                     break;
>             }
>             break;
>     }

and please simplify this mess


[...]
> 
> /* Downmix the output.
>  * This function downmixes the output when the number of input
>  * channels is not equal to the number of output channels requested.
>  */
> static void do_downmix(AC3DecodeContext *ctx)
> {
>     int from = ctx->acmod;
>     int to = ctx->blkoutput;
> 
>     if (to == AC3_OUTPUT_UNMODIFIED)
>         return;
> 
>     switch (from) {
>         case AC3_INPUT_DUALMONO:
>             switch (to) {
>                 case AC3_OUTPUT_MONO:
>                     mix_dualmono_to_mono(ctx);
>                     break;
>                 case AC3_OUTPUT_STEREO: /* We assume that sum of both mono channels is requested */
>                     mix_dualmono_to_stereo(ctx);
>                     break;
>             }
>             break;
>         case AC3_INPUT_MONO:
>             switch (to) {
>                 case AC3_OUTPUT_STEREO:
>                     upmix_mono_to_stereo(ctx);
>                     break;
>             }
>             break;
>         case AC3_INPUT_STEREO:
>             switch (to) {
>                 case AC3_OUTPUT_MONO:
>                     mix_stereo_to_mono(ctx);
>                     break;
>             }
>             break;
>         case AC3_INPUT_3F:
>             switch (to) {
>                 case AC3_OUTPUT_MONO:
>                     mix_3f_to_mono(ctx);
>                     break;
>                 case AC3_OUTPUT_STEREO:
>                     mix_3f_to_stereo(ctx);
>                     break;
>             }
>             break;
>         case AC3_INPUT_2F_1R:
>             switch (to) {
>                 case AC3_OUTPUT_MONO:
>                     mix_2f_1r_to_mono(ctx);
>                     break;
>                 case AC3_OUTPUT_STEREO:
>                     mix_2f_1r_to_stereo(ctx);
>                     break;
>                 case AC3_OUTPUT_DOLBY:
>                     mix_2f_1r_to_dolby(ctx);
>                     break;
>             }
>             break;
>         case AC3_INPUT_3F_1R:
>             switch (to) {
>                 case AC3_OUTPUT_MONO:
>                     mix_3f_1r_to_mono(ctx);
>                     break;
>                 case AC3_OUTPUT_STEREO:
>                     mix_3f_1r_to_stereo(ctx);
>                     break;
>                 case AC3_OUTPUT_DOLBY:
>                     mix_3f_1r_to_dolby(ctx);
>                     break;
>             }
>             break;
>         case AC3_INPUT_2F_2R:
>             switch (to) {
>                 case AC3_OUTPUT_MONO:
>                     mix_2f_2r_to_mono(ctx);
>                     break;
>                 case AC3_OUTPUT_STEREO:
>                     mix_2f_2r_to_stereo(ctx);
>                     break;
>                 case AC3_OUTPUT_DOLBY:
>                     mix_2f_2r_to_dolby(ctx);
>                     break;
>             }
>             break;
>         case AC3_INPUT_3F_2R:
>             switch (to) {
>                 case AC3_OUTPUT_MONO:
>                     mix_3f_2r_to_mono(ctx);
>                     break;
>                 case AC3_OUTPUT_STEREO:
>                     mix_3f_2r_to_stereo(ctx);
>                     break;
>                 case AC3_OUTPUT_DOLBY:
>                     mix_3f_2r_to_dolby(ctx);
>                     break;
>             }
>             break;
>     }

an array of function pointers, initalizd with
[AC3_INPUT_... + X*AC3_OUTPUT_...]= ...,
...
seems much simpler ... (and eventually this can b changed to offsets
into dspcontext)


[...]

>     if (get_bits1(gb)) { /* dynamic range */
>         dynrng = get_sbits(gb, 8);
>         ctx->dynrng = ((((dynrng & 0x1f) | 0x20) << 13) * scale_factors[3 - (dynrng >> 5)]);
>     }
> 
>     if (acmod == 0x00 && get_bits1(gb)) { /* dynamic range 1+1 mode */ 
>         dynrng = get_sbits(gb, 8);
>         ctx->dynrng2 = ((((dynrng & 0x1f) | 0x20) << 13) * scale_factors[3 - (dynrng >> 5)]);
>     }

maybe change to

for(i=0; i<=!acmod; i++){
    if(get_bits1(gb)){
        dynrng = get_sbits(gb, 8);
        ctx->dynrng[i] = ((((dynrng & 0x1f) | 0x20) << 13) * scale_factors[3 - (dynrng >> 5)]);
    }
}


> 
>     get_downmix_coeffs(ctx);
> 
>     if (get_bits1(gb)) { /* coupling strategy */
>         ctx->cplinu = get_bits1(gb);
>         ctx->cplbndstrc = 0;
>         ctx->chincpl = 0;
>         if (ctx->cplinu) { /* coupling in use */
>             for (i = 0; i < nfchans; i++)
>                 ctx->chincpl |= get_bits1(gb) << i;

reading nfchans bits in reverse is done several times either
A. change the thing so a simple get_bits(gb, nfchans) can be used
B. add a function / macro which does this reverse reading


[...]
> static inline int16_t convert(int32_t i)
> {
>     if (i > 0x43c07fff)
>         return 32767;
>     else if (i <= 0x43bf8000)
>         return -32768;
>     else
>         return (i - 0x43c00000);
> }

this should be replaced by float_to_int16 from dspcontext


> 
> static int frame_count = 0;

uhm ...


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

In the past you could go to a library and read, borrow or copy any book
Today you'd get arrested for mere telling someone where the library is




More information about the ffmpeg-devel mailing list