[FFmpeg-soc] [soc]: r1138 - in eac3: ac3dec.c ac3dec.h checkout.sh eac3.h eac3dec.c ffmpeg.patch

bwolowiec subversion at mplayerhq.hu
Tue Aug 21 22:50:09 CEST 2007


Author: bwolowiec
Date: Tue Aug 21 22:50:09 2007
New Revision: 1138

Log:
adding stereo downmix


Modified:
   eac3/ac3dec.c
   eac3/ac3dec.h
   eac3/checkout.sh
   eac3/eac3.h
   eac3/eac3dec.c
   eac3/ffmpeg.patch

Modified: eac3/ac3dec.c
==============================================================================
--- eac3/ac3dec.c	(original)
+++ eac3/ac3dec.c	Tue Aug 21 22:50:09 2007
@@ -721,7 +721,7 @@ static inline void do_imdct(AC3DecodeCon
 /**
  * Downmix the output to mono or stereo.
  */
-static void ac3_downmix(float samples[AC3_MAX_CHANNELS][256], int nfchans,
+void ff_ac3_downmix(float samples[AC3_MAX_CHANNELS][256], int nfchans,
                         int output_mode, float coef[AC3_MAX_CHANNELS][2])
 {
     int i, j;
@@ -1041,7 +1041,7 @@ static int ac3_parse_audio_block(AC3Deco
     /* downmix output if needed */
     if(ctx->nchans != ctx->out_channels && !((ctx->output_mode & AC3_OUTPUT_LFEON) &&
             ctx->nfchans == ctx->out_channels)) {
-        ac3_downmix(ctx->output, ctx->nfchans, ctx->output_mode,
+        ff_ac3_downmix(ctx->output, ctx->nfchans, ctx->output_mode,
                     ctx->downmix_coeffs);
     }
 

Modified: eac3/ac3dec.h
==============================================================================
--- eac3/ac3dec.h	(original)
+++ eac3/ac3dec.h	Tue Aug 21 22:50:09 2007
@@ -85,7 +85,13 @@ void ff_ac3_do_rematrixing(float (*trans
 void ff_ac3_do_imdct_256(float *tmp_output, float *transform_coeffs,
         MDCTContext *imdct_256, float *tmp_imdct);
 
+void ff_ac3_downmix(float samples[AC3_MAX_CHANNELS][256], int nfchans,
+                        int output_mode, float coef[AC3_MAX_CHANNELS][2]);
+
 /** Adjustments in dB gain */
+#define LEVEL_PLUS_3DB          1.4142135623730950
+#define LEVEL_PLUS_1POINT5DB    1.1892071150027209
+#define LEVEL_MINUS_1POINT5DB   0.8408964152537145
 #define LEVEL_MINUS_3DB         0.7071067811865476
 #define LEVEL_MINUS_4POINT5DB   0.5946035575013605
 #define LEVEL_MINUS_6DB         0.5000000000000000

Modified: eac3/checkout.sh
==============================================================================
--- eac3/checkout.sh	(original)
+++ eac3/checkout.sh	Tue Aug 21 22:50:09 2007
@@ -1,7 +1,7 @@
 FILES="ac3.c ac3.h ac3tab.c ac3tab.h eac3dec.c eac3.h ac3dec.c ac3dec.h"
 
 echo "checking out ffmpeg svn"
-for i in $FILES ac3_parser.c Makefile aac_ac3_parser.c aac_ac3_parser.h aac_parser.c allcodecs.c avcodec.h ../libavformat/allformats.h ../libavformat/raw.c allcodecs.h ac3enc.c; do
+for i in $FILES ac3_parser.c Makefile aac_ac3_parser.c aac_ac3_parser.h aac_parser.c allcodecs.c avcodec.h ../libavformat/allformats.h ../libavformat/raw.c allcodecs.h ac3enc.c ../ffmpeg.c; do
     rm -f ffmpeg/libavcodec/$i
 done
 svn checkout svn://svn.mplayerhq.hu/ffmpeg/trunk/ ffmpeg -r 10118

Modified: eac3/eac3.h
==============================================================================
--- eac3/eac3.h	(original)
+++ eac3/eac3.h	Tue Aug 21 22:50:09 2007
@@ -37,14 +37,6 @@
 #define MAX_BLOCKS 6
 #define MAX_SPX_CODES 18
 
-// TODO use new downmixing
-/** output configurations. */
-#define AC3_OUTPUT_UNMODIFIED 0x01
-#define AC3_OUTPUT_MONO       0x02
-#define AC3_OUTPUT_STEREO     0x04
-#define AC3_OUTPUT_DOLBY      0x08
-#define AC3_OUTPUT_LFEON      0x10
-
 typedef struct EAC3Context{
     AVCodecContext *avctx;           ///< Parent context
     int syncword;
@@ -63,10 +55,6 @@ typedef struct EAC3Context{
     int chanmap;                     ///< Custom channel map
     int mixmdate;                    ///< Mixing meta-data exists
     int dmixmod;                     ///< Preferred stereo downmix mode
-    int ltrtcmixlev;                 ///< Lt/Rt center mix level
-    int lorocmixlev;                 ///< Lo/Ro center mix level
-    int ltrtsurmixlev;               ///< Lt/Rt surround mix level
-    int lorosurmixlev;               ///< Lo/Ro surround mix level
     int lfemixlevcode;               ///< lfe mix level code exists
     int lfemixlevcod;                ///< lfe mix level code
     int pgmscl[2];                   ///< Program scale factor
@@ -110,6 +98,7 @@ typedef struct EAC3Context{
     int blksw[AC3_MAX_CHANNELS];     ///< Block switch flag
     int dithflag[AC3_MAX_CHANNELS];  ///< Dither flag
     float dynrng[2];                 ///< Dynamic range gain word
+    float downmix_coeffs[AC3_MAX_CHANNELS][2];  ///< stereo downmix coefficients
     int spxinu;                      ///< spectral extension in use
     int chinspx[AC3_MAX_CHANNELS];   ///< Channel in spectral extension
     int spxstrtf;                    ///< Spectral extension start copy frequency code
@@ -214,8 +203,6 @@ typedef struct EAC3Context{
 
     float add_bias;                  ///< offset for float_to_int16 conversion
     float mul_bias;                  ///< scaling for float_to_int16 conversion
-
-    AC3ChannelMode  blkoutput;
 }EAC3Context;
 
 /** Channel gain adaptive quantization mode */

Modified: eac3/eac3dec.c
==============================================================================
--- eac3/eac3dec.c	(original)
+++ eac3/eac3dec.c	Tue Aug 21 22:50:09 2007
@@ -40,6 +40,33 @@ static void get_eac3_transform_coeffs_ch
 static void uncouple_channels(EAC3Context *s);
 static void log_missing_feature(AVCodecContext *avctx, const char *log);
 
+/**
+ * Table for default stereo downmixing coefficients
+ * reference: Section 7.8.2 Downmixing Into Two Channels
+ */
+static const uint8_t eac3_default_coeffs[8][5][2] = {
+    { { 2, 7 }, { 7, 2 },                               },
+    { { 4, 4 },                                         },
+    { { 2, 7 }, { 7, 2 },                               },
+    { { 2, 7 }, { 5, 5 }, { 7, 2 },                     },
+    { { 2, 7 }, { 7, 2 }, { 6, 6 },                     },
+    { { 2, 7 }, { 5, 5 }, { 7, 2 }, { 8, 8 },           },
+    { { 2, 7 }, { 7, 2 }, { 6, 7 }, { 7, 6 },           },
+    { { 2, 7 }, { 5, 5 }, { 7, 2 }, { 6, 7 }, { 7, 6 }, },
+};
+
+static const float mixlevels[9] = {
+    LEVEL_PLUS_3DB,
+    LEVEL_PLUS_1POINT5DB,
+    LEVEL_ONE,
+    LEVEL_MINUS_1POINT5DB,
+    LEVEL_MINUS_3DB,
+    LEVEL_MINUS_4POINT5DB,
+    LEVEL_MINUS_6DB,
+    LEVEL_ZERO,
+    LEVEL_MINUS_9DB
+};
+
 static int parse_bsi(GetBitContext *gbc, EAC3Context *s){
     int i, blk;
 
@@ -96,6 +123,14 @@ static int parse_bsi(GetBitContext *gbc,
             //TODO default channel map based on acmod and lfeon
         }
     }
+
+    /* set stereo downmixing coefficients
+       reference: Section 7.8.2 Downmixing Into Two Channels */
+    for(i=0; i<s->nfchans; i++) {
+        s->downmix_coeffs[i][0] = mixlevels[eac3_default_coeffs[s->acmod][i][0]];
+        s->downmix_coeffs[i][1] = mixlevels[eac3_default_coeffs[s->acmod][i][1]];
+    }
+
     GET_BITS(s->mixmdate, gbc, 1);
     if(s->mixmdate){
         /* Mixing metadata */
@@ -105,14 +140,22 @@ static int parse_bsi(GetBitContext *gbc,
         }
         if((s->acmod & 0x1) && (s->acmod > 0x2)){
             /* if three front channels exist */
-            GET_BITS(s->ltrtcmixlev, gbc, 3);
-            GET_BITS(s->lorocmixlev, gbc, 3);
+            skip_bits(gbc, 3); //skip Lt/Rt center mix level
+            s->downmix_coeffs[1][0] = s->downmix_coeffs[1][1] = mixlevels[get_bits(gbc, 3)];
         }
         if(s->acmod & 0x4){
             /* if a surround channel exists */
-
-            GET_BITS(s->ltrtsurmixlev, gbc, 3);
-            GET_BITS(s->lorosurmixlev, gbc, 3);
+            float surmixlev;
+            skip_bits(gbc, 3); //skip Lt/Rt surround mix level
+            surmixlev = mixlevels[get_bits(gbc, 3)];
+            if(s->acmod & 0x2){
+                //two surround channels
+                s->downmix_coeffs[s->acmod-4][0] = s->downmix_coeffs[s->acmod-3][1] =
+                    surmixlev;
+            }else{
+                s->downmix_coeffs[s->acmod-2][0] = s->downmix_coeffs[s->acmod-2][1] =
+                    surmixlev * LEVEL_MINUS_3DB;
+            }
         }
         if(s->lfeon){
             /* if the LFE channel exists */
@@ -1235,10 +1278,10 @@ static void do_imdct(EAC3Context *ctx)
                                           ctx->tmp_imdct);
         }
         /* apply window function, overlap/add output, save delay */
-        ctx->dsp.vector_fmul_add_add(ctx->output[ch], ctx->tmp_output,
-                                     ctx->window, ctx->delay[ch], 0,
+        ctx->dsp.vector_fmul_add_add(ctx->output[ch-1], ctx->tmp_output,
+                                     ctx->window, ctx->delay[ch-1], 0,
                                      AC3_BLOCK_SIZE, 1);
-        ctx->dsp.vector_fmul_reverse(ctx->delay[ch], ctx->tmp_output+256,
+        ctx->dsp.vector_fmul_reverse(ctx->delay[ch-1], ctx->tmp_output+256,
                                      ctx->window, AC3_BLOCK_SIZE);
     }
 }
@@ -1272,7 +1315,20 @@ static int eac3_decode_frame(AVCodecCont
 #ifdef DEBUG
     av_log(NULL, AV_LOG_INFO, "bitrate = %i\n", avctx->bit_rate);
 #endif
-    avctx->channels = c->nfchans + c->lfeon; // TODO lfe
+
+    /* channel config */
+    if (avctx->channels == 0) {
+        avctx->channels = c->ntchans;
+    } else if(c->ntchans < avctx->channels) {
+        av_log(avctx, AV_LOG_ERROR, "Cannot upmix EAC3 from %d to %d channels.\n",
+               c->ntchans, avctx->channels);
+        return -1;
+    }
+    if(avctx->channels > 2 && avctx->channels != c->ntchans) {
+        av_log(avctx, AV_LOG_ERROR, "Cannot downmix EAC3 from %d to %d channels.\n",
+               c->ntchans, avctx->channels);
+        return -1;
+    }
 
     for(blk = 0; blk < ff_eac3_blocks[c->numblkscod]; blk++){
         for(i=0; i<AC3_MAX_CHANNELS+1; i++){
@@ -1295,7 +1351,6 @@ static int eac3_decode_frame(AVCodecCont
         ff_ac3_do_rematrixing(c->transform_coeffs,
                 FFMIN(c->endmant[1], c->endmant[2]),
                 c->nrematbnds, c->rematflg);
-        //TODO downmix_scaling...
 
         /* apply scaling to coefficients (dialnorm, dynrng) */
         for(ch=1; ch<=c->nfchans + c->lfeon; ch++) {
@@ -1311,29 +1366,13 @@ static int eac3_decode_frame(AVCodecCont
         }
 
         do_imdct(c);
-        //TODO downmix
-
-#ifdef DEBUG
-        av_log(avctx, AV_LOG_INFO, "channels = %i\n", avctx->channels);
-#endif
 
-        // set output mode
-        c->blkoutput = 0;
-        if (avctx->channels == 1) {
-            c->blkoutput |= AC3_OUTPUT_MONO;
-        } else if (avctx->channels == 2) {
-            c->blkoutput |= AC3_OUTPUT_STEREO;
-        } else {
-            if (avctx->channels && avctx->channels < c->nfchans + c->lfeon )
-                av_log(avctx, AV_LOG_INFO, "ac3_decoder: E-AC3 Source Channels Are Less Then Specified %d: Output to %d Channels\n",avctx->channels, c->nfchans + c->lfeon);
-            c->blkoutput |= AC3_OUTPUT_UNMODIFIED;
-            if (c->lfeon)
-                c->blkoutput |= AC3_OUTPUT_LFEON;
-            avctx->channels = c->nfchans + c->lfeon;
+        if(avctx->channels != c->ntchans){
+            ff_ac3_downmix(c->output, c->nfchans, avctx->channels, c->downmix_coeffs);
         }
 
         // convert float to 16-bit integer
-       for(ch = 1; ch<=c->nfchans + c->lfeon; ch++) { // <- out_channels TODO
+       for(ch = 0; ch<avctx->channels; ch++) {
             for(i=0; i<AC3_BLOCK_SIZE; i++) {
                 c->output[ch][i] = c->output[ch][i] * c->mul_bias +
                     c->add_bias;
@@ -1342,7 +1381,7 @@ static int eac3_decode_frame(AVCodecCont
                     AC3_BLOCK_SIZE);
         }
         for (k = 0; k < AC3_BLOCK_SIZE; k++) {
-            for (i = 1; i <= avctx->channels; i++) {
+            for (i = 0; i < avctx->channels; i++) {
                 *(out_samples++) = c->int_output[i][k];
             }
         }

Modified: eac3/ffmpeg.patch
==============================================================================
--- eac3/ffmpeg.patch	(original)
+++ eac3/ffmpeg.patch	Tue Aug 21 22:50:09 2007
@@ -67,6 +67,15 @@ Index: libavcodec/aac_ac3_parser.c
                                &samples);
                  if (len == 0) {
                      /* no sync found : move by one byte (inefficient, but simple!) */
+@@ -59,7 +59,7 @@
+                     /* update codec info */
+                     avctx->sample_rate = sample_rate;
+                     /* set channels,except if the user explicitly requests 1 or 2 channels, XXX/FIXME this is a bit ugly */
+-                    if(avctx->codec_id == CODEC_ID_AC3){
++                    if(avctx->codec_id == CODEC_ID_AC3 || avctx->codec_id == CODEC_ID_EAC3){
+                         if(avctx->channels!=1 && avctx->channels!=2){
+                             avctx->channels = channels;
+                         }
 Index: libavcodec/aac_ac3_parser.h
 ===================================================================
 --- libavcodec/aac_ac3_parser.h	(wersja 10118)
@@ -183,3 +192,15 @@ Index: libavcodec/ac3enc.c
              frame_bits += compute_mantissa_size(s, bap[i][ch],
                                                   s->nb_coefs[ch]);
          }
+Index: ffmpeg.c
+===================================================================
+--- ffmpeg.c	(wersja 10118)
++++ ffmpeg.c	(kopia robocza)
+@@ -1569,6 +1569,7 @@
+                 } else {
+                     if (codec->channels != icodec->channels &&
+                         (icodec->codec_id == CODEC_ID_AC3 ||
++                         icodec->codec_id == CODEC_ID_EAC3 ||
+                          icodec->codec_id == CODEC_ID_DTS)) {
+                         /* Special case for 5:1 AC3 and DTS input */
+                         /* and mono or stereo output      */



More information about the FFmpeg-soc mailing list