[FFmpeg-cvslog] r9659 - trunk/libavcodec/ac3dec.c

jbr subversion
Sat Jul 14 17:58:42 CEST 2007


Author: jbr
Date: Sat Jul 14 17:58:42 2007
New Revision: 9659

Log:
AC-3 decoder, soc revision 48, Aug 16 11:27:49 2006 UTC by cloud9
I realized that the bug was not in the imdct routine but in the
get_transform_coeffs.
Fixed it.
Code now uses the ffmpeg's imdct routines.
All the mplayer's ac3 samples are decoded
successfully.
Also improved downmixing.
Now all the downmixing coeffcients for channels
are normalized such that the sum of coefficients
used to construct the output for single channel
never exceeds 1.0.

Modified:
   trunk/libavcodec/ac3dec.c

Modified: trunk/libavcodec/ac3dec.c
==============================================================================
--- trunk/libavcodec/ac3dec.c	(original)
+++ trunk/libavcodec/ac3dec.c	Sat Jul 14 17:58:42 2007
@@ -34,6 +34,7 @@
 #include "avutil.h"
 #include "common.h"
 #include "math.h"
+#include "crc.h"
 
 #define N 512   /* constant for IMDCT Block size */
 
@@ -158,8 +159,8 @@ typedef struct {
     DECLARE_ALIGNED_16(float, transform_coeffs[MAX_CHANNELS][BLOCK_SIZE]);
 
     /* For IMDCT. */
-    FFTContext fft_64;  //N/8 point IFFT context
-    FFTContext fft_128; //N/4 point IFFT context
+    MDCTContext imdct_512;  //N/8 point IFFT context
+    MDCTContext imdct_256;  //N/4 point IFFT context
     DECLARE_ALIGNED_16(float, output[MAX_CHANNELS][BLOCK_SIZE]);
     DECLARE_ALIGNED_16(float, delay[MAX_CHANNELS][BLOCK_SIZE]);
     DECLARE_ALIGNED_16(float, tmp_imdct[BLOCK_SIZE]);
@@ -398,8 +399,8 @@ static int ac3_decode_init(AVCodecContex
     AC3DecodeContext *ctx = avctx->priv_data;
 
     ac3_tables_init();
-    ff_fft_init(&ctx->fft_64, 6, 1);
-    ff_fft_init(&ctx->fft_128, 7, 1);
+    ff_mdct_init(&ctx->imdct_256, 8, 1);
+    ff_mdct_init(&ctx->imdct_512, 9, 1);
     dither_seed(&ctx->dith_state, 0);
 
     return 0;
@@ -838,9 +839,9 @@ static int get_transform_coeffs_cpling(A
                 case 0:
                     for (ch = 0; ch < ctx->nfchans; ch++)
                         if (((ctx->chincpl) >> ch) & 1) {
-                            if (!(((ctx->dithflag) >> 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];
+                                ctx->transform_coeffs[ch + 1][start] = cplcoeff * cplcos[ch] * LEVEL_MINUS_3DB;
                             } else
                                 ctx->transform_coeffs[ch + 1][start] = 0;
                         }
@@ -887,7 +888,7 @@ static int get_transform_coeffs_cpling(A
                     break;
 
                 default:
-                    TRANSFORM_COEFF(cplcoeff, get_bits(gb, qntztab[tbap]) << (16 - qntztab[tbap]),
+                    TRANSFORM_COEFF(cplcoeff, get_sbits(gb, qntztab[tbap]) << (16 - qntztab[tbap]),
                             exps[start], scale_factors);
             }
             for (ch = 0; ch < ctx->nfchans; ch++)
@@ -932,13 +933,13 @@ static int get_transform_coeffs_ch(AC3De
         tbap = bap[i];
         switch (tbap) {
             case 0:
-                if (dithflag) {
+                if (!dithflag) {
                     coeffs[i] = 0;
                     continue;
                 }
                 else {
                     TRANSFORM_COEFF(coeffs[i], dither_int16(&ctx->dith_state), exps[i], factors);
-                    coeffs[i] *= LEVEL_PLUS_3DB;
+                    coeffs[i] *= LEVEL_MINUS_3DB;
                     continue;
                 }
 
@@ -983,7 +984,7 @@ static int get_transform_coeffs_ch(AC3De
                 continue;
 
             default:
-                TRANSFORM_COEFF(coeffs[i], get_bits(gb, qntztab[tbap]) << (16 - qntztab[tbap]), exps[i], factors);
+                TRANSFORM_COEFF(coeffs[i], get_sbits(gb, qntztab[tbap]) << (16 - qntztab[tbap]), exps[i], factors);
                 continue;
         }
     }
@@ -1075,6 +1076,7 @@ static void get_downmix_coeffs(AC3Decode
     int to = ctx->blkoutput;
     float clev = clevs[ctx->cmixlev];
     float slev = slevs[ctx->surmixlev];
+    float nf = 1.0; //normalization factor for downmix coeffs
 
     if (to == AC3_OUTPUT_UNMODIFIED)
         return;
@@ -1084,107 +1086,142 @@ static void get_downmix_coeffs(AC3Decode
             switch (to) {
                 case AC3_OUTPUT_MONO:
                 case AC3_OUTPUT_STEREO: /* We Assume that sum of both mono channels is requested */
-                    ctx->chcoeffs[0] *= LEVEL_MINUS_6DB;
-                    ctx->chcoeffs[1] *= LEVEL_MINUS_6DB;
+                    nf = 0.5;
+                    ctx->chcoeffs[0] *= nf;
+                    ctx->chcoeffs[1] *= nf;
                     break;
             }
             break;
         case AC3_INPUT_MONO:
             switch (to) {
                 case AC3_OUTPUT_STEREO:
-                    ctx->chcoeffs[0] *= LEVEL_MINUS_3DB;
+                    nf = LEVEL_MINUS_3DB;
+                    ctx->chcoeffs[0] *= nf;
                     break;
             }
             break;
         case AC3_INPUT_STEREO:
             switch (to) {
                 case AC3_OUTPUT_MONO:
-                    ctx->chcoeffs[0] *= LEVEL_MINUS_3DB;
-                    ctx->chcoeffs[1] *= LEVEL_MINUS_3DB;
+                    nf = LEVEL_MINUS_3DB;
+                    ctx->chcoeffs[0] *= nf;
+                    ctx->chcoeffs[1] *= nf;
                     break;
             }
             break;
         case AC3_INPUT_3F:
             switch (to) {
                 case AC3_OUTPUT_MONO:
-                    ctx->chcoeffs[0] *= LEVEL_MINUS_3DB;
-                    ctx->chcoeffs[2] *= LEVEL_MINUS_3DB;
-                    ctx->chcoeffs[1] *= (clev * LEVEL_PLUS_3DB);
+                    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:
-                    ctx->chcoeffs[1] *= clev;
+                    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:
-                    ctx->chcoeffs[0] *= LEVEL_MINUS_3DB;
-                    ctx->chcoeffs[1] *= LEVEL_MINUS_3DB;
-                    ctx->chcoeffs[2] *= slev * LEVEL_MINUS_3DB;
+                    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:
-                    ctx->chcoeffs[2] *= slev * LEVEL_MINUS_3DB;
+                    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:
-                    ctx->chcoeffs[2] *= LEVEL_MINUS_3DB;
+                    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:
-                    ctx->chcoeffs[0] *= LEVEL_MINUS_3DB;
-                    ctx->chcoeffs[2] *= LEVEL_MINUS_3DB;
-                    ctx->chcoeffs[1] *= clev * LEVEL_PLUS_3DB;
-                    ctx->chcoeffs[3] *= slev * LEVEL_MINUS_3DB;
+                    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:
-                    ctx->chcoeffs[1] *= clev;
-                    ctx->chcoeffs[3] *= slev * LEVEL_MINUS_3DB;
+                    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:
-                    ctx->chcoeffs[1] *= LEVEL_MINUS_3DB;
-                    ctx->chcoeffs[3] *= LEVEL_MINUS_3DB;
+                    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:
-                    ctx->chcoeffs[0] *= LEVEL_MINUS_3DB;
-                    ctx->chcoeffs[1] *= LEVEL_MINUS_3DB;
-                    ctx->chcoeffs[2] *= slev * LEVEL_MINUS_3DB;
-                    ctx->chcoeffs[3] *= slev * LEVEL_MINUS_3DB;
+                    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:
-                    ctx->chcoeffs[2] *= slev;
-                    ctx->chcoeffs[3] *= slev;
+                    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:
-                    ctx->chcoeffs[2] *= LEVEL_MINUS_3DB;
-                    ctx->chcoeffs[3] *= LEVEL_MINUS_3DB;
+                    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:
-                    ctx->chcoeffs[0] *= LEVEL_MINUS_3DB;
-                    ctx->chcoeffs[2] *= LEVEL_MINUS_3DB;
-                    ctx->chcoeffs[1] *= clev * LEVEL_PLUS_3DB;
-                    ctx->chcoeffs[3] *= slev * LEVEL_MINUS_3DB;
-                    ctx->chcoeffs[4] *= slev * LEVEL_MINUS_3DB;
+                    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:
-                    ctx->chcoeffs[1] *= clev;
-                    ctx->chcoeffs[3] *= slev;
-                    ctx->chcoeffs[4] *= slev;
+                    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:
-                    ctx->chcoeffs[1] *= LEVEL_MINUS_3DB;
-                    ctx->chcoeffs[3] *= LEVEL_MINUS_3DB;
-                    ctx->chcoeffs[4] *= LEVEL_MINUS_3DB;
+                    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);
+                    ctx->chcoeffs[3] *= (nf * LEVEL_MINUS_3DB);
+                    ctx->chcoeffs[4] *= (nf * LEVEL_MINUS_3DB);
                     break;
             }
             break;
@@ -1529,102 +1566,39 @@ static void dump_floats(const char *name
     (pim) = _are * _bim + _aim * _bre;\
 }
 
-static void do_imdct_256(FFTContext *fft_ctx, float *coeffs, float *output,
-        float *delay, float *tmp_imdct, float *tmp_output)
+static void do_imdct_256(AC3DecodeContext *ctx, int chindex)
 {
-    int k, n2, n4, n8;
+    int k;
     float x1[128], x2[128];
-    FFTComplex *z1 = (FFTComplex *)tmp_imdct;
-    FFTComplex *z2 = (FFTComplex *)(tmp_imdct +  128);
-
-    n2 = N / 2;
-    n4 = N / 4;
-    n8 = N / 8;
-
-    for (k = 0; k < n4; k++) {
-        x1[k] = coeffs[2 * k];
-        x2[k] = coeffs[2 * k + 1];
-    }
-
-    /* Pre IFFT Complex Multiply Step. */
-    for (k = 0; k < n8; k++) {
-        CMUL(z1[k].re, z1[k].im, x1[n4 - 2 * k - 1], x1[2 * k], x_cos2[k], x_sin2[k]);
-        CMUL(z2[k].re, z2[k].im, x2[n4 - 2 * k - 1], x2[2 * k], x_cos2[k], x_sin2[k]);
-    }
-
-    /* N/8 pointe complex IFFT. */
-    ff_fft_permute(fft_ctx, z1);
-    ff_fft_calc(fft_ctx, z1);
-    ff_fft_permute(fft_ctx, z2);
-    ff_fft_calc(fft_ctx, z2);
 
-
-    /* Post IFFT Complex Multiply Step. */
-    for (k = 0; k < n8; k++) {
-        CMUL(z1[k].re, z1[k].im, z1[k].re, z1[k].im, x_cos2[k], x_sin2[k]);
-        CMUL(z2[k].re, z2[k].im, z2[k].re, z2[k].im, x_cos2[k], x_sin2[k]);
+    for (k = 0; k < N / 4; k++) {
+        x1[k] = ctx->transform_coeffs[chindex][2 * k];
+        x2[k] = ctx->transform_coeffs[chindex][2 * k + 1];
     }
 
-    /* Windowing and de-interleaving step. */
-    for (k = 0; k < n8; k++) {
-        tmp_output[2 * k] = -z1[k].im * window[2 * k];
-        tmp_output[2 * k + 1] = z1[n8 - k - 1].re * window[2 * k + 1];
-        tmp_output[n4 + 2 * k] = -z1[k].re * window[n4 + 2 * k];
-        tmp_output[n4 + 2 * k + 1] = z1[n8 - k - 1].im * window[n4 + 2 * k + 1];
-        tmp_output[n2 + 2 * k] = -z2[k].re * window[n2 - 2 * k - 1];
-        tmp_output[n2 + 2* k + 1] = z2[n8 - k - 1].im * window[n2 - 2 * k - 2];
-        tmp_output[3 * n4 + 2 * k] = z2[k].im * window[n4 - 2 * k - 1] ;
-        tmp_output[3 * n4 + 2 * k + 1] = -z2[n8 - k - 1].re * window[n4 - 2 * k - 2] ;
-    }
+    ff_imdct_calc(&ctx->imdct_256, ctx->tmp_output, x1, ctx->tmp_imdct);
+    ff_imdct_calc(&ctx->imdct_256, ctx->tmp_output + 256, x2, ctx->tmp_imdct);
 
-    /* Overlap and add step. */
-    for (k = 0; k < n2; k++) {
-        output[k] = 2 * (tmp_output[k] + delay[k]);
-        delay[k] = tmp_output[n2 + k];
+    for (k = 0; k < N / 2; k++) {
+        ctx->output[chindex][k] = ctx->tmp_output[k] * window[k] + ctx->delay[chindex][k];
+        //dump_floats("samples", 10, ctx->output[chindex], 256);
+        ctx->delay[chindex][k] = ctx->tmp_output[N / 2 + k] * window[255 - k];
     }
 }
 
-static void do_imdct_512(FFTContext *fft_ctx, float *coeffs, float *output,
-        float *delay, float *tmp_imdct, float *tmp_output)
+static void do_imdct_512(AC3DecodeContext *ctx, int chindex)
 {
-    int k, n2, n4, n8;
-    FFTComplex *z = (FFTComplex *)tmp_imdct;
-
-    n2 = N / 2;
-    n4 = N / 4;
-    n8 = N / 8;
-
-
-    /* Pre IFFT Complex Multiply Step. */
-    for (k = 0; k < n4; k++)
-        CMUL(z[k].re, z[k].im, coeffs[n2 - 2 * k - 1], coeffs[2 * k], x_cos1[k], x_sin1[k]);
-
-    /* Permutation needed before calling ff_fft_calc. */
-    ff_fft_permute(fft_ctx, z);
-
-    /* N/4 pointe complex IFFT. */
-    ff_fft_calc(fft_ctx, z);
-
-    /* Post IFFT Complex Multiply Step. */
-    for (k = 0; k < n4; k++)
-        CMUL(z[k].re, z[k].im, z[k].re, z[k].im, x_cos1[k], x_sin1[k]);
+    int k;
 
-    /* Windowing and de-interleaving step. */
-    for (k = 0; k < n8; k++) {
-        tmp_output[2 * k] = -z[n8 + k].im * window[2 * k];
-        tmp_output[2 * k + 1] = z[n8 - k - 1].re * window[2 * k + 1];
-        tmp_output[n4 + 2 * k] = -z[k].re * window[n4 + 2 * k];
-        tmp_output[n4 + 2 * k + 1] = z[n4 - k - 1].im * window[n4 + 2 * k + 1];
-        tmp_output[n2 + 2 * k] = -z[n8 + k].re * window[n2 - 2 * k - 1];
-        tmp_output[n2 + 2* k + 1] = z[n8 - k - 1].im * window[n2 - 2 * k - 2];
-        tmp_output[3 * n4 + 2 * k] = z[k].im * window[n4 - 2 * k - 1] ;
-        tmp_output[3 * n4 + 2 * k + 1] = -z[n4 - k - 1].re * window[n4 - 2 * k - 2] ;
-    }
+    ff_imdct_calc(&ctx->imdct_512, ctx->tmp_output,
+            ctx->transform_coeffs[chindex], ctx->tmp_imdct);
+    //ff_imdct_calc_ac3_512(&ctx->imdct_512, ctx->tmp_output, ctx->transform_coeffs[chindex],
+    //        ctx->tmp_imdct, window);
 
-    /* Overlap and add step. */
-    for (k = 0; k < n2; k++) {
-        output[k] = 2 * (tmp_output[k] + delay[k]);
-        delay[k] = tmp_output[n2 + k];
+    for (k = 0; k < N / 2; k++) {
+        ctx->output[chindex][k] = ctx->tmp_output[k] * window[k] + ctx->delay[chindex][k];
+        //dump_floats("samples", 10, ctx->output[chindex], 256);
+        ctx->delay[chindex][k] = ctx->tmp_output[N / 2 + k] * window[255 - k];
     }
 }
 
@@ -1633,18 +1607,13 @@ static inline void do_imdct(AC3DecodeCon
     int i;
 
     if (ctx->blkoutput & AC3_OUTPUT_LFEON) {
-        do_imdct_512(&ctx->fft_128, ctx->transform_coeffs[0], ctx->output[0],
-                ctx->delay[0], ctx->tmp_imdct, ctx->tmp_output);
+        do_imdct_512(ctx, 0);
     }
     for (i = 0; i < ctx->nfchans; i++) {
-        if (!((ctx->blksw >> i) & 1)) {
-            do_imdct_512(&ctx->fft_128, ctx->transform_coeffs[i + 1], ctx->output[i + 1],
-                    ctx->delay[i + 1], ctx->tmp_imdct, ctx->tmp_output);
-        } else {
-            av_log(NULL, AV_LOG_INFO, "block switching enabled.\n");
-            do_imdct_256(&ctx->fft_64, ctx->transform_coeffs[i + 1], ctx->output[i + 1],
-                    ctx->delay[i + 1], ctx->tmp_imdct, ctx->tmp_output);
-        }
+        if ((ctx->blksw >> i) & 1)
+            do_imdct_256(ctx, i + 1);
+        else
+            do_imdct_512(ctx, i + 1);
     }
 }
 
@@ -1661,7 +1630,7 @@ static int ac3_parse_audio_block(AC3Deco
     int dynrng, chbwcod, ngrps, cplabsexp, skipl;
 
     for (i = 0; i < 5; i++)
-        ctx->chcoeffs[i] = 1.0;
+        ctx->chcoeffs[i] = 2.0;
 
     for (i = 0; i < nfchans; i++) /*block switch flag */
         ctx->blksw |= get_bits1(gb) << i;
@@ -1670,14 +1639,14 @@ static int ac3_parse_audio_block(AC3Deco
         ctx->dithflag |= get_bits1(gb) << i;
 
     if (get_bits1(gb)) { /* dynamic range */
-        dynrng = get_bits(gb, 8);
+        dynrng = get_sbits(gb, 8);
         drange = ((((dynrng & 0x1f) | 0x20) << 13) * scale_factors[3 - (dynrng >> 5)]);
         for (i = 0; i < nfchans; i++)
             ctx->chcoeffs[i] *= drange;
     }
 
     if (acmod == 0x00 && get_bits1(gb)) { /* dynamic range 1+1 mode */
-        dynrng = get_bits(gb, 8);
+        dynrng = get_sbits(gb, 8);
         drange = ((((dynrng & 0x1f) | 0x20) << 13) * scale_factors[3 - (dynrng >> 5)]);
         ctx->chcoeffs[1] *= drange;
     }
@@ -1931,9 +1900,12 @@ static int ac3_parse_audio_block(AC3Deco
 
 static inline int16_t convert(float f)
 {
-    int a;
-    a = lrintf(f * 32767.0);
-    return ((int16_t)a);
+    if (f >= 1.0)
+        return 32767;
+    else if (f <= -1.0)
+        return -32768;
+    else
+        return (lrintf(f * 32767.0));
 }
 
 static int frame_count = 0;
@@ -1943,7 +1915,8 @@ static int ac3_decode_frame(AVCodecConte
     AC3DecodeContext *ctx = (AC3DecodeContext *)avctx->priv_data;
     int frame_start;
     int16_t *out_samples = (int16_t *)data;
-    int i, j, k, value;
+    int i, j, k, value, fs_58;
+    uint16_t crc1;
 
     av_log(NULL, AV_LOG_INFO, "decoding frame %d buf_size = %d\n", frame_count++, buf_size);
 
@@ -1966,38 +1939,34 @@ static int ac3_decode_frame(AVCodecConte
         return buf_size;
     }
 
-    //Check for the errors.
-    /* if (ac3_error_check(ctx)) {
-        *data_size = 0;
-        return -1;
-    } */
-
     //Parse the BSI.
     //If 'bsid' is not valid decoder shall not decode the audio as per the standard.
     ac3_parse_bsi(ctx);
 
     avctx->sample_rate = ctx->sampling_rate;
     avctx->bit_rate = ctx->bit_rate;
-    avctx->channels = 0;
+
     if (avctx->channels == 0) {
         ctx->blkoutput |= AC3_OUTPUT_UNMODIFIED;
-        avctx->channels = ctx->nfchans;
-    } else if (ctx->nfchans + ctx->lfeon < avctx->channels) {
-        av_log(avctx, AV_LOG_INFO, "ac3_decoder: AC3 Source Channels Are Less Then Specified %d: Output to %d Channels\n",
-                avctx->channels, ctx->nfchans + ctx->lfeon);
-        avctx->channels = ctx->nfchans;
-        ctx->blkoutput |= AC3_OUTPUT_UNMODIFIED;
-    } else if (avctx->channels == 1) {
+        if (ctx->lfeon)
+            ctx->blkoutput |= AC3_OUTPUT_LFEON;
+        avctx->channels = ctx->nfchans + ctx->lfeon;
+    }
+    else if (avctx->channels == 1)
         ctx->blkoutput |= AC3_OUTPUT_MONO;
-    } else if (avctx->channels == 2) {
+    else if (avctx->channels == 2) {
         if (ctx->dsurmod == 0x02)
             ctx->blkoutput |= AC3_OUTPUT_DOLBY;
         else
             ctx->blkoutput |= AC3_OUTPUT_STEREO;
     }
-    if (ctx->lfeon) {
-        avctx->channels++;
-        ctx->blkoutput |= AC3_OUTPUT_LFEON;
+    else {
+        if (avctx->channels < (ctx->nfchans + ctx->lfeon))
+            av_log(avctx, AV_LOG_INFO, "ac3_decoder: AC3 Source Channels Are Less Then Specified %d: Output to %d Channels\n",avctx->channels, ctx->nfchans + ctx->lfeon);
+        ctx->blkoutput |= AC3_OUTPUT_UNMODIFIED;
+        if (ctx->lfeon)
+            ctx->blkoutput |= AC3_OUTPUT_LFEON;
+        avctx->channels = ctx->nfchans + ctx->lfeon;
     }
 
     av_log(avctx, AV_LOG_INFO, "channels = %d \t bit rate = %d \t sampling rate = %d \n", avctx->channels, avctx->bit_rate * 1000, avctx->sample_rate);
@@ -2009,10 +1978,9 @@ static int ac3_decode_frame(AVCodecConte
             *data_size = 0;
             return ctx->frame_size;
         }
-        j = ((ctx->blkoutput & AC3_OUTPUT_LFEON) ? 0 : 1);
         for (k = 0; k < BLOCK_SIZE; k++) {
-            j = ((ctx->blkoutput & AC3_OUTPUT_LFEON) ? 0 : 1);
-            for (;j < avctx->channels + 1; j++) {
+            j = (ctx->blkoutput & AC3_OUTPUT_LFEON) ? 0 : 1;
+            for (; j <= avctx->channels; j++) {
                 value = convert(ctx->output[j][k]);
                 *(out_samples++) = value;
             }




More information about the ffmpeg-cvslog mailing list